From b21c0e461db5a3869a30821b843e3c646078d215 Mon Sep 17 00:00:00 2001 From: Laura Yu <60276246+lauraway@users.noreply.github.com> Date: Tue, 28 Feb 2023 10:18:46 -0800 Subject: [PATCH] Fix Completion bug with null string (#168) --- languageservice/src/complete.test.ts | 13 ++++++++ .../src/utils/expression-detection.ts | 2 +- .../src/templates/template-reader.ts | 31 ++++++++++--------- 3 files changed, 31 insertions(+), 15 deletions(-) diff --git a/languageservice/src/complete.test.ts b/languageservice/src/complete.test.ts index b6c7436..84abd19 100644 --- a/languageservice/src/complete.test.ts +++ b/languageservice/src/complete.test.ts @@ -320,6 +320,19 @@ on: expect(result).toHaveLength(0); }); + it("null strings still give suggestions", async () => { + const input = ` +on: push +jobs: + one: + runs-on: ubuntu-latest + |: + - uses: actions/checkout@v2 +`; + const result = await complete(...getPositionFromCursor(input)); + expect(result).toHaveLength(16); + }); + it("well known mapping keys have descriptions", async () => { const input = ` o| diff --git a/languageservice/src/utils/expression-detection.ts b/languageservice/src/utils/expression-detection.ts index 2242d8a..4406c78 100644 --- a/languageservice/src/utils/expression-detection.ts +++ b/languageservice/src/utils/expression-detection.ts @@ -7,6 +7,6 @@ import {TemplateToken} from "@github/actions-workflow-parser/templates/tokens/in export function isPotentiallyExpression(token: TemplateToken): boolean { const isAlwaysExpression = token.definition?.definitionType === DefinitionType.String && (token.definition as StringDefinition).isExpression; - const containsExpression = isString(token) && token.value.indexOf(OPEN_EXPRESSION) >= 0; + const containsExpression = isString(token) && token.value != null && token.value.indexOf(OPEN_EXPRESSION) >= 0; return isAlwaysExpression || containsExpression; } diff --git a/workflow-parser/src/templates/template-reader.ts b/workflow-parser/src/templates/template-reader.ts index 7d5bce0..02df3d7 100644 --- a/workflow-parser/src/templates/template-reader.ts +++ b/workflow-parser/src/templates/template-reader.ts @@ -203,14 +203,15 @@ class TemplateReader { ); // Duplicate - const upperKey = nextKey.value.toUpperCase(); - if (upperKeys[upperKey]) { - this._context.error(nextKey, `'${nextKey.value}' is already defined`); - this.skipValue(); - continue; + if (nextKey.value) { + const upperKey = nextKey.value.toUpperCase(); + if (upperKeys[upperKey]) { + this._context.error(nextKey, `'${nextKey.value}' is already defined`); + this.skipValue(); + continue; + } + upperKeys[upperKey] = true; } - upperKeys[upperKey] = true; - // Well known const nextPropertyDef = this._schema.matchPropertyAndFilter(mappingDefinitions, nextKey.value); if (nextPropertyDef) { @@ -339,13 +340,15 @@ class TemplateReader { ); // Duplicate - const upperKey = nextKey.value.toUpperCase(); - if (upperKeys[upperKey]) { - this._context.error(nextKey, `'${nextKey.value}' is already defined`); - this.skipValue(); - continue; + if (nextKey.value) { + const upperKey = nextKey.value.toUpperCase(); + if (upperKeys[upperKey]) { + this._context.error(nextKey, `'${nextKey.value}' is already defined`); + this.skipValue(); + continue; + } + upperKeys[upperKey] = true; } - upperKeys[upperKey] = true; // Validate this.validate(nextKey, keyDefinition); @@ -443,7 +446,7 @@ class TemplateReader { private parseScalar(token: LiteralToken, definitionInfo: DefinitionInfo): ScalarToken { // Not a string - if (!isString(token)) { + if (!isString(token) || !token.value) { return token; }