From e5a0bae3d0f8f4eea34f2e1411ecf272a2c3baf9 Mon Sep 17 00:00:00 2001 From: Beth Brennan Date: Fri, 2 Dec 2022 17:19:48 -0500 Subject: [PATCH] Add descriptions to completion item detail --- actions-languageservice/src/complete.test.ts | 28 +++++++++++++++++++ actions-languageservice/src/complete.ts | 6 +++- .../src/value-providers/definition.ts | 18 +++++++++--- package-lock.json | 3 ++ package.json | 5 +++- 5 files changed, 54 insertions(+), 6 deletions(-) diff --git a/actions-languageservice/src/complete.test.ts b/actions-languageservice/src/complete.test.ts index ddf3a2c..002f227 100644 --- a/actions-languageservice/src/complete.test.ts +++ b/actions-languageservice/src/complete.test.ts @@ -286,6 +286,11 @@ jobs: "with", "working-directory" ]); + + // Includes detail when available. Using continue-on-error as a sample here. + expect(result.map(x => x.detail)).toContain( + "Prevents a job from failing when a step fails. Set to true to allow a job to pass when this step fails." + ); }); it("loose mapping keys have no completion suggestions", async () => { @@ -301,4 +306,27 @@ on: const result = await complete(...getPositionFromCursor(input)); expect(result).toHaveLength(0); }); + + it("well known mapping keys have descriptions", async () => { + const input = ` +o| +`; + const result = await complete(...getPositionFromCursor(input)); + const onResult = result.find(x => x.label === "on"); + expect(onResult).not.toBeUndefined(); + expect(onResult?.detail).toEqual( + "The name of the GitHub event that triggers the workflow. You can provide a single event string, array of events, array of event types, or an event configuration map that schedules a workflow or restricts the execution of a workflow to specific files, tags, or branch changes. For a list of available events, see https://help.github.com/en/github/automating-your-workflow-with-github-actions/events-that-trigger-workflows." + ); + }); + + it("event list includes descriptions when available ", async () => { + const input = ` + on: [check_run, |]`; + const result = await complete(...getPositionFromCursor(input)); + const dispatchResult = result.find(x => x.label === "workflow_dispatch"); + expect(dispatchResult).not.toBeUndefined(); + expect(dispatchResult?.detail).toEqual( + "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." + ); + }); }); diff --git a/actions-languageservice/src/complete.ts b/actions-languageservice/src/complete.ts index 273ddfb..6d99e76 100644 --- a/actions-languageservice/src/complete.ts +++ b/actions-languageservice/src/complete.ts @@ -91,7 +91,11 @@ export async function complete( } const values = await getValues(token, keyToken, parent, valueProviderConfig, workflowContext); - return values.map(value => CompletionItem.create(value.label)); + return values.map(value => { + const item = CompletionItem.create(value.label); + item.detail = value.description; + return item; + }); } async function getValues( diff --git a/actions-languageservice/src/value-providers/definition.ts b/actions-languageservice/src/value-providers/definition.ts index 65c5149..81aaf6a 100644 --- a/actions-languageservice/src/value-providers/definition.ts +++ b/actions-languageservice/src/value-providers/definition.ts @@ -12,7 +12,7 @@ export function definitionValues(def: Definition): Value[] { const schema = getWorkflowSchema(); if (def instanceof MappingDefinition) { - return mappingValues(def); + return mappingValues(def, schema.definitions); } if (def instanceof OneOfDefinition) { @@ -24,7 +24,12 @@ export function definitionValues(def: Definition): Value[] { } if (def instanceof StringDefinition && def.constant) { - return stringsToValues([def.constant]); + return [ + { + label: def.constant, + description: def.description + } + ]; } if (def instanceof SequenceDefinition) { @@ -37,10 +42,15 @@ export function definitionValues(def: Definition): Value[] { return []; } -function mappingValues(mappingDefinition: MappingDefinition): Value[] { +function mappingValues(mappingDefinition: MappingDefinition, definitions: {[key: string]: Definition}): Value[] { const properties: Value[] = []; for (const [key, value] of Object.entries(mappingDefinition.properties)) { - properties.push({label: key, description: value.description}); + let description: string | undefined; + if (value.type) { + const typeDef = definitions[value.type]; + description = typeDef?.description; + } + properties.push({label: key, description: description}); } return properties; } diff --git a/package-lock.json b/package-lock.json index 22f4db6..4dfb35d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,6 +9,9 @@ "actions-languageservice", "actions-languageserver" ], + "dependencies": { + "@github/actions-workflow-parser": "^0.0.25" + }, "devDependencies": { "lerna": "^6.0.3" } diff --git a/package.json b/package.json index 67d76cd..39f6a35 100644 --- a/package.json +++ b/package.json @@ -7,5 +7,8 @@ "devDependencies": { "lerna": "^6.0.3" }, - "name": "actions-languageservices" + "name": "actions-languageservices", + "dependencies": { + "@github/actions-workflow-parser": "^0.0.25" + } }