add 12 missing NODE_FIELDS (#13577)
* test: add fields test * fix(babel-types): add missing NODE_FIELDS and tests fix #13558 fix #13563 * chore: avoid using fs-extra * chore: code cleanup * chore: avoid util.promisify * fix: remove bad ts-expect-error suppressions
This commit is contained in:
parent
844baebd26
commit
1d48bb0d8c
@ -548,12 +548,10 @@ export function OpaqueType(
|
||||
this.print(node.supertype, node);
|
||||
}
|
||||
|
||||
// @ts-expect-error todo(flow->ts) `.impltype` does not exist on t.DeclareOpaqueType
|
||||
if (node.impltype) {
|
||||
this.space();
|
||||
this.token("=");
|
||||
this.space();
|
||||
// @ts-expect-error todo(flow->ts) `.impltype` does not exist on t.DeclareOpaqueType
|
||||
this.print(node.impltype, node);
|
||||
}
|
||||
this.semicolon();
|
||||
|
||||
@ -116,7 +116,6 @@ export const Flow = {
|
||||
} else if (t.isImportDeclaration(node)) {
|
||||
return node.importKind === "type" || node.importKind === "typeof";
|
||||
} else if (t.isExportDeclaration(node)) {
|
||||
// @ts-expect-error todo(flow->ts) `exportKind` does not exist on ExportAllDeclaration
|
||||
return node.exportKind === "type";
|
||||
} else if (t.isImportSpecifier(node)) {
|
||||
return node.importKind === "type" || node.importKind === "typeof";
|
||||
|
||||
@ -30,7 +30,8 @@
|
||||
"devDependencies": {
|
||||
"@babel/generator": "workspace:*",
|
||||
"@babel/parser": "workspace:*",
|
||||
"chalk": "^4.1.0"
|
||||
"chalk": "^4.1.0",
|
||||
"glob": "^7.1.7"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.9.0"
|
||||
|
||||
@ -643,6 +643,7 @@ export interface RestElement extends BaseNode {
|
||||
type: "RestElement";
|
||||
argument: LVal;
|
||||
decorators?: Array<Decorator> | null;
|
||||
optional?: boolean | null;
|
||||
typeAnnotation?: TypeAnnotation | TSTypeAnnotation | Noop | null;
|
||||
}
|
||||
|
||||
@ -653,6 +654,7 @@ export interface RestProperty extends BaseNode {
|
||||
type: "RestProperty";
|
||||
argument: LVal;
|
||||
decorators?: Array<Decorator> | null;
|
||||
optional?: boolean | null;
|
||||
typeAnnotation?: TypeAnnotation | TSTypeAnnotation | Noop | null;
|
||||
}
|
||||
|
||||
@ -751,6 +753,7 @@ export interface ArrayPattern extends BaseNode {
|
||||
type: "ArrayPattern";
|
||||
elements: Array<null | PatternLike>;
|
||||
decorators?: Array<Decorator> | null;
|
||||
optional?: boolean | null;
|
||||
typeAnnotation?: TypeAnnotation | TSTypeAnnotation | Noop | null;
|
||||
}
|
||||
|
||||
@ -835,6 +838,7 @@ export interface ExportDefaultDeclaration extends BaseNode {
|
||||
| TSDeclareFunction
|
||||
| ClassDeclaration
|
||||
| Expression;
|
||||
exportKind?: "value" | null;
|
||||
}
|
||||
|
||||
export interface ExportNamedDeclaration extends BaseNode {
|
||||
@ -1024,6 +1028,7 @@ export interface ClassProperty extends BaseNode {
|
||||
optional?: boolean | null;
|
||||
override?: boolean;
|
||||
readonly?: boolean | null;
|
||||
variance?: Variance | null;
|
||||
}
|
||||
|
||||
export interface ClassPrivateProperty extends BaseNode {
|
||||
@ -1032,7 +1037,10 @@ export interface ClassPrivateProperty extends BaseNode {
|
||||
value?: Expression | null;
|
||||
decorators?: Array<Decorator> | null;
|
||||
static: any;
|
||||
definite?: boolean | null;
|
||||
readonly?: boolean | null;
|
||||
typeAnnotation?: TypeAnnotation | TSTypeAnnotation | Noop | null;
|
||||
variance?: Variance | null;
|
||||
}
|
||||
|
||||
export interface ClassPrivateMethod extends BaseNode {
|
||||
@ -1142,6 +1150,7 @@ export interface DeclareOpaqueType extends BaseNode {
|
||||
id: Identifier;
|
||||
typeParameters?: TypeParameterDeclaration | null;
|
||||
supertype?: FlowType | null;
|
||||
impltype?: FlowType | null;
|
||||
}
|
||||
|
||||
export interface DeclareVariable extends BaseNode {
|
||||
@ -1651,6 +1660,8 @@ export interface TSParameterProperty extends BaseNode {
|
||||
type: "TSParameterProperty";
|
||||
parameter: Identifier | AssignmentPattern;
|
||||
accessibility?: "public" | "private" | "protected" | null;
|
||||
decorators?: Array<Decorator> | null;
|
||||
override?: boolean | null;
|
||||
readonly?: boolean | null;
|
||||
}
|
||||
|
||||
@ -1710,6 +1721,7 @@ export interface TSPropertySignature extends BaseNode {
|
||||
typeAnnotation?: TSTypeAnnotation | null;
|
||||
initializer?: Expression | null;
|
||||
computed?: boolean | null;
|
||||
kind: "get" | "set";
|
||||
optional?: boolean | null;
|
||||
readonly?: boolean | null;
|
||||
}
|
||||
@ -1992,6 +2004,7 @@ export interface TSImportEqualsDeclaration extends BaseNode {
|
||||
type: "TSImportEqualsDeclaration";
|
||||
id: Identifier;
|
||||
moduleReference: TSEntityName | TSExternalModuleReference;
|
||||
importKind?: "type" | "value" | null;
|
||||
isExport: boolean;
|
||||
}
|
||||
|
||||
|
||||
@ -900,6 +900,11 @@ defineType("RestElement", {
|
||||
? assertNodeType("LVal")
|
||||
: assertNodeType("Identifier", "Pattern", "MemberExpression"),
|
||||
},
|
||||
// For Flow
|
||||
optional: {
|
||||
validate: assertValueType("boolean"),
|
||||
optional: true,
|
||||
},
|
||||
},
|
||||
validate(parent, key) {
|
||||
if (!process.env.BABEL_TYPES_8_BREAKING) return;
|
||||
@ -1206,6 +1211,10 @@ defineType("ArrayPattern", {
|
||||
),
|
||||
optional: true,
|
||||
},
|
||||
optional: {
|
||||
validate: assertValueType("boolean"),
|
||||
optional: true,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
@ -1440,6 +1449,7 @@ defineType("ExportDefaultDeclaration", {
|
||||
"Expression",
|
||||
),
|
||||
},
|
||||
exportKind: validateOptional(assertOneOf("value")),
|
||||
},
|
||||
});
|
||||
|
||||
@ -2095,6 +2105,10 @@ defineType("ClassProperty", {
|
||||
validate: assertValueType("boolean"),
|
||||
optional: true,
|
||||
},
|
||||
variance: {
|
||||
validate: assertNodeType("Variance"),
|
||||
optional: true,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
@ -2123,6 +2137,18 @@ defineType("ClassPrivateProperty", {
|
||||
),
|
||||
optional: true,
|
||||
},
|
||||
readonly: {
|
||||
validate: assertValueType("boolean"),
|
||||
optional: true,
|
||||
},
|
||||
definite: {
|
||||
validate: assertValueType("boolean"),
|
||||
optional: true,
|
||||
},
|
||||
variance: {
|
||||
validate: assertNodeType("Variance"),
|
||||
optional: true,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
@ -121,6 +121,7 @@ defineType("DeclareOpaqueType", {
|
||||
id: validateType("Identifier"),
|
||||
typeParameters: validateOptionalType("TypeParameterDeclaration"),
|
||||
supertype: validateOptionalType("FlowType"),
|
||||
impltype: validateOptionalType("FlowType"),
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
@ -49,6 +49,17 @@ defineType("TSParameterProperty", {
|
||||
parameter: {
|
||||
validate: assertNodeType("Identifier", "AssignmentPattern"),
|
||||
},
|
||||
override: {
|
||||
validate: assertValueType("boolean"),
|
||||
optional: true,
|
||||
},
|
||||
decorators: {
|
||||
validate: chain(
|
||||
assertValueType("array"),
|
||||
assertEach(assertNodeType("Decorator")),
|
||||
),
|
||||
optional: true,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
@ -110,6 +121,9 @@ defineType("TSPropertySignature", {
|
||||
readonly: validateOptional(bool),
|
||||
typeAnnotation: validateOptionalType("TSTypeAnnotation"),
|
||||
initializer: validateOptionalType("Expression"),
|
||||
kind: {
|
||||
validate: assertOneOf("get", "set"),
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
@ -494,6 +508,10 @@ defineType("TSImportEqualsDeclaration", {
|
||||
"TSEntityName",
|
||||
"TSExternalModuleReference",
|
||||
]),
|
||||
importKind: {
|
||||
validate: assertOneOf("type", "value"),
|
||||
optional: true,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
116
packages/babel-types/test/fields.js
Normal file
116
packages/babel-types/test/fields.js
Normal file
@ -0,0 +1,116 @@
|
||||
import * as t from "../lib";
|
||||
import glob from "glob";
|
||||
import path from "path";
|
||||
import fs from "fs";
|
||||
import { inspect } from "util";
|
||||
|
||||
// eslint-disable-next-line no-restricted-globals
|
||||
const packages = path.resolve(__dirname, "..", "..");
|
||||
|
||||
function readJson(file) {
|
||||
return new Promise((resolve, reject) => {
|
||||
fs.readFile(file, "utf8", (err, data) => {
|
||||
if (err) reject(err);
|
||||
else resolve(JSON.parse(data));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function traverse(thing, visitor) {
|
||||
if (Array.isArray(thing)) {
|
||||
thing.forEach(elem => traverse(elem, visitor));
|
||||
} else if (thing instanceof Object && typeof thing.type === "string") {
|
||||
visitor(thing);
|
||||
for (const key in thing) {
|
||||
const value = thing[key];
|
||||
if (value instanceof Object) traverse(value, visitor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const files = glob.sync(
|
||||
path.join("babel-parser", "test", "**", "output.json"),
|
||||
{
|
||||
cwd: packages,
|
||||
ignore: [
|
||||
path.join("**", "estree*", "**"),
|
||||
path.join("**", "is-expression-babel-parser", "**"),
|
||||
],
|
||||
},
|
||||
);
|
||||
|
||||
const ignoredFields = {
|
||||
ArrowFunctionExpression: { id: true, predicate: true },
|
||||
ClassMethod: { id: true, predicate: true },
|
||||
ClassPrivateMethod: { id: true, predicate: true },
|
||||
ClassPrivateProperty: { declare: true, optional: true },
|
||||
FunctionDeclaration: { predicate: true },
|
||||
FunctionExpression: { predicate: true },
|
||||
ImportDeclaration: { attributes: true },
|
||||
ObjectProperty: { method: true },
|
||||
ObjectMethod: { method: true, id: true, predicate: true },
|
||||
StaticBlock: { static: true },
|
||||
TSDeclareMethod: { id: true },
|
||||
};
|
||||
|
||||
function isEmpty(obj) {
|
||||
for (const key in obj) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
describe("NODE_FIELDS contains all fields in", function () {
|
||||
files.forEach(file =>
|
||||
it(`${file}`, async function () {
|
||||
const ast = await readJson(path.resolve(packages, file));
|
||||
if (ast.type === "File" && ast.errors && ast.errors.length) return;
|
||||
t[`assert${ast.type}`](ast);
|
||||
const missingFields = {};
|
||||
traverse(ast, node => {
|
||||
const { type } = node;
|
||||
switch (type) {
|
||||
case "File":
|
||||
case "CommentBlock":
|
||||
case "CommentLine":
|
||||
return;
|
||||
}
|
||||
if (ignoredFields[type] === true) return;
|
||||
const fields = t.NODE_FIELDS[type];
|
||||
if (!fields) {
|
||||
if (!missingFields[type]) {
|
||||
missingFields[type] = {
|
||||
MISSING_TYPE: true,
|
||||
};
|
||||
}
|
||||
return;
|
||||
}
|
||||
for (const field in node) {
|
||||
switch (field) {
|
||||
case "type":
|
||||
case "start":
|
||||
case "end":
|
||||
case "loc":
|
||||
case "range":
|
||||
case "leadingComments":
|
||||
case "innerComments":
|
||||
case "trailingComments":
|
||||
case "comments":
|
||||
case "extra":
|
||||
continue;
|
||||
}
|
||||
if (!fields[field]) {
|
||||
if (ignoredFields[type] && ignoredFields[type][field]) continue;
|
||||
if (!missingFields[type]) missingFields[type] = {};
|
||||
if (!missingFields[type][field]) {
|
||||
missingFields[type][field] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
if (!isEmpty(missingFields)) {
|
||||
throw new Error(
|
||||
`the following NODE_FIELDS were missing: ${inspect(missingFields)}`,
|
||||
);
|
||||
}
|
||||
}),
|
||||
);
|
||||
});
|
||||
Loading…
x
Reference in New Issue
Block a user