Skip to content

feat(@schematics/angular): remove tslint and codelyzer from new projects #20291

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Mar 16, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions packages/angular/cli/commands/deploy-impl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,11 @@
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import { ArchitectCommand, ArchitectCommandOptions } from '../models/architect-command';
import { ArchitectCommand } from '../models/architect-command';
import { Arguments } from '../models/interface';
import { Schema as DeployCommandSchema } from './deploy';

const BuilderMissing = `

Cannot find "deploy" target for the specified project.

You should add a package that implements deployment capabilities for your
Expand Down
22 changes: 17 additions & 5 deletions packages/angular/cli/commands/lint-impl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,27 @@
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import { ArchitectCommand, ArchitectCommandOptions } from '../models/architect-command';
import { ArchitectCommand } from '../models/architect-command';
import { Arguments } from '../models/interface';
import { Schema as LintCommandSchema } from './lint';

const MissingBuilder = `
Cannot find "lint" target for the specified project.

You should add a package that implements linting capabilities.

For example:
ng add @angular-eslint/schematics
`;

export class LintCommand extends ArchitectCommand<LintCommandSchema> {
public readonly target = 'lint';
public readonly multiTarget = true;
readonly target = 'lint';
readonly multiTarget = true;
readonly missingTargetError = MissingBuilder;

public async run(options: ArchitectCommandOptions & Arguments) {
return this.runArchitectTarget(options);
async initialize(options: LintCommandSchema & Arguments): Promise<number | void> {
if (!options.help) {
return super.initialize(options);
}
}
}
23 changes: 18 additions & 5 deletions packages/angular/cli/commands/lint-long.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,20 @@
Takes the name of the project, as specified in the `projects` section of the `angular.json` workspace configuration file.
When a project name is not supplied, it will execute for all projects.
The command takes an optional project name, as specified in the `projects` section of the `angular.json` workspace configuration file.
When a project name is not supplied, executes the `lint` builder for the default project.

The default linting tool is [TSLint](https://palantir.github.io/tslint/), and the default configuration is specified in the project's `tslint.json` file.
To use the `ng lint` command, use `ng add` to add a package that implements linting capabilities. Adding the package automatically updates your workspace configuration, adding a lint [CLI builder](guide/cli-builder).
For example:

**Note**: TSLint has been discontinued and support has been deprecated in the Angular CLI. The options shown below are for the deprecated TSLint builder.
To opt-in using the community driven ESLint builder, see [angular-eslint](https://github.com/angular-eslint/angular-eslint#migrating-an-angular-cli-project-from-codelyzer-and-tslint) README.
```json
"projects": {
"my-project": {
...
"architect": {
...
"lint": {
"builder": "@angular-eslint/builder:lint",
"options": {}
}
}
}
}
```
7 changes: 3 additions & 4 deletions packages/angular/cli/commands/lint.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"description": "Runs linting tools on Angular app code in a given project folder.",
"$longDescription": "./lint-long.md",

"$aliases": [ "l" ],
"$aliases": ["l"],
"$scope": "in",
"$type": "architect",
"$impl": "./lint-impl#LintCommand",
Expand All @@ -22,15 +22,14 @@
}
},
"configuration": {
"description": "The linting configuration to use.",
"description": "One or more named builder configurations as a comma-separated list as specified in the \"configurations\" section of angular.json.\nThe builder uses the named configurations to run the given target.\nFor more information, see https://angular.io/guide/workspace-config#alternate-build-configurations.",
"type": "string",
"aliases": [
"c"
]
}
},
"required": [
]
"required": []
},
{
"$ref": "./definitions.json#/definitions/base"
Expand Down
18 changes: 0 additions & 18 deletions packages/schematics/angular/application/files/tslint.json.template

This file was deleted.

38 changes: 1 addition & 37 deletions packages/schematics/angular/application/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ import { NodePackageInstallTask } from '@angular-devkit/schematics/tasks';
import { Schema as ComponentOptions } from '../component/schema';
import { Schema as E2eOptions } from '../e2e/schema';
import { NodeDependencyType, addPackageJsonDependency } from '../utility/dependencies';
import { JSONFile } from '../utility/json-file';
import { latestVersions } from '../utility/latest-versions';
import { applyLintFix } from '../utility/lint-fix';
import { relativePathToWorkspaceRoot } from '../utility/paths';
Expand Down Expand Up @@ -68,28 +67,6 @@ function addDependenciesToPackageJson(options: ApplicationOptions) {
};
}

/**
* Merges the application tslint.json with the workspace tslint.json
* when the application being created is a root application
*
* @param {Tree} parentHost The root host of the schematic
*/
function mergeWithRootTsLint(parentHost: Tree) {
return (host: Tree) => {
const tsLintPath = '/tslint.json';
const rulesPath = ['rules'];
if (!host.exists(tsLintPath)) {
return;
}

const rootTsLintFile = new JSONFile(parentHost, tsLintPath);
const rootRules = rootTsLintFile.get(rulesPath) as {};
const appRules = new JSONFile(host, tsLintPath).get(rulesPath) as {};
rootTsLintFile.modify(rulesPath, { ...rootRules, ...appRules });
host.overwrite(tsLintPath, rootTsLintFile.content);
};
}

function addAppToWorkspaceFile(options: ApplicationOptions, appDir: string): Rule {
let projectRoot = appDir;
if (projectRoot) {
Expand Down Expand Up @@ -245,18 +222,6 @@ function addAppToWorkspaceFile(options: ApplicationOptions, appDir: string): Rul
scripts: [],
},
},
lint: options.minimal ? undefined : {
builder: Builders.TsLint,
options: {
tsConfig: [
`${projectRoot}tsconfig.app.json`,
`${projectRoot}tsconfig.spec.json`,
],
exclude: [
'**/node_modules/**',
],
},
},
},
};

Expand All @@ -272,7 +237,7 @@ function addAppToWorkspaceFile(options: ApplicationOptions, appDir: string): Rul
});
}
function minimalPathFilter(path: string): boolean {
const toRemoveList = /(test.ts|tsconfig.spec.json|karma.conf.js|tslint.json).template$/;
const toRemoveList = /(test.ts|tsconfig.spec.json|karma.conf.js).template$/;

return !toRemoveList.test(path);
}
Expand Down Expand Up @@ -327,7 +292,6 @@ export default function (options: ApplicationOptions): Rule {
appName: options.name,
isRootApp,
}),
isRootApp ? mergeWithRootTsLint(host) : noop(),
move(appDir),
]), MergeStrategy.Overwrite),
schematic('module', {
Expand Down
65 changes: 1 addition & 64 deletions packages/schematics/angular/application/index_spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,6 @@ describe('Application Schematic', () => {
'/projects/foo/karma.conf.js',
'/projects/foo/tsconfig.app.json',
'/projects/foo/tsconfig.spec.json',
'/projects/foo/tslint.json',
'/projects/foo/src/environments/environment.ts',
'/projects/foo/src/environments/environment.prod.ts',
'/projects/foo/src/favicon.ico',
Expand Down Expand Up @@ -153,42 +152,21 @@ describe('Application Schematic', () => {
expect(_extends).toBe('../../tsconfig.json');
});

it('should set the right path and prefix in the tslint file', async () => {
const tree = await schematicRunner.runSchematicAsync('application', defaultOptions, workspaceTree)
.toPromise();
const path = '/projects/foo/tslint.json';
const content = JSON.parse(tree.readContent(path));
expect(content.extends).toMatch('../../tslint.json');
expect(content.rules['directive-selector'][2]).toMatch('app');
expect(content.rules['component-selector'][2]).toMatch('app');
});

it('should set the right prefix in the tslint file when provided is kebabed', async () => {
const options: ApplicationOptions = { ...defaultOptions, prefix: 'foo-bar' };
const tree = await schematicRunner.runSchematicAsync('application', options, workspaceTree)
.toPromise();
const path = '/projects/foo/tslint.json';
const content = JSON.parse(tree.readContent(path));
expect(content.rules['directive-selector'][2]).toMatch('fooBar');
expect(content.rules['component-selector'][2]).toMatch('foo-bar');
});

it('should set the right coverage folder in the karma.json file', async () => {
const tree = await schematicRunner.runSchematicAsync('application', defaultOptions, workspaceTree)
.toPromise();
const karmaConf = getFileContent(tree, '/projects/foo/karma.conf.js');
expect(karmaConf).toContain(`dir: require('path').join(__dirname, '../../coverage/foo')`);
});

it('minimal=true should not create e2e, lint and test targets', async () => {
it('minimal=true should not create e2e and test targets', async () => {
const options = { ...defaultOptions, minimal: true };
const tree = await schematicRunner.runSchematicAsync('application', options, workspaceTree)
.toPromise();
const config = JSON.parse(tree.readContent('/angular.json'));
const architect = config.projects.foo.architect;
expect(architect.test).not.toBeDefined();
expect(architect.e2e).not.toBeDefined();
expect(architect.e2e).not.toBeDefined();
});

it('minimal=true should configure the schematics options for components', async () => {
Expand Down Expand Up @@ -235,7 +213,6 @@ describe('Application Schematic', () => {
const files = tree.files;
[
'/projects/foo/tsconfig.spec.json',
'/projects/foo/tslint.json',
'/projects/foo/karma.conf.js',
'/projects/foo/src/test.ts',
'/projects/foo/src/app/app.component.css',
Expand Down Expand Up @@ -264,7 +241,6 @@ describe('Application Schematic', () => {
const files = tree.files;
[
'/projects/foo/tsconfig.spec.json',
'/projects/foo/tslint.json',
'/projects/foo/karma.conf.js',
'/projects/foo/src/test.ts',
'/projects/foo/src/app/app.component.html',
Expand Down Expand Up @@ -293,7 +269,6 @@ describe('Application Schematic', () => {
const files = tree.files;
[
'/projects/foo/tsconfig.spec.json',
'/projects/foo/tslint.json',
'/projects/foo/karma.conf.js',
'/projects/foo/src/test.ts',
'/projects/foo/src/app/app.component.css',
Expand Down Expand Up @@ -355,18 +330,6 @@ describe('Application Schematic', () => {
const packageJson = JSON.parse(tree.readContent('package.json'));
expect(packageJson.devDependencies['@angular-devkit/build-angular']).toBeUndefined();
});

it('should set the lint tsConfig option', async () => {
const tree = await schematicRunner.runSchematicAsync('application', defaultOptions, workspaceTree)
.toPromise();
const workspace = JSON.parse(tree.readContent('/angular.json'));
const lintOptions = workspace.projects.foo.architect.lint.options;
expect(lintOptions.tsConfig).toEqual([
'projects/foo/tsconfig.app.json',
'projects/foo/tsconfig.spec.json',
'projects/foo/e2e/tsconfig.json',
]);
});
});

describe('custom projectRoot', () => {
Expand All @@ -380,7 +343,6 @@ describe('Application Schematic', () => {
'/karma.conf.js',
'/tsconfig.app.json',
'/tsconfig.spec.json',
'/tslint.json',
'/src/environments/environment.ts',
'/src/environments/environment.prod.ts',
'/src/favicon.ico',
Expand Down Expand Up @@ -448,31 +410,6 @@ describe('Application Schematic', () => {
expect(specTsConfig.files).toEqual(['src/test.ts', 'src/polyfills.ts']);
});

it('should set the relative path and prefix in the tslint file', async () => {
const options = { ...defaultOptions, projectRoot: '' };

const tree = await schematicRunner.runSchematicAsync('application', options, workspaceTree)
.toPromise();
const content = JSON.parse(tree.readContent('/tslint.json'));
expect(content.extends).toMatch('tslint:recommended');
expect(content.rules['directive-selector'][2]).toMatch('app');
expect(content.rules['component-selector'][2]).toMatch('app');
});

it('should merge tslint file', async () => {
const options = { ...defaultOptions, projectRoot: '' };

const tree = await schematicRunner.runSchematicAsync('application', options, workspaceTree)
.toPromise();
const content = JSON.parse(tree.readContent('/tslint.json'));
expect(content.extends).toMatch('tslint:recommended');
expect(content.rules['component-selector'][2]).toMatch('app');
expect(content.rules['no-console']).toBeDefined();
// codelyzer rules should be after base tslint rules
expect(Object.keys(content.rules).indexOf('component-selector'))
.toBeGreaterThan(Object.keys(content.rules).indexOf('no-console'));
});

it(`should create correct paths when 'newProjectRoot' is blank`, async () => {
const workspaceTree = await schematicRunner.runSchematicAsync('workspace', { ...workspaceOptions, newProjectRoot: '' }).toPromise();
const options = { ...defaultOptions, projectRoot: undefined };
Expand Down
7 changes: 0 additions & 7 deletions packages/schematics/angular/e2e/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,13 +62,6 @@ export default function (options: E2eOptions): Rule {
},
});

const e2eTsConfig = `${root}/tsconfig.json`;
const lintTarget = project.targets.get('lint');
if (lintTarget && lintTarget.options && Array.isArray(lintTarget.options.tsConfig)) {
lintTarget.options.tsConfig =
lintTarget.options.tsConfig.concat(e2eTsConfig);
}

return chain([
updateWorkspace(workspace),
mergeWith(
Expand Down
17 changes: 0 additions & 17 deletions packages/schematics/angular/library/files/tslint.json.template

This file was deleted.

12 changes: 0 additions & 12 deletions packages/schematics/angular/library/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -116,18 +116,6 @@ function addLibToWorkspaceFile(
karmaConfig: `${projectRoot}/karma.conf.js`,
},
},
lint: {
builder: Builders.TsLint,
options: {
tsConfig: [
`${projectRoot}/tsconfig.lib.json`,
`${projectRoot}/tsconfig.spec.json`,
],
exclude: [
'**/node_modules/**',
],
},
},
},
});
});
Expand Down
Loading