Skip to content

Commit

Permalink
fix(linter): remove config builder option for @nrwl/linter:lint whe…
Browse files Browse the repository at this point in the history
…n using eslint (#3093)

- eslint automatically detects .eslintrc files already
- removing the config option also enables nested configs
- provide a migration to remove config as long as users didn't customize it
  • Loading branch information
jaysoo committed May 29, 2020
1 parent f2f9c2b commit c2b8c22
Show file tree
Hide file tree
Showing 9 changed files with 127 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,6 @@ describe('schematic:cypress-project', () => {
builder: '@nrwl/linter:lint',
options: {
linter: 'eslint',
config: 'apps/my-app-e2e/.eslintrc',
tsConfig: ['apps/my-app-e2e/tsconfig.e2e.json'],
exclude: ['**/node_modules/**', '!apps/my-app-e2e/**'],
},
Expand Down
12 changes: 8 additions & 4 deletions packages/linter/src/builders/lint/lint.impl.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { createBuilder } from '@angular-devkit/architect';
import { BuilderContext, createBuilder } from '@angular-devkit/architect';
import { CLIEngine } from 'eslint';
import { writeFileSync, mkdirSync } from 'fs';
import { writeFileSync } from 'fs';
import * as path from 'path';
import { Schema } from './schema';
import { BuilderContext } from '@angular-devkit/architect';
import { createProgram } from './utility/ts-utils';
import { lint, loadESLint } from './utility/eslint-utils';
import { createDirectory } from '@nrwl/workspace';

/**
* Adapted from @angular-eslint/builder source
*/
Expand Down Expand Up @@ -41,7 +41,11 @@ async function run(options: Schema, context: BuilderContext): Promise<any> {
throw new Error('ESLint must be version 6.1 or higher.');
}

const eslintConfigPath = path.resolve(systemRoot, options.config);
// We want users to have the option of not specifying the config path, and let
// eslint automatically resolve the `.eslintrc` files in each folder.
const eslintConfigPath = options.config
? path.resolve(systemRoot, options.config)
: undefined;

let lintReports: CLIEngine.LintReport[] = [];
const lintedFiles = new Set<string>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,10 @@ describe('eslint-util', () => {
).catch(() => {});
expect(CLIEngine).toHaveBeenCalledWith({
configFile: './.eslintrc',
useEslintrc: false,
fix: true,
cache: true,
cacheLocation: '/root/cache',
useEslintrc: true,
});
});
it('should not lint the same files twice', async () => {
Expand Down
2 changes: 1 addition & 1 deletion packages/linter/src/builders/lint/utility/eslint-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ export async function lint(
const projectESLint = await loadESLint();
const cli: CLIEngine = new projectESLint.CLIEngine({
configFile: eslintConfigPath,
useEslintrc: false,
useEslintrc: true,
fix: !!options.fix,
cache: !!options.cache,
cacheLocation: options.cacheLocation,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
declare module '*.svg' {
const content: any;
export const ReactComponent: any;
Expand Down
5 changes: 5 additions & 0 deletions packages/workspace/migrations.json
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,11 @@
"version": "9.3.0-beta.1",
"description": "Update prettier to v2",
"factory": "./src/migrations/update-9-3-0/update-9-3-0"
},
"update-eslint-config": {
"version": "9.4.0-beta.1",
"description": "Remove config builder option when using eslint to enable automatic detection",
"factory": "./src/migrations/update-9-4-0/update-eslint-config"
}
},
"packageJsonUpdates": {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import { Tree } from '@angular-devkit/schematics';
import { readWorkspace } from '@nrwl/workspace';
import { createEmptyWorkspace } from '@nrwl/workspace/testing';
import { callRule, runMigration } from '../../utils/testing';
import { updateWorkspace } from '@nrwl/workspace/src/utils/workspace';

describe('Update eslint config for 9.4.0', () => {
let tree: Tree;

beforeEach(async () => {
tree = Tree.empty();
tree = createEmptyWorkspace(tree);
tree = await callRule(
updateWorkspace((workspace) => {
workspace.projects.add({
name: 'proj1',
root: 'proj1',
architect: {
lint: {
builder: '@angular-devkit/build-angular:tslint',
options: {
config: 'proj1/tslint.json',
},
},
},
});
workspace.projects.add({
name: 'proj2',
root: 'proj2',
architect: {
lint: {
builder: '@nrwl/linter:lint',
options: {
linter: 'eslint',
config: 'proj2/.eslintrc',
},
},
},
});
workspace.projects.add({
name: 'proj3',
root: 'proj3',
architect: {
lint: {
builder: '@nrwl/linter:lint',
options: {
linter: 'tslint',
config: 'proj3/tslint.json',
},
},
},
});
workspace.projects.add({
name: 'proj4',
root: 'proj4',
architect: {
lint: {
builder: '@nrwl/linter:lint',
options: {
linter: 'eslint',
config: 'proj4/.eslintrc.custom',
},
},
},
});
}),
tree
);
});

it('should remove config builder option when using eslint', async () => {
const result = await runMigration('update-eslint-config', {}, tree);

const json = readWorkspace(result);

expect(json.projects.proj1.architect.lint.options.config).toMatch(
'proj1/tslint.json'
);
expect(json.projects.proj2.architect.lint.options.config).toBeUndefined();
expect(json.projects.proj3.architect.lint.options.config).toMatch(
'proj3/tslint.json'
);
expect(json.projects.proj4.architect.lint.options.config).toMatch(
'proj4/.eslintrc.custom'
);
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { chain, SchematicContext, Tree } from '@angular-devkit/schematics';
import { formatFiles, updateWorkspaceInTree } from '@nrwl/workspace';

function removeEslintConfigOption(host: Tree, context: SchematicContext) {
return updateWorkspaceInTree((json) => {
Object.keys(json.projects).forEach((name) => {
const p = json.projects[name];
if (
p.architect?.lint.builder === '@nrwl/linter:lint' &&
p.architect?.lint.options?.config === `${p.root}/.eslintrc`
) {
delete p.architect.lint.options.config;
}
});
return json;
});
}

export default function () {
return chain([removeEslintConfigOption, formatFiles()]);
}
4 changes: 3 additions & 1 deletion packages/workspace/src/utils/lint.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,10 @@ export function generateProjectLint(
return {
builder: '@nrwl/linter:lint',
options: {
// No config option here because eslint resolve them automatically.
// By not specifying a config option we allow eslint to support
// nested configurations.
linter: 'eslint',
config: projectRoot + '/.eslintrc',
tsConfig: [tsConfigPath],
exclude: ['**/node_modules/**', '!' + projectRoot + '/**'],
},
Expand Down

0 comments on commit c2b8c22

Please sign in to comment.