diff --git a/actions-languageservice/src/complete.test.ts b/actions-languageservice/src/complete.test.ts index 2ba5a6f..2bb413a 100644 --- a/actions-languageservice/src/complete.test.ts +++ b/actions-languageservice/src/complete.test.ts @@ -374,6 +374,37 @@ jobs: }); }); + + it("sets a range for invalid tokens", async () => { + const input = "on: push\njobs:\n build:\n runs-o|"; + const result = await complete(...getPositionFromCursor(input)); + + expect(result).not.toBeUndefined(); + expect(result.map(e => e.label)).toContain("runs-on"); + + let textEdit = result.filter(e => e.label === "runs-on")[0].textEdit as TextEdit; + expect(textEdit.newText).toEqual("runs-on"); + expect(textEdit.range).toEqual({ + start: {line: 3, character: 4}, + end: {line: 3, character: 10} + }); + }); + + it("sets a 0-length range while no initial token", async () => { + const input = "on: push\njobs:\n build:\n |"; + const result = await complete(...getPositionFromCursor(input)); + + expect(result).not.toBeUndefined(); + expect(result.map(e => e.label)).toContain("runs-on"); + + let textEdit = result.filter(e => e.label === "runs-on")[0].textEdit as TextEdit; + expect(textEdit.newText).toEqual("runs-on"); + expect(textEdit.range).toEqual({ + start: {line: 3, character: 4}, + end: {line: 3, character: 4} + }); + }); + describe("completes with indentation", () => { it("default indentation", async () => { const input = `on: push diff --git a/actions-languageservice/src/complete.ts b/actions-languageservice/src/complete.ts index 44c3c3f..a38a53e 100644 --- a/actions-languageservice/src/complete.ts +++ b/actions-languageservice/src/complete.ts @@ -103,6 +103,13 @@ export async function complete( if (token?.range) { replaceRange = mapRange(token.range); } + else if (!token) { + // Not a valid token, create a range from the current position + const line = newDoc.getText({start: {line: position.line, character: 0}, end: position}); + // Get the length of the current word + const val = line.match(/[\w_-]*$/)?.[0].length || 0; + replaceRange = Range.create({ line: position.line, character: position.character - val } as Position, position); + } return values.map(value => { const newText = value.insertText || value.label;