187 lines
6.5 KiB
Plaintext
187 lines
6.5 KiB
Plaintext
import path from 'path';
|
|
import semver from 'semver';
|
|
import entries from 'object.entries';
|
|
import { version } from 'eslint/package.json';
|
|
import flatMap from 'array.prototype.flatmap';
|
|
|
|
let tsParserVersion;
|
|
try {
|
|
// eslint-disable-next-line import/no-unresolved, global-require
|
|
tsParserVersion = require('@typescript-eslint/parser/package.json').version;
|
|
} catch (e) { /**/ }
|
|
|
|
const disableNewTS = semver.satisfies(tsParserVersion, '>= 4.1') // this rule is not useful on v4.1+ of the TS parser
|
|
? (x) => ({ ...x, features: [].concat(x.features, 'no-ts-new') })
|
|
: (x) => x;
|
|
|
|
function minEcmaVersion(features, parserOptions) {
|
|
const minEcmaVersionForFeatures = {
|
|
'class fields': 2022,
|
|
'optional chaining': 2020,
|
|
'nullish coalescing': 2020,
|
|
};
|
|
const result = Math.max(
|
|
...[].concat(
|
|
(parserOptions && parserOptions.ecmaVersion) || [],
|
|
flatMap(entries(minEcmaVersionForFeatures), (entry) => {
|
|
const f = entry[0];
|
|
const y = entry[1];
|
|
return features.has(f) ? y : [];
|
|
}),
|
|
).map((y) => (y > 5 && y < 2015 ? y + 2009 : y)), // normalize editions to years
|
|
);
|
|
return Number.isFinite(result) ? result : undefined;
|
|
}
|
|
|
|
const NODE_MODULES = '../../node_modules';
|
|
|
|
const parsers = {
|
|
BABEL_ESLINT: path.join(__dirname, NODE_MODULES, 'babel-eslint'),
|
|
'@BABEL_ESLINT': path.join(__dirname, NODE_MODULES, '@babel/eslint-parser'),
|
|
TYPESCRIPT_ESLINT: path.join(__dirname, NODE_MODULES, 'typescript-eslint-parser'),
|
|
'@TYPESCRIPT_ESLINT': path.join(__dirname, NODE_MODULES, '@typescript-eslint/parser'),
|
|
disableNewTS,
|
|
babelParserOptions: function parserOptions(test, features) {
|
|
return {
|
|
...test.parserOptions,
|
|
requireConfigFile: false,
|
|
babelOptions: {
|
|
presets: [
|
|
'@babel/preset-react',
|
|
],
|
|
plugins: [
|
|
'@babel/plugin-syntax-do-expressions',
|
|
'@babel/plugin-syntax-function-bind',
|
|
['@babel/plugin-syntax-decorators', { legacy: true }],
|
|
],
|
|
parserOpts: {
|
|
allowSuperOutsideMethod: false,
|
|
allowReturnOutsideFunction: false,
|
|
},
|
|
},
|
|
ecmaFeatures: {
|
|
|
|
...test.parserOptions && test.parserOptions.ecmaFeatures,
|
|
jsx: true,
|
|
modules: true,
|
|
legacyDecorators: features.has('decorators'),
|
|
},
|
|
};
|
|
},
|
|
all: function all(tests) {
|
|
const t = flatMap(tests, (test) => {
|
|
/* eslint no-param-reassign: 0 */
|
|
if (typeof test === 'string') {
|
|
test = { code: test };
|
|
}
|
|
if ('parser' in test) {
|
|
delete test.features;
|
|
return test;
|
|
}
|
|
const features = new Set([].concat(test.features || []));
|
|
delete test.features;
|
|
|
|
const es = minEcmaVersion(features, test.parserOptions);
|
|
|
|
function addComment(testObject, parser) {
|
|
const extras = [].concat(
|
|
`features: [${Array.from(features).join(',')}]`,
|
|
`parser: ${parser}`,
|
|
testObject.parserOptions ? `parserOptions: ${JSON.stringify(testObject.parserOptions)}` : [],
|
|
testObject.options ? `options: ${JSON.stringify(testObject.options)}` : [],
|
|
testObject.settings ? `settings: ${JSON.stringify(testObject.settings)}` : [],
|
|
);
|
|
|
|
const extraComment = `\n// ${extras.join(', ')}`;
|
|
|
|
// Augment expected fix code output with extraComment
|
|
const nextCode = { code: testObject.code + extraComment };
|
|
const nextOutput = testObject.output && { output: testObject.output + extraComment };
|
|
|
|
// Augment expected suggestion outputs with extraComment
|
|
// `errors` may be a number (expected number of errors) or an array of
|
|
// error objects.
|
|
const nextErrors = testObject.errors
|
|
&& typeof testObject.errors !== 'number'
|
|
&& {
|
|
errors: testObject.errors.map(
|
|
(errorObject) => {
|
|
const nextSuggestions = errorObject.suggestions && {
|
|
suggestions: errorObject.suggestions.map((suggestion) => ({ ...suggestion, output: suggestion.output + extraComment })),
|
|
};
|
|
|
|
return { ...errorObject, ...nextSuggestions };
|
|
},
|
|
),
|
|
};
|
|
|
|
return {
|
|
|
|
...testObject,
|
|
...nextCode,
|
|
...nextOutput,
|
|
...nextErrors,
|
|
};
|
|
}
|
|
|
|
const skipBase = (features.has('class fields') && semver.satisfies(version, '< 8'))
|
|
|| (es >= 2020 && semver.satisfies(version, '< 6'))
|
|
|| features.has('no-default')
|
|
|| features.has('bind operator')
|
|
|| features.has('do expressions')
|
|
|| features.has('decorators')
|
|
|| features.has('flow')
|
|
|| features.has('ts')
|
|
|| features.has('types')
|
|
|| (features.has('fragment') && semver.satisfies(version, '< 5'));
|
|
|
|
const skipBabel = features.has('no-babel');
|
|
const skipOldBabel = skipBabel
|
|
|| features.has('no-babel-old')
|
|
|| features.has('optional chaining')
|
|
|| semver.satisfies(version, '>= 8');
|
|
const skipNewBabel = skipBabel
|
|
|| features.has('no-babel-new')
|
|
|| !semver.satisfies(version, '^7.5.0') // require('@babel/eslint-parser/package.json').peerDependencies.eslint
|
|
|| features.has('flow')
|
|
|| features.has('types')
|
|
|| features.has('ts');
|
|
const skipTS = semver.satisfies(version, '<= 5') // TODO: make these pass on eslint 5
|
|
|| features.has('no-ts')
|
|
|| features.has('flow')
|
|
|| features.has('jsx namespace')
|
|
|| features.has('bind operator')
|
|
|| features.has('do expressions');
|
|
const tsOld = !skipTS && !features.has('no-ts-old');
|
|
const tsNew = !skipTS && !features.has('no-ts-new');
|
|
|
|
return [].concat(
|
|
skipBase ? [] : addComment(
|
|
{
|
|
...test,
|
|
...typeof es === 'number' && {
|
|
parserOptions: { ...test.parserOptions, ecmaVersion: es },
|
|
},
|
|
},
|
|
'default',
|
|
),
|
|
skipOldBabel ? [] : addComment({
|
|
...test,
|
|
parser: parsers.BABEL_ESLINT,
|
|
parserOptions: parsers.babelParserOptions(test, features),
|
|
}, 'babel-eslint'),
|
|
skipNewBabel ? [] : addComment({
|
|
...test,
|
|
parser: parsers['@BABEL_ESLINT'],
|
|
parserOptions: parsers.babelParserOptions(test, features),
|
|
}, '@babel/eslint-parser'),
|
|
tsOld ? addComment({ ...test, parser: parsers.TYPESCRIPT_ESLINT }, 'typescript-eslint') : [],
|
|
tsNew ? addComment({ ...test, parser: parsers['@TYPESCRIPT_ESLINT'] }, '@typescript-eslint/parser') : [],
|
|
);
|
|
});
|
|
return t;
|
|
},
|
|
};
|
|
|
|
export default parsers;
|