Fix validation with moved definition

This commit is contained in:
Beth Brennan
2022-12-01 11:37:50 -05:00
parent 272e29a775
commit cd0c836769
3 changed files with 43 additions and 19 deletions
+2 -2
View File
@@ -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 {File} from "@github/actions-workflow-parser/workflows/file";
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 {token, keyToken, parent} = findToken(position, result.value);
const {token} = findToken(position, result.value);
if (result.value && token) {
return getHover(token);
@@ -158,4 +158,33 @@ jobs:
}
} 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);
});
});
+12 -17
View File
@@ -3,7 +3,6 @@ import {Expr} from "@github/actions-expressions/ast";
import {
convertWorkflowTemplate,
isBasicExpression,
isSequence,
isString,
parseWorkflow,
ParseWorkflowResult,
@@ -11,6 +10,7 @@ import {
} from "@github/actions-workflow-parser";
import {ErrorPolicy} from "@github/actions-workflow-parser/model/convert";
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 {StringToken} from "@github/actions-workflow-parser/templates/tokens/string-token";
import {TemplateToken} from "@github/actions-workflow-parser/templates/tokens/template-token";
@@ -114,12 +114,18 @@ async function additionalValidations(
valueProviderConfig: ValueProviderConfig | 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 (isBasicExpression(token)) {
await validateExpression(
diagnostics,
token,
validationDefinition,
contextProviderConfig,
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
// a value provider is defined for a token and if it is, validate the values match.
if (valueProviderConfig && token.range && token.definition?.key) {
const defKey = token.definition.key;
if (valueProviderConfig && token.range && validationDefinition) {
const defKey = validationDefinition.key;
// Try a custom value provider first
let valueProvider = valueProviderConfig[defKey];
@@ -141,18 +147,6 @@ async function additionalValidations(
const customValues = await valueProvider.get(getProviderContext(documentUri, template, root, token));
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 (!customValuesMap.has(token.value)) {
invalidValue(diagnostics, token, valueProvider.kind);
@@ -202,12 +196,13 @@ function getProviderContext(
async function validateExpression(
diagnostics: Diagnostic[],
token: BasicExpressionToken,
definition: Definition | undefined,
contextProviderConfig: ContextProviderConfig | undefined,
workflowContext: WorkflowContext
) {
// Validate the expression
for (const expression of token.originalExpressions || [token]) {
const allowedContexts = token.definition?.readerContext || [];
const allowedContexts = definition?.readerContext || [];
const {namedContexts, functions} = splitAllowedContext(allowedContexts);
let expr: Expr | undefined;