/
fields.js
117 lines (110 loc) 路 3.29 KB
/
fields.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
import * as t from "../lib";
import glob from "glob";
import path from "path";
import fs from "fs";
import { inspect } from "util";
import { fileURLToPath } from "url";
const dirname = path.dirname(fileURLToPath(import.meta.url));
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)}`,
);
}
}),
);
});