WIP
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
import {documentLinks, hover, validate, ValidationConfig} from "@actions/languageservice";
|
import {documentLinks, documentSymbols, 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";
|
||||||
@@ -7,6 +7,8 @@ import {
|
|||||||
Connection,
|
Connection,
|
||||||
DocumentLink,
|
DocumentLink,
|
||||||
DocumentLinkParams,
|
DocumentLinkParams,
|
||||||
|
DocumentSymbol,
|
||||||
|
DocumentSymbolParams,
|
||||||
ExecuteCommandParams,
|
ExecuteCommandParams,
|
||||||
Hover,
|
Hover,
|
||||||
HoverParams,
|
HoverParams,
|
||||||
@@ -72,6 +74,10 @@ export function initConnection(connection: Connection) {
|
|||||||
hoverProvider: true,
|
hoverProvider: true,
|
||||||
documentLinkProvider: {
|
documentLinkProvider: {
|
||||||
resolveProvider: false
|
resolveProvider: false
|
||||||
|
},
|
||||||
|
documentSymbolProvider: {
|
||||||
|
label: "GitHub Actions",
|
||||||
|
workDoneProgress: false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -158,6 +164,11 @@ export function initConnection(connection: Connection) {
|
|||||||
return documentLinks(getDocument(documents, textDocument), repoContext?.workspaceUri);
|
return documentLinks(getDocument(documents, textDocument), repoContext?.workspaceUri);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
connection.onDocumentSymbol(async ({textDocument}: DocumentSymbolParams): Promise<DocumentSymbol[] | null> => {
|
||||||
|
const repoContext = repos.find(repo => textDocument.uri.startsWith(repo.workspaceUri));
|
||||||
|
return documentSymbols(getDocument(documents, textDocument), repoContext?.workspaceUri);
|
||||||
|
});
|
||||||
|
|
||||||
// Make the text document manager listen on the connection
|
// Make the text document manager listen on the connection
|
||||||
// for open, change and close text document events
|
// for open, change and close text document events
|
||||||
documents.listen(connection);
|
documents.listen(connection);
|
||||||
|
|||||||
@@ -0,0 +1,70 @@
|
|||||||
|
import {ErrorPolicy} from "@actions/workflow-parser/model/convert";
|
||||||
|
import {File} from "@actions/workflow-parser/workflows/file";
|
||||||
|
import {TextDocument} from "vscode-languageserver-textdocument";
|
||||||
|
import {DocumentSymbol, SymbolKind} from "vscode-languageserver-types";
|
||||||
|
import {mapRange} from "./utils/range";
|
||||||
|
import {fetchOrConvertWorkflowTemplate, fetchOrParseWorkflow} from "./utils/workflow-cache";
|
||||||
|
|
||||||
|
export async function documentSymbols(
|
||||||
|
document: TextDocument,
|
||||||
|
workspace: string | undefined
|
||||||
|
): Promise<DocumentSymbol[]> {
|
||||||
|
const file: File = {
|
||||||
|
name: document.uri,
|
||||||
|
content: document.getText()
|
||||||
|
};
|
||||||
|
|
||||||
|
const parsedWorkflow = fetchOrParseWorkflow(file, document.uri);
|
||||||
|
if (!parsedWorkflow?.value) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
const template = await fetchOrConvertWorkflowTemplate(
|
||||||
|
parsedWorkflow.context,
|
||||||
|
parsedWorkflow.value,
|
||||||
|
document.uri,
|
||||||
|
undefined,
|
||||||
|
{
|
||||||
|
errorPolicy: ErrorPolicy.TryConversion
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!template) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
const symbols: DocumentSymbol[] = [];
|
||||||
|
|
||||||
|
const onSymbol = DocumentSymbol.create(
|
||||||
|
"`on` Triggers",
|
||||||
|
undefined,
|
||||||
|
SymbolKind.Key,
|
||||||
|
mapRange(template.events.range),
|
||||||
|
mapRange(template.events.range)
|
||||||
|
);
|
||||||
|
symbols.push(onSymbol);
|
||||||
|
|
||||||
|
const jobsSymbol = DocumentSymbol.create(
|
||||||
|
"Jobs",
|
||||||
|
undefined,
|
||||||
|
SymbolKind.Namespace,
|
||||||
|
mapRange(template.jobs?.[0].id.range),
|
||||||
|
mapRange(template.jobs?.[0].id.range),
|
||||||
|
[]
|
||||||
|
);
|
||||||
|
symbols.push(jobsSymbol);
|
||||||
|
|
||||||
|
for (const job of template.jobs || []) {
|
||||||
|
const jobSymbol = DocumentSymbol.create(
|
||||||
|
`Job ${job.name?.toDisplayString() || job.id?.toString()}`,
|
||||||
|
"detail",
|
||||||
|
SymbolKind.Class,
|
||||||
|
mapRange(job.id.range),
|
||||||
|
mapRange(job.id.range)
|
||||||
|
);
|
||||||
|
|
||||||
|
jobsSymbol.children!.push(jobSymbol);
|
||||||
|
}
|
||||||
|
|
||||||
|
return symbols;
|
||||||
|
}
|
||||||
@@ -1,7 +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 {documentSymbols} from "./document-symbols";
|
||||||
export {hover} from "./hover";
|
export {hover} from "./hover";
|
||||||
export {Logger, LogLevel, registerLogger, setLogLevel} from "./log";
|
export {LogLevel, Logger, registerLogger, setLogLevel} from "./log";
|
||||||
export {validate, ValidationConfig, ActionsMetadataProvider} from "./validate";
|
export {ActionsMetadataProvider, ValidationConfig, validate} from "./validate";
|
||||||
export {ValueProviderConfig, ValueProviderKind} from "./value-providers/config";
|
export {ValueProviderConfig, ValueProviderKind} from "./value-providers/config";
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import {handleTemplateTokenErrors} from "./converter/handle-errors";
|
|||||||
import {convertJobs} from "./converter/jobs";
|
import {convertJobs} from "./converter/jobs";
|
||||||
import {convertReferencedWorkflow} from "./converter/referencedWorkflow";
|
import {convertReferencedWorkflow} from "./converter/referencedWorkflow";
|
||||||
import {isReusableWorkflowJob} from "./type-guards";
|
import {isReusableWorkflowJob} from "./type-guards";
|
||||||
import {WorkflowTemplate} from "./workflow-template";
|
import {EventsConfig, WorkflowTemplate} from "./workflow-template";
|
||||||
|
|
||||||
export enum ErrorPolicy {
|
export enum ErrorPolicy {
|
||||||
ReturnErrorsOnly,
|
ReturnErrorsOnly,
|
||||||
@@ -73,7 +73,9 @@ export async function convertWorkflowTemplate(
|
|||||||
|
|
||||||
switch (key.value) {
|
switch (key.value) {
|
||||||
case "on":
|
case "on":
|
||||||
result.events = handleTemplateTokenErrors(root, context, {}, () => convertOn(context, item.value));
|
result.events = handleTemplateTokenErrors(root, context, {range: item.key.range} as EventsConfig, () =>
|
||||||
|
convertOn(context, item.value)
|
||||||
|
);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "jobs":
|
case "jobs":
|
||||||
|
|||||||
@@ -23,12 +23,15 @@ export function convertOn(context: TemplateContext, token: TemplateToken): Event
|
|||||||
const event = token.assertString("on");
|
const event = token.assertString("on");
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
range: token.range,
|
||||||
[event.value]: {}
|
[event.value]: {}
|
||||||
} as EventsConfig;
|
} as EventsConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isSequence(token)) {
|
if (isSequence(token)) {
|
||||||
const result = {} as EventsConfig;
|
const result = {
|
||||||
|
range: token.range
|
||||||
|
} as EventsConfig;
|
||||||
|
|
||||||
for (const item of token) {
|
for (const item of token) {
|
||||||
const event = item.assertString("on");
|
const event = item.assertString("on");
|
||||||
@@ -39,7 +42,9 @@ export function convertOn(context: TemplateContext, token: TemplateToken): Event
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (isMapping(token)) {
|
if (isMapping(token)) {
|
||||||
const result = {} as EventsConfig;
|
const result = {
|
||||||
|
range: token.range
|
||||||
|
} as EventsConfig;
|
||||||
|
|
||||||
for (const item of token) {
|
for (const item of token) {
|
||||||
const eventKey = item.key.assertString("event name");
|
const eventKey = item.key.assertString("event name");
|
||||||
@@ -77,7 +82,9 @@ export function convertOn(context: TemplateContext, token: TemplateToken): Event
|
|||||||
}
|
}
|
||||||
|
|
||||||
context.error(token, "Invalid format for 'on'");
|
context.error(token, "Invalid format for 'on'");
|
||||||
return {};
|
return {
|
||||||
|
range: token.range
|
||||||
|
} as EventsConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
function convertPatternFilter<T extends BranchFilterConfig & TagFilterConfig & PathFilterConfig>(
|
function convertPatternFilter<T extends BranchFilterConfig & TagFilterConfig & PathFilterConfig>(
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import {
|
|||||||
StringToken,
|
StringToken,
|
||||||
TemplateToken
|
TemplateToken
|
||||||
} from "../templates/tokens";
|
} from "../templates/tokens";
|
||||||
|
import {TokenRange} from "../templates/tokens/token-range";
|
||||||
|
|
||||||
export type WorkflowTemplate = {
|
export type WorkflowTemplate = {
|
||||||
events: EventsConfig;
|
events: EventsConfig;
|
||||||
@@ -99,6 +100,8 @@ export type ActionStep = BaseStep & {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export type EventsConfig = {
|
export type EventsConfig = {
|
||||||
|
range: TokenRange;
|
||||||
|
|
||||||
schedule?: ScheduleConfig[];
|
schedule?: ScheduleConfig[];
|
||||||
workflow_dispatch?: WorkflowDispatchConfig;
|
workflow_dispatch?: WorkflowDispatchConfig;
|
||||||
workflow_call?: WorkflowCallConfig;
|
workflow_call?: WorkflowCallConfig;
|
||||||
|
|||||||
Reference in New Issue
Block a user