Merge pull request #13 from github/joshmgross/separate-value-providers

Separate value providers from definition values
This commit is contained in:
Josh Gross
2022-11-22 17:26:55 -05:00
committed by GitHub
3 changed files with 68 additions and 75 deletions
+13 -5
View File
@@ -15,6 +15,7 @@ import {findToken} from "./utils/find-token";
import {transform} from "./utils/transform";
import {Value, ValueProviderConfig} from "./value-providers/config";
import {defaultValueProviders} from "./value-providers/default";
import {definitionValues} from "./value-providers/definition";
export function getExpressionInput(input: string, pos: number): string {
// Find start marker around the cursor position
@@ -98,16 +99,23 @@ async function getValues(
const valueProviders = defaultValueProviders();
// Use the key from the parent if we don't have a value provider for the current key
// Ideally each token would have a valid key
// Use the value provider from the parent if we don't have a value provider for the current key
const valueProvider =
(token?.definition?.key && valueProviders[token.definition.key]) ||
(parent?.definition?.key && valueProviders[parent.definition.key]);
if (!valueProvider) {
(parent.definition?.key && valueProviders[parent.definition.key]);
if (valueProvider) {
const values = valueProvider();
return filterAndSortCompletionOptions(values, existingValues);
}
// Use the definition if there are no value providers
const def = token?.definition || parent.definition;
if (!def) {
return [];
}
const values = valueProvider();
const values = definitionValues(def);
return filterAndSortCompletionOptions(values, existingValues);
}
@@ -1,24 +1,7 @@
import {BooleanDefinition} from "@github/actions-workflow-parser/templates/schema/boolean-definition";
import {Definition} from "@github/actions-workflow-parser/templates/schema/definition";
import {MappingDefinition} from "@github/actions-workflow-parser/templates/schema/mapping-definition";
import {OneOfDefinition} from "@github/actions-workflow-parser/templates/schema/one-of-definition";
import {StringDefinition} from "@github/actions-workflow-parser/templates/schema/string-definition";
import {getWorkflowSchema} from "@github/actions-workflow-parser/workflows/workflow-schema";
import {Value, ValueProvider} from "./config";
export function defaultValueProviders(): {[key: string]: ValueProvider} {
const schema = getWorkflowSchema();
const map: {[key: string]: ValueProvider} = {};
for (const key of Object.keys(schema.definitions)) {
const provider = definitionValueProvider(key, schema.definitions);
if (provider) {
map[key] = provider;
}
}
return {
...map,
"runs-on": () =>
stringsToValues([
"ubuntu-latest",
@@ -36,58 +19,6 @@ export function defaultValueProviders(): {[key: string]: ValueProvider} {
};
}
function definitionValueProvider(key: string, definitions: {[key: string]: Definition}): ValueProvider | undefined {
const def = definitions[key];
if (def instanceof MappingDefinition) {
return mappingValueProvider(def);
}
if (def instanceof OneOfDefinition) {
return oneOfValueProvider(def, definitions);
}
if (def instanceof BooleanDefinition) {
return () => stringsToValues(["true", "false"]);
}
if (def instanceof StringDefinition && def.constant) {
return () => stringsToValues([def.constant]);
}
}
function mappingValueProvider(mappingDefinition: MappingDefinition): ValueProvider {
const properties: Value[] = [];
for (const [key, value] of Object.entries(mappingDefinition.properties)) {
properties.push({label: key, description: value.description});
}
return () => properties;
}
function oneOfValueProvider(oneOfDefinition: OneOfDefinition, definitions: {[key: string]: Definition}): ValueProvider {
return () => {
const values: Value[] = [];
for (const key of oneOfDefinition.oneOf) {
const provider = definitionValueProvider(key, definitions);
if (!provider) {
continue;
}
for (const prop of provider()) {
values.push(prop);
}
}
return distinctValues(values);
};
}
function stringsToValues(labels: string[]): Value[] {
export function stringsToValues(labels: string[]): Value[] {
return labels.map(x => ({label: x}));
}
function distinctValues(values: Value[]): Value[] {
const map = new Map<string, Value>();
for (const value of values) {
map.set(value.label, value);
}
return Array.from(map.values());
}
@@ -0,0 +1,54 @@
import {BooleanDefinition} from "@github/actions-workflow-parser/templates/schema/boolean-definition";
import {Definition} from "@github/actions-workflow-parser/templates/schema/definition";
import {MappingDefinition} from "@github/actions-workflow-parser/templates/schema/mapping-definition";
import {OneOfDefinition} from "@github/actions-workflow-parser/templates/schema/one-of-definition";
import {StringDefinition} from "@github/actions-workflow-parser/templates/schema/string-definition";
import {getWorkflowSchema} from "@github/actions-workflow-parser/workflows/workflow-schema";
import {Value} from "./config";
import {stringsToValues} from "./default";
export function definitionValues(def: Definition): Value[] {
const schema = getWorkflowSchema();
if (def instanceof MappingDefinition) {
return mappingValues(def);
}
if (def instanceof OneOfDefinition) {
return oneOfValues(def, schema.definitions);
}
if (def instanceof BooleanDefinition) {
return stringsToValues(["true", "false"]);
}
if (def instanceof StringDefinition && def.constant) {
return stringsToValues([def.constant]);
}
return [];
}
function mappingValues(mappingDefinition: MappingDefinition): Value[] {
const properties: Value[] = [];
for (const [key, value] of Object.entries(mappingDefinition.properties)) {
properties.push({label: key, description: value.description});
}
return properties;
}
function oneOfValues(oneOfDefinition: OneOfDefinition, definitions: {[key: string]: Definition}): Value[] {
const values: Value[] = [];
for (const key of oneOfDefinition.oneOf) {
values.push(...definitionValues(definitions[key]));
}
return distinctValues(values);
}
function distinctValues(values: Value[]): Value[] {
const map = new Map<string, Value>();
for (const value of values) {
map.set(value.label, value);
}
return Array.from(map.values());
}