Correctly indent completion options
This commit is contained in:
@@ -4,8 +4,8 @@ import {complete} from "./complete";
|
|||||||
import {registerLogger} from "./log";
|
import {registerLogger} from "./log";
|
||||||
import {getPositionFromCursor} from "./test-utils/cursor-position";
|
import {getPositionFromCursor} from "./test-utils/cursor-position";
|
||||||
import {TestLogger} from "./test-utils/logger";
|
import {TestLogger} from "./test-utils/logger";
|
||||||
import {ValueProviderConfig, ValueProviderKind} from "./value-providers/config";
|
|
||||||
import {clearCache} from "./utils/workflow-cache";
|
import {clearCache} from "./utils/workflow-cache";
|
||||||
|
import {ValueProviderConfig, ValueProviderKind} from "./value-providers/config";
|
||||||
|
|
||||||
registerLogger(new TestLogger());
|
registerLogger(new TestLogger());
|
||||||
|
|
||||||
@@ -475,7 +475,7 @@ jobs:
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it("adds a new line and indentation for mapping keys", async () => {
|
it("adds a new line and indentation for mapping keys when the key is given", async () => {
|
||||||
const input = "concurrency: |";
|
const input = "concurrency: |";
|
||||||
|
|
||||||
const result = await complete(...getPositionFromCursor(input));
|
const result = await complete(...getPositionFromCursor(input));
|
||||||
@@ -485,4 +485,12 @@ jobs:
|
|||||||
]);
|
]);
|
||||||
expect(result.filter(x => x.label === "group").map(x => x.textEdit?.newText)).toEqual(["\n group: "]);
|
expect(result.filter(x => x.label === "group").map(x => x.textEdit?.newText)).toEqual(["\n group: "]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("does not add new line if no key in line", async () => {
|
||||||
|
const input = "run-n|";
|
||||||
|
|
||||||
|
const result = await complete(...getPositionFromCursor(input));
|
||||||
|
|
||||||
|
expect(result.filter(x => x.label === "run-name").map(x => x.textEdit?.newText)).toEqual(["run-name: "]);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ import {isPlaceholder, transform} from "./utils/transform";
|
|||||||
import {fetchOrConvertWorkflowTemplate, fetchOrParseWorkflow} from "./utils/workflow-cache";
|
import {fetchOrConvertWorkflowTemplate, fetchOrParseWorkflow} from "./utils/workflow-cache";
|
||||||
import {Value, ValueProviderConfig} from "./value-providers/config";
|
import {Value, ValueProviderConfig} from "./value-providers/config";
|
||||||
import {defaultValueProviders} from "./value-providers/default";
|
import {defaultValueProviders} from "./value-providers/default";
|
||||||
import {definitionValues} from "./value-providers/definition";
|
import {DefinitionValueMode, definitionValues} from "./value-providers/definition";
|
||||||
|
|
||||||
export function getExpressionInput(input: string, pos: number): string {
|
export function getExpressionInput(input: string, pos: number): string {
|
||||||
// Find start marker around the cursor position
|
// Find start marker around the cursor position
|
||||||
@@ -180,7 +180,7 @@ async function getValues(
|
|||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
const values = definitionValues(def, indentation);
|
const values = definitionValues(def, indentation, keyToken ? DefinitionValueMode.Key : DefinitionValueMode.Parent);
|
||||||
return filterAndSortCompletionOptions(values, existingValues);
|
return filterAndSortCompletionOptions(values, existingValues);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,15 +9,30 @@ import {getWorkflowSchema} from "@actions/workflow-parser/workflows/workflow-sch
|
|||||||
import {Value} from "./config";
|
import {Value} from "./config";
|
||||||
import {stringsToValues} from "./strings-to-values";
|
import {stringsToValues} from "./strings-to-values";
|
||||||
|
|
||||||
export function definitionValues(def: Definition, indentation: string): Value[] {
|
export enum DefinitionValueMode {
|
||||||
|
/**
|
||||||
|
* We're getting completion options for a parent token
|
||||||
|
* foo:
|
||||||
|
* ba|
|
||||||
|
*/
|
||||||
|
Parent,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* We're getting completion options for a key token. For example:
|
||||||
|
* foo: |
|
||||||
|
*/
|
||||||
|
Key
|
||||||
|
}
|
||||||
|
|
||||||
|
export function definitionValues(def: Definition, indentation: string, mode: DefinitionValueMode): Value[] {
|
||||||
const schema = getWorkflowSchema();
|
const schema = getWorkflowSchema();
|
||||||
|
|
||||||
if (def instanceof MappingDefinition) {
|
if (def instanceof MappingDefinition) {
|
||||||
return mappingValues(def, schema.definitions, indentation);
|
return mappingValues(def, schema.definitions, indentation, mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (def instanceof OneOfDefinition) {
|
if (def instanceof OneOfDefinition) {
|
||||||
return oneOfValues(def, schema.definitions, indentation);
|
return oneOfValues(def, schema.definitions, indentation, mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (def instanceof BooleanDefinition) {
|
if (def instanceof BooleanDefinition) {
|
||||||
@@ -36,7 +51,7 @@ export function definitionValues(def: Definition, indentation: string): Value[]
|
|||||||
if (def instanceof SequenceDefinition) {
|
if (def instanceof SequenceDefinition) {
|
||||||
const itemDef = schema.getDefinition(def.itemType);
|
const itemDef = schema.getDefinition(def.itemType);
|
||||||
if (itemDef) {
|
if (itemDef) {
|
||||||
return definitionValues(itemDef, indentation);
|
return definitionValues(itemDef, indentation, mode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -46,7 +61,8 @@ export function definitionValues(def: Definition, indentation: string): Value[]
|
|||||||
function mappingValues(
|
function mappingValues(
|
||||||
mappingDefinition: MappingDefinition,
|
mappingDefinition: MappingDefinition,
|
||||||
definitions: {[key: string]: Definition},
|
definitions: {[key: string]: Definition},
|
||||||
indentation: string
|
indentation: string,
|
||||||
|
mode: DefinitionValueMode
|
||||||
): Value[] {
|
): Value[] {
|
||||||
const properties: Value[] = [];
|
const properties: Value[] = [];
|
||||||
for (const [key, value] of Object.entries(mappingDefinition.properties)) {
|
for (const [key, value] of Object.entries(mappingDefinition.properties)) {
|
||||||
@@ -73,8 +89,13 @@ function mappingValues(
|
|||||||
|
|
||||||
case DefinitionType.String:
|
case DefinitionType.String:
|
||||||
case DefinitionType.Boolean:
|
case DefinitionType.Boolean:
|
||||||
insertText = `\n${indentation}${key}: `;
|
if (mode == DefinitionValueMode.Key) {
|
||||||
|
insertText = `\n${indentation}${key}: `;
|
||||||
|
} else {
|
||||||
|
insertText = `${key}: `;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
insertText = `${key}: `;
|
insertText = `${key}: `;
|
||||||
}
|
}
|
||||||
@@ -93,11 +114,12 @@ function mappingValues(
|
|||||||
function oneOfValues(
|
function oneOfValues(
|
||||||
oneOfDefinition: OneOfDefinition,
|
oneOfDefinition: OneOfDefinition,
|
||||||
definitions: {[key: string]: Definition},
|
definitions: {[key: string]: Definition},
|
||||||
indentation: string
|
indentation: string,
|
||||||
|
mode: DefinitionValueMode
|
||||||
): Value[] {
|
): Value[] {
|
||||||
const values: Value[] = [];
|
const values: Value[] = [];
|
||||||
for (const key of oneOfDefinition.oneOf) {
|
for (const key of oneOfDefinition.oneOf) {
|
||||||
values.push(...definitionValues(definitions[key], indentation));
|
values.push(...definitionValues(definitions[key], indentation, mode));
|
||||||
}
|
}
|
||||||
return distinctValues(values);
|
return distinctValues(values);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user