Skip to content

Commit dfb7b2e

Browse files
authored
Merge pull request #678 from benjamn/literal-type-improvements
Use `makeLiteralExtra` helper function to unify `node.extra` field definitions for literal types
2 parents 414bd1c + dc8adc4 commit dfb7b2e

File tree

6 files changed

+88
-97
lines changed

6 files changed

+88
-97
lines changed

def/babel-core.ts

Lines changed: 52 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,13 @@ import { namedTypes as N } from "../gen/namedTypes";
77
export default function (fork: Fork) {
88
fork.use(esProposalsDef);
99

10-
var types = fork.use(typesPlugin);
11-
var defaults = fork.use(sharedPlugin).defaults;
12-
var def = types.Type.def;
13-
var or = types.Type.or;
10+
const types = fork.use(typesPlugin);
11+
const defaults = fork.use(sharedPlugin).defaults;
12+
const def = types.Type.def;
13+
const or = types.Type.or;
14+
const {
15+
undefined: isUndefined,
16+
} = types.builtInTypes;
1417

1518
def("Noop")
1619
.bases("Statement")
@@ -78,58 +81,60 @@ export default function (fork: Fork) {
7881
.field("directives", [def("Directive")], defaults.emptyArray)
7982
.field("interpreter", or(def("InterpreterDirective"), null), defaults["null"]);
8083

84+
function makeLiteralExtra<
85+
// Allowing N.RegExpLiteral explicitly here is important because the
86+
// node.value field of RegExpLiteral nodes can be undefined, which is not
87+
// allowed for other Literal subtypes.
88+
TNode extends Omit<N.Literal, "type"> | N.RegExpLiteral
89+
>(
90+
rawValueType: any = String,
91+
toRaw?: (value: any) => string,
92+
): Parameters<import("../lib/types").Def["field"]> {
93+
return [
94+
"extra",
95+
{
96+
rawValue: rawValueType,
97+
raw: String,
98+
},
99+
function getDefault(this: TNode) {
100+
const value = types.getFieldValue(this, "value");
101+
return {
102+
rawValue: value,
103+
raw: toRaw ? toRaw(value) : String(value),
104+
};
105+
},
106+
];
107+
}
108+
81109
// Split Literal
82110
def("StringLiteral")
83111
.bases("Literal")
84112
.build("value")
85-
.field("value", String);
113+
.field("value", String)
114+
.field(...makeLiteralExtra<N.StringLiteral>(String, val => JSON.stringify(val)));
86115

87116
def("NumericLiteral")
88117
.bases("Literal")
89118
.build("value")
90119
.field("value", Number)
91120
.field("raw", or(String, null), defaults["null"])
92-
.field("extra", {
93-
rawValue: Number,
94-
raw: String
95-
}, function getDefault(this: N.NumericLiteral) {
96-
return {
97-
rawValue: this.value,
98-
raw: this.value + ""
99-
}
100-
});
121+
.field(...makeLiteralExtra<N.NumericLiteral>(Number));
101122

102123
def("BigIntLiteral")
103124
.bases("Literal")
104125
.build("value")
105126
// Only String really seems appropriate here, since BigInt values
106127
// often exceed the limits of JS numbers.
107128
.field("value", or(String, Number))
108-
.field("extra", {
109-
rawValue: String,
110-
raw: String
111-
}, function getDefault(this: N.BigIntLiteral) {
112-
return {
113-
rawValue: String(this.value),
114-
raw: this.value + "n",
115-
};
116-
});
129+
.field(...makeLiteralExtra<N.BigIntLiteral>(String, val => val + "n"));
117130

118131
// https://github.com/tc39/proposal-decimal
119132
// https://github.com/babel/babel/pull/11640
120133
def("DecimalLiteral")
121134
.bases("Literal")
122135
.build("value")
123136
.field("value", String)
124-
.field("extra", {
125-
rawValue: String,
126-
raw: String
127-
}, function getDefault(this: N.DecimalLiteral) {
128-
return {
129-
rawValue: String(this.value),
130-
raw: this.value + "m",
131-
};
132-
});
137+
.field(...makeLiteralExtra<N.DecimalLiteral>(String, val => val + "m"));
133138

134139
def("NullLiteral")
135140
.bases("Literal")
@@ -148,6 +153,21 @@ export default function (fork: Fork) {
148153
.field("flags", String)
149154
.field("value", RegExp, function (this: N.RegExpLiteral) {
150155
return new RegExp(this.pattern, this.flags);
156+
})
157+
.field(...makeLiteralExtra<N.RegExpLiteral>(
158+
or(RegExp, isUndefined),
159+
exp => `/${exp.pattern}/${exp.flags || ""}`,
160+
))
161+
// I'm not sure why this field exists, but it's "specified" by estree:
162+
// https://github.com/estree/estree/blob/master/es5.md#regexpliteral
163+
.field("regex", {
164+
pattern: String,
165+
flags: String
166+
}, function (this: N.RegExpLiteral) {
167+
return {
168+
pattern: this.pattern,
169+
flags: this.flags,
170+
};
151171
});
152172

153173
var ObjectExpressionProperty = or(

def/core.ts

Lines changed: 1 addition & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -335,26 +335,7 @@ export default function (fork: Fork) {
335335
def("Literal")
336336
.bases("Expression")
337337
.build("value")
338-
.field("value", or(String, Boolean, null, Number, RegExp))
339-
.field("regex", or({
340-
pattern: String,
341-
flags: String
342-
}, null), function (this: N.Literal) {
343-
if (this.value instanceof RegExp) {
344-
var flags = "";
345-
346-
if (this.value.ignoreCase) flags += "i";
347-
if (this.value.multiline) flags += "m";
348-
if (this.value.global) flags += "g";
349-
350-
return {
351-
pattern: this.value.source,
352-
flags: flags
353-
};
354-
}
355-
356-
return null;
357-
});
338+
.field("value", or(String, Boolean, null, Number, RegExp, BigInt));
358339

359340
// Abstract (non-buildable) comment supertype. Not a Node.
360341
def("Comment")

gen/builders.ts

Lines changed: 11 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -432,16 +432,12 @@ export interface PropertyBuilder {
432432
}
433433

434434
export interface LiteralBuilder {
435-
(value: string | boolean | null | number | RegExp): namedTypes.Literal;
435+
(value: string | boolean | null | number | RegExp | BigInt): namedTypes.Literal;
436436
from(
437437
params: {
438438
comments?: K.CommentKind[] | null,
439439
loc?: K.SourceLocationKind | null,
440-
regex?: {
441-
pattern: string,
442-
flags: string
443-
} | null,
444-
value: string | boolean | null | number | RegExp
440+
value: string | boolean | null | number | RegExp | BigInt
445441
}
446442
): namedTypes.Literal;
447443
}
@@ -1484,10 +1480,6 @@ export interface JSXTextBuilder {
14841480
comments?: K.CommentKind[] | null,
14851481
loc?: K.SourceLocationKind | null,
14861482
raw?: string,
1487-
regex?: {
1488-
pattern: string,
1489-
flags: string
1490-
} | null,
14911483
value: string
14921484
}
14931485
): namedTypes.JSXText;
@@ -2659,11 +2651,11 @@ export interface StringLiteralBuilder {
26592651
from(
26602652
params: {
26612653
comments?: K.CommentKind[] | null,
2654+
extra?: {
2655+
rawValue: string,
2656+
raw: string
2657+
},
26622658
loc?: K.SourceLocationKind | null,
2663-
regex?: {
2664-
pattern: string,
2665-
flags: string
2666-
} | null,
26672659
value: string
26682660
}
26692661
): namedTypes.StringLiteral;
@@ -2680,10 +2672,6 @@ export interface NumericLiteralBuilder {
26802672
},
26812673
loc?: K.SourceLocationKind | null,
26822674
raw?: string | null,
2683-
regex?: {
2684-
pattern: string,
2685-
flags: string
2686-
} | null,
26872675
value: number
26882676
}
26892677
): namedTypes.NumericLiteral;
@@ -2699,10 +2687,6 @@ export interface BigIntLiteralBuilder {
26992687
raw: string
27002688
},
27012689
loc?: K.SourceLocationKind | null,
2702-
regex?: {
2703-
pattern: string,
2704-
flags: string
2705-
} | null,
27062690
value: string | number
27072691
}
27082692
): namedTypes.BigIntLiteral;
@@ -2718,10 +2702,6 @@ export interface DecimalLiteralBuilder {
27182702
raw: string
27192703
},
27202704
loc?: K.SourceLocationKind | null,
2721-
regex?: {
2722-
pattern: string,
2723-
flags: string
2724-
} | null,
27252705
value: string
27262706
}
27272707
): namedTypes.DecimalLiteral;
@@ -2733,10 +2713,6 @@ export interface NullLiteralBuilder {
27332713
params: {
27342714
comments?: K.CommentKind[] | null,
27352715
loc?: K.SourceLocationKind | null,
2736-
regex?: {
2737-
pattern: string,
2738-
flags: string
2739-
} | null,
27402716
value?: null
27412717
}
27422718
): namedTypes.NullLiteral;
@@ -2748,10 +2724,6 @@ export interface BooleanLiteralBuilder {
27482724
params: {
27492725
comments?: K.CommentKind[] | null,
27502726
loc?: K.SourceLocationKind | null,
2751-
regex?: {
2752-
pattern: string,
2753-
flags: string
2754-
} | null,
27552727
value: boolean
27562728
}
27572729
): namedTypes.BooleanLiteral;
@@ -2762,13 +2734,17 @@ export interface RegExpLiteralBuilder {
27622734
from(
27632735
params: {
27642736
comments?: K.CommentKind[] | null,
2737+
extra?: {
2738+
rawValue: RegExp | undefined,
2739+
raw: string
2740+
},
27652741
flags: string,
27662742
loc?: K.SourceLocationKind | null,
27672743
pattern: string,
27682744
regex?: {
27692745
pattern: string,
27702746
flags: string
2771-
} | null,
2747+
},
27722748
value?: RegExp
27732749
}
27742750
): namedTypes.RegExpLiteral;

gen/namedTypes.ts

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -233,11 +233,7 @@ export namespace namedTypes {
233233

234234
export interface Literal extends Omit<Expression, "type"> {
235235
type: "Literal";
236-
value: string | boolean | null | number | RegExp;
237-
regex?: {
238-
pattern: string,
239-
flags: string
240-
} | null;
236+
value: string | boolean | null | number | RegExp | BigInt;
241237
}
242238

243239
export interface SequenceExpression extends Omit<Expression, "type"> {
@@ -1222,6 +1218,10 @@ export namespace namedTypes {
12221218
export interface StringLiteral extends Omit<Literal, "type" | "value"> {
12231219
type: "StringLiteral";
12241220
value: string;
1221+
extra?: {
1222+
rawValue: string,
1223+
raw: string
1224+
};
12251225
}
12261226

12271227
export interface NumericLiteral extends Omit<Literal, "type" | "value"> {
@@ -1267,6 +1267,14 @@ export namespace namedTypes {
12671267
pattern: string;
12681268
flags: string;
12691269
value?: RegExp;
1270+
extra?: {
1271+
rawValue: RegExp | undefined,
1272+
raw: string
1273+
};
1274+
regex?: {
1275+
pattern: string,
1276+
flags: string
1277+
};
12701278
}
12711279

12721280
export interface ClassMethod extends Omit<Declaration, "type">, Omit<Function, "type" | "body"> {

lib/types.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -400,6 +400,7 @@ export default function typesPlugin(_fork: Fork) {
400400
boolean: boolean;
401401
null: null;
402402
undefined: undefined;
403+
BigInt: BigInt;
403404
};
404405

405406
function defBuiltInType<K extends keyof BuiltInTypes>(
@@ -434,6 +435,9 @@ export default function typesPlugin(_fork: Fork) {
434435
const isBoolean = defBuiltInType("boolean", true);
435436
const isNull = defBuiltInType("null", null);
436437
const isUndefined = defBuiltInType("undefined", undefined);
438+
const isBigInt = typeof BigInt === "function"
439+
? defBuiltInType("BigInt", BigInt(1234))
440+
: new PredicateType<BigInt>("BigInt", () => false);
437441

438442
const builtInTypes = {
439443
string: isString,
@@ -446,6 +450,7 @@ export default function typesPlugin(_fork: Fork) {
446450
boolean: isBoolean,
447451
null: isNull,
448452
undefined: isUndefined,
453+
BigInt: isBigInt,
449454
};
450455

451456
// In order to return the same Def instance every time Type.def is called

test/ecmascript.ts

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2331,15 +2331,16 @@ describe("RegExpLiteral nodes", function() {
23312331

23322332
it("should typecheck with explicit .regex field", function() {
23332333
var stringLiteral = b.literal("asdf");
2334-
assert.strictEqual(stringLiteral.regex, null);
2334+
assert.strictEqual(hasOwn.call(stringLiteral, "regex"), false);
23352335
n.Literal.assert(stringLiteral, true);
23362336

2337-
var regExpLiteral: any = b.literal(/a.b/gi);
2338-
assert.strictEqual(regExpLiteral.regex.pattern, "a.b");
2339-
assert.strictEqual(regExpLiteral.regex.flags, "ig");
2337+
const regExpLiteral = b.regExpLiteral("a.b", "gi");
2338+
const regex = rawTypes.getFieldValue(regExpLiteral, "regex");
2339+
assert.strictEqual(regex.pattern, "a.b");
2340+
assert.strictEqual(regex.flags, "gi");
23402341
n.Literal.assert(regExpLiteral, true);
23412342

2342-
regExpLiteral.regex.pattern = 1234;
2343+
regex.pattern = 1234;
23432344
assert.strictEqual(n.Literal.check(regExpLiteral, true), false);
23442345
});
23452346
});

0 commit comments

Comments
 (0)