Skip to content

Commit

Permalink
fix: allow enum member without initializer after non-literal member (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
lightmare committed Oct 22, 2021
1 parent c75fa21 commit cfe6739
Show file tree
Hide file tree
Showing 5 changed files with 58 additions and 21 deletions.
40 changes: 22 additions & 18 deletions packages/babel-plugin-transform-typescript/src/enum.ts
Expand Up @@ -98,47 +98,51 @@ function enumFill(path, t, id) {
* Z = X | Y,
* }
*/
type PreviousEnumMembers = {
[name: string]: number | string;
};
type PreviousEnumMembers = Map<string, number | string>;

export function translateEnumValues(
path: NodePath<t.TSEnumDeclaration>,
t: typeof import("@babel/types"),
): Array<[name: string, value: t.Expression]> {
const seen: PreviousEnumMembers = Object.create(null);
const seen: PreviousEnumMembers = new Map();
// Start at -1 so the first enum member is its increment, 0.
let prev: number | typeof undefined = -1;
let constValue: number | string | undefined = -1;
let lastName: string;

return path.node.members.map(member => {
const name = t.isIdentifier(member.id) ? member.id.name : member.id.value;
const initializer = member.initializer;
let value: t.Expression;
if (initializer) {
const constValue = evaluate(initializer, seen);
constValue = evaluate(initializer, seen);
if (constValue !== undefined) {
seen[name] = constValue;
seen.set(name, constValue);
if (typeof constValue === "number") {
value = t.numericLiteral(constValue);
prev = constValue;
} else {
assert(typeof constValue === "string");
value = t.stringLiteral(constValue);
prev = undefined;
}
} else {
value = initializer;
prev = undefined;
}
} else if (typeof constValue === "number") {
constValue += 1;
value = t.numericLiteral(constValue);
seen.set(name, constValue);
} else if (typeof constValue === "string") {
throw path.buildCodeFrameError("Enum member must have initializer.");
} else {
if (prev !== undefined) {
prev++;
value = t.numericLiteral(prev);
seen[name] = prev;
} else {
throw path.buildCodeFrameError("Enum member must have initializer.");
}
// create dynamic initializer: 1 + ENUM["PREVIOUS"]
const lastRef = t.memberExpression(
t.cloneNode(path.node.id),
t.stringLiteral(lastName),
true,
);
value = t.binaryExpression("+", t.numericLiteral(1), lastRef);
}

lastName = name;
return [name, value];
});
}
Expand All @@ -163,7 +167,7 @@ function evaluate(
case "ParenthesizedExpression":
return evalConstant(expr.expression);
case "Identifier":
return seen[expr.name];
return seen.get(expr.name);
case "TemplateLiteral":
if (expr.quasis.length === 1) {
return expr.quasis[0].value.cooked;
Expand Down

This file was deleted.

@@ -0,0 +1,6 @@
var E;

(function (E) {
E[E["a"] = Math.sin(1)] = "a";
E[E["b"] = 1 + E["a"]] = "b";
})(E || (E = {}));
@@ -0,0 +1,13 @@
enum socketType {
SOCKET,
SERVER,
IPC,
}

enum constants {
SOCKET = socketType.SOCKET,
SERVER = socketType.SERVER,
IPC = socketType.IPC,
UV_READABLE,
UV_WRITABLE,
}
@@ -0,0 +1,17 @@
var socketType;

(function (socketType) {
socketType[socketType["SOCKET"] = 0] = "SOCKET";
socketType[socketType["SERVER"] = 1] = "SERVER";
socketType[socketType["IPC"] = 2] = "IPC";
})(socketType || (socketType = {}));

var constants;

(function (constants) {
constants[constants["SOCKET"] = socketType.SOCKET] = "SOCKET";
constants[constants["SERVER"] = socketType.SERVER] = "SERVER";
constants[constants["IPC"] = socketType.IPC] = "IPC";
constants[constants["UV_READABLE"] = 1 + constants["IPC"]] = "UV_READABLE";
constants[constants["UV_WRITABLE"] = 1 + constants["UV_READABLE"]] = "UV_WRITABLE";
})(constants || (constants = {}));

0 comments on commit cfe6739

Please sign in to comment.