fix(linter): fix flat config file paths (#20386)

This commit is contained in:
Miroslav Jonaš 2023-11-23 21:43:05 +01:00 committed by GitHub
parent 0e0b3b9e0d
commit 905ef65136
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 74 additions and 122 deletions

View File

@ -381,20 +381,15 @@ exports[`convert-to-flat-config generator should convert json successfully 2`] =
module.exports = [
...baseConfig,
{
files: [
'libs/test-lib/**/*.ts',
'libs/test-lib/**/*.tsx',
'libs/test-lib/**/*.js',
'libs/test-lib/**/*.jsx',
],
files: ['**/*.ts', '**/*.tsx', '**/*.js', '**/*.jsx'],
rules: {},
},
{
files: ['libs/test-lib/**/*.ts', 'libs/test-lib/**/*.tsx'],
files: ['**/*.ts', '**/*.tsx'],
rules: {},
},
{
files: ['libs/test-lib/**/*.js', 'libs/test-lib/**/*.jsx'],
files: ['**/*.js', '**/*.jsx'],
rules: {},
},
];
@ -451,20 +446,15 @@ exports[`convert-to-flat-config generator should convert yaml successfully 2`] =
module.exports = [
...baseConfig,
{
files: [
'libs/test-lib/**/*.ts',
'libs/test-lib/**/*.tsx',
'libs/test-lib/**/*.js',
'libs/test-lib/**/*.jsx',
],
files: ['**/*.ts', '**/*.tsx', '**/*.js', '**/*.jsx'],
rules: {},
},
{
files: ['libs/test-lib/**/*.ts', 'libs/test-lib/**/*.tsx'],
files: ['**/*.ts', '**/*.tsx'],
rules: {},
},
{
files: ['libs/test-lib/**/*.js', 'libs/test-lib/**/*.jsx'],
files: ['**/*.js', '**/*.jsx'],
rules: {},
},
];
@ -521,20 +511,15 @@ exports[`convert-to-flat-config generator should convert yml successfully 2`] =
module.exports = [
...baseConfig,
{
files: [
'libs/test-lib/**/*.ts',
'libs/test-lib/**/*.tsx',
'libs/test-lib/**/*.js',
'libs/test-lib/**/*.jsx',
],
files: ['**/*.ts', '**/*.tsx', '**/*.js', '**/*.jsx'],
rules: {},
},
{
files: ['libs/test-lib/**/*.ts', 'libs/test-lib/**/*.tsx'],
files: ['**/*.ts', '**/*.tsx'],
rules: {},
},
{
files: ['libs/test-lib/**/*.js', 'libs/test-lib/**/*.jsx'],
files: ['**/*.js', '**/*.jsx'],
rules: {},
},
];
@ -547,24 +532,19 @@ exports[`convert-to-flat-config generator should handle custom eslintignores 1`]
module.exports = [
...baseConfig,
{
files: [
'libs/test-lib/**/*.ts',
'libs/test-lib/**/*.tsx',
'libs/test-lib/**/*.js',
'libs/test-lib/**/*.jsx',
],
files: ['**/*.ts', '**/*.tsx', '**/*.js', '**/*.jsx'],
rules: {},
},
{
files: ['libs/test-lib/**/*.ts', 'libs/test-lib/**/*.tsx'],
files: ['**/*.ts', '**/*.tsx'],
rules: {},
},
{
files: ['libs/test-lib/**/*.js', 'libs/test-lib/**/*.jsx'],
files: ['**/*.js', '**/*.jsx'],
rules: {},
},
{ ignores: ['libs/test-lib/ignore/me'] },
{ ignores: ['libs/test-lib/ignore/me/as/well'] },
{ ignores: ['ignore/me'] },
{ ignores: ['ignore/me/as/well'] },
];
"
`;

View File

@ -194,10 +194,10 @@ describe('convertEslintJsonToFlatConfig', () => {
{ rules: { "@next/next/no-html-link-for-pages": "off" } },
{
files: [
"mylib/**/*.ts",
"mylib/**/*.tsx",
"mylib/**/*.js",
"mylib/**/*.jsx"
"**/*.ts",
"**/*.tsx",
"**/*.js",
"**/*.jsx"
],
rules: { "@next/next/no-html-link-for-pages": [
"error",
@ -206,25 +206,25 @@ describe('convertEslintJsonToFlatConfig', () => {
},
{
files: [
"mylib/**/*.ts",
"mylib/**/*.tsx"
"**/*.ts",
"**/*.tsx"
],
rules: {}
},
{
files: [
"mylib/**/*.js",
"mylib/**/*.jsx"
"**/*.js",
"**/*.jsx"
],
rules: {}
},
...compat.config({ parser: "jsonc-eslint-parser" }).map(config => ({
...config,
files: ["mylib/**/*.json"],
files: ["**/*.json"],
rules: { "@nx/dependency-checks": "error" }
})),
{ ignores: ["mylib/.next/**/*"] },
{ ignores: ["mylib/something/else"] }
{ ignores: [".next/**/*"] },
{ ignores: ["something/else"] }
];
"
`);

View File

@ -7,10 +7,10 @@ import {
generateFlatOverride,
generatePluginExtendsElement,
generateSpreadElement,
mapFilePath,
stringifyNodeList,
} from '../../utils/flat-config/ast-utils';
import { getPluginImport } from '../../utils/eslint-file';
import { mapFilePath } from '../../utils/flat-config/path-utils';
/**
* Converts an ESLint JSON config to a flat config.
@ -148,7 +148,7 @@ export function convertEslintJsonToFlatConfig(
) {
isFlatCompatNeeded = true;
}
exportElements.push(generateFlatOverride(override, root));
exportElements.push(generateFlatOverride(override));
});
}
@ -161,7 +161,7 @@ export function convertEslintJsonToFlatConfig(
if (patterns.length > 0) {
exportElements.push(
generateAst({
ignores: patterns.map((path) => mapFilePath(path, root)),
ignores: patterns.map((path) => mapFilePath(path)),
})
);
}
@ -173,7 +173,7 @@ export function convertEslintJsonToFlatConfig(
.read(ignorePath, 'utf-8')
.split('\n')
.filter((line) => line.length > 0 && line !== 'node_modules')
.map((path) => mapFilePath(path, root));
.map((path) => mapFilePath(path));
if (patterns.length > 0) {
exportElements.push(generateAst({ ignores: patterns }));
}
@ -188,7 +188,7 @@ export function convertEslintJsonToFlatConfig(
);
return {
content: stringifyNodeList(nodeList, root),
content: stringifyNodeList(nodeList),
addESLintRC: isFlatCompatNeeded,
addESLintJS: isESLintJSNeeded,
};

View File

@ -193,20 +193,15 @@ describe('convert-to-flat-config generator', () => {
module.exports = [
...baseConfig,
{
files: [
'libs/test-lib/**/*.ts',
'libs/test-lib/**/*.tsx',
'libs/test-lib/**/*.js',
'libs/test-lib/**/*.jsx',
],
files: ['**/*.ts', '**/*.tsx', '**/*.js', '**/*.jsx'],
rules: {},
},
{
files: ['libs/test-lib/**/*.ts', 'libs/test-lib/**/*.tsx'],
files: ['**/*.ts', '**/*.tsx'],
rules: {},
},
{
files: ['libs/test-lib/**/*.js', 'libs/test-lib/**/*.jsx'],
files: ['**/*.js', '**/*.jsx'],
rules: {},
},
];

View File

@ -96,7 +96,7 @@ export const getGlobalFlatEslintConfiguration = (
rootProject?: boolean
): string => {
const nodeList = createNodeList(new Map(), [], true);
let content = stringifyNodeList(nodeList, '');
let content = stringifyNodeList(nodeList);
content = addImportToFlatConfig(content, 'nxPlugin', '@nx/eslint-plugin');
content = addPluginsToExportsBlock(content, [
{ name: '@nx', varName: 'nxPlugin', imp: '@nx/eslint-plugin' },
@ -104,21 +104,21 @@ export const getGlobalFlatEslintConfiguration = (
if (!rootProject) {
content = addBlockToFlatConfigExport(
content,
generateFlatOverride(moduleBoundariesOverride, '')
generateFlatOverride(moduleBoundariesOverride)
);
}
content = addBlockToFlatConfigExport(
content,
generateFlatOverride(typeScriptOverride, '')
generateFlatOverride(typeScriptOverride)
);
content = addBlockToFlatConfigExport(
content,
generateFlatOverride(javaScriptOverride, '')
generateFlatOverride(javaScriptOverride)
);
if (unitTestRunner === 'jest') {
content = addBlockToFlatConfigExport(
content,
generateFlatOverride(jestOverride, '')
generateFlatOverride(jestOverride)
);
}

View File

@ -209,10 +209,10 @@ function createEsLintConfiguration(
nodes.push(generateSpreadElement('baseConfig'));
}
overrides.forEach((override) => {
nodes.push(generateFlatOverride(override, projectConfig.root));
nodes.push(generateFlatOverride(override));
});
const nodeList = createNodeList(importMap, nodes, isCompatNeeded);
const content = stringifyNodeList(nodeList, projectConfig.root);
const content = stringifyNodeList(nodeList);
tree.write(join(projectConfig.root, 'eslint.config.js'), content);
} else {
writeJson(tree, join(projectConfig.root, `.eslintrc.json`), {

View File

@ -17,11 +17,11 @@ import {
generateFlatOverride,
generatePluginExtendsElement,
hasOverride,
mapFilePath,
removeOverridesFromLintConfig,
replaceOverride,
} from './flat-config/ast-utils';
import ts = require('typescript');
import { mapFilePath } from './flat-config/path-utils';
export const eslintConfigFileWhitelist = [
'.eslintrc',
@ -180,7 +180,7 @@ export function addOverrideToLintConfig(
root,
isBase ? baseEsLintFlatConfigFile : 'eslint.config.js'
);
const flatOverride = generateFlatOverride(override, root);
const flatOverride = generateFlatOverride(override);
let content = tree.read(fileName, 'utf8');
// we will be using compat here so we need to make sure it's added
if (overrideNeedsCompat(override)) {
@ -282,7 +282,7 @@ export function replaceOverridesInLintConfig(
}
content = removeOverridesFromLintConfig(content);
overrides.forEach((override) => {
const flatOverride = generateFlatOverride(override, root);
const flatOverride = generateFlatOverride(override);
addBlockToFlatConfigExport(content, flatOverride);
});
@ -359,7 +359,7 @@ export function addIgnoresToLintConfig(
if (useFlatConfig(tree)) {
const fileName = joinPathFragments(root, 'eslint.config.js');
const block = generateAst<ts.ObjectLiteralExpression>({
ignores: ignorePatterns.map((path) => mapFilePath(path, root)),
ignores: ignorePatterns.map((path) => mapFilePath(path)),
});
tree.write(
fileName,

View File

@ -6,6 +6,7 @@ import {
} from '@nx/devkit';
import { Linter } from 'eslint';
import * as ts from 'typescript';
import { mapFilePath } from './path-utils';
/**
* Remove all overrides from the config file
@ -166,7 +167,7 @@ export function replaceOverride(
length: end - start,
});
const updatedData = update(data);
mapFilePaths(updatedData, root);
mapFilePaths(updatedData);
changes.push({
type: ChangeType.Insert,
index: start,
@ -694,12 +695,11 @@ export function stringifyNodeList(
| ts.Identifier
| ts.ExpressionStatement
| ts.SourceFile
>,
root: string
>
): string {
const printer = ts.createPrinter({ newLine: ts.NewLineKind.LineFeed });
const resultFile = ts.createSourceFile(
joinPathFragments(root, ''),
'',
'',
ts.ScriptTarget.Latest,
true,
@ -749,10 +749,9 @@ export function generateRequire(
* Generates AST object or spread element based on JSON override object
*/
export function generateFlatOverride(
override: Linter.ConfigOverride<Linter.RulesRecord>,
root: string
override: Linter.ConfigOverride<Linter.RulesRecord>
): ts.ObjectLiteralExpression | ts.SpreadElement {
mapFilePaths(override, root);
mapFilePaths(override);
if (
!override.env &&
!override.extends &&
@ -810,43 +809,24 @@ export function generateFlatOverride(
}
export function mapFilePaths(
override: Linter.ConfigOverride<Linter.RulesRecord>,
root: string
override: Linter.ConfigOverride<Linter.RulesRecord>
) {
if (override.files) {
override.files = Array.isArray(override.files)
? override.files
: [override.files];
override.files = override.files.map((file) => mapFilePath(file, root));
override.files = override.files.map((file) => mapFilePath(file));
}
if (override.excludedFiles) {
override.excludedFiles = Array.isArray(override.excludedFiles)
? override.excludedFiles
: [override.excludedFiles];
override.excludedFiles = override.excludedFiles.map((file) =>
mapFilePath(file, root)
mapFilePath(file)
);
}
}
export function mapFilePath(filePath: string, root: string) {
if (filePath.startsWith('!')) {
const fileWithoutBang = filePath.slice(1);
if (fileWithoutBang.startsWith('*.')) {
return `!${joinPathFragments(root, '**', fileWithoutBang)}`;
} else if (!fileWithoutBang.startsWith(root)) {
return `!${joinPathFragments(root, fileWithoutBang)}`;
}
return filePath;
}
if (filePath.startsWith('*.')) {
return joinPathFragments(root, '**', filePath);
} else if (!filePath.startsWith(root)) {
return joinPathFragments(root, filePath);
}
return filePath;
}
function addTSObjectProperty(
elements: ts.ObjectLiteralElementLike[],
key: string,

View File

@ -2,30 +2,27 @@ import { joinPathFragments } from '@nx/devkit';
import type { Linter } from 'eslint';
export function updateFiles(
override: Linter.ConfigOverride<Linter.RulesRecord>,
root: string
override: Linter.ConfigOverride<Linter.RulesRecord>
) {
if (override.files) {
override.files = Array.isArray(override.files)
? override.files
: [override.files];
override.files = override.files.map((file) => mapFilePath(file, root));
override.files = override.files.map((file) => mapFilePath(file));
}
return override;
}
function mapFilePath(filePath: string, root: string) {
export function mapFilePath(filePath: string) {
if (filePath.startsWith('!')) {
const fileWithoutBang = filePath.slice(1);
if (fileWithoutBang.startsWith('*.')) {
return `!${joinPathFragments(root, '**', fileWithoutBang)}`;
} else {
return `!${joinPathFragments(root, fileWithoutBang)}`;
return `!${joinPathFragments('**', fileWithoutBang)}`;
}
return filePath;
}
if (filePath.startsWith('*.')) {
return joinPathFragments(root, '**', filePath);
} else {
return joinPathFragments(root, filePath);
return joinPathFragments('**', filePath);
}
return filePath;
}

View File

@ -133,16 +133,16 @@ describe('updateEslint', () => {
module.exports = [
{
files: ["my-app/**/*.*"],
files: ["**/*.*"],
rules: { "@next/next/no-html-link-for-pages": "off" }
},
...baseConfig,
{
"files": [
"my-app/**/*.ts",
"my-app/**/*.tsx",
"my-app/**/*.js",
"my-app/**/*.jsx"
"**/*.ts",
"**/*.tsx",
"**/*.js",
"**/*.jsx"
],
"rules": {
"@next/next/no-html-link-for-pages": [
@ -153,15 +153,15 @@ describe('updateEslint', () => {
},
{
files: [
"my-app/**/*.ts",
"my-app/**/*.tsx"
"**/*.ts",
"**/*.tsx"
],
rules: {}
},
{
files: [
"my-app/**/*.js",
"my-app/**/*.jsx"
"**/*.js",
"**/*.jsx"
],
rules: {}
},
@ -169,13 +169,13 @@ describe('updateEslint', () => {
...compat.config({ env: { jest: true } }).map(config => ({
...config,
files: [
"my-app/**/*.spec.ts",
"my-app/**/*.spec.tsx",
"my-app/**/*.spec.js",
"my-app/**/*.spec.jsx"
"**/*.spec.ts",
"**/*.spec.tsx",
"**/*.spec.js",
"**/*.spec.jsx"
]
})),
{ ignores: ["my-app/.next/**/*"] }
{ ignores: [".next/**/*"] }
];
"
`);