Fix validation with moved definition
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
import {isMapping, parseWorkflow} from "@github/actions-workflow-parser";
|
import {parseWorkflow} from "@github/actions-workflow-parser";
|
||||||
import {TemplateToken} from "@github/actions-workflow-parser/templates/tokens/template-token";
|
import {TemplateToken} from "@github/actions-workflow-parser/templates/tokens/template-token";
|
||||||
import {File} from "@github/actions-workflow-parser/workflows/file";
|
import {File} from "@github/actions-workflow-parser/workflows/file";
|
||||||
import {Position, TextDocument} from "vscode-languageserver-textdocument";
|
import {Position, TextDocument} from "vscode-languageserver-textdocument";
|
||||||
@@ -14,7 +14,7 @@ export async function hover(document: TextDocument, position: Position): Promise
|
|||||||
};
|
};
|
||||||
const result = parseWorkflow(file.name, [file], nullTrace);
|
const result = parseWorkflow(file.name, [file], nullTrace);
|
||||||
|
|
||||||
const {token, keyToken, parent} = findToken(position, result.value);
|
const {token} = findToken(position, result.value);
|
||||||
|
|
||||||
if (result.value && token) {
|
if (result.value && token) {
|
||||||
return getHover(token);
|
return getHover(token);
|
||||||
|
|||||||
@@ -158,4 +158,33 @@ jobs:
|
|||||||
}
|
}
|
||||||
} as Diagnostic);
|
} as Diagnostic);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("unknown event type", async () => {
|
||||||
|
const result = await validate(
|
||||||
|
createDocument(
|
||||||
|
"wf.yaml",
|
||||||
|
`on: [push, check_run, pr]
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on:
|
||||||
|
- ubuntu-latest`
|
||||||
|
),
|
||||||
|
defaultValueProviders
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(result.length).toBe(1);
|
||||||
|
expect(result[0]).toEqual({
|
||||||
|
message: "Unexpected value 'pr'",
|
||||||
|
range: {
|
||||||
|
end: {
|
||||||
|
character: 24,
|
||||||
|
line: 0
|
||||||
|
},
|
||||||
|
start: {
|
||||||
|
character: 22,
|
||||||
|
line: 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} as Diagnostic);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ import {Expr} from "@github/actions-expressions/ast";
|
|||||||
import {
|
import {
|
||||||
convertWorkflowTemplate,
|
convertWorkflowTemplate,
|
||||||
isBasicExpression,
|
isBasicExpression,
|
||||||
isSequence,
|
|
||||||
isString,
|
isString,
|
||||||
parseWorkflow,
|
parseWorkflow,
|
||||||
ParseWorkflowResult,
|
ParseWorkflowResult,
|
||||||
@@ -11,6 +10,7 @@ import {
|
|||||||
} from "@github/actions-workflow-parser";
|
} from "@github/actions-workflow-parser";
|
||||||
import {ErrorPolicy} from "@github/actions-workflow-parser/model/convert";
|
import {ErrorPolicy} from "@github/actions-workflow-parser/model/convert";
|
||||||
import {splitAllowedContext} from "@github/actions-workflow-parser/templates/allowed-context";
|
import {splitAllowedContext} from "@github/actions-workflow-parser/templates/allowed-context";
|
||||||
|
import {Definition} from "@github/actions-workflow-parser/templates/schema/definition";
|
||||||
import {BasicExpressionToken} from "@github/actions-workflow-parser/templates/tokens/basic-expression-token";
|
import {BasicExpressionToken} from "@github/actions-workflow-parser/templates/tokens/basic-expression-token";
|
||||||
import {StringToken} from "@github/actions-workflow-parser/templates/tokens/string-token";
|
import {StringToken} from "@github/actions-workflow-parser/templates/tokens/string-token";
|
||||||
import {TemplateToken} from "@github/actions-workflow-parser/templates/tokens/template-token";
|
import {TemplateToken} from "@github/actions-workflow-parser/templates/tokens/template-token";
|
||||||
@@ -114,12 +114,18 @@ async function additionalValidations(
|
|||||||
valueProviderConfig: ValueProviderConfig | undefined,
|
valueProviderConfig: ValueProviderConfig | undefined,
|
||||||
contextProviderConfig: ContextProviderConfig | undefined
|
contextProviderConfig: ContextProviderConfig | undefined
|
||||||
) {
|
) {
|
||||||
for (const token of TemplateToken.traverse(root)) {
|
for (const [parent, token, key] of TemplateToken.traverse(root)) {
|
||||||
|
// If the token is a value in a pair, use the key definition for validation
|
||||||
|
// If the token has a parent (map, sequence, etc), use this definition for validation
|
||||||
|
const validationToken = key || parent || token;
|
||||||
|
const validationDefinition = validationToken.definition;
|
||||||
|
|
||||||
// If this is an expression, validate it
|
// If this is an expression, validate it
|
||||||
if (isBasicExpression(token)) {
|
if (isBasicExpression(token)) {
|
||||||
await validateExpression(
|
await validateExpression(
|
||||||
diagnostics,
|
diagnostics,
|
||||||
token,
|
token,
|
||||||
|
validationDefinition,
|
||||||
contextProviderConfig,
|
contextProviderConfig,
|
||||||
getProviderContext(documentUri, template, root, token)
|
getProviderContext(documentUri, template, root, token)
|
||||||
);
|
);
|
||||||
@@ -127,8 +133,8 @@ async function additionalValidations(
|
|||||||
|
|
||||||
// Allowed values coming from the schema have already been validated. Only check if
|
// Allowed values coming from the schema have already been validated. Only check if
|
||||||
// a value provider is defined for a token and if it is, validate the values match.
|
// a value provider is defined for a token and if it is, validate the values match.
|
||||||
if (valueProviderConfig && token.range && token.definition?.key) {
|
if (valueProviderConfig && token.range && validationDefinition) {
|
||||||
const defKey = token.definition.key;
|
const defKey = validationDefinition.key;
|
||||||
|
|
||||||
// Try a custom value provider first
|
// Try a custom value provider first
|
||||||
let valueProvider = valueProviderConfig[defKey];
|
let valueProvider = valueProviderConfig[defKey];
|
||||||
@@ -141,18 +147,6 @@ async function additionalValidations(
|
|||||||
const customValues = await valueProvider.get(getProviderContext(documentUri, template, root, token));
|
const customValues = await valueProvider.get(getProviderContext(documentUri, template, root, token));
|
||||||
const customValuesMap = new Set(customValues.map(x => x.label));
|
const customValuesMap = new Set(customValues.map(x => x.label));
|
||||||
|
|
||||||
if (isSequence(token)) {
|
|
||||||
for (let i = 0; i < token.count; ++i) {
|
|
||||||
const entry = token.get(i);
|
|
||||||
|
|
||||||
if (isString(entry)) {
|
|
||||||
if (!customValuesMap.has(entry.value)) {
|
|
||||||
invalidValue(diagnostics, entry, valueProvider.kind);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isString(token)) {
|
if (isString(token)) {
|
||||||
if (!customValuesMap.has(token.value)) {
|
if (!customValuesMap.has(token.value)) {
|
||||||
invalidValue(diagnostics, token, valueProvider.kind);
|
invalidValue(diagnostics, token, valueProvider.kind);
|
||||||
@@ -202,12 +196,13 @@ function getProviderContext(
|
|||||||
async function validateExpression(
|
async function validateExpression(
|
||||||
diagnostics: Diagnostic[],
|
diagnostics: Diagnostic[],
|
||||||
token: BasicExpressionToken,
|
token: BasicExpressionToken,
|
||||||
|
definition: Definition | undefined,
|
||||||
contextProviderConfig: ContextProviderConfig | undefined,
|
contextProviderConfig: ContextProviderConfig | undefined,
|
||||||
workflowContext: WorkflowContext
|
workflowContext: WorkflowContext
|
||||||
) {
|
) {
|
||||||
// Validate the expression
|
// Validate the expression
|
||||||
for (const expression of token.originalExpressions || [token]) {
|
for (const expression of token.originalExpressions || [token]) {
|
||||||
const allowedContexts = token.definition?.readerContext || [];
|
const allowedContexts = definition?.readerContext || [];
|
||||||
const {namedContexts, functions} = splitAllowedContext(allowedContexts);
|
const {namedContexts, functions} = splitAllowedContext(allowedContexts);
|
||||||
|
|
||||||
let expr: Expr | undefined;
|
let expr: Expr | undefined;
|
||||||
|
|||||||
Reference in New Issue
Block a user