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

Commit 1e82159

Browse files
committed
chore: bound values carry closer syntax (#36)
1 parent 73ba6aa commit 1e82159

File tree

10 files changed

+298
-222
lines changed

10 files changed

+298
-222
lines changed

src/binding/binder.ts

Lines changed: 67 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,10 @@ import {
88
VersionSyntax,
99
BlockSyntax,
1010
SyntaxKind,
11-
BaseValueSyntax,
12-
StringValueSyntax,
13-
StringArrayValueSyntax,
14-
ObjectValueSyntax,
11+
BasePropertySyntax,
12+
StringPropertySyntax,
13+
ArrayPropertySyntax,
14+
ObjectPropertySyntax,
1515
} from "../parsing/syntax-nodes";
1616
import {
1717
BoundDocument,
@@ -26,6 +26,8 @@ import {
2626
BoundEnv,
2727
BoundSecrets,
2828
BoundUses,
29+
BoundStringValue,
30+
BoundObjectMember,
2931
} from "./bound-nodes";
3032
import { TokenKind } from "../scanning/tokens";
3133
import { MAXIMUM_SUPPORTED_VERSION } from "../util/constants";
@@ -92,15 +94,15 @@ export function bindDocument(root: DocumentSyntax, bag: DiagnosticBag): BoundDoc
9294
if (on) {
9395
bag.propertyAlreadyDefined(property.key);
9496
} else {
95-
on = new BoundOn(bindString(property.value), property);
97+
on = new BoundOn(bindString(property), property);
9698
}
9799
break;
98100
}
99101
case TokenKind.ResolvesKeyword: {
100102
if (resolves) {
101103
bag.propertyAlreadyDefined(property.key);
102104
} else {
103-
resolves = new BoundResolves(bindStringOrArray(property.value), property);
105+
resolves = new BoundResolves(bindStringOrArray(property), property);
104106
}
105107
break;
106108
}
@@ -131,42 +133,42 @@ export function bindDocument(root: DocumentSyntax, bag: DiagnosticBag): BoundDoc
131133
if (uses) {
132134
bag.propertyAlreadyDefined(property.key);
133135
} else {
134-
uses = new BoundUses(bindString(property.value), property);
136+
uses = new BoundUses(bindString(property), property);
135137
}
136138
break;
137139
}
138140
case TokenKind.NeedsKeyword: {
139141
if (needs) {
140142
bag.propertyAlreadyDefined(property.key);
141143
} else {
142-
needs = new BoundNeeds(bindStringOrArray(property.value), property);
144+
needs = new BoundNeeds(bindStringOrArray(property), property);
143145
}
144146
break;
145147
}
146148
case TokenKind.RunsKeyword: {
147149
if (runs) {
148150
bag.propertyAlreadyDefined(property.key);
149151
} else {
150-
runs = new BoundRuns(bindStringOrArray(property.value), property);
152+
runs = new BoundRuns(bindStringOrArray(property), property);
151153
}
152154
break;
153155
}
154156
case TokenKind.ArgsKeyword: {
155157
if (args) {
156158
bag.propertyAlreadyDefined(property.key);
157159
} else {
158-
args = new BoundArgs(bindStringOrArray(property.value), property);
160+
args = new BoundArgs(bindStringOrArray(property), property);
159161
}
160162
break;
161163
}
162164
case TokenKind.EnvKeyword: {
163165
if (env) {
164166
bag.propertyAlreadyDefined(property.key);
165167
} else {
166-
env = new BoundEnv(bindObject(property.value), property);
167-
for (const variable of env.variables.keys()) {
168-
if (variable.startsWith("GITHUB_")) {
169-
bag.reservedEnvironmentVariable(property.key.range);
168+
env = new BoundEnv(bindObject(property), property);
169+
for (const variable of env.variables) {
170+
if (variable.name.startsWith("GITHUB_")) {
171+
bag.reservedEnvironmentVariable(variable.syntax.name.range);
170172
}
171173
}
172174
}
@@ -176,7 +178,7 @@ export function bindDocument(root: DocumentSyntax, bag: DiagnosticBag): BoundDoc
176178
if (secrets) {
177179
bag.propertyAlreadyDefined(property.key);
178180
} else {
179-
secrets = new BoundSecrets(bindStringOrArray(property.value), property);
181+
secrets = new BoundSecrets(bindStringOrArray(property), property);
180182
}
181183
break;
182184
}
@@ -193,43 +195,55 @@ export function bindDocument(root: DocumentSyntax, bag: DiagnosticBag): BoundDoc
193195
actions.push(new BoundAction(removeDoubleQuotes(syntax.name.text), uses, needs, runs, args, env, secrets, syntax));
194196
}
195197

196-
function bindString(syntax: BaseValueSyntax | undefined): string {
198+
function bindString(syntax: BasePropertySyntax | undefined): BoundStringValue | undefined {
197199
if (!syntax) {
198-
return "";
200+
return undefined;
199201
}
200202

201203
switch (syntax.kind) {
202-
case SyntaxKind.StringValue: {
203-
return removeDoubleQuotes((syntax as StringValueSyntax).value.text);
204+
case SyntaxKind.StringProperty: {
205+
const property = syntax as StringPropertySyntax;
206+
if (property.value) {
207+
const value = removeDoubleQuotes(property.value.text);
208+
return new BoundStringValue(value, property.value);
209+
}
210+
return undefined;
204211
}
205-
case SyntaxKind.StringArrayValue: {
206-
bag.valueIsNotString((syntax as StringArrayValueSyntax).openBracket.range);
207-
return "";
212+
case SyntaxKind.ArrayProperty: {
213+
bag.valueIsNotString(syntax.key.range);
214+
return undefined;
208215
}
209-
case SyntaxKind.ObjectValue: {
210-
bag.valueIsNotString((syntax as ObjectValueSyntax).openBracket.range);
211-
return "";
216+
case SyntaxKind.ObjectProperty: {
217+
bag.valueIsNotString(syntax.key.range);
218+
return undefined;
212219
}
213220
default: {
214221
throw new Error(`Unexpected Syntax kind '${syntax.kind}'`);
215222
}
216223
}
217224
}
218225

219-
function bindStringOrArray(syntax: BaseValueSyntax | undefined): ReadonlyArray<string> {
226+
function bindStringOrArray(syntax: BasePropertySyntax | undefined): ReadonlyArray<BoundStringValue> {
220227
if (!syntax) {
221228
return [];
222229
}
223230

224231
switch (syntax.kind) {
225-
case SyntaxKind.StringValue: {
226-
return [removeDoubleQuotes((syntax as StringValueSyntax).value.text)];
232+
case SyntaxKind.StringProperty: {
233+
const property = syntax as StringPropertySyntax;
234+
if (property.value) {
235+
const value = removeDoubleQuotes(property.value.text);
236+
return [new BoundStringValue(value, property.value)];
237+
}
238+
return [];
227239
}
228-
case SyntaxKind.StringArrayValue: {
229-
return (syntax as StringArrayValueSyntax).values.map(v => removeDoubleQuotes(v.value.text));
240+
case SyntaxKind.ArrayProperty: {
241+
return (syntax as ArrayPropertySyntax).items.map(
242+
item => new BoundStringValue(removeDoubleQuotes(item.value.text), item.value),
243+
);
230244
}
231-
case SyntaxKind.ObjectValue: {
232-
bag.valueIsNotStringOrArray((syntax as ObjectValueSyntax).openBracket.range);
245+
case SyntaxKind.ObjectProperty: {
246+
bag.valueIsNotStringOrArray(syntax.key.range);
233247
return [];
234248
}
235249
default: {
@@ -238,37 +252,29 @@ export function bindDocument(root: DocumentSyntax, bag: DiagnosticBag): BoundDoc
238252
}
239253
}
240254

241-
function bindObject(syntax: BaseValueSyntax | undefined): ReadonlyMap<string, string> {
242-
const map = new Map<string, string>();
243-
if (syntax) {
244-
switch (syntax.kind) {
245-
case SyntaxKind.StringValue: {
246-
bag.valueIsNotAnObject((syntax as StringValueSyntax).value.range);
247-
break;
248-
}
249-
case SyntaxKind.StringArrayValue: {
250-
bag.valueIsNotAnObject((syntax as StringArrayValueSyntax).openBracket.range);
251-
break;
252-
}
253-
case SyntaxKind.ObjectValue: {
254-
(syntax as ObjectValueSyntax).members.forEach(variable => {
255-
const key = variable.name.text;
256-
if (map.has(key)) {
257-
bag.duplicateKey(key, variable.name.range);
258-
} else {
259-
const value = removeDoubleQuotes(variable.value.text);
260-
map.set(key, value);
261-
}
262-
});
263-
break;
264-
}
265-
default: {
266-
throw new Error(`Unexpected Syntax kind '${syntax.kind}'`);
267-
}
268-
}
255+
function bindObject(syntax: BasePropertySyntax | undefined): ReadonlyArray<BoundObjectMember> {
256+
if (!syntax) {
257+
return [];
269258
}
270259

271-
return map;
260+
switch (syntax.kind) {
261+
case SyntaxKind.StringProperty: {
262+
bag.valueIsNotAnObject(syntax.key.range);
263+
return [];
264+
}
265+
case SyntaxKind.ArrayProperty: {
266+
bag.valueIsNotAnObject(syntax.key.range);
267+
return [];
268+
}
269+
case SyntaxKind.ObjectProperty: {
270+
return (syntax as ObjectPropertySyntax).members.map(
271+
member => new BoundObjectMember(member.name.text, removeDoubleQuotes(member.value.text), member),
272+
);
273+
}
274+
default: {
275+
throw new Error(`Unexpected Syntax kind '${syntax.kind}'`);
276+
}
277+
}
272278
}
273279

274280
function removeDoubleQuotes(value: string): string {

src/binding/bound-node-visitor.ts

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,12 @@ import {
1717
BoundArgs,
1818
BoundEnv,
1919
BoundSecrets,
20+
BoundStringValue,
21+
BoundObjectMember,
2022
} from "./bound-nodes";
21-
import { BaseSyntaxNode } from "../parsing/syntax-nodes";
2223

2324
export abstract class BoundNodeVisitor {
24-
protected visit(node: BaseBoundNode<BaseSyntaxNode>): void {
25+
protected visit(node: BaseBoundNode): void {
2526
switch (node.kind) {
2627
case BoundKind.Document: {
2728
return this.visitDocument(node as BoundDocument);
@@ -59,6 +60,12 @@ export abstract class BoundNodeVisitor {
5960
case BoundKind.Secrets: {
6061
return this.visitSecrets(node as BoundSecrets);
6162
}
63+
case BoundKind.StringValue: {
64+
return this.visitStringValue(node as BoundStringValue);
65+
}
66+
case BoundKind.ObjectMember: {
67+
return this.visitObjectMember(node as BoundObjectMember);
68+
}
6269
default: {
6370
throw new Error(`Unexpected bound kind: '${node.kind}'`);
6471
}
@@ -113,7 +120,15 @@ export abstract class BoundNodeVisitor {
113120
return this.visitDefault(node);
114121
}
115122

116-
private visitDefault(node: BaseBoundNode<BaseSyntaxNode>): void {
123+
protected visitStringValue(node: BoundStringValue): void {
124+
return this.visitDefault(node);
125+
}
126+
127+
protected visitObjectMember(node: BoundObjectMember): void {
128+
return this.visitDefault(node);
129+
}
130+
131+
private visitDefault(node: BaseBoundNode): void {
117132
node.children.forEach(child => {
118133
this.visit(child);
119134
});

0 commit comments

Comments
 (0)