Merge pull request #13 from github/joshmgross/separate-value-providers
Separate value providers from definition values
This commit is contained in:
@@ -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());
|
||||
}
|
||||
Reference in New Issue
Block a user