From bdcb592f90cd2ad2c0b78cbcaa61b9b840b1f438 Mon Sep 17 00:00:00 2001 From: Beth Brennan Date: Tue, 6 Dec 2022 16:15:35 -0500 Subject: [PATCH 1/3] Add range to CompletionItems --- actions-languageservice/src/complete.test.ts | 22 +++++++++++++ actions-languageservice/src/complete.ts | 34 +++++++++++++++++++- 2 files changed, 55 insertions(+), 1 deletion(-) diff --git a/actions-languageservice/src/complete.test.ts b/actions-languageservice/src/complete.test.ts index 002f227..3ec5c2b 100644 --- a/actions-languageservice/src/complete.test.ts +++ b/actions-languageservice/src/complete.test.ts @@ -1,3 +1,4 @@ +import {TextEdit} from "vscode-languageserver-types"; import {complete} from "./complete"; import {WorkflowContext} from "./context/workflow-context"; import {getPositionFromCursor} from "./test-utils/cursor-position"; @@ -329,4 +330,25 @@ o| "You can now create workflows that are manually triggered with the new workflow_dispatch event. You will then see a 'Run workflow' button on the Actions tab, enabling you to easily trigger a run." ); }); + + it("sets range when completing token", async () => { + const input = `on: push +jobs: + pre-build: + runs-on: ubuntu-latest + build: + runs-on: ubuntu-latest + needs: pre-bu|`; + + const result = await complete(...getPositionFromCursor(input)); + expect(result).not.toBeUndefined(); + expect(result.length).toEqual(1); + + let textEdit = result[0].textEdit as TextEdit; + expect(textEdit.newText).toEqual("pre-build"); + expect(textEdit.range).toEqual({ + start: {line: 6, character: 11}, + end: {line: 6, character: 17} + }); + }); }); diff --git a/actions-languageservice/src/complete.ts b/actions-languageservice/src/complete.ts index 6d99e76..f47b0d0 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} from "vscode-languageserver-types"; +import {CompletionItem, TextEdit, Range} from "vscode-languageserver-types"; import {ContextProviderConfig} from "./context-providers/config"; import {getContext} from "./context-providers/default"; import {getWorkflowContext, WorkflowContext} from "./context/workflow-context"; @@ -91,9 +91,27 @@ export async function complete( } const values = await getValues(token, keyToken, parent, valueProviderConfig, workflowContext); + let replaceRange: Range | undefined; + if (token?.range) { + replaceRange = { + start: { + line: token.range.start[0] - 1, + character: token.range.start[1] - 1 + }, + end: { + line: token.range.end[0] - 1, + character: token.range.end[1] - 1 + } + }; + } + return values.map(value => { const item = CompletionItem.create(value.label); item.detail = value.description; + if (replaceRange) { + item.textEdit = TextEdit.replace(replaceRange, value.label); + } + return item; }); } @@ -183,3 +201,17 @@ function filterAndSortCompletionOptions(options: Value[], existingValues?: Set a.label.localeCompare(b.label)); return options; } + +// function getTokenRange(document: TextDocument, position: Position) { +// const lineRange: Range = { +// start: {line: position.line, character: 0}, +// end: {line: position.line, character: Number.MAX_SAFE_INTEGER} +// }; +// let line = document.getText(lineRange); +// const wordArray = line.split(/[\s,]+/); +// const word = wordArray[wordArray.length - 1]; + +// const start = new Position(position.line, Math.max(0, position.character - word.length)); +// const end = new Position(position.line, position.character); +// return {start, end}; +// } From 3eb3855cb1137d57785495662ac1bcd119acda64 Mon Sep 17 00:00:00 2001 From: Beth Brennan Date: Wed, 7 Dec 2022 10:44:20 -0500 Subject: [PATCH 2/3] Remove comment --- actions-languageservice/src/complete.ts | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/actions-languageservice/src/complete.ts b/actions-languageservice/src/complete.ts index f47b0d0..d8512aa 100644 --- a/actions-languageservice/src/complete.ts +++ b/actions-languageservice/src/complete.ts @@ -201,17 +201,3 @@ function filterAndSortCompletionOptions(options: Value[], existingValues?: Set a.label.localeCompare(b.label)); return options; } - -// function getTokenRange(document: TextDocument, position: Position) { -// const lineRange: Range = { -// start: {line: position.line, character: 0}, -// end: {line: position.line, character: Number.MAX_SAFE_INTEGER} -// }; -// let line = document.getText(lineRange); -// const wordArray = line.split(/[\s,]+/); -// const word = wordArray[wordArray.length - 1]; - -// const start = new Position(position.line, Math.max(0, position.character - word.length)); -// const end = new Position(position.line, position.character); -// return {start, end}; -// } From 424bc471ce61200f5d49df5755367bb733a317b5 Mon Sep 17 00:00:00 2001 From: Beth Brennan Date: Wed, 7 Dec 2022 10:51:44 -0500 Subject: [PATCH 3/3] Use mapRange --- actions-languageservice/src/complete.ts | 12 ++------- actions-languageservice/src/hover.ts | 12 ++------- actions-languageservice/src/utils/range.ts | 28 ++++++++++++++++++++ actions-languageservice/src/validate.ts | 30 ++-------------------- 4 files changed, 34 insertions(+), 48 deletions(-) create mode 100644 actions-languageservice/src/utils/range.ts diff --git a/actions-languageservice/src/complete.ts b/actions-languageservice/src/complete.ts index d8512aa..ca9d58c 100644 --- a/actions-languageservice/src/complete.ts +++ b/actions-languageservice/src/complete.ts @@ -16,6 +16,7 @@ import {getWorkflowContext, WorkflowContext} from "./context/workflow-context"; import {nullTrace} from "./nulltrace"; import {getAllowedContext} from "./utils/allowed-context"; import {findToken} from "./utils/find-token"; +import {mapRange} from "./utils/range"; import {transform} from "./utils/transform"; import {Value, ValueProviderConfig} from "./value-providers/config"; import {defaultValueProviders} from "./value-providers/default"; @@ -93,16 +94,7 @@ export async function complete( const values = await getValues(token, keyToken, parent, valueProviderConfig, workflowContext); let replaceRange: Range | undefined; if (token?.range) { - replaceRange = { - start: { - line: token.range.start[0] - 1, - character: token.range.start[1] - 1 - }, - end: { - line: token.range.end[0] - 1, - character: token.range.end[1] - 1 - } - }; + replaceRange = mapRange(token.range); } return values.map(value => { diff --git a/actions-languageservice/src/hover.ts b/actions-languageservice/src/hover.ts index 5154db8..297f1b6 100644 --- a/actions-languageservice/src/hover.ts +++ b/actions-languageservice/src/hover.ts @@ -5,6 +5,7 @@ import {Position, TextDocument} from "vscode-languageserver-textdocument"; import {Hover} from "vscode-languageserver-types"; import {nullTrace} from "./nulltrace"; import {findToken} from "./utils/find-token"; +import {mapRange} from "./utils/range"; // Render value description and Context when hovering over a key in a MappingToken export async function hover(document: TextDocument, position: Position): Promise { @@ -38,16 +39,7 @@ function getHover(token: TemplateToken): Hover | null { return { contents: description, - range: { - start: { - line: token.range!.start[0] - 1, - character: token.range!.start[1] - 1 - }, - end: { - line: token.range!.end[0] - 1, - character: token.range!.end[1] - 1 - } - } + range: mapRange(token.range) } as Hover; } return null; diff --git a/actions-languageservice/src/utils/range.ts b/actions-languageservice/src/utils/range.ts new file mode 100644 index 0000000..d16085a --- /dev/null +++ b/actions-languageservice/src/utils/range.ts @@ -0,0 +1,28 @@ +import {TokenRange} from "@github/actions-workflow-parser/templates/tokens/token-range"; +import {Range} from "vscode-languageserver-types"; + +export function mapRange(range: TokenRange | undefined): Range { + if (!range) { + return { + start: { + line: 1, + character: 1 + }, + end: { + line: 1, + character: 1 + } + }; + } + + return { + start: { + line: range.start[0] - 1, + character: range.start[1] - 1 + }, + end: { + line: range.end[0] - 1, + character: range.end[1] - 1 + } + }; +} diff --git a/actions-languageservice/src/validate.ts b/actions-languageservice/src/validate.ts index 4624dd8..d0ca448 100644 --- a/actions-languageservice/src/validate.ts +++ b/actions-languageservice/src/validate.ts @@ -14,10 +14,9 @@ import {Definition} from "@github/actions-workflow-parser/templates/schema/defin import {BasicExpressionToken} from "@github/actions-workflow-parser/templates/tokens/basic-expression-token"; import {StringToken} from "@github/actions-workflow-parser/templates/tokens/string-token"; import {TemplateToken} from "@github/actions-workflow-parser/templates/tokens/template-token"; -import {TokenRange} from "@github/actions-workflow-parser/templates/tokens/token-range"; import {File} from "@github/actions-workflow-parser/workflows/file"; import {TextDocument} from "vscode-languageserver-textdocument"; -import {Diagnostic, DiagnosticSeverity, Range, URI} from "vscode-languageserver-types"; +import {Diagnostic, DiagnosticSeverity, URI} from "vscode-languageserver-types"; import {ContextProviderConfig} from "./context-providers/config"; import {getContext} from "./context-providers/default"; @@ -25,6 +24,7 @@ import {getWorkflowContext, WorkflowContext} from "./context/workflow-context"; import {AccessError, wrapDictionary} from "./expression-validation/error-dictionary"; import {nullTrace} from "./nulltrace"; import {findToken} from "./utils/find-token"; +import {mapRange} from "./utils/range"; import {ValueProviderConfig, ValueProviderKind} from "./value-providers/config"; import {defaultValueProviders} from "./value-providers/default"; @@ -80,32 +80,6 @@ export async function validate( return diagnostics; } -function mapRange(range: TokenRange | undefined): Range { - if (!range) { - return { - start: { - line: 1, - character: 1 - }, - end: { - line: 1, - character: 1 - } - }; - } - - return { - start: { - line: range.start[0] - 1, - character: range.start[1] - 1 - }, - end: { - line: range.end[0] - 1, - character: range.end[1] - 1 - } - }; -} - async function additionalValidations( diagnostics: Diagnostic[], documentUri: URI,