Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| db3896d0aa |
@@ -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 {clearCache, clearCacheEntry} from "@actions/languageservice/utils/workflow-cache";
|
||||
import {Octokit} from "@octokit/rest";
|
||||
@@ -7,6 +7,8 @@ import {
|
||||
Connection,
|
||||
DocumentLink,
|
||||
DocumentLinkParams,
|
||||
DocumentSymbol,
|
||||
DocumentSymbolParams,
|
||||
ExecuteCommandParams,
|
||||
Hover,
|
||||
HoverParams,
|
||||
@@ -72,6 +74,10 @@ export function initConnection(connection: Connection) {
|
||||
hoverProvider: true,
|
||||
documentLinkProvider: {
|
||||
resolveProvider: false
|
||||
},
|
||||
documentSymbolProvider: {
|
||||
label: "GitHub Actions",
|
||||
workDoneProgress: false
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -158,6 +164,11 @@ export function initConnection(connection: Connection) {
|
||||
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
|
||||
// for open, change and close text document events
|
||||
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 {ContextProviderConfig} from "./context-providers/config";
|
||||
export {documentLinks} from "./document-links";
|
||||
export {documentSymbols} from "./document-symbols";
|
||||
export {hover} from "./hover";
|
||||
export {Logger, LogLevel, registerLogger, setLogLevel} from "./log";
|
||||
export {validate, ValidationConfig, ActionsMetadataProvider} from "./validate";
|
||||
export {LogLevel, Logger, registerLogger, setLogLevel} from "./log";
|
||||
export {ActionsMetadataProvider, ValidationConfig, validate} from "./validate";
|
||||
export {ValueProviderConfig, ValueProviderKind} from "./value-providers/config";
|
||||
|
||||
@@ -9,7 +9,7 @@ import {handleTemplateTokenErrors} from "./converter/handle-errors";
|
||||
import {convertJobs} from "./converter/jobs";
|
||||
import {convertReferencedWorkflow} from "./converter/referencedWorkflow";
|
||||
import {isReusableWorkflowJob} from "./type-guards";
|
||||
import {WorkflowTemplate} from "./workflow-template";
|
||||
import {EventsConfig, WorkflowTemplate} from "./workflow-template";
|
||||
|
||||
export enum ErrorPolicy {
|
||||
ReturnErrorsOnly,
|
||||
@@ -73,7 +73,9 @@ export async function convertWorkflowTemplate(
|
||||
|
||||
switch (key.value) {
|
||||
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;
|
||||
|
||||
case "jobs":
|
||||
|
||||
@@ -23,12 +23,15 @@ export function convertOn(context: TemplateContext, token: TemplateToken): Event
|
||||
const event = token.assertString("on");
|
||||
|
||||
return {
|
||||
range: token.range,
|
||||
[event.value]: {}
|
||||
} as EventsConfig;
|
||||
}
|
||||
|
||||
if (isSequence(token)) {
|
||||
const result = {} as EventsConfig;
|
||||
const result = {
|
||||
range: token.range
|
||||
} as EventsConfig;
|
||||
|
||||
for (const item of token) {
|
||||
const event = item.assertString("on");
|
||||
@@ -39,7 +42,9 @@ export function convertOn(context: TemplateContext, token: TemplateToken): Event
|
||||
}
|
||||
|
||||
if (isMapping(token)) {
|
||||
const result = {} as EventsConfig;
|
||||
const result = {
|
||||
range: token.range
|
||||
} as EventsConfig;
|
||||
|
||||
for (const item of token) {
|
||||
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'");
|
||||
return {};
|
||||
return {
|
||||
range: token.range
|
||||
} as EventsConfig;
|
||||
}
|
||||
|
||||
function convertPatternFilter<T extends BranchFilterConfig & TagFilterConfig & PathFilterConfig>(
|
||||
|
||||
@@ -6,6 +6,7 @@ import {
|
||||
StringToken,
|
||||
TemplateToken
|
||||
} from "../templates/tokens";
|
||||
import {TokenRange} from "../templates/tokens/token-range";
|
||||
|
||||
export type WorkflowTemplate = {
|
||||
events: EventsConfig;
|
||||
@@ -99,6 +100,8 @@ export type ActionStep = BaseStep & {
|
||||
};
|
||||
|
||||
export type EventsConfig = {
|
||||
range: TokenRange;
|
||||
|
||||
schedule?: ScheduleConfig[];
|
||||
workflow_dispatch?: WorkflowDispatchConfig;
|
||||
workflow_call?: WorkflowCallConfig;
|
||||
|
||||
Reference in New Issue
Block a user