Skip to content

Commit

Permalink
fix(linter): migrate custom ignorePath to flat config
Browse files Browse the repository at this point in the history
  • Loading branch information
meeroslav committed Nov 2, 2023
1 parent 61770bd commit a7b2ce4
Show file tree
Hide file tree
Showing 5 changed files with 117 additions and 25 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ module.exports = [
"
`;

exports[`convert-to-flat-config generator should add global gitignores 1`] = `
exports[`convert-to-flat-config generator should add global eslintignores 1`] = `
"const { FlatCompat } = require('@eslint/eslintrc');
const nxEslintPlugin = require('@nx/eslint-plugin');
const js = require('@eslint/js');
Expand Down Expand Up @@ -317,6 +317,33 @@ module.exports = [
"
`;

exports[`convert-to-flat-config generator should handle custom eslintignores 1`] = `
"const baseConfig = require('../../eslint.config.js');
module.exports = [
...baseConfig,
{
files: [
'libs/test-lib/**/*.ts',
'libs/test-lib/**/*.tsx',
'libs/test-lib/**/*.js',
'libs/test-lib/**/*.jsx',
],
rules: {},
},
{
files: ['libs/test-lib/**/*.ts', 'libs/test-lib/**/*.tsx'],
rules: {},
},
{
files: ['libs/test-lib/**/*.js', 'libs/test-lib/**/*.jsx'],
rules: {},
},
{ ignores: ['libs/test-lib/ignore/me'] },
{ ignores: ['libs/test-lib/ignore/me/as/well'] },
];
"
`;

exports[`convert-to-flat-config generator should run successfully 1`] = `
"const { FlatCompat } = require('@eslint/eslintrc');
const nxEslintPlugin = require('@nx/eslint-plugin');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,8 @@ describe('convertEslintJsonToFlatConfig', () => {
tree,
'',
'.eslintrc.json',
'eslint.config.js'
'eslint.config.js',
['.eslintignore']
);

expect(tree.read('eslint.config.js', 'utf-8')).toMatchInlineSnapshot(`
Expand Down Expand Up @@ -119,7 +120,6 @@ describe('convertEslintJsonToFlatConfig', () => {
`);

expect(tree.exists('.eslintrc.json')).toBeFalsy();
expect(tree.exists('.eslintignore')).toBeFalsy();
});

it('should convert project configs', async () => {
Expand Down Expand Up @@ -174,7 +174,8 @@ describe('convertEslintJsonToFlatConfig', () => {
tree,
'mylib',
'.eslintrc.json',
'eslint.config.js'
'eslint.config.js',
['mylib/.eslintignore']
);

expect(tree.read('mylib/eslint.config.js', 'utf-8')).toMatchInlineSnapshot(`
Expand Down Expand Up @@ -229,6 +230,5 @@ describe('convertEslintJsonToFlatConfig', () => {
`);

expect(tree.exists('mylib/.eslintrc.json')).toBeFalsy();
expect(tree.exists('mylib/.eslintignore')).toBeFalsy();
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ export function convertEslintJsonToFlatConfig(
tree: Tree,
root: string,
sourceFile: string,
destinationFile: string
destinationFile: string,
ignorePaths: string[]
) {
const importsMap = new Map<string, string>();
const exportElements: ts.Expression[] = [];
Expand Down Expand Up @@ -174,19 +175,20 @@ export function convertEslintJsonToFlatConfig(
}
}

if (tree.exists(`${root}/.eslintignore`)) {
const patterns = tree
.read(`${root}/.eslintignore`, 'utf-8')
.split('\n')
.filter((line) => line.length > 0 && line !== 'node_modules')
.map((path) => mapFilePath(path, root));
if (patterns.length > 0) {
exportElements.push(generateAst({ ignores: patterns }));
for (const ignorePath of ignorePaths) {
if (tree.exists(ignorePath)) {
const patterns = tree
.read(ignorePath, 'utf-8')
.split('\n')
.filter((line) => line.length > 0 && line !== 'node_modules')
.map((path) => mapFilePath(path, root));
if (patterns.length > 0) {
exportElements.push(generateAst({ ignores: patterns }));
}
}
}

tree.delete(join(root, sourceFile));
tree.delete(join(root, '.eslintignore'));

// create the node list and print it to new file
const nodeList = createNodeList(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { ConvertToFlatConfigGeneratorSchema } from './schema';
import { lintProjectGenerator } from '../lint-project/lint-project';
import { Linter } from '../utils/linter';
import { eslintrcVersion } from '../../utils/versions';
import { read } from 'fs';

describe('convert-to-flat-config generator', () => {
let tree: Tree;
Expand Down Expand Up @@ -153,7 +154,7 @@ describe('convert-to-flat-config generator', () => {
).toEqual(eslintrcVersion);
});

it('should add global gitignores', async () => {
it('should add global eslintignores', async () => {
await lintProjectGenerator(tree, {
skipFormat: false,
linter: Linter.EsLint,
Expand All @@ -164,7 +165,39 @@ describe('convert-to-flat-config generator', () => {
tree.write('.eslintignore', 'ignore/me');
await convertToFlatConfigGenerator(tree, options);

expect(tree.read('eslint.config.js', 'utf-8')).toMatchSnapshot();
const config = tree.read('eslint.config.js', 'utf-8');
expect(config).toContain('ignore/me');
expect(config).toMatchSnapshot();
expect(tree.exists('.eslintignore')).toBeFalsy();
});

it('should handle custom eslintignores', async () => {
await lintProjectGenerator(tree, {
skipFormat: false,
linter: Linter.EsLint,
eslintFilePatterns: ['**/*.ts'],
project: 'test-lib',
setParserOptionsProject: false,
});
tree.write('another-folder/.myeslintignore', 'ignore/me');
updateJson(tree, 'libs/test-lib/project.json', (json) => {
json.targets.lint.options.ignorePath = 'another-folder/.myeslintignore';
return json;
});
tree.write('libs/test-lib/.eslintignore', 'ignore/me/as/well');

await convertToFlatConfigGenerator(tree, options);

expect(
tree.read('libs/test-lib/eslint.config.js', 'utf-8')
).toMatchSnapshot();
expect(tree.exists('another-folder/.myeslintignore')).toBeFalsy();
expect(tree.exists('libs/test-lib/.eslintignore')).toBeFalsy();

expect(
readJson(tree, 'libs/test-lib/project.json').targets.lint.options
.ignorePath
).toBeUndefined();
});

it('should add settings', async () => {
Expand Down
46 changes: 38 additions & 8 deletions packages/eslint/src/generators/convert-to-flat-config/generator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,28 @@ export async function convertToFlatConfigGenerator(
);
}

// rename root eslint config to eslint.config.js
convertRootToFlatConfig(tree, eslintFile);
// rename and map files
const eslintIgnoreFiles = new Set<string>(['.eslintignore']);

// convert project eslint files to eslint.config.js
const projects = getProjects(tree);
for (const [project, projectConfig] of projects) {
convertProjectToFlatConfig(tree, project, projectConfig, readNxJson(tree));
convertProjectToFlatConfig(
tree,
project,
projectConfig,
readNxJson(tree),
eslintIgnoreFiles
);
}

// convert root eslint config to eslint.config.js
convertRootToFlatConfig(tree, eslintFile);

// delete all .eslintignore files
for (const ignoreFile of eslintIgnoreFiles) {
tree.delete(ignoreFile);
}

// replace references in nx.json
updateNxJsonConfig(tree);
// install missing packages
Expand Down Expand Up @@ -60,18 +75,24 @@ function convertProjectToFlatConfig(
tree: Tree,
project: string,
projectConfig: ProjectConfiguration,
nxJson: NxJsonConfiguration
nxJson: NxJsonConfiguration,
eslintIgnoreFiles: Set<string>
) {
if (tree.exists(`${projectConfig.root}/.eslintrc.json`)) {
if (projectConfig.targets) {
const eslintTargets = Object.keys(projectConfig.targets || {}).filter(
(t) => projectConfig.targets[t].executor === '@nx/eslint:lint'
);
let ignorePath: string | undefined;
for (const target of eslintTargets) {
// remove any obsolete `eslintConfig` options pointing to the old config file
if (projectConfig.targets[target].options?.eslintConfig) {
delete projectConfig.targets[target].options.eslintConfig;
}
if (projectConfig.targets[target].options?.ignorePath) {
ignorePath = projectConfig.targets[target].options.ignorePath;
delete projectConfig.targets[target].options.ignorePath;
}
updateProjectConfiguration(tree, project, projectConfig);
}
const nxHasLintTargets = Object.keys(nxJson.targetDefaults || {}).some(
Expand All @@ -85,8 +106,13 @@ function convertProjectToFlatConfig(
tree,
projectConfig.root,
'.eslintrc.json',
'eslint.config.js'
'eslint.config.js',
ignorePath
);
eslintIgnoreFiles.add(`${projectConfig.root}/.eslintignore`);
if (ignorePath) {
eslintIgnoreFiles.add(ignorePath);
}
}
}
}
Expand Down Expand Up @@ -121,7 +147,11 @@ function convertConfigToFlatConfig(
tree: Tree,
root: string,
source: string,
target: string
target: string,
ignorePath?: string
) {
convertEslintJsonToFlatConfig(tree, root, source, target);
const ignorePaths = ignorePath
? [ignorePath, `${root}/.eslintignore`]
: [`${root}/.eslintignore`];
convertEslintJsonToFlatConfig(tree, root, source, target, ignorePaths);
}

0 comments on commit a7b2ce4

Please sign in to comment.