Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@ansible/ansible-language-server

Package Overview
Dependencies
Maintainers
4
Versions
45
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@ansible/ansible-language-server - npm Package Compare versions

Comparing version 0.2.6 to 0.3.0

0001-Release-0.3.0-from-GitHub-Actions-CI-CD.patch

17

CHANGELOG.md

@@ -9,2 +9,16 @@ <!-- markdownlint-disable no-duplicate-heading -->

## [0.3.0] - 2021-11-18
### Minor Changes
* Added support for nested module options (suboptions) (#116) @tomaciazek
* Adopted use of `creator-ee` execution environment (#132) @ssbarnea
* Updated container cleanup logic for execution environment (#111) @ganeshrn
### Bugfixes
* Updated plugin doc cache validate logic for execution environment (#109)
@ganeshrn
* Fixed issue with container copy command (#110) @ganeshrn
## [0.2.6] - 2021-10-29

@@ -14,3 +28,4 @@

* Fix autocompletion of the builtin modules with EE (#94) @ganeshrn
* Fixed autocompletion to account for the builtin modules when used
with EE (#94) @ganeshrn

@@ -17,0 +32,0 @@ ## [0.2.5] - 2021-10-23

2

out/server/src/interfaces/module.d.ts

@@ -37,3 +37,3 @@ import { YAMLError } from 'yaml/util';

versionAdded?: string;
suboptions?: unknown;
suboptions?: Map<string, IOption>;
}

@@ -117,75 +117,60 @@ "use strict";

}
// Finally, check if we're looking for module options
// In that case, the module name is a key of a map
const parentKeyPath = new yaml_1.AncestryBuilder(path)
.parentOfKey()
.parent(types_1.YAMLMap)
.getKeyPath();
if (parentKeyPath && (0, yaml_1.isTaskParam)(parentKeyPath)) {
const parentKeyNode = parentKeyPath[parentKeyPath.length - 1];
if (parentKeyNode instanceof types_1.Scalar) {
let module;
if (parentKeyNode.value === 'args') {
module = yield (0, yaml_1.findProvidedModule)(parentKeyPath, document, docsLibrary);
// Finally, check if we're looking for module options or sub-options
const options = yield (0, yaml_1.getPossibleOptionsForPath)(path, document, docsLibrary);
if (options) {
const optionMap = new yaml_1.AncestryBuilder(path)
.parentOfKey()
.get();
// find options that have been already provided by the user
const providedOptions = new Set((0, yaml_1.getYamlMapKeys)(optionMap));
const remainingOptions = [...options.entries()].filter(([, specs]) => !providedOptions.has(specs.name));
const nodeRange = getNodeRange(node, document);
return remainingOptions
.map(([option, specs]) => {
return {
name: option,
specs: specs,
};
})
.map((option, index) => {
// translate option documentation to CompletionItem
const details = (0, docsFormatter_1.getDetails)(option.specs);
let priority;
if (isAlias(option)) {
priority = priorityMap.aliasOption;
}
else if (option.specs.required) {
priority = priorityMap.requiredOption;
}
else {
[module] = yield docsLibrary.findModule(parentKeyNode.value, parentKeyPath, document.uri);
priority = priorityMap.option;
}
if (module && module.documentation) {
const moduleOptions = module.documentation.options;
const optionMap = new yaml_1.AncestryBuilder(parentKeyPath).parent(types_1.Pair).get().value;
// find options that have been already provided by the user
const providedOptions = new Set((0, yaml_1.getYamlMapKeys)(optionMap));
const remainingOptions = [...moduleOptions.entries()].filter(([, specs]) => !providedOptions.has(specs.name));
const nodeRange = getNodeRange(node, document);
return remainingOptions
.map(([option, specs]) => {
return {
name: option,
specs: specs,
};
})
.map((option, index) => {
// translate option documentation to CompletionItem
const details = (0, docsFormatter_1.getDetails)(option.specs);
let priority;
if (isAlias(option)) {
priority = priorityMap.aliasOption;
}
else if (option.specs.required) {
priority = priorityMap.requiredOption;
}
else {
priority = priorityMap.option;
}
const completionItem = {
label: option.name,
detail: details,
// using index preserves order from the specification
// except when overridden by the priority
sortText: priority.toString() + index.toString().padStart(3),
kind: isAlias(option)
? vscode_languageserver_1.CompletionItemKind.Reference
: vscode_languageserver_1.CompletionItemKind.Property,
documentation: (0, docsFormatter_1.formatOption)(option.specs),
insertText: atEndOfLine(document, position)
? `${option.name}:`
: undefined,
};
const insertText = atEndOfLine(document, position)
? `${option.name}:`
: option.name;
if (nodeRange) {
completionItem.textEdit = {
range: nodeRange,
newText: insertText,
};
}
else {
completionItem.insertText = insertText;
}
return completionItem;
});
const completionItem = {
label: option.name,
detail: details,
// using index preserves order from the specification
// except when overridden by the priority
sortText: priority.toString() + index.toString().padStart(3),
kind: isAlias(option)
? vscode_languageserver_1.CompletionItemKind.Reference
: vscode_languageserver_1.CompletionItemKind.Property,
documentation: (0, docsFormatter_1.formatOption)(option.specs),
insertText: atEndOfLine(document, position)
? `${option.name}:`
: undefined,
};
const insertText = atEndOfLine(document, position)
? `${option.name}:`
: option.name;
if (nodeRange) {
completionItem.textEdit = {
range: nodeRange,
newText: insertText,
};
}
}
else {
completionItem.insertText = insertText;
}
return completionItem;
});
}

@@ -192,0 +177,0 @@ }

@@ -62,26 +62,10 @@ "use strict";

}
// hovering over a module parameter
// can either be directly under module or in 'args'
const parentKeyPath = new yaml_1.AncestryBuilder(path)
.parentOfKey()
.parent(types_1.YAMLMap)
.getKeyPath();
if (parentKeyPath && (0, yaml_1.isTaskParam)(parentKeyPath)) {
const parentKeyNode = parentKeyPath[parentKeyPath.length - 1];
if (parentKeyNode instanceof types_1.Scalar) {
let module;
if (parentKeyNode.value === 'args') {
module = yield (0, yaml_1.findProvidedModule)(parentKeyPath, document, docsLibrary);
}
else {
[module] = yield docsLibrary.findModule(parentKeyNode.value, parentKeyPath, document.uri);
}
if (module && module.documentation) {
const option = module.documentation.options.get(node.value);
if (option) {
return {
contents: (0, docsFormatter_1.formatOption)(option, true),
};
}
}
// hovering over a module option or sub-option
const options = yield (0, yaml_1.getPossibleOptionsForPath)(path, document, docsLibrary);
if (options) {
const option = options.get(node.value);
if (option) {
return {
contents: (0, docsFormatter_1.formatOption)(option, true),
};
}

@@ -88,0 +72,0 @@ }

@@ -40,2 +40,3 @@ "use strict";

function markSemanticTokens(path, builder, document, docsLibrary) {
var _a, _b;
return __awaiter(this, void 0, void 0, function* () {

@@ -72,3 +73,3 @@ const node = path[path.length - 1];

// highlight module parameters
markModuleParameters(pair.value, module, builder, document);
markModuleParameters(pair.value, (_a = module.documentation) === null || _a === void 0 ? void 0 : _a.options, builder, document);
}

@@ -84,3 +85,3 @@ }

// highlight module parameters
markModuleParameters(pair.value, module, builder, document);
markModuleParameters(pair.value, (_b = module.documentation) === null || _b === void 0 ? void 0 : _b.options, builder, document);
}

@@ -118,15 +119,34 @@ }

}
function markModuleParameters(moduleParamMap, module, builder, document) {
var _a;
function markModuleParameters(moduleParamMap, options, builder, document) {
for (const moduleParamPair of moduleParamMap.items) {
if (moduleParamPair.key instanceof types_1.Scalar) {
const option = (_a = module.documentation) === null || _a === void 0 ? void 0 : _a.options.get(moduleParamPair.key.value);
const option = options === null || options === void 0 ? void 0 : options.get(moduleParamPair.key.value);
if (option) {
markNode(moduleParamPair.key, vscode_languageserver_1.SemanticTokenTypes.method, [], builder, document);
if (option.type === 'dict' &&
moduleParamPair.value instanceof types_1.YAMLMap) {
// highlight sub-parameters
markModuleParameters(moduleParamPair.value, option.suboptions, builder, document);
}
else if (option.type === 'list' &&
moduleParamPair.value instanceof types_1.YAMLSeq) {
// highlight list of sub-parameters
for (const item of moduleParamPair.value.items) {
if (item instanceof types_1.YAMLMap) {
markModuleParameters(item, option.suboptions, builder, document);
}
else {
markAllNestedKeysAsOrdinary(item, builder, document);
}
}
}
else {
markAllNestedKeysAsOrdinary(moduleParamPair.value, builder, document);
}
}
else {
markOrdinaryKey(moduleParamPair.key, builder, document);
markAllNestedKeysAsOrdinary(moduleParamPair.value, builder, document);
}
}
if (moduleParamPair.value instanceof types_1.Node) {
else if (moduleParamPair.value instanceof types_1.Node) {
markAllNestedKeysAsOrdinary(moduleParamPair.value, builder, document);

@@ -133,0 +153,0 @@ }

@@ -7,2 +7,3 @@ import { Connection } from 'vscode-languageserver';

private useProgressTracker;
private successFileMarker;
private _container_engine;

@@ -16,2 +17,3 @@ private _container_image;

cleanUpContainer(containerName: string): void;
doesContainerNameExist(containerName: string): boolean;
private isPluginInPath;

@@ -21,2 +23,3 @@ private runContainer;

private updateCachePaths;
private isPluginDocCacheValid;
}

@@ -24,2 +24,3 @@ "use strict";

this.useProgressTracker = false;
this.successFileMarker = 'SUCCESS';
this.connection = connection;

@@ -107,3 +108,3 @@ this.context = context;

}
if (fs.existsSync(hostCacheBasePath)) {
if (this.isPluginDocCacheValid(hostCacheBasePath)) {
ansibleConfig.collections_paths = this.updateCachePaths(ansibleConfig.collections_paths, hostCacheBasePath);

@@ -138,2 +139,4 @@ ansibleConfig.module_locations = this.updateCachePaths(ansibleConfig.module_locations, hostCacheBasePath);

}
// plugin cache successfully created
fs.closeSync(fs.openSync(path.join(hostCacheBasePath, this.successFileMarker), 'w'));
}

@@ -182,6 +185,11 @@ catch (error) {

cleanUpContainer(containerName) {
[
const cleanUpCommands = [
`${this._container_engine} stop ${containerName}`,
`${this._container_engine} rm ${containerName}`,
].forEach((command) => {
];
if (!this.doesContainerNameExist(containerName)) {
console.log(`clean up container not required as container with name ${containerName} does not exist`);
return;
}
for (const command of cleanUpCommands) {
try {

@@ -194,5 +202,17 @@ child_process.execSync(command, {

// container already stopped and/or removed
break;
}
});
}
}
doesContainerNameExist(containerName) {
let containerNameExist = false;
try {
child_process.execSync(`${this._container_engine} inspect ${containerName}`);
containerNameExist = true;
}
catch (error) {
containerNameExist = false;
}
return containerNameExist;
}
isPluginInPath(containerName, searchPath, pluginFolderPath) {

@@ -248,3 +268,3 @@ const command = `${this._container_engine} exec ${containerName} find ${searchPath} -path '${pluginFolderPath}'`;

fs.mkdirSync(destPath, { recursive: true });
const copyCommand = `docker cp ${containerName}:${srcPath} ${destPathFolder}`;
const copyCommand = `${this._container_engine} cp ${containerName}:${srcPath} ${destPathFolder}`;
this.connection.console.log(`Copying plugins from container to local cache path ${copyCommand}`);

@@ -270,4 +290,8 @@ (0, misc_1.asyncExec)(copyCommand, {

}
isPluginDocCacheValid(hostCacheBasePath) {
const markerFilePath = path.join(hostCacheBasePath, this.successFileMarker);
return true ? fs.existsSync(markerFilePath) : false;
}
}
exports.ExecutionEnvironment = ExecutionEnvironment;
//# sourceMappingURL=executionEnvironment.js.map

@@ -26,3 +26,3 @@ "use strict";

enabled: false,
image: 'quay.io/ansible/ansible-navigator-demo-ee:0.6.0',
image: 'quay.io/ansible/creator-ee:latest',
pullPolicy: 'missing'

@@ -29,0 +29,0 @@ }

@@ -84,3 +84,3 @@ "use strict";

default: rawOption.default,
suboptions: rawOption.suboptions,
suboptions: processRawOptions(rawOption.suboptions),
};

@@ -87,0 +87,0 @@ if (isIDescription(rawOption.description))

@@ -8,7 +8,7 @@ /// <reference types="node" />

export declare function toLspRange(range: [number, number], textDocument: TextDocument): Range;
export declare function hasOwnProperty<X extends unknown, Y extends PropertyKey>(obj: X, prop: Y): obj is X & Record<Y, unknown>;
export declare function hasOwnProperty<X, Y extends PropertyKey>(obj: X, prop: Y): obj is X & Record<Y, unknown>;
/**
* Checks whether `obj` is a non-null object.
*/
export declare function isObject<X extends unknown>(obj: X): obj is X & Record<PropertyKey, unknown>;
export declare function isObject<X>(obj: X): obj is X & Record<PropertyKey, unknown>;
export declare function insert(str: string, index: number, val: string): string;

@@ -15,0 +15,0 @@ /**

import { Position, TextDocument } from 'vscode-languageserver-textdocument';
import { Document, Options } from 'yaml';
import { Node, Pair, YAMLMap } from 'yaml/types';
import { IModuleMetadata } from '../interfaces/module';
import { IModuleMetadata, IOption } from '../interfaces/module';
import { DocsLibrary } from '../services/docsLibrary';

@@ -83,2 +83,15 @@ /**

/**
* If the path points at a parameter or sub-parameter provided for a module, it
* will return the list of all possible options or sub-options at that
* level/indentation.
*/
export declare function getPossibleOptionsForPath(path: Node[], document: TextDocument, docsLibrary: DocsLibrary): Promise<Map<string, IOption> | null>;
/**
* For a given path, it searches up that path until a path to the task parameter
* (typically a module name) is found. The trace of keys with indication whether
* the values hold a 'list' or a 'dict' is preserved along the way and returned
* alongside.
*/
export declare function getTaskParamPathWithTrace(path: Node[]): [Node[], [string, 'list' | 'dict'][]];
/**
* For a given Ansible task parameter path, find the module if it has been

@@ -85,0 +98,0 @@ * provided for the task.

@@ -12,3 +12,3 @@ "use strict";

Object.defineProperty(exports, "__esModule", { value: true });
exports.isPlaybook = exports.parseAllDocuments = exports.getOrigRange = exports.getYamlMapKeys = exports.findProvidedModule = exports.isRoleParam = exports.isBlockParam = exports.isPlayParam = exports.getDeclaredCollections = exports.isTaskParam = exports.tasksKey = exports.getPathAtOffset = exports.contains = exports.getPathAt = exports.AncestryBuilder = void 0;
exports.isPlaybook = exports.parseAllDocuments = exports.getOrigRange = exports.getYamlMapKeys = exports.findProvidedModule = exports.getTaskParamPathWithTrace = exports.getPossibleOptionsForPath = exports.isRoleParam = exports.isBlockParam = exports.isPlayParam = exports.getDeclaredCollections = exports.isTaskParam = exports.tasksKey = exports.getPathAtOffset = exports.contains = exports.getPathAt = exports.AncestryBuilder = void 0;
const _ = require("lodash");

@@ -318,2 +318,88 @@ const yaml_1 = require("yaml");

/**
* If the path points at a parameter or sub-parameter provided for a module, it
* will return the list of all possible options or sub-options at that
* level/indentation.
*/
function getPossibleOptionsForPath(path, document, docsLibrary) {
return __awaiter(this, void 0, void 0, function* () {
const [taskParamPath, suboptionTrace] = getTaskParamPathWithTrace(path);
if (!taskParamPath)
return null;
const optionTraceElement = suboptionTrace.pop();
if (!optionTraceElement || optionTraceElement[1] !== 'dict') {
// that element must always be a `dict`
// (unlike for sub-options, which can also be a 'list')
return null;
}
// The module name is a key of the task parameters map
const taskParamNode = taskParamPath[taskParamPath.length - 1];
if (!(taskParamNode instanceof types_1.Scalar))
return null;
let module;
// Module options can either be directly under module or in 'args'
if (taskParamNode.value === 'args') {
module = yield findProvidedModule(taskParamPath, document, docsLibrary);
}
else {
[module] = yield docsLibrary.findModule(taskParamNode.value, taskParamPath, document.uri);
}
if (!module || !module.documentation)
return null;
let options = module.documentation.options;
suboptionTrace.reverse(); // now going down the path
for (const [optionName, optionType] of suboptionTrace) {
const option = options.get(optionName);
if (optionName && (option === null || option === void 0 ? void 0 : option.type) === optionType && option.suboptions) {
options = option.suboptions;
}
else {
return null; // suboption structure mismatch
}
}
return options;
});
}
exports.getPossibleOptionsForPath = getPossibleOptionsForPath;
/**
* For a given path, it searches up that path until a path to the task parameter
* (typically a module name) is found. The trace of keys with indication whether
* the values hold a 'list' or a 'dict' is preserved along the way and returned
* alongside.
*/
function getTaskParamPathWithTrace(path) {
const trace = [];
while (!isTaskParam(path)) {
let parentKeyPath = new AncestryBuilder(path)
.parentOfKey()
.parent(types_1.YAMLMap)
.getKeyPath();
if (parentKeyPath) {
const parentKeyNode = parentKeyPath[parentKeyPath.length - 1];
if (parentKeyNode instanceof types_1.Scalar &&
typeof parentKeyNode.value === 'string') {
trace.push([parentKeyNode.value, 'dict']);
path = parentKeyPath;
continue;
}
}
parentKeyPath = new AncestryBuilder(path)
.parentOfKey()
.parent(types_1.YAMLSeq)
.parent(types_1.YAMLMap)
.getKeyPath();
if (parentKeyPath) {
const parentKeyNode = parentKeyPath[parentKeyPath.length - 1];
if (parentKeyNode instanceof types_1.Scalar &&
typeof parentKeyNode.value === 'string') {
trace.push([parentKeyNode.value, 'list']);
path = parentKeyPath;
continue;
}
}
return [[], []]; // return empty if no structural match found
}
return [path, trace];
}
exports.getTaskParamPathWithTrace = getTaskParamPathWithTrace;
/**
* For a given Ansible task parameter path, find the module if it has been

@@ -320,0 +406,0 @@ * provided for the task.

@@ -7,3 +7,3 @@ {

"license": "MIT",
"version": "0.2.6",
"version": "0.3.0",
"contributors": [

@@ -10,0 +10,0 @@ {

@@ -153,3 +153,2 @@ # Ansible Language Server

* The shorthand syntax for module options (key=value pairs) is not supported.
* Nested module options are not supported yet.
* Only Jinja *expressions* inside Ansible YAML files are supported. In order to

@@ -156,0 +155,0 @@ have syntax highlighting of Jinja template files, you'll need to install other

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc