This commit is contained in:
Francesco Renzi
2025-11-28 14:57:59 +00:00
parent e5800c8843
commit 73dd3c33c4
11 changed files with 123 additions and 129 deletions
+24 -24
View File
@@ -1,7 +1,7 @@
import { documentLinks, getCodeActions, hover, validate, ValidationConfig } from "@actions/languageservice"; import {documentLinks, getCodeActions, hover, validate, ValidationConfig} from "@actions/languageservice";
import { registerLogger, setLogLevel } from "@actions/languageservice/log"; import {registerLogger, setLogLevel} from "@actions/languageservice/log";
import { clearCache, clearCacheEntry } from "@actions/languageservice/utils/workflow-cache"; import {clearCache, clearCacheEntry} from "@actions/languageservice/utils/workflow-cache";
import { Octokit } from "@octokit/rest"; import {Octokit} from "@octokit/rest";
import { import {
CodeAction, CodeAction,
CodeActionKind, CodeActionKind,
@@ -20,19 +20,19 @@ import {
TextDocuments, TextDocuments,
TextDocumentSyncKind TextDocumentSyncKind
} from "vscode-languageserver"; } from "vscode-languageserver";
import { TextDocument } from "vscode-languageserver-textdocument"; import {TextDocument} from "vscode-languageserver-textdocument";
import { getClient } from "./client"; import {getClient} from "./client";
import { Commands } from "./commands"; import {Commands} from "./commands";
import { contextProviders } from "./context-providers"; import {contextProviders} from "./context-providers";
import { descriptionProvider } from "./description-provider"; import {descriptionProvider} from "./description-provider";
import { getFileProvider } from "./file-provider"; import {getFileProvider} from "./file-provider";
import { InitializationOptions, RepositoryContext } from "./initializationOptions"; import {InitializationOptions, RepositoryContext} from "./initializationOptions";
import { onCompletion } from "./on-completion"; import {onCompletion} from "./on-completion";
import { ReadFileRequest, Requests } from "./request"; import {ReadFileRequest, Requests} from "./request";
import { getActionsMetadataProvider } from "./utils/action-metadata"; import {getActionsMetadataProvider} from "./utils/action-metadata";
import { TTLCache } from "./utils/cache"; import {TTLCache} from "./utils/cache";
import { timeOperation } from "./utils/timer"; import {timeOperation} from "./utils/timer";
import { valueProviders } from "./value-providers"; import {valueProviders} from "./value-providers";
export function initConnection(connection: Connection) { export function initConnection(connection: Connection) {
const documents: TextDocuments<TextDocument> = new TextDocuments(TextDocument); const documents: TextDocuments<TextDocument> = new TextDocuments(TextDocument);
@@ -116,15 +116,15 @@ export function initConnection(connection: Connection) {
contextProviderConfig: contextProviders(client, repoContext, cache), contextProviderConfig: contextProviders(client, repoContext, cache),
actionsMetadataProvider: getActionsMetadataProvider(client, cache), actionsMetadataProvider: getActionsMetadataProvider(client, cache),
fileProvider: getFileProvider(client, cache, repoContext?.workspaceUri, async path => { fileProvider: getFileProvider(client, cache, repoContext?.workspaceUri, async path => {
return await connection.sendRequest(Requests.ReadFile, { path } satisfies ReadFileRequest); return await connection.sendRequest(Requests.ReadFile, {path} satisfies ReadFileRequest);
}) })
}; };
const result = await validate(textDocument, config); const result = await validate(textDocument, config);
await connection.sendDiagnostics({ uri: textDocument.uri, diagnostics: result }); await connection.sendDiagnostics({uri: textDocument.uri, diagnostics: result});
} }
connection.onCompletion(async ({ position, textDocument }: TextDocumentPositionParams): Promise<CompletionItem[]> => { connection.onCompletion(async ({position, textDocument}: TextDocumentPositionParams): Promise<CompletionItem[]> => {
return timeOperation( return timeOperation(
"completion", "completion",
async () => async () =>
@@ -139,14 +139,14 @@ export function initConnection(connection: Connection) {
); );
}); });
connection.onHover(async ({ position, textDocument }: HoverParams): Promise<Hover | null> => { connection.onHover(async ({position, textDocument}: HoverParams): Promise<Hover | null> => {
return timeOperation("hover", async () => { return timeOperation("hover", async () => {
const repoContext = repos.find(repo => textDocument.uri.startsWith(repo.workspaceUri)); const repoContext = repos.find(repo => textDocument.uri.startsWith(repo.workspaceUri));
return await hover(getDocument(documents, textDocument), position, { return await hover(getDocument(documents, textDocument), position, {
descriptionProvider: descriptionProvider(client, cache), descriptionProvider: descriptionProvider(client, cache),
contextProviderConfig: repoContext && contextProviders(client, repoContext, cache), contextProviderConfig: repoContext && contextProviders(client, repoContext, cache),
fileProvider: getFileProvider(client, cache, repoContext?.workspaceUri, async path => { fileProvider: getFileProvider(client, cache, repoContext?.workspaceUri, async path => {
return await connection.sendRequest(Requests.ReadFile, { path }); return await connection.sendRequest(Requests.ReadFile, {path});
}) })
}); });
}); });
@@ -159,7 +159,7 @@ export function initConnection(connection: Connection) {
} }
}); });
connection.onDocumentLinks(async ({ textDocument }: DocumentLinkParams): Promise<DocumentLink[] | null> => { connection.onDocumentLinks(async ({textDocument}: DocumentLinkParams): Promise<DocumentLink[] | null> => {
const repoContext = repos.find(repo => textDocument.uri.startsWith(repo.workspaceUri)); const repoContext = repos.find(repo => textDocument.uri.startsWith(repo.workspaceUri));
return documentLinks(getDocument(documents, textDocument), repoContext?.workspaceUri); return documentLinks(getDocument(documents, textDocument), repoContext?.workspaceUri);
}); });
@@ -169,7 +169,7 @@ export function initConnection(connection: Connection) {
return getCodeActions({ return getCodeActions({
uri: params.textDocument.uri, uri: params.textDocument.uri,
diagnostics: params.context.diagnostics, diagnostics: params.context.diagnostics,
only: params.context.only, only: params.context.only
}); });
}); });
}); });
+6 -4
View File
@@ -1,6 +1,6 @@
import { Connection } from "vscode-languageserver"; import {Connection} from "vscode-languageserver";
import { initConnection } from "./connection.js"; import {initConnection} from "./connection.js";
/** Helper function determining whether we are executing with node runtime */ /** Helper function determining whether we are executing with node runtime */
function isNode(): boolean { function isNode(): boolean {
@@ -9,10 +9,12 @@ function isNode(): boolean {
async function getConnection(): Promise<Connection> { async function getConnection(): Promise<Connection> {
if (isNode()) { if (isNode()) {
const { createConnection } = await import("vscode-languageserver/node.js"); const {createConnection} = await import("vscode-languageserver/node.js");
return createConnection(); return createConnection();
} else { } else {
const { BrowserMessageReader, BrowserMessageWriter, createConnection } = await import("vscode-languageserver/browser.js"); const {BrowserMessageReader, BrowserMessageWriter, createConnection} = await import(
"vscode-languageserver/browser.js"
);
const messageReader = new BrowserMessageReader(self); const messageReader = new BrowserMessageReader(self);
const messageWriter = new BrowserMessageWriter(self); const messageWriter = new BrowserMessageWriter(self);
return createConnection(messageReader, messageWriter); return createConnection(messageReader, messageWriter);
+7 -8
View File
@@ -1,10 +1,10 @@
import { CodeAction, CodeActionKind, Diagnostic } from "vscode-languageserver-types"; import {CodeAction, CodeActionKind, Diagnostic} from "vscode-languageserver-types";
import { CodeActionContext, CodeActionProvider } from "./types"; import {CodeActionContext, CodeActionProvider} from "./types";
import { quickfixProviders } from "./quickfix"; import {quickfixProviders} from "./quickfix";
// Aggregate all providers by kind // Aggregate all providers by kind
const providersByKind: Map<string, CodeActionProvider[]> = new Map([ const providersByKind: Map<string, CodeActionProvider[]> = new Map([
[CodeActionKind.QuickFix, quickfixProviders], [CodeActionKind.QuickFix, quickfixProviders]
// [CodeActionKind. Refactor, refactorProviders], // [CodeActionKind. Refactor, refactorProviders],
// [CodeActionKind.Source, sourceProviders], // [CodeActionKind.Source, sourceProviders],
// etc // etc
@@ -23,14 +23,13 @@ export interface CodeActionParams {
export function getCodeActions(params: CodeActionParams, config?: CodeActionConfig): CodeAction[] { export function getCodeActions(params: CodeActionParams, config?: CodeActionConfig): CodeAction[] {
const actions: CodeAction[] = []; const actions: CodeAction[] = [];
const context: CodeActionContext = { const context: CodeActionContext = {
uri: params.uri, uri: params.uri
}; };
// Filter to requested kinds, or use all if none specified // Filter to requested kinds, or use all if none specified
const requestedKinds = params.only; const requestedKinds = params.only;
const kindsToCheck = requestedKinds const kindsToCheck = requestedKinds
? [...providersByKind.keys()].filter(kind => ? [...providersByKind.keys()].filter(kind => requestedKinds.some(requested => kind.startsWith(requested)))
requestedKinds.some(requested => kind.startsWith(requested)))
: [...providersByKind.keys()]; : [...providersByKind.keys()];
for (const diagnostic of params.diagnostics) { for (const diagnostic of params.diagnostics) {
@@ -52,4 +51,4 @@ export function getCodeActions(params: CodeActionParams, config?: CodeActionConf
return actions; return actions;
} }
export type { CodeActionContext, CodeActionProvider } from "./types"; export type {CodeActionContext, CodeActionProvider} from "./types";
@@ -1,6 +1,6 @@
import { CodeAction, TextEdit } from "vscode-languageserver-types"; import {CodeAction, TextEdit} from "vscode-languageserver-types";
import { CodeActionContext, CodeActionProvider } from "../types"; import {CodeActionContext, CodeActionProvider} from "../types";
import { DiagnosticCode, MissingInputsDiagnosticData } from "../../validate-action"; import {DiagnosticCode, MissingInputsDiagnosticData} from "../../validate-action";
export const addMissingInputsProvider: CodeActionProvider = { export const addMissingInputsProvider: CodeActionProvider = {
diagnosticCodes: [DiagnosticCode.MissingRequiredInputs], diagnosticCodes: [DiagnosticCode.MissingRequiredInputs],
@@ -22,11 +22,11 @@ export const addMissingInputsProvider: CodeActionProvider = {
title: `Add missing input${data.missingInputs.length > 1 ? "s" : ""}: ${inputNames}`, title: `Add missing input${data.missingInputs.length > 1 ? "s" : ""}: ${inputNames}`,
edit: { edit: {
changes: { changes: {
[context.uri]: edits, [context.uri]: edits
}, }
}, }
}; };
}, }
}; };
function createInputEdits(data: MissingInputsDiagnosticData): TextEdit[] | undefined { function createInputEdits(data: MissingInputsDiagnosticData): TextEdit[] | undefined {
@@ -42,8 +42,8 @@ function createInputEdits(data: MissingInputsDiagnosticData): TextEdit[] | undef
}); });
edits.push({ edits.push({
range: { start: data.insertPosition, end: data.insertPosition }, range: {start: data.insertPosition, end: data.insertPosition},
newText: inputLines.map(line => line + "\n").join(""), newText: inputLines.map(line => line + "\n").join("")
}); });
} else { } else {
// No `with:` key - use step indentation for `with:`, +2 for inputs // No `with:` key - use step indentation for `with:`, +2 for inputs
@@ -58,8 +58,8 @@ function createInputEdits(data: MissingInputsDiagnosticData): TextEdit[] | undef
const newText = [`${withIndent}with:\n`, ...inputLines.map(line => `${line}\n`)].join(""); const newText = [`${withIndent}with:\n`, ...inputLines.map(line => `${line}\n`)].join("");
edits.push({ edits.push({
range: { start: data.insertPosition, end: data.insertPosition }, range: {start: data.insertPosition, end: data.insertPosition},
newText, newText
}); });
} }
@@ -1,6 +1,4 @@
import { CodeActionProvider } from "../types"; import {CodeActionProvider} from "../types";
import { addMissingInputsProvider } from "./add-missing-inputs"; import {addMissingInputsProvider} from "./add-missing-inputs";
export const quickfixProviders: CodeActionProvider[] = [ export const quickfixProviders: CodeActionProvider[] = [addMissingInputsProvider];
addMissingInputsProvider,
];
@@ -1,9 +1,9 @@
import * as path from "path"; import * as path from "path";
import { fileURLToPath } from "url"; import {fileURLToPath} from "url";
import { loadTestCases, runTestCase } from "./runner"; import {loadTestCases, runTestCase} from "./runner";
import { ValidationConfig } from "../../validate"; import {ValidationConfig} from "../../validate";
import { ActionMetadata, ActionReference } from "../../action"; import {ActionMetadata, ActionReference} from "../../action";
import { clearCache } from "../../utils/workflow-cache"; import {clearCache} from "../../utils/workflow-cache";
// ESM-compatible __dirname // ESM-compatible __dirname
const __filename = fileURLToPath(import.meta.url); const __filename = fileURLToPath(import.meta.url);
@@ -22,17 +22,17 @@ const validationConfig: ValidationConfig = {
inputs: { inputs: {
path: { path: {
description: "A list of files to cache", description: "A list of files to cache",
required: true, required: true
}, },
key: { key: {
description: "Cache key", description: "Cache key",
required: true, required: true
}, },
"restore-keys": { "restore-keys": {
description: "Restore keys", description: "Restore keys",
required: false, required: false
}, }
}, }
}, },
"actions/setup-node@v3": { "actions/setup-node@v3": {
name: "Setup Node", name: "Setup Node",
@@ -41,15 +41,15 @@ const validationConfig: ValidationConfig = {
"node-version": { "node-version": {
description: "Node version", description: "Node version",
required: true, required: true,
default: "16", default: "16"
}, }
}, }
}, }
}; };
return Promise.resolve(metadata[key]); return Promise.resolve(metadata[key]);
}, }
}, }
}; };
// Point to the source testdata directory // Point to the source testdata directory
@@ -1,9 +1,9 @@
import * as fs from "fs"; import * as fs from "fs";
import * as path from "path"; import * as path from "path";
import { TextEdit } from "vscode-languageserver-types"; import {TextEdit} from "vscode-languageserver-types";
import { TextDocument } from "vscode-languageserver-textdocument"; import {TextDocument} from "vscode-languageserver-textdocument";
import { validate, ValidationConfig } from "../../validate"; import {validate, ValidationConfig} from "../../validate";
import { getCodeActions, CodeActionParams } from "../index"; import {getCodeActions, CodeActionParams} from "../index";
// Marker pattern: # want "diagnostic message" fix="code-action-name" // Marker pattern: # want "diagnostic message" fix="code-action-name"
const MARKER_PATTERN = /#\s*want\s+"([^"]+)"(?:\s+fix="([^"]+)")?/; const MARKER_PATTERN = /#\s*want\s+"([^"]+)"(?:\s+fix="([^"]+)")?/;
@@ -44,7 +44,7 @@ export function parseMarkers(content: string): Marker[] {
markers.push({ markers.push({
line: i, line: i,
message: match[1], message: match[1],
fix: match[2], fix: match[2]
}); });
} }
} }
@@ -69,7 +69,7 @@ export function loadTestCases(testdataDir: string): TestCase[] {
const testCases: TestCase[] = []; const testCases: TestCase[] = [];
function walkDir(dir: string) { function walkDir(dir: string) {
const entries = fs.readdirSync(dir, { withFileTypes: true }); const entries = fs.readdirSync(dir, {withFileTypes: true});
for (const entry of entries) { for (const entry of entries) {
const fullPath = path.join(dir, entry.name); const fullPath = path.join(dir, entry.name);
@@ -89,7 +89,7 @@ export function loadTestCases(testdataDir: string): TestCase[] {
goldenPath, goldenPath,
input, input,
golden, golden,
markers: parseMarkers(input), markers: parseMarkers(input)
}); });
} }
} }
@@ -136,10 +136,7 @@ export function applyEdits(content: string, edits: TextEdit[]): string {
/** /**
* Run a single test case * Run a single test case
*/ */
export async function runTestCase( export async function runTestCase(testCase: TestCase, validationConfig: ValidationConfig): Promise<TestResult> {
testCase: TestCase,
validationConfig: ValidationConfig
): Promise<TestResult> {
const strippedInput = stripMarkers(testCase.input); const strippedInput = stripMarkers(testCase.input);
const document = TextDocument.create("file:///test.yml", "yaml", 1, strippedInput); const document = TextDocument.create("file:///test.yml", "yaml", 1, strippedInput);
@@ -149,9 +146,7 @@ export async function runTestCase(
// 2. Verify all expected diagnostics are present // 2. Verify all expected diagnostics are present
const missingDiagnostics: string[] = []; const missingDiagnostics: string[] = [];
for (const marker of testCase.markers) { for (const marker of testCase.markers) {
const found = diagnostics.find( const found = diagnostics.find(d => d.range.start.line === marker.line && d.message.includes(marker.message));
d => d.range.start.line === marker.line && d.message.includes(marker.message)
);
if (!found) { if (!found) {
missingDiagnostics.push(`line ${marker.line}: "${marker.message}"`); missingDiagnostics.push(`line ${marker.line}: "${marker.message}"`);
} }
@@ -161,7 +156,9 @@ export async function runTestCase(
return { return {
name: testCase.name, name: testCase.name,
passed: false, passed: false,
error: `Missing expected diagnostics:\n ${missingDiagnostics.join("\n ")}\n\nActual diagnostics:\n ${diagnostics.map(d => `line ${d.range.start.line}: "${d.message}"`).join("\n ")}`, error: `Missing expected diagnostics:\n ${missingDiagnostics.join(
"\n "
)}\n\nActual diagnostics:\n ${diagnostics.map(d => `line ${d.range.start.line}: "${d.message}"`).join("\n ")}`
}; };
} }
@@ -173,9 +170,7 @@ export async function runTestCase(
continue; continue;
} }
const diagnostic = diagnostics.find( const diagnostic = diagnostics.find(d => d.range.start.line === marker.line && d.message.includes(marker.message));
d => d.range.start.line === marker.line && d.message.includes(marker.message)
);
if (!diagnostic) { if (!diagnostic) {
continue; // Already reported above continue; // Already reported above
@@ -183,19 +178,19 @@ export async function runTestCase(
const params: CodeActionParams = { const params: CodeActionParams = {
uri: document.uri, uri: document.uri,
diagnostics: [diagnostic], diagnostics: [diagnostic]
}; };
const actions = getCodeActions(params); const actions = getCodeActions(params);
const matchingAction = actions.find(a => const matchingAction = actions.find(a => a.title.toLowerCase().includes(marker.fix!.toLowerCase()));
a.title.toLowerCase().includes(marker.fix!.toLowerCase())
);
if (!matchingAction) { if (!matchingAction) {
return { return {
name: testCase.name, name: testCase.name,
passed: false, passed: false,
error: `Code action "${marker.fix}" not found for diagnostic on line ${marker.line}.\nAvailable actions: ${actions.map(a => a.title).join(", ") || "(none)"}`, error: `Code action "${marker.fix}" not found for diagnostic on line ${marker.line}.\nAvailable actions: ${
actions.map(a => a.title).join(", ") || "(none)"
}`
}; };
} }
@@ -203,7 +198,7 @@ export async function runTestCase(
return { return {
name: testCase.name, name: testCase.name,
passed: false, passed: false,
error: `Code action "${marker.fix}" has no edits`, error: `Code action "${marker.fix}" has no edits`
}; };
} }
@@ -221,12 +216,12 @@ export async function runTestCase(
passed: false, passed: false,
error: "Output does not match golden file", error: "Output does not match golden file",
expected: expectedOutput, expected: expectedOutput,
actual: actualOutput, actual: actualOutput
}; };
} }
return { return {
name: testCase.name, name: testCase.name,
passed: true, passed: true
}; };
} }
+1 -1
View File
@@ -1,4 +1,4 @@
import { CodeAction, Diagnostic } from "vscode-languageserver-types"; import {CodeAction, Diagnostic} from "vscode-languageserver-types";
export interface CodeActionContext { export interface CodeActionContext {
uri: string; uri: string;
+8 -8
View File
@@ -1,8 +1,8 @@
export { complete } from "./complete"; export {complete} from "./complete";
export { ContextProviderConfig } from "./context-providers/config"; export {ContextProviderConfig} from "./context-providers/config";
export { documentLinks } from "./document-links"; export {documentLinks} from "./document-links";
export { hover } from "./hover"; export {hover} from "./hover";
export { Logger, LogLevel, registerLogger, setLogLevel } from "./log"; export {Logger, LogLevel, registerLogger, setLogLevel} from "./log";
export { validate, ValidationConfig, ActionsMetadataProvider } from "./validate"; export {validate, ValidationConfig, ActionsMetadataProvider} from "./validate";
export { ValueProviderConfig, ValueProviderKind } from "./value-providers/config"; export {ValueProviderConfig, ValueProviderKind} from "./value-providers/config";
export { getCodeActions } from "./code-actions"; export {getCodeActions} from "./code-actions";
+17 -17
View File
@@ -1,15 +1,15 @@
import { isMapping } from "@actions/workflow-parser"; import {isMapping} from "@actions/workflow-parser";
import { isActionStep } from "@actions/workflow-parser/model/type-guards"; import {isActionStep} from "@actions/workflow-parser/model/type-guards";
import { Step } from "@actions/workflow-parser/model/workflow-template"; import {Step} from "@actions/workflow-parser/model/workflow-template";
import { ScalarToken } from "@actions/workflow-parser/templates/tokens/scalar-token"; import {ScalarToken} from "@actions/workflow-parser/templates/tokens/scalar-token";
import { TemplateToken } from "@actions/workflow-parser/templates/tokens/template-token"; import {TemplateToken} from "@actions/workflow-parser/templates/tokens/template-token";
import { Diagnostic, DiagnosticSeverity } from "vscode-languageserver-types"; import {Diagnostic, DiagnosticSeverity} from "vscode-languageserver-types";
import { ActionReference, parseActionReference } from "./action"; import {ActionReference, parseActionReference} from "./action";
import { mapRange } from "./utils/range"; import {mapRange} from "./utils/range";
import { ValidationConfig } from "./validate"; import {ValidationConfig} from "./validate";
export const DiagnosticCode = { export const DiagnosticCode = {
MissingRequiredInputs: "missing-required-inputs", MissingRequiredInputs: "missing-required-inputs"
} as const; } as const;
export interface MissingInputsDiagnosticData { export interface MissingInputsDiagnosticData {
@@ -23,7 +23,7 @@ export interface MissingInputsDiagnosticData {
withIndent?: number; withIndent?: number;
stepIndent: number; stepIndent: number;
// Position where new content should be inserted // Position where new content should be inserted
insertPosition: { line: number; character: number }; insertPosition: {line: number; character: number};
} }
export async function validateAction( export async function validateAction(
@@ -53,7 +53,7 @@ export async function validateAction(
let withKey: ScalarToken | undefined; let withKey: ScalarToken | undefined;
let withToken: TemplateToken | undefined; let withToken: TemplateToken | undefined;
for (const { key, value } of stepToken) { for (const {key, value} of stepToken) {
if (key.toString() === "with") { if (key.toString() === "with") {
withKey = key; withKey = key;
withToken = value; withToken = value;
@@ -63,7 +63,7 @@ export async function validateAction(
const stepInputs = new Map<string, ScalarToken>(); const stepInputs = new Map<string, ScalarToken>();
if (withToken && isMapping(withToken)) { if (withToken && isMapping(withToken)) {
for (const { key } of withToken) { for (const {key} of withToken) {
stepInputs.set(key.toString(), key); stepInputs.set(key.toString(), key);
} }
} }
@@ -109,16 +109,16 @@ export async function validateAction(
action, action,
missingInputs: missingRequiredInputs.map(([name, input]) => ({ missingInputs: missingRequiredInputs.map(([name, input]) => ({
name, name,
default: input.default, default: input.default
})), })),
hasWithKey: withKey !== undefined, hasWithKey: withKey !== undefined,
withIndent, withIndent,
stepIndent, stepIndent,
insertPosition: withToken?.range insertPosition: withToken?.range
? { line: withToken.range.end.line - 1, character: 0 } ? {line: withToken.range.end.line - 1, character: 0}
: stepToken.range : stepToken.range
? { line: stepToken.range.end.line - 1, character: 0 } ? {line: stepToken.range.end.line - 1, character: 0}
: { line: 0, character: 0 }, : {line: 0, character: 0}
}; };
diagnostics.push({ diagnostics.push({
+9 -9
View File
@@ -1,11 +1,11 @@
import { DiagnosticSeverity } from "vscode-languageserver-types"; import {DiagnosticSeverity} from "vscode-languageserver-types";
import { ActionMetadata, ActionReference } from "./action"; import {ActionMetadata, ActionReference} from "./action";
import { registerLogger } from "./log"; import {registerLogger} from "./log";
import { createDocument } from "./test-utils/document"; import {createDocument} from "./test-utils/document";
import { TestLogger } from "./test-utils/logger"; import {TestLogger} from "./test-utils/logger";
import { validate, ValidationConfig } from "./validate"; import {validate, ValidationConfig} from "./validate";
import { ValueProviderKind } from "./value-providers/config"; import {ValueProviderKind} from "./value-providers/config";
import { clearCache } from "./utils/workflow-cache"; import {clearCache} from "./utils/workflow-cache";
registerLogger(new TestLogger()); registerLogger(new TestLogger());
@@ -415,7 +415,7 @@ jobs:
"step-with": { "step-with": {
kind: ValueProviderKind.AllowedValues, kind: ValueProviderKind.AllowedValues,
get: () => { get: () => {
return Promise.resolve([{ label: "repository", description: "Repository name with owner." }]); return Promise.resolve([{label: "repository", description: "Repository name with owner."}]);
} }
} }
}; };