From 2a671e71044e6d8b5dcd7ee1d91c5e3df8efcb5d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leosvel=20P=C3=A9rez=20Espinosa?= Date: Mon, 14 Nov 2022 14:51:50 +0100 Subject: [PATCH] cleanup(angular): add @angular-eslint/builder:lint builder migrator (#13151) --- .../builders/angular-eslint-lint.migrator.ts | 208 ++++++++++++++++++ .../migrators/builders/builder.migrator.ts | 2 +- .../ng-add/migrators/builders/index.ts | 1 + .../generators/ng-add/migrators/migrator.ts | 9 + .../migrators/projects/app.migrator.spec.ts | 14 +- .../ng-add/migrators/projects/app.migrator.ts | 163 ++------------ .../migrators/projects/lib.migrator.spec.ts | 14 +- .../ng-add/migrators/projects/lib.migrator.ts | 144 +----------- .../migrators/projects/project.migrator.ts | 27 --- 9 files changed, 252 insertions(+), 330 deletions(-) create mode 100644 packages/angular/src/generators/ng-add/migrators/builders/angular-eslint-lint.migrator.ts diff --git a/packages/angular/src/generators/ng-add/migrators/builders/angular-eslint-lint.migrator.ts b/packages/angular/src/generators/ng-add/migrators/builders/angular-eslint-lint.migrator.ts new file mode 100644 index 0000000000000..c371d8e76c8ba --- /dev/null +++ b/packages/angular/src/generators/ng-add/migrators/builders/angular-eslint-lint.migrator.ts @@ -0,0 +1,208 @@ +import { + ProjectConfiguration, + TargetConfiguration, + Tree, + updateJson, +} from '@nrwl/devkit'; +import { + joinPathFragments, + offsetFromRoot, + readJson, + updateProjectConfiguration, +} from '@nrwl/devkit'; +import { hasRulesRequiringTypeChecking } from '@nrwl/linter'; +import { dirname } from 'path'; +import type { + Logger, + ProjectMigrationInfo, + ValidationError, + ValidationResult, +} from '../../utilities'; +import { arrayToString } from '../../utilities'; +import { BuilderMigrator } from './builder.migrator'; + +export class AngularEslintLintMigrator extends BuilderMigrator { + private oldEsLintConfigPath: string; + private newEsLintConfigPath: string; + + constructor( + tree: Tree, + project: ProjectMigrationInfo, + projectConfig: ProjectConfiguration, + logger: Logger + ) { + super( + tree, + '@angular-eslint/builder:lint', + 'eslint', + project, + projectConfig, + logger + ); + } + + override migrate(): void { + for (const [name, target] of this.targets) { + this.oldEsLintConfigPath = + target.options?.eslintConfig ?? + joinPathFragments(this.project.oldRoot, '.eslintrc.json'); + this.newEsLintConfigPath = this.convertRootPath(this.oldEsLintConfigPath); + + this.moveProjectRootFile(this.oldEsLintConfigPath); + this.updateTargetConfiguration(name, target); + this.updateEsLintConfig(); + this.updateCacheableOperations([name]); + } + + if (!this.targets.size && this.projectConfig.root === '') { + // there could still be a .eslintrc.json file in the root + // so move to new location + const eslintConfig = '.eslintrc.json'; + if (this.tree.exists(eslintConfig)) { + this.logger.info( + 'No "lint" target was found, but an ESLint config file was found in the project root. The file will be moved to the new location.' + ); + this.moveProjectRootFile(eslintConfig); + } + } + } + + override validate(): ValidationResult { + const errors: ValidationError[] = []; + // TODO(leo): keeping restriction until the full refactor is done and we start + // expanding what's supported. + if (this.targets.size > 1) { + errors.push({ + message: `There is more than one target using a builder that is used to lint the project (${arrayToString( + [...this.targets.keys()] + )}).`, + hint: `Make sure the project only has one target with a builder that is used to lint the project.`, + }); + } + + return errors.length ? errors : null; + } + + private async updateTargetConfiguration( + targetName: string, + target: TargetConfiguration + ): Promise { + target.executor = '@nrwl/linter:eslint'; + + if (!target.options) { + this.logger.warn( + `The target "${targetName}" is not specifying any options. Skipping updating the target configuration.` + ); + return; + } + + const existEsLintConfigPath = this.tree.exists(this.newEsLintConfigPath); + if (!existEsLintConfigPath) { + this.logger.warn( + `The ESLint config file "${this.oldEsLintConfigPath}" could not be found. Skipping updating the file.` + ); + } + + target.options.eslintConfig = + target.options.eslintConfig && this.newEsLintConfigPath; + target.options.lintFilePatterns = + target.options.lintFilePatterns && + target.options.lintFilePatterns.map((pattern) => { + // replace the old source root with the new root, we want to lint all + // matching files in the project, not just the ones in the source root + if (pattern.startsWith(this.project.oldSourceRoot)) { + return joinPathFragments( + this.project.newRoot, + pattern.replace(this.project.oldSourceRoot, '') + ); + } + + // replace the old root with the new root + if (pattern.startsWith(this.project.oldRoot)) { + return joinPathFragments( + this.project.newRoot, + pattern.replace(this.project.oldRoot, '') + ); + } + + // do nothing, warn about the pattern + this.logger.warn( + `The lint file pattern "${pattern}" specified in the "${targetName}" target is not contained in the project root or source root. The pattern will not be updated.` + ); + + return pattern; + }); + + if (existEsLintConfigPath) { + const eslintConfig = readJson(this.tree, this.newEsLintConfigPath); + if (hasRulesRequiringTypeChecking(eslintConfig)) { + target.options.hasTypeAwareRules = true; + } + } + + updateProjectConfiguration(this.tree, this.project.name, { + ...this.projectConfig, + }); + } + + private updateEsLintConfig(): void { + if (!this.tree.exists(this.newEsLintConfigPath)) { + return; + } + + updateJson(this.tree, this.newEsLintConfigPath, (json) => { + delete json.root; + json.ignorePatterns = ['!**/*']; + + const rootEsLintConfigRelativePath = joinPathFragments( + offsetFromRoot(this.projectConfig.root), + '.eslintrc.json' + ); + if (Array.isArray(json.extends)) { + json.extends = json.extends.map((extend: string) => + this.convertEsLintConfigExtendToNewPath( + this.oldEsLintConfigPath, + extend + ) + ); + + // it might have not been extending from the root config, make sure it does + if (!json.extends.includes(rootEsLintConfigRelativePath)) { + json.extends.unshift(rootEsLintConfigRelativePath); + } + } else { + json.extends = rootEsLintConfigRelativePath; + } + + json.overrides?.forEach((override) => { + if (!override.parserOptions?.project) { + return; + } + + override.parserOptions.project = [ + `${this.projectConfig.root}/tsconfig.*?.json`, + ]; + }); + + return json; + }); + } + + private convertEsLintConfigExtendToNewPath( + eslintConfigPath: string, + extendPath: string + ): string { + if (!extendPath.startsWith('..')) { + // we only need to adjust paths that are on a different directory, files + // in the same directory are moved together so their relative paths are + // not changed + return extendPath; + } + + return joinPathFragments( + offsetFromRoot(this.project.newRoot), + dirname(eslintConfigPath), + extendPath + ); + } +} diff --git a/packages/angular/src/generators/ng-add/migrators/builders/builder.migrator.ts b/packages/angular/src/generators/ng-add/migrators/builders/builder.migrator.ts index 766b8be68caa3..c106ba42ae1a9 100644 --- a/packages/angular/src/generators/ng-add/migrators/builders/builder.migrator.ts +++ b/packages/angular/src/generators/ng-add/migrators/builders/builder.migrator.ts @@ -11,7 +11,7 @@ import type { import { Migrator } from '../migrator'; export abstract class BuilderMigrator extends Migrator { - protected targets: Map = new Map(); + targets: Map = new Map(); constructor( tree: Tree, diff --git a/packages/angular/src/generators/ng-add/migrators/builders/index.ts b/packages/angular/src/generators/ng-add/migrators/builders/index.ts index 78fe0ab98c2e3..2c133b15f6896 100644 --- a/packages/angular/src/generators/ng-add/migrators/builders/index.ts +++ b/packages/angular/src/generators/ng-add/migrators/builders/index.ts @@ -1,4 +1,5 @@ export * from './angular-devkit-karma.migrator'; export * from './angular-devkit-ng-packagr.migrator'; +export * from './angular-eslint-lint.migrator'; export * from './builder-migrator-class.type'; export * from './builder.migrator'; diff --git a/packages/angular/src/generators/ng-add/migrators/migrator.ts b/packages/angular/src/generators/ng-add/migrators/migrator.ts index 15f3d3396aa53..688cfdbb81032 100644 --- a/packages/angular/src/generators/ng-add/migrators/migrator.ts +++ b/packages/angular/src/generators/ng-add/migrators/migrator.ts @@ -41,6 +41,15 @@ export abstract class Migrator { } } + protected convertRootPath(originalPath: string): string { + return originalPath?.startsWith(this.project.oldRoot) + ? joinPathFragments( + this.project.newRoot, + originalPath.replace(this.project.oldRoot, '') + ) + : originalPath; + } + protected moveFile(from: string, to: string, required: boolean = true): void { if (!this.tree.exists(from)) { if (required) { diff --git a/packages/angular/src/generators/ng-add/migrators/projects/app.migrator.spec.ts b/packages/angular/src/generators/ng-add/migrators/projects/app.migrator.spec.ts index fa7b0e004b1d9..0ba35770f8ce3 100644 --- a/packages/angular/src/generators/ng-add/migrators/projects/app.migrator.spec.ts +++ b/packages/angular/src/generators/ng-add/migrators/projects/app.migrator.spec.ts @@ -125,8 +125,8 @@ describe('app migrator', () => { expect(result[0].messageGroup.messages).toStrictEqual([ 'The "build" target is using an unsupported builder "@not/supported:builder".', ]); - expect(result[0].hint).toBe( - 'The supported builders for applications are: "@angular-devkit/build-angular:browser", "@angular-devkit/build-angular:protractor", "@cypress/schematic:cypress", "@angular-devkit/build-angular:extract-i18n", "@angular-eslint/builder:lint", "@nguniversal/builders:prerender", "@angular-devkit/build-angular:dev-server", "@angular-devkit/build-angular:server", "@nguniversal/builders:ssr-dev-server" and "@angular-devkit/build-angular:karma".' + expect(result[0].hint).toMatchInlineSnapshot( + `"The supported builders for applications are: \\"@angular-devkit/build-angular:browser\\", \\"@angular-devkit/build-angular:protractor\\", \\"@cypress/schematic:cypress\\", \\"@angular-devkit/build-angular:extract-i18n\\", \\"@nguniversal/builders:prerender\\", \\"@angular-devkit/build-angular:dev-server\\", \\"@angular-devkit/build-angular:server\\", \\"@nguniversal/builders:ssr-dev-server\\", \\"@angular-devkit/build-angular:karma\\" and \\"@angular-eslint/builder:lint\\"."` ); }); @@ -148,8 +148,8 @@ describe('app migrator', () => { 'The "build" target is using an unsupported builder "@not/supported:builder".', 'The "test" target is using an unsupported builder "@other/not-supported:builder".', ]); - expect(result[0].hint).toBe( - 'The supported builders for applications are: "@angular-devkit/build-angular:browser", "@angular-devkit/build-angular:protractor", "@cypress/schematic:cypress", "@angular-devkit/build-angular:extract-i18n", "@angular-eslint/builder:lint", "@nguniversal/builders:prerender", "@angular-devkit/build-angular:dev-server", "@angular-devkit/build-angular:server", "@nguniversal/builders:ssr-dev-server" and "@angular-devkit/build-angular:karma".' + expect(result[0].hint).toMatchInlineSnapshot( + `"The supported builders for applications are: \\"@angular-devkit/build-angular:browser\\", \\"@angular-devkit/build-angular:protractor\\", \\"@cypress/schematic:cypress\\", \\"@angular-devkit/build-angular:extract-i18n\\", \\"@nguniversal/builders:prerender\\", \\"@angular-devkit/build-angular:dev-server\\", \\"@angular-devkit/build-angular:server\\", \\"@nguniversal/builders:ssr-dev-server\\", \\"@angular-devkit/build-angular:karma\\" and \\"@angular-eslint/builder:lint\\"."` ); }); @@ -167,8 +167,8 @@ describe('app migrator', () => { expect(result[0].messageGroup.messages).toStrictEqual([ 'The "my-build" target is using an unsupported builder "@not/supported:builder".', ]); - expect(result[0].hint).toBe( - 'The supported builders for applications are: "@angular-devkit/build-angular:browser", "@angular-devkit/build-angular:protractor", "@cypress/schematic:cypress", "@angular-devkit/build-angular:extract-i18n", "@angular-eslint/builder:lint", "@nguniversal/builders:prerender", "@angular-devkit/build-angular:dev-server", "@angular-devkit/build-angular:server", "@nguniversal/builders:ssr-dev-server" and "@angular-devkit/build-angular:karma".' + expect(result[0].hint).toMatchInlineSnapshot( + `"The supported builders for applications are: \\"@angular-devkit/build-angular:browser\\", \\"@angular-devkit/build-angular:protractor\\", \\"@cypress/schematic:cypress\\", \\"@angular-devkit/build-angular:extract-i18n\\", \\"@nguniversal/builders:prerender\\", \\"@angular-devkit/build-angular:dev-server\\", \\"@angular-devkit/build-angular:server\\", \\"@nguniversal/builders:ssr-dev-server\\", \\"@angular-devkit/build-angular:karma\\" and \\"@angular-eslint/builder:lint\\"."` ); }); @@ -1578,8 +1578,8 @@ describe('app migrator', () => { 'test', 'e2e', 'myCustomTest', - 'myCustomBuild', 'myCustomLint', + 'myCustomBuild', ]); }); diff --git a/packages/angular/src/generators/ng-add/migrators/projects/app.migrator.ts b/packages/angular/src/generators/ng-add/migrators/projects/app.migrator.ts index c799d2fd43745..c0859314ce814 100644 --- a/packages/angular/src/generators/ng-add/migrators/projects/app.migrator.ts +++ b/packages/angular/src/generators/ng-add/migrators/projects/app.migrator.ts @@ -1,12 +1,10 @@ -import type { TargetConfiguration, Tree } from '@nrwl/devkit'; +import type { Tree } from '@nrwl/devkit'; import { joinPathFragments, offsetFromRoot, - readJson, updateJson, updateProjectConfiguration, } from '@nrwl/devkit'; -import { hasRulesRequiringTypeChecking } from '@nrwl/linter'; import { convertToNxProjectGenerator } from '@nrwl/workspace/generators'; import { getRootTsConfigPathInTree } from '@nrwl/workspace/src/utilities/typescript'; import { basename } from 'path'; @@ -18,7 +16,10 @@ import type { ValidationResult, } from '../../utilities'; import type { BuilderMigratorClassType } from '../builders'; -import { AngularDevkitKarmaMigrator } from '../builders'; +import { + AngularDevkitKarmaMigrator, + AngularEslintLintMigrator, +} from '../builders'; import { E2eMigrator } from './e2e.migrator'; import { ProjectMigrator } from './project.migrator'; @@ -26,7 +27,6 @@ type SupportedTargets = | 'build' | 'e2e' | 'i18n' - | 'lint' | 'prerender' | 'serve' | 'server' @@ -41,7 +41,6 @@ const supportedTargets: Record = { ], }, i18n: { builders: ['@angular-devkit/build-angular:extract-i18n'] }, - lint: { builders: ['@angular-eslint/builder:lint'] }, prerender: { builders: ['@nguniversal/builders:prerender'] }, serve: { builders: ['@angular-devkit/build-angular:dev-server'] }, server: { builders: ['@angular-devkit/build-angular:server'] }, @@ -51,12 +50,11 @@ const supportedTargets: Record = { // TODO(leo): this will replace `supportedTargets` once the full refactor is done. const supportedBuilderMigrators: BuilderMigratorClassType[] = [ AngularDevkitKarmaMigrator, + AngularEslintLintMigrator, ]; export class AppMigrator extends ProjectMigrator { private e2eMigrator: E2eMigrator; - private newEsLintConfigPath: string; - private oldEsLintConfigPath: string; constructor( tree: Tree, @@ -74,20 +72,18 @@ export class AppMigrator extends ProjectMigrator { supportedBuilderMigrators ); + const eslintBuilderMigrator = + this.builderMigrators[ + supportedBuilderMigrators.indexOf(AngularEslintLintMigrator) + ]; this.e2eMigrator = new E2eMigrator( tree, options, project, - this.targetNames.lint + eslintBuilderMigrator.targets.size + ? Object.keys(eslintBuilderMigrator.targets)[0] + : undefined ); - - if (this.targetNames.lint) { - this.oldEsLintConfigPath = - this.projectConfig.targets[this.targetNames.lint].options - ?.eslintConfig ?? - joinPathFragments(this.project.oldRoot, '.eslintrc.json'); - this.newEsLintConfigPath = this.convertRootPath(this.oldEsLintConfigPath); - } } override async migrate(): Promise { @@ -101,13 +97,8 @@ export class AppMigrator extends ProjectMigrator { } this.updateTsConfigs(); - this.updateEsLintConfig(); this.updateCacheableOperations( - [ - this.targetNames.build, - this.targetNames.lint, - this.targetNames.e2e, - ].filter(Boolean) + [this.targetNames.build, this.targetNames.e2e].filter(Boolean) ); } @@ -151,20 +142,6 @@ export class AppMigrator extends ProjectMigrator { ); } - if (this.targetNames.lint) { - this.moveProjectRootFile(this.oldEsLintConfigPath); - } else { - // there could still be a .eslintrc.json file in the root - // so move to new location - const eslintConfig = '.eslintrc.json'; - if (this.tree.exists(eslintConfig)) { - this.logger.info( - 'No "lint" target was found, but an ESLint config file was found in the project root. The file will be moved to the new location.' - ); - this.moveProjectRootFile(eslintConfig); - } - } - this.moveDir(this.project.oldSourceRoot, this.project.newSourceRoot); } @@ -181,7 +158,6 @@ export class AppMigrator extends ProjectMigrator { ); } else { this.updateBuildTargetConfiguration(); - this.updateLintTargetConfiguration(); this.updateServerTargetConfiguration(); this.updatePrerenderTargetConfiguration(); this.updateServeSsrTargetConfiguration(); @@ -208,49 +184,6 @@ export class AppMigrator extends ProjectMigrator { this.updateTsConfigFileUsedByServerTarget(projectOffsetFromRoot); } - private updateEsLintConfig(): void { - if (!this.targetNames.lint || !this.tree.exists(this.newEsLintConfigPath)) { - return; - } - - updateJson(this.tree, this.newEsLintConfigPath, (json) => { - delete json.root; - json.ignorePatterns = ['!**/*']; - - const rootEsLintConfigRelativePath = joinPathFragments( - offsetFromRoot(this.projectConfig.root), - '.eslintrc.json' - ); - if (Array.isArray(json.extends)) { - json.extends = json.extends.map((extend: string) => - this.convertEsLintConfigExtendToNewPath( - this.oldEsLintConfigPath, - extend - ) - ); - - // it might have not been extending from the root config, make sure it does - if (!json.extends.includes(rootEsLintConfigRelativePath)) { - json.extends.unshift(rootEsLintConfigRelativePath); - } - } else { - json.extends = rootEsLintConfigRelativePath; - } - - json.overrides?.forEach((override) => { - if (!override.parserOptions?.project) { - return; - } - - override.parserOptions.project = [ - `${this.projectConfig.root}/tsconfig.*?.json`, - ]; - }); - - return json; - }); - } - private convertBuildOptions(buildOptions: any): void { buildOptions.outputPath = buildOptions.outputPath && @@ -345,74 +278,6 @@ export class AppMigrator extends ProjectMigrator { ); } - private updateLintTargetConfiguration(): void { - if (!this.targetNames.lint) { - return; - } - - this.projectConfig.targets[this.targetNames.lint].executor = - '@nrwl/linter:eslint'; - - const lintOptions = - this.projectConfig.targets[this.targetNames.lint].options; - if (!lintOptions) { - this.logger.warn( - `The target "${this.targetNames.lint}" is not specifying any options. Skipping updating the target configuration.` - ); - return; - } - - const existEsLintConfigPath = this.tree.exists(this.newEsLintConfigPath); - if (!existEsLintConfigPath) { - this.logger.warn( - `The ESLint config file "${this.oldEsLintConfigPath}" could not be found. Skipping updating the file.` - ); - } - - lintOptions.eslintConfig = - lintOptions.eslintConfig && - joinPathFragments( - this.project.newRoot, - basename(lintOptions.eslintConfig) - ); - lintOptions.lintFilePatterns = - lintOptions.lintFilePatterns && - lintOptions.lintFilePatterns.map((pattern) => { - // replace the old source root with the new root, we want to lint all - // matching files in the project, not just the ones in the source root - if (pattern.startsWith(this.project.oldSourceRoot)) { - return joinPathFragments( - this.project.newRoot, - pattern.replace(this.project.oldSourceRoot, '') - ); - } - - // replace the old root with the new root - if (pattern.startsWith(this.project.oldRoot)) { - return joinPathFragments( - this.project.newRoot, - pattern.replace(this.project.oldRoot, '') - ); - } - - // do nothing, warn about the pattern - this.logger.warn( - `The lint file pattern "${pattern}" specified in the "${this.targetNames.lint}" target is not contained in the project root or source root. The pattern will not be updated.` - ); - - return pattern; - }); - - if (!existEsLintConfigPath) { - return; - } - - const eslintConfig = readJson(this.tree, this.newEsLintConfigPath); - if (hasRulesRequiringTypeChecking(eslintConfig)) { - lintOptions.hasTypeAwareRules = true; - } - } - private updatePrerenderTargetConfiguration(): void { if (!this.targetNames.prerender) { return; diff --git a/packages/angular/src/generators/ng-add/migrators/projects/lib.migrator.spec.ts b/packages/angular/src/generators/ng-add/migrators/projects/lib.migrator.spec.ts index 6b76634ec2270..bd540ae8fc5c7 100644 --- a/packages/angular/src/generators/ng-add/migrators/projects/lib.migrator.spec.ts +++ b/packages/angular/src/generators/ng-add/migrators/projects/lib.migrator.spec.ts @@ -129,7 +129,7 @@ describe('lib migrator', () => { 'The "build" target is using an unsupported builder "@not/supported:builder".', ]); expect(result[0].hint).toMatchInlineSnapshot( - `"The supported builders for libraries are: \\"@angular-eslint/builder:lint\\", \\"@angular-devkit/build-angular:ng-packagr\\" and \\"@angular-devkit/build-angular:karma\\"."` + `"The supported builders for libraries are: \\"@angular-devkit/build-angular:ng-packagr\\", \\"@angular-devkit/build-angular:karma\\" and \\"@angular-eslint/builder:lint\\"."` ); }); @@ -152,7 +152,7 @@ describe('lib migrator', () => { 'The "test" target is using an unsupported builder "@other/not-supported:builder".', ]); expect(result[0].hint).toMatchInlineSnapshot( - `"The supported builders for libraries are: \\"@angular-eslint/builder:lint\\", \\"@angular-devkit/build-angular:ng-packagr\\" and \\"@angular-devkit/build-angular:karma\\"."` + `"The supported builders for libraries are: \\"@angular-devkit/build-angular:ng-packagr\\", \\"@angular-devkit/build-angular:karma\\" and \\"@angular-eslint/builder:lint\\"."` ); }); @@ -171,7 +171,7 @@ describe('lib migrator', () => { 'The "my-build" target is using an unsupported builder "@not/supported:builder".', ]); expect(result[0].hint).toMatchInlineSnapshot( - `"The supported builders for libraries are: \\"@angular-eslint/builder:lint\\", \\"@angular-devkit/build-angular:ng-packagr\\" and \\"@angular-devkit/build-angular:karma\\"."` + `"The supported builders for libraries are: \\"@angular-devkit/build-angular:ng-packagr\\", \\"@angular-devkit/build-angular:karma\\" and \\"@angular-eslint/builder:lint\\"."` ); }); @@ -212,16 +212,16 @@ describe('lib migrator', () => { expect(result).toHaveLength(2); expect(result[0].message).toBe( - 'There is more than one target using a builder that is used to lint the project ("lint1" and "lint2").' + 'There is more than one target using a builder that is used to build the project ("build1" and "build2").' ); expect(result[0].hint).toBe( - 'Make sure the project only has one target with a builder that is used to lint the project.' + 'Make sure the project only has one target with a builder that is used to build the project.' ); expect(result[1].message).toBe( - 'There is more than one target using a builder that is used to build the project ("build1" and "build2").' + 'There is more than one target using a builder that is used to lint the project ("lint1" and "lint2").' ); expect(result[1].hint).toBe( - 'Make sure the project only has one target with a builder that is used to build the project.' + 'Make sure the project only has one target with a builder that is used to lint the project.' ); }); diff --git a/packages/angular/src/generators/ng-add/migrators/projects/lib.migrator.ts b/packages/angular/src/generators/ng-add/migrators/projects/lib.migrator.ts index 25f137de7cd76..25bcc14ff2f33 100644 --- a/packages/angular/src/generators/ng-add/migrators/projects/lib.migrator.ts +++ b/packages/angular/src/generators/ng-add/migrators/projects/lib.migrator.ts @@ -1,18 +1,10 @@ import type { Tree } from '@nrwl/devkit'; -import { - joinPathFragments, - offsetFromRoot, - readJson, - updateJson, - updateProjectConfiguration, -} from '@nrwl/devkit'; -import { hasRulesRequiringTypeChecking } from '@nrwl/linter'; +import { updateProjectConfiguration } from '@nrwl/devkit'; import { convertToNxProjectGenerator } from '@nrwl/workspace/generators'; import type { GeneratorOptions } from '../../schema'; import type { Logger, MigrationProjectConfiguration, - Target, ValidationError, ValidationResult, } from '../../utilities'; @@ -20,23 +12,17 @@ import type { BuilderMigratorClassType } from '../builders'; import { AngularDevkitKarmaMigrator, AngularDevkitNgPackagrMigrator, + AngularEslintLintMigrator, } from '../builders'; import { ProjectMigrator } from './project.migrator'; -type SupportedTargets = 'lint'; -const supportedTargets: Record = { - lint: { builders: ['@angular-eslint/builder:lint'] }, -}; -// TODO(leo): this will replace `supportedTargets` once the full refactor is done. const supportedBuilderMigrators: BuilderMigratorClassType[] = [ AngularDevkitNgPackagrMigrator, AngularDevkitKarmaMigrator, + AngularEslintLintMigrator, ]; -export class LibMigrator extends ProjectMigrator { - private oldEsLintConfigPath: string; - private newEsLintConfigPath: string; - +export class LibMigrator extends ProjectMigrator { constructor( tree: Tree, options: GeneratorOptions, @@ -46,20 +32,12 @@ export class LibMigrator extends ProjectMigrator { super( tree, options, - supportedTargets, + {}, project, 'libs', logger, supportedBuilderMigrators ); - - if (this.targetNames.lint) { - this.oldEsLintConfigPath = - this.projectConfig.targets[this.targetNames.lint].options - ?.eslintConfig ?? - joinPathFragments(this.project.oldRoot, '.eslintrc.json'); - this.newEsLintConfigPath = this.convertRootPath(this.oldEsLintConfigPath); - } } override async migrate(): Promise { @@ -69,9 +47,6 @@ export class LibMigrator extends ProjectMigrator { for (const builderMigrator of this.builderMigrators ?? []) { await builderMigrator.migrate(); } - - this.updateEsLintConfig(); - this.updateCacheableOperations([this.targetNames.lint].filter(Boolean)); } override validate(): ValidationResult { @@ -99,8 +74,6 @@ export class LibMigrator extends ProjectMigrator { this.logger.warn( 'The project does not have any targets configured. This might not be an issue. Skipping updating targets.' ); - } else { - this.updateLintTargetConfiguration(); } updateProjectConfiguration(this.tree, this.project.name, { @@ -112,111 +85,4 @@ export class LibMigrator extends ProjectMigrator { skipFormat: true, }); } - - private updateEsLintConfig(): void { - if (!this.targetNames.lint || !this.tree.exists(this.newEsLintConfigPath)) { - return; - } - - updateJson(this.tree, this.newEsLintConfigPath, (json) => { - delete json.root; - json.ignorePatterns = ['!**/*']; - - const rootEsLintConfigRelativePath = joinPathFragments( - offsetFromRoot(this.projectConfig.root), - '.eslintrc.json' - ); - if (Array.isArray(json.extends)) { - json.extends = json.extends.map((extend: string) => - this.convertEsLintConfigExtendToNewPath( - this.oldEsLintConfigPath, - extend - ) - ); - - // it might have not been extending from the root config, make sure it does - if (!json.extends.includes(rootEsLintConfigRelativePath)) { - json.extends.unshift(rootEsLintConfigRelativePath); - } - } else { - json.extends = rootEsLintConfigRelativePath; - } - - json.overrides?.forEach((override) => { - if (!override.parserOptions?.project) { - return; - } - - override.parserOptions.project = [ - `${this.projectConfig.root}/tsconfig.*?.json`, - ]; - }); - - return json; - }); - } - - private updateLintTargetConfiguration(): void { - if (!this.targetNames.lint) { - return; - } - - this.projectConfig.targets[this.targetNames.lint].executor = - '@nrwl/linter:eslint'; - - const lintOptions = - this.projectConfig.targets[this.targetNames.lint].options; - if (!lintOptions) { - this.logger.warn( - `The target "${this.targetNames.lint}" is not specifying any options. Skipping updating the target configuration.` - ); - return; - } - - const existEsLintConfigPath = this.tree.exists(this.oldEsLintConfigPath); - if (!existEsLintConfigPath) { - this.logger.warn( - `The ESLint config file "${this.oldEsLintConfigPath}" could not be found. Skipping updating the file.` - ); - } - - lintOptions.eslintConfig = - lintOptions.eslintConfig && this.newEsLintConfigPath; - lintOptions.lintFilePatterns = - lintOptions.lintFilePatterns && - lintOptions.lintFilePatterns.map((pattern) => { - // replace the old source root with the new root, we want to lint all - // matching files in the project, not just the ones in the source root - if (pattern.startsWith(this.project.oldSourceRoot)) { - return joinPathFragments( - this.project.newRoot, - pattern.replace(this.project.oldSourceRoot, '') - ); - } - - // replace the old root with the new root - if (pattern.startsWith(this.project.oldRoot)) { - return joinPathFragments( - this.project.newRoot, - pattern.replace(this.project.oldRoot, '') - ); - } - - // do nothing, warn about the pattern - this.logger.warn( - `The lint file pattern "${pattern}" specified in the "${this.targetNames.lint}" target is not contained in the project root or source root. The pattern will not be updated.` - ); - - return pattern; - }); - - if (!existEsLintConfigPath) { - return; - } - - const eslintConfig = readJson(this.tree, this.oldEsLintConfigPath); - if (hasRulesRequiringTypeChecking(eslintConfig)) { - lintOptions.hasTypeAwareRules = true; - } - } } diff --git a/packages/angular/src/generators/ng-add/migrators/projects/project.migrator.ts b/packages/angular/src/generators/ng-add/migrators/projects/project.migrator.ts index 1ed7b5687ba73..9fb6abaf69d5c 100644 --- a/packages/angular/src/generators/ng-add/migrators/projects/project.migrator.ts +++ b/packages/angular/src/generators/ng-add/migrators/projects/project.migrator.ts @@ -185,33 +185,6 @@ export abstract class ProjectMigrator< return errors.length ? errors : null; } - protected convertEsLintConfigExtendToNewPath( - eslintConfigPath: string, - extendPath: string - ): string { - if (!extendPath.startsWith('..')) { - // we only need to adjust paths that are on a different directory, files - // in the same directory are moved together so their relative paths are - // not changed - return extendPath; - } - - return joinPathFragments( - offsetFromRoot(this.project.newRoot), - dirname(eslintConfigPath), - extendPath - ); - } - - protected convertRootPath(originalPath: string): string { - return originalPath?.startsWith(this.project.oldRoot) - ? joinPathFragments( - this.project.newRoot, - originalPath.replace(this.project.oldRoot, '') - ) - : originalPath; - } - protected convertPath(originalPath: string): string { if (originalPath?.startsWith(this.project.oldSourceRoot)) { return joinPathFragments(