Skip to content

Commit ce4d57f

Browse files
ROSSROSALESljharb
andcommittedOct 11, 2022
[Tests] migrate helper parsers function from eslint-plugin-react
Co-authored-by: Ross Rosales <52366381+ROSSROSALES@users.noreply.github.com> Co-authored-by: Jordan Harband <ljharb@gmail.com>
1 parent 9688ad8 commit ce4d57f

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+534
-280
lines changed
 
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import { version } from 'eslint/package.json';
2+
import semver from 'semver';
3+
4+
const isESLintV8 = semver.major(version) >= 8;
5+
6+
// eslint-disable-next-line global-require, import/no-dynamic-require, import/no-unresolved
7+
const getESLintCoreRule = (ruleId) => (isESLintV8 ? require('eslint/use-at-your-own-risk').builtinRules.get(ruleId) : require(`eslint/lib/rules/${ruleId}`));
8+
9+
export default getESLintCoreRule;

‎__tests__/__util__/helpers/parsers.js

+186
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,186 @@
1+
import path from 'path';
2+
import semver from 'semver';
3+
import entries from 'object.entries';
4+
import { version } from 'eslint/package.json';
5+
import flatMap from 'array.prototype.flatmap';
6+
7+
let tsParserVersion;
8+
try {
9+
// eslint-disable-next-line import/no-unresolved, global-require
10+
tsParserVersion = require('@typescript-eslint/parser/package.json').version;
11+
} catch (e) { /**/ }
12+
13+
const disableNewTS = semver.satisfies(tsParserVersion, '>= 4.1') // this rule is not useful on v4.1+ of the TS parser
14+
? (x) => ({ ...x, features: [].concat(x.features, 'no-ts-new') })
15+
: (x) => x;
16+
17+
function minEcmaVersion(features, parserOptions) {
18+
const minEcmaVersionForFeatures = {
19+
'class fields': 2022,
20+
'optional chaining': 2020,
21+
'nullish coalescing': 2020,
22+
};
23+
const result = Math.max(
24+
...[].concat(
25+
(parserOptions && parserOptions.ecmaVersion) || [],
26+
flatMap(entries(minEcmaVersionForFeatures), (entry) => {
27+
const f = entry[0];
28+
const y = entry[1];
29+
return features.has(f) ? y : [];
30+
}),
31+
).map((y) => (y > 5 && y < 2015 ? y + 2009 : y)), // normalize editions to years
32+
);
33+
return Number.isFinite(result) ? result : undefined;
34+
}
35+
36+
const NODE_MODULES = '../../node_modules';
37+
38+
const parsers = {
39+
BABEL_ESLINT: path.join(__dirname, NODE_MODULES, 'babel-eslint'),
40+
'@BABEL_ESLINT': path.join(__dirname, NODE_MODULES, '@babel/eslint-parser'),
41+
TYPESCRIPT_ESLINT: path.join(__dirname, NODE_MODULES, 'typescript-eslint-parser'),
42+
'@TYPESCRIPT_ESLINT': path.join(__dirname, NODE_MODULES, '@typescript-eslint/parser'),
43+
disableNewTS,
44+
babelParserOptions: function parserOptions(test, features) {
45+
return {
46+
...test.parserOptions,
47+
requireConfigFile: false,
48+
babelOptions: {
49+
presets: [
50+
'@babel/preset-react',
51+
],
52+
plugins: [
53+
'@babel/plugin-syntax-do-expressions',
54+
'@babel/plugin-syntax-function-bind',
55+
['@babel/plugin-syntax-decorators', { legacy: true }],
56+
],
57+
parserOpts: {
58+
allowSuperOutsideMethod: false,
59+
allowReturnOutsideFunction: false,
60+
},
61+
},
62+
ecmaFeatures: {
63+
64+
...test.parserOptions && test.parserOptions.ecmaFeatures,
65+
jsx: true,
66+
modules: true,
67+
legacyDecorators: features.has('decorators'),
68+
},
69+
};
70+
},
71+
all: function all(tests) {
72+
const t = flatMap(tests, (test) => {
73+
/* eslint no-param-reassign: 0 */
74+
if (typeof test === 'string') {
75+
test = { code: test };
76+
}
77+
if ('parser' in test) {
78+
delete test.features;
79+
return test;
80+
}
81+
const features = new Set([].concat(test.features || []));
82+
delete test.features;
83+
84+
const es = minEcmaVersion(features, test.parserOptions);
85+
86+
function addComment(testObject, parser) {
87+
const extras = [].concat(
88+
`features: [${Array.from(features).join(',')}]`,
89+
`parser: ${parser}`,
90+
testObject.parserOptions ? `parserOptions: ${JSON.stringify(testObject.parserOptions)}` : [],
91+
testObject.options ? `options: ${JSON.stringify(testObject.options)}` : [],
92+
testObject.settings ? `settings: ${JSON.stringify(testObject.settings)}` : [],
93+
);
94+
95+
const extraComment = `\n// ${extras.join(', ')}`;
96+
97+
// Augment expected fix code output with extraComment
98+
const nextCode = { code: testObject.code + extraComment };
99+
const nextOutput = testObject.output && { output: testObject.output + extraComment };
100+
101+
// Augment expected suggestion outputs with extraComment
102+
// `errors` may be a number (expected number of errors) or an array of
103+
// error objects.
104+
const nextErrors = testObject.errors
105+
&& typeof testObject.errors !== 'number'
106+
&& {
107+
errors: testObject.errors.map(
108+
(errorObject) => {
109+
const nextSuggestions = errorObject.suggestions && {
110+
suggestions: errorObject.suggestions.map((suggestion) => ({ ...suggestion, output: suggestion.output + extraComment })),
111+
};
112+
113+
return { ...errorObject, ...nextSuggestions };
114+
},
115+
),
116+
};
117+
118+
return {
119+
120+
...testObject,
121+
...nextCode,
122+
...nextOutput,
123+
...nextErrors,
124+
};
125+
}
126+
127+
const skipBase = (features.has('class fields') && semver.satisfies(version, '< 8'))
128+
|| (es >= 2020 && semver.satisfies(version, '< 6'))
129+
|| features.has('no-default')
130+
|| features.has('bind operator')
131+
|| features.has('do expressions')
132+
|| features.has('decorators')
133+
|| features.has('flow')
134+
|| features.has('ts')
135+
|| features.has('types')
136+
|| (features.has('fragment') && semver.satisfies(version, '< 5'));
137+
138+
const skipBabel = features.has('no-babel');
139+
const skipOldBabel = skipBabel
140+
|| features.has('no-babel-old')
141+
|| features.has('optional chaining')
142+
|| semver.satisfies(version, '>= 8');
143+
const skipNewBabel = skipBabel
144+
|| features.has('no-babel-new')
145+
|| !semver.satisfies(version, '^7.5.0') // require('@babel/eslint-parser/package.json').peerDependencies.eslint
146+
|| features.has('flow')
147+
|| features.has('types')
148+
|| features.has('ts');
149+
const skipTS = semver.satisfies(version, '<= 5') // TODO: make these pass on eslint 5
150+
|| features.has('no-ts')
151+
|| features.has('flow')
152+
|| features.has('jsx namespace')
153+
|| features.has('bind operator')
154+
|| features.has('do expressions');
155+
const tsOld = !skipTS && !features.has('no-ts-old');
156+
const tsNew = !skipTS && !features.has('no-ts-new');
157+
158+
return [].concat(
159+
skipBase ? [] : addComment(
160+
{
161+
...test,
162+
...typeof es === 'number' && {
163+
parserOptions: { ...test.parserOptions, ecmaVersion: es },
164+
},
165+
},
166+
'default',
167+
),
168+
skipOldBabel ? [] : addComment({
169+
...test,
170+
parser: parsers.BABEL_ESLINT,
171+
parserOptions: parsers.babelParserOptions(test, features),
172+
}, 'babel-eslint'),
173+
skipNewBabel ? [] : addComment({
174+
...test,
175+
parser: parsers['@BABEL_ESLINT'],
176+
parserOptions: parsers.babelParserOptions(test, features),
177+
}, '@babel/eslint-parser'),
178+
tsOld ? addComment({ ...test, parser: parsers.TYPESCRIPT_ESLINT }, 'typescript-eslint') : [],
179+
tsNew ? addComment({ ...test, parser: parsers['@TYPESCRIPT_ESLINT'] }, '@typescript-eslint/parser') : [],
180+
);
181+
});
182+
return t;
183+
},
184+
};
185+
186+
export default parsers;

0 commit comments

Comments
 (0)
Please sign in to comment.