diff --git a/actions-languageservice/src/utils/transform.test.ts b/actions-languageservice/src/utils/transform.test.ts new file mode 100644 index 0000000..e9b2339 --- /dev/null +++ b/actions-languageservice/src/utils/transform.test.ts @@ -0,0 +1,47 @@ +import {getPositionFromCursor} from "../test-utils/cursor-position"; +import {transform} from "./transform"; + +describe("transform", () => { + it("adds : at end of line", () => { + const [doc, pos] = getPositionFromCursor("on: push\njobs:\n build:\n runs-on|"); + const [newDoc, newPos] = transform(doc, pos); + + expect(newDoc.getText()).toEqual(`on: push +jobs: + build: + runs-on:`); + expect(newPos.character).toEqual(11); + }); + + it("adds placeholder node in empty sequence", () => { + const [doc, pos] = getPositionFromCursor(`on: push +jobs: + build: + runs-on: + - |`); + const [newDoc, newPos] = transform(doc, pos); + + expect(newDoc.getText()).toEqual(`on: push +jobs: + build: + runs-on: + - dummy`); + expect(newPos.character).toEqual(9); + }); + + it("adds placeholder node in empty line", () => { + const [doc, pos] = getPositionFromCursor(`on: push +jobs: + build: + runs-on: + |`); + const [newDoc, newPos] = transform(doc, pos); + + expect(newDoc.getText()).toEqual(`on: push +jobs: + build: + runs-on: + dummy:`); + expect(newPos.character).toEqual(7); + }); +}); diff --git a/actions-languageservice/src/utils/transform.ts b/actions-languageservice/src/utils/transform.ts index 35fb54d..4b45798 100644 --- a/actions-languageservice/src/utils/transform.ts +++ b/actions-languageservice/src/utils/transform.ts @@ -5,16 +5,12 @@ const DUMMY_KEY = "dummy"; // Transform a document to work around YAML parsing issues // Based on `_transform` in https://github.com/cschleiden/github-actions-parser/blob/main/src/lib/parser/complete.ts#L311 export function transform(doc: TextDocument, pos: Position): [TextDocument, Position] { - const input = doc.getText(); let offset = doc.offsetAt(pos); - // TODO: Optimize this... - const lines = input.split("\n"); - const lineNo = input - .substring(0, offset) - .split("") - .filter(x => x === "\n").length; - const linePos = offset - lines.slice(0, lineNo).reduce((p, l) => p + l.length + 1, 0); - const line = lines[lineNo]; + let line = doc.getText({ + start: {line: pos.line, character: 0}, + end: {line: pos.line, character: Number.MAX_SAFE_INTEGER} + }); + const linePos = pos.character; let partialInput = line.trim(); // Special case for Actions, if this line contains an expression marker, do _not_ transform. This is @@ -32,24 +28,32 @@ export function transform(doc: TextDocument, pos: Position): [TextDocument, Posi offset++; } - lines[lineNo] = + line = line.substring(0, linePos) + spacer + DUMMY_KEY + (trimmedLine === "-" ? "" : ":") + line.substring(linePos); // Adjust pos by one to prevent a sequence node being marked as active offset++; } else if (!trimmedLine.startsWith("-")) { // Add `:` to end of line - lines[lineNo] = line + ":"; - } - - if (trimmedLine.startsWith("-")) { - partialInput = trimmedLine.substring(trimmedLine.indexOf("-") + 1).trim(); + line = line + ":"; } } else { - partialInput = (offset > colon ? line.substring(colon + 1) : line.substring(0, colon)).trim(); offset = offset - 1; } } - const newDoc = TextDocument.create(doc.uri, doc.languageId, doc.version, lines.join("\n")); + + const newDoc = TextDocument.create(doc.uri, doc.languageId, doc.version, doc.getText()); + + TextDocument.update( + newDoc, + [ + { + range: {start: {line: pos.line, character: 0}, end: {line: pos.line, character: Number.MAX_SAFE_INTEGER}}, + text: line + } + ], + newDoc.version + 1 + ); + return [newDoc, newDoc.positionAt(offset)]; }