diff --git a/actions-languageservice/package.json b/actions-languageservice/package.json index e441757..d7ec8ad 100644 --- a/actions-languageservice/package.json +++ b/actions-languageservice/package.json @@ -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" } -} +} \ No newline at end of file diff --git a/actions-languageservice/src/complete.expressions.test.ts b/actions-languageservice/src/complete.expressions.test.ts index 6af1866..be97f15 100644 --- a/actions-languageservice/src/complete.expressions.test.ts +++ b/actions-languageservice/src/complete.expressions.test.ts @@ -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"; @@ -632,4 +633,37 @@ 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(); + }); }); diff --git a/actions-languageservice/src/complete.ts b/actions-languageservice/src/complete.ts index cc714ab..b675281 100644 --- a/actions-languageservice/src/complete.ts +++ b/actions-languageservice/src/complete.ts @@ -9,7 +9,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"; @@ -95,7 +95,13 @@ export async function complete( const allowedContext = getAllowedContext(token, parent); const context = await getContext(allowedContext, contextProviderConfig, workflowContext, Mode.Completion); - return completeExpression(expressionInput, context, []); + return completeExpression(expressionInput, context, []).map(item => { + return { + label: item.label, + insertText: item.function ? item.label + "()" : undefined, + kind: item.function ? CompletionItemKind.Function : CompletionItemKind.Variable + }; + }); } }