Merge pull request #59 from github/joshmgross/improve-expression-completion
Improve auto-completion for expression functions
This commit is contained in:
@@ -39,6 +39,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@github/actions-workflow-parser": "*",
|
||||
"@github/actions-expressions": "*",
|
||||
"vscode-languageserver-textdocument": "^1.0.7",
|
||||
"vscode-languageserver-types": "^3.17.2",
|
||||
"yaml": "^2.1.1"
|
||||
@@ -58,4 +59,4 @@
|
||||
"ts-jest": "^29.0.3",
|
||||
"typescript": "^4.8.4"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
import {data} from "@github/actions-expressions";
|
||||
import {CompletionItemKind} from "vscode-languageserver-types";
|
||||
import {complete, getExpressionInput} from "./complete";
|
||||
import {ContextProviderConfig} from "./context-providers/config";
|
||||
import {registerLogger} from "./log";
|
||||
@@ -672,4 +673,53 @@ jobs:
|
||||
expect(result.map(x => x.label)).toEqual(["color"]);
|
||||
});
|
||||
});
|
||||
|
||||
it("context completion items include kind and insert text", async () => {
|
||||
const input = `
|
||||
on: push
|
||||
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- run: echo \${{ | }}.txt
|
||||
`;
|
||||
|
||||
const result = await complete(...getPositionFromCursor(input), undefined, contextProviderConfig);
|
||||
|
||||
// Built-in function
|
||||
const toJSON = result.find(x => x.label === "toJson");
|
||||
expect(toJSON).toBeDefined();
|
||||
expect(toJSON!.kind).toBe(CompletionItemKind.Function);
|
||||
expect(toJSON!.insertText).toBe("toJson()");
|
||||
|
||||
// Function from context
|
||||
const hashFiles = result.find(x => x.label === "hashFiles");
|
||||
expect(hashFiles).toBeDefined();
|
||||
expect(hashFiles!.kind).toBe(CompletionItemKind.Function);
|
||||
expect(hashFiles!.insertText).toBe("hashFiles()");
|
||||
|
||||
// Not a function
|
||||
const github = result.find(x => x.label === "github");
|
||||
expect(github).toBeDefined();
|
||||
expect(github!.kind).toBe(CompletionItemKind.Variable);
|
||||
expect(github!.insertText).toBeUndefined();
|
||||
});
|
||||
|
||||
it("function parentheses are not inserted when parentheses already exist", async () => {
|
||||
const input = `
|
||||
on: push
|
||||
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- run: echo \${{ toJS|(github.event) }}
|
||||
`;
|
||||
|
||||
const result = await complete(...getPositionFromCursor(input), undefined, contextProviderConfig);
|
||||
|
||||
expect(result.find(x => x.label === "toJson")!.insertText).toBe("toJson");
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import {complete as completeExpression} from "@github/actions-expressions";
|
||||
import {CompletionItem as ExpressionCompletionItem} from "@github/actions-expressions/completion";
|
||||
import {convertWorkflowTemplate, isSequence, isString, parseWorkflow} from "@github/actions-workflow-parser";
|
||||
import {ErrorPolicy} from "@github/actions-workflow-parser/model/convert";
|
||||
import {DefinitionType} from "@github/actions-workflow-parser/templates/schema/definition-type";
|
||||
@@ -9,7 +10,7 @@ import {MappingToken} from "@github/actions-workflow-parser/templates/tokens/map
|
||||
import {TokenType} from "@github/actions-workflow-parser/templates/tokens/types";
|
||||
import {File} from "@github/actions-workflow-parser/workflows/file";
|
||||
import {Position, TextDocument} from "vscode-languageserver-textdocument";
|
||||
import {CompletionItem, CompletionItemTag, Range, TextEdit} from "vscode-languageserver-types";
|
||||
import {CompletionItem, CompletionItemKind, CompletionItemTag, Range, TextEdit} from "vscode-languageserver-types";
|
||||
import {ContextProviderConfig} from "./context-providers/config";
|
||||
import {getContext, Mode} from "./context-providers/default";
|
||||
import {getWorkflowContext, WorkflowContext} from "./context/workflow-context";
|
||||
@@ -87,7 +88,9 @@ export async function complete(
|
||||
const allowedContext = token.definitionInfo?.allowedContext || [];
|
||||
const context = await getContext(allowedContext, contextProviderConfig, workflowContext, Mode.Completion);
|
||||
|
||||
return completeExpression(expressionInput, context, []);
|
||||
return completeExpression(expressionInput, context, []).map(item =>
|
||||
mapExpressionCompletionItem(item, currentInput[relCharPos])
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -192,3 +195,17 @@ function filterAndSortCompletionOptions(options: Value[], existingValues?: Set<s
|
||||
options.sort((a, b) => a.label.localeCompare(b.label));
|
||||
return options;
|
||||
}
|
||||
|
||||
function mapExpressionCompletionItem(item: ExpressionCompletionItem, charAfterPos: string): CompletionItem {
|
||||
let insertText: string | undefined;
|
||||
// Insert parentheses if the cursor is after a function
|
||||
// and the function does not have any parantheses already
|
||||
if (item.function) {
|
||||
insertText = charAfterPos === "(" ? item.label : item.label + "()";
|
||||
}
|
||||
return {
|
||||
label: item.label,
|
||||
insertText: insertText,
|
||||
kind: item.function ? CompletionItemKind.Function : CompletionItemKind.Variable
|
||||
};
|
||||
}
|
||||
|
||||
Generated
+8
-6
@@ -43,6 +43,7 @@
|
||||
"version": "0.1.57",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@github/actions-expressions": "*",
|
||||
"@github/actions-workflow-parser": "*",
|
||||
"vscode-languageserver-textdocument": "^1.0.7",
|
||||
"vscode-languageserver-types": "^3.17.2",
|
||||
@@ -683,9 +684,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@github/actions-expressions": {
|
||||
"version": "0.0.7",
|
||||
"resolved": "https://npm.pkg.github.com/download/@github/actions-expressions/0.0.7/deed2be11b9f74791730303b6e33f9aca701d6a7",
|
||||
"integrity": "sha512-PG8dQUafOckk/ny5O1wcUcfml5IZM8REoi7WBBY1HfpnRR7mL7gqTczQEmQWNTpoHb9f1VQK47y2hBZTOg9Y7g==",
|
||||
"version": "0.0.8",
|
||||
"resolved": "https://npm.pkg.github.com/download/@github/actions-expressions/0.0.8/055f455fcb0ed907f52c349b9385728aeed38f9a",
|
||||
"integrity": "sha512-SPuGfnjgKAbMzJNCk4sZPAK2bxHlRXDJCk6vrwIi9VJL16Eh1YyiyM4fU9kV5EXEE5AV9aPFlZAPXu6t0mmBNw==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 16"
|
||||
@@ -13500,9 +13501,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"@github/actions-expressions": {
|
||||
"version": "0.0.7",
|
||||
"resolved": "https://npm.pkg.github.com/download/@github/actions-expressions/0.0.7/deed2be11b9f74791730303b6e33f9aca701d6a7",
|
||||
"integrity": "sha512-PG8dQUafOckk/ny5O1wcUcfml5IZM8REoi7WBBY1HfpnRR7mL7gqTczQEmQWNTpoHb9f1VQK47y2hBZTOg9Y7g=="
|
||||
"version": "0.0.8",
|
||||
"resolved": "https://npm.pkg.github.com/download/@github/actions-expressions/0.0.8/055f455fcb0ed907f52c349b9385728aeed38f9a",
|
||||
"integrity": "sha512-SPuGfnjgKAbMzJNCk4sZPAK2bxHlRXDJCk6vrwIi9VJL16Eh1YyiyM4fU9kV5EXEE5AV9aPFlZAPXu6t0mmBNw=="
|
||||
},
|
||||
"@github/actions-languageserver": {
|
||||
"version": "file:actions-languageserver",
|
||||
@@ -13524,6 +13525,7 @@
|
||||
"@github/actions-languageservice": {
|
||||
"version": "file:actions-languageservice",
|
||||
"requires": {
|
||||
"@github/actions-expressions": "*",
|
||||
"@github/actions-workflow-parser": "*",
|
||||
"@types/jest": "^29.0.3",
|
||||
"jest": "^29.0.3",
|
||||
|
||||
Reference in New Issue
Block a user