Skip to content
This repository has been archived by the owner on Jun 15, 2021. It is now read-only.

Commit

Permalink
feat: report errors on unknown event types (#45)
Browse files Browse the repository at this point in the history
Fixes #4
  • Loading branch information
OmarTawfik committed Mar 12, 2019
1 parent 5572f59 commit 7b3720b
Show file tree
Hide file tree
Showing 15 changed files with 259 additions and 225 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@
"vscode": "1.1.30"
},
"dependencies": {
"@octokit/webhooks-definitions": "1.1.2",
"chalk": "2.4.2",
"vscode-languageclient": "3.3.0",
"vscode-languageserver": "3.3.0"
Expand Down
4 changes: 0 additions & 4 deletions src/analysis/blocks-analyzer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,6 @@ class BlocksAnalyzer extends BoundNodeVisitor {
this.bag.tooManyActions(node.syntax.name.range);
this.actionsExceededMaximum = true;
}

super.visitAction(node);
}

protected visitWorkflow(node: BoundWorkflow): void {
Expand All @@ -60,7 +58,5 @@ class BlocksAnalyzer extends BoundNodeVisitor {
} else {
this.allWorkflows.add(node.name);
}

super.visitWorkflow(node);
}
}
71 changes: 71 additions & 0 deletions src/analysis/properties-analyzer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
/*!
* Copyright 2019 Omar Tawfik. Please see LICENSE file at the root of this repository.
*/

import { BoundNodeVisitor } from "../binding/bound-node-visitor";
import { DiagnosticBag } from "../util/diagnostics";
import { BoundDocument, BoundResolves, BoundSecrets, BoundOn, BoundEnv } from "../binding/bound-nodes";
import { MAXIMUM_SUPPORTED_SECRETS } from "../util/constants";
import * as webhooks from "@octokit/webhooks-definitions";

export function analyzeProperties(document: BoundDocument, actions: ReadonlySet<string>, bag: DiagnosticBag): void {
new PropertiesAnalyzer(document, actions, bag);
}

class PropertiesAnalyzer extends BoundNodeVisitor {
private exceededMaximum = false;
private allSecrets = new Set<string>();

public constructor(
document: BoundDocument,
private readonly actions: ReadonlySet<string>,
private readonly bag: DiagnosticBag,
) {
super();
this.visit(document);
}

protected visitResolves(node: BoundResolves): void {
for (const action of node.actions) {
if (!this.actions.has(action.value)) {
this.bag.actionDoesNotExist(action.value, action.syntax.range);
}
}
}

protected visitSecrets(node: BoundSecrets): void {
const localSecrets = new Set<string>();
for (const secret of node.secrets) {
if (localSecrets.has(secret.value)) {
this.bag.duplicateSecrets(secret.value, secret.syntax.range);
} else {
localSecrets.add(secret.value);
}
}

if (!this.exceededMaximum) {
for (const secret of node.secrets) {
this.allSecrets.add(secret.value);
if (this.allSecrets.size > MAXIMUM_SUPPORTED_SECRETS) {
this.bag.tooManySecrets(secret.syntax.range);
this.exceededMaximum = true;
break;
}
}
}
}

protected visitOn(node: BoundOn): void {
if (node.event && !webhooks.some(definition => definition.name === node.event!.value)) {
this.bag.unrecognizedEvent(node.event.value, node.event.syntax.range);
}
}

protected visitEnv(node: BoundEnv): void {
for (const variable of node.variables) {
if (variable.name.startsWith("GITHUB_")) {
this.bag.reservedEnvironmentVariable(variable.syntax.name.range);
}
}
}
}
32 changes: 0 additions & 32 deletions src/analysis/resolves-analyzer.ts

This file was deleted.

46 changes: 0 additions & 46 deletions src/analysis/secrets-analyzer.ts

This file was deleted.

21 changes: 8 additions & 13 deletions src/binding/binder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -166,11 +166,6 @@ export function bindDocument(root: DocumentSyntax, bag: DiagnosticBag): BoundDoc
bag.propertyAlreadyDefined(property.key);
} else {
env = new BoundEnv(bindObject(property), property);
for (const variable of env.variables) {
if (variable.name.startsWith("GITHUB_")) {
bag.reservedEnvironmentVariable(variable.syntax.name.range);
}
}
}
break;
}
Expand Down Expand Up @@ -203,7 +198,7 @@ export function bindDocument(root: DocumentSyntax, bag: DiagnosticBag): BoundDoc
switch (syntax.kind) {
case SyntaxKind.StringProperty: {
const property = syntax as StringPropertySyntax;
if (property.value) {
if (property.value && property.value.kind !== TokenKind.Missing) {
const value = removeDoubleQuotes(property.value.text);
return new BoundStringValue(value, property.value);
}
Expand Down Expand Up @@ -231,16 +226,16 @@ export function bindDocument(root: DocumentSyntax, bag: DiagnosticBag): BoundDoc
switch (syntax.kind) {
case SyntaxKind.StringProperty: {
const property = syntax as StringPropertySyntax;
if (property.value) {
if (property.value && property.value.kind !== TokenKind.Missing) {
const value = removeDoubleQuotes(property.value.text);
return [new BoundStringValue(value, property.value)];
}
return [];
}
case SyntaxKind.ArrayProperty: {
return (syntax as ArrayPropertySyntax).items.map(
item => new BoundStringValue(removeDoubleQuotes(item.value.text), item.value),
);
return (syntax as ArrayPropertySyntax).items
.filter(item => item.value.kind !== TokenKind.Missing)
.map(item => new BoundStringValue(removeDoubleQuotes(item.value.text), item.value));
}
case SyntaxKind.ObjectProperty: {
bag.valueIsNotStringOrArray(syntax.key.range);
Expand All @@ -267,9 +262,9 @@ export function bindDocument(root: DocumentSyntax, bag: DiagnosticBag): BoundDoc
return [];
}
case SyntaxKind.ObjectProperty: {
return (syntax as ObjectPropertySyntax).members.map(
member => new BoundObjectMember(member.name.text, removeDoubleQuotes(member.value.text), member),
);
return (syntax as ObjectPropertySyntax).members
.filter(member => member.name.kind !== TokenKind.Missing && member.value.kind !== TokenKind.Missing)
.map(member => new BoundObjectMember(member.name.text, removeDoubleQuotes(member.value.text), member));
}
default: {
throw new Error(`Unexpected Syntax kind '${syntax.kind}'`);
Expand Down
6 changes: 2 additions & 4 deletions src/util/compilation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,8 @@ import { DocumentSyntax } from "../parsing/syntax-nodes";
import { parseTokens } from "../parsing/parser";
import { BoundDocument } from "../binding/bound-nodes";
import { bindDocument } from "../binding/binder";
import { analyzeSecrets } from "../analysis/secrets-analyzer";
import { analyzeBlocks } from "../analysis/blocks-analyzer";
import { analyzeResolves } from "../analysis/resolves-analyzer";
import { analyzeProperties } from "../analysis/properties-analyzer";

export class Compilation {
private readonly bag: DiagnosticBag;
Expand All @@ -27,8 +26,7 @@ export class Compilation {
this.document = bindDocument(this.syntax, this.bag);

const { actions } = analyzeBlocks(this.document, this.bag);
analyzeResolves(this.document, actions, this.bag);
analyzeSecrets(this.document, this.bag);
analyzeProperties(this.document, actions, this.bag);
}

public get diagnostics(): ReadonlyArray<Diagnostic> {
Expand Down
9 changes: 9 additions & 0 deletions src/util/diagnostics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ export enum DiagnosticCode {
TooManyActions,
DuplicateBlock,
ActionDoesNotExist,
UnrecognizedEvent,
}

export interface Diagnostic {
Expand Down Expand Up @@ -224,4 +225,12 @@ export class DiagnosticBag {
message: `The action '${action}' does not exist in the same workflow file.`,
});
}

public unrecognizedEvent(event: string, range: TextRange): void {
this.items.push({
range,
code: DiagnosticCode.UnrecognizedEvent,
message: `The event '${event}' is not a known event type.`,
});
}
}
22 changes: 0 additions & 22 deletions test/binding-errors.spec.ts → test/binding.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -223,28 +223,6 @@ ERROR: Value must be an object.
5 | }
6 |
"
`);
});

it("reports errors on reserved environment variables", () => {
expectDiagnostics(`
action "x" {
uses = "./ci"
env = {
GITHUB_ACTION = "1"
GITHUBNOUNDERSCORE = "2"
SOMETHING_ELSE = "3"
}
}`).toMatchInlineSnapshot(`
"
ERROR: Environment variables starting with 'GITHUB_' are reserved.
3 | uses = \\"./ci\\"
4 | env = {
5 | GITHUB_ACTION = \\"1\\"
| ^^^^^^^^^^^^^
6 | GITHUBNOUNDERSCORE = \\"2\\"
7 | SOMETHING_ELSE = \\"3\\"
"
`);
});
});
Loading

0 comments on commit 7b3720b

Please sign in to comment.