forked from eslint/espree
-
Notifications
You must be signed in to change notification settings - Fork 0
/
create-test.js
130 lines (107 loc) · 4.07 KB
/
create-test.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
118
119
120
121
122
123
124
125
126
127
128
129
130
/* eslint-disable node/no-process-exit */
/**
* @fileoverview A simple script to help generate test cases
* @author Nicholas C. Zakas
*/
/*
* Usage:
* node tools/create-test.js ecma-features/binaryLiterals/ file_with_code.js
*
* The file with code should use "/*!espree-section: name/" as a separator between examples
*/
//------------------------------------------------------------------------------
// Requirements
//------------------------------------------------------------------------------
import shelljs from "shelljs";
import { parse } from "../espree.js";
import path from "path";
import { fileURLToPath } from "url";
//------------------------------------------------------------------------------
// Initialization
//------------------------------------------------------------------------------
// eslint-disable-next-line no-underscore-dangle -- Conventional
const __dirname = path.dirname(fileURLToPath(import.meta.url));
const PATTERN = /\/\*!espree-section:\s*[a-z\d-]+\*\//giu;
const filename = process.argv[2],
codeFilename = process.argv[3];
/**
* @typedef {{start: number, end: number}} StartEnd
*/
/**
* acorn adds these "start" and "end" properties
* which we don't officially support, we remove
* them before creating our test fixtures
* @param {StartEnd[]} o The array or object to modify
* @returns {void}
*/
function recursivelyRemoveStartAndEnd(o) {
if (Array.isArray(o)) {
o.forEach(recursivelyRemoveStartAndEnd);
return;
}
if (o && typeof o === "object") {
delete o.start;
delete o.end;
Object.keys(o).filter(key => key !== "loc").forEach(key => {
recursivelyRemoveStartAndEnd(o[key]);
});
}
}
if (!codeFilename) {
console.error("Missing code to generate tests for");
console.error("Usage: node create-test.js ecma-features/binaryLiterals/ file_with_code.js");
process.exit(1);
}
if (!filename) {
console.error("Missing filename to generate tests for");
console.error("Usage: node create-test.js ecma-features/binaryLiterals/ file_with_code.js");
process.exit(1);
}
const rawCode = shelljs.cat(codeFilename),
code = rawCode.split(PATTERN),
sections = rawCode.match(PATTERN);
// pop off first code, it will be an empty string
code.shift();
if (!sections || sections.length !== code.length) {
console.error("Missing a /*!espree-section: name*/ in the code file.");
process.exit(1);
}
code.forEach((source, index) => {
const fullFilename = `${filename}/${sections[index].slice(18, sections[index].length - 2).trim()}`,
testSourceFilename = path.resolve(__dirname, `../tests/fixtures/${fullFilename}.src.js`),
testResultFilename = path.resolve(__dirname, `../tests/fixtures/${fullFilename}.result.js`);
let result,
sourceCode = source.trim();
// add an extra semicolon if there's not already one at the end - helps normalize empty lines at end of input
if (sourceCode[sourceCode.length - 1] !== ";") {
sourceCode += ";";
}
//------------------------------------------------------------------------------
// Run the code against Esprima to generate the AST to match against
//------------------------------------------------------------------------------
try {
result = parse(sourceCode, {
ecmaVersion: 8, // change as needed
ecmaFeatures: {
experimentalObjectRestSpread: true
},
sourceType: "script", // change as needed
loc: true,
range: true,
tokens: true
});
} catch (ex) {
result = {
message: ex.message,
column: ex.column,
index: ex.index,
lineNumber: ex.lineNumber
};
}
recursivelyRemoveStartAndEnd(result);
sourceCode.to(testSourceFilename);
let resultCode = `export default ${JSON.stringify(result, (key, value) =>
((typeof value === "bigint") ? `bigint<${value}n>` : value), 4)};`;
resultCode = resultCode.replace(/"bigint<(\d+n)>"/gu, "$1");
resultCode.to(testResultFilename);
});