-
Notifications
You must be signed in to change notification settings - Fork 12k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
refactor(lint): use tslint api for linting (#4248)
Closes #867, #3993 BREAKING CHANGE: In order to use the updated `ng lint` command, the following section will have to be added to the project's `angular-cli.json` at the root level of the json object. ```json "lint": [ { "files": "src/**/*.ts", "project": "src/tsconfig.json" }, { "files": "e2e/**/*.ts", "project": "e2e/tsconfig.json" } ], ``` Alternatively, you can run `ng update`.
- Loading branch information
1 parent
1bbd12d
commit 0664beb
Showing
14 changed files
with
224 additions
and
32 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,8 +1,14 @@ | ||
<!-- Links in /docs/documentation should NOT have `.md` at the end, because they end up in our wiki at release. --> | ||
|
||
# ng lint | ||
|
||
## Overview | ||
`ng lint` will lint your app code. | ||
`ng lint` will lint you app code using tslint. | ||
|
||
## Options | ||
|
||
`--fix` will attempt to fix lint errors | ||
|
||
This will use the `lint` npm script that in generated projects uses `tslint`. | ||
`--force` will always return error code 0 even with lint errors | ||
|
||
You can modify the these scripts in `package.json` to run whatever tool you prefer. | ||
`--format` (`-t`) the output formatter to use |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,16 +1,29 @@ | ||
const Command = require('../ember-cli/lib/models/command'); | ||
|
||
export interface LintCommandOptions { | ||
fix?: boolean; | ||
format?: string; | ||
force?: boolean; | ||
} | ||
|
||
export default Command.extend({ | ||
name: 'lint', | ||
aliases: ['l'], | ||
description: 'Lints code in existing project', | ||
works: 'insideProject', | ||
run: function () { | ||
availableOptions: [ | ||
{ name: 'fix', type: Boolean, default: false }, | ||
{ name: 'force', type: Boolean, default: false }, | ||
{ name: 'format', alias: 't', type: String, default: 'prose' } | ||
], | ||
run: function (commandOptions: LintCommandOptions) { | ||
const LintTask = require('../tasks/lint').default; | ||
|
||
const lintTask = new LintTask({ | ||
ui: this.ui, | ||
project: this.project | ||
}); | ||
|
||
return lintTask.run(); | ||
return lintTask.run(commandOptions); | ||
} | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,22 +1,61 @@ | ||
const Task = require('../ember-cli/lib/models/task'); | ||
import * as chalk from 'chalk'; | ||
import {exec} from 'child_process'; | ||
import * as path from 'path'; | ||
import { requireDependency } from '../utilities/require-project-module'; | ||
import { CliConfig } from '../models/config'; | ||
import { LintCommandOptions } from '../commands/lint'; | ||
import { oneLine } from 'common-tags'; | ||
|
||
export default Task.extend({ | ||
run: function () { | ||
run: function (commandOptions: LintCommandOptions) { | ||
const ui = this.ui; | ||
const projectRoot = this.project.root; | ||
|
||
return new Promise(function(resolve, reject) { | ||
exec('npm run lint', (err, stdout) => { | ||
ui.writeLine(stdout); | ||
if (err) { | ||
ui.writeLine(chalk.red('Lint errors found in the listed files.')); | ||
reject(); | ||
} else { | ||
ui.writeLine(chalk.green('All files pass linting.')); | ||
resolve(); | ||
} | ||
return new Promise(function (resolve, reject) { | ||
const tslint = requireDependency(projectRoot, 'tslint'); | ||
const Linter = tslint.Linter; | ||
const Configuration = tslint.Configuration; | ||
|
||
const lintConfigs = CliConfig.fromProject().config.lint || []; | ||
|
||
if (lintConfigs.length === 0) { | ||
ui.writeLine(chalk.yellow(oneLine` | ||
No lint config(s) found. | ||
If this is not intended, run "ng update". | ||
`)); | ||
return resolve(0); | ||
} | ||
|
||
let errors = 0; | ||
|
||
lintConfigs.forEach((config) => { | ||
const program = Linter.createProgram(config.project); | ||
const files: string[] = Linter.getFileNames(program); | ||
|
||
const linter = new Linter({ | ||
fix: commandOptions.fix, | ||
formatter: commandOptions.format | ||
}, program); | ||
|
||
files.forEach((file) => { | ||
const fileContents = program.getSourceFile(file).getFullText(); | ||
const configLoad = Configuration.findConfiguration(config.tslintConfig, file); | ||
linter.lint(file, fileContents, configLoad.results); | ||
}); | ||
|
||
const result = linter.getResult(); | ||
errors += result.failureCount; | ||
|
||
ui.writeLine(result.output.trim().concat('\n')); | ||
}); | ||
|
||
if (errors > 0) { | ||
ui.writeLine(chalk.red('Lint errors found in the listed files.')); | ||
return commandOptions.force ? resolve(0) : resolve(2); | ||
} | ||
|
||
ui.writeLine(chalk.green('All files pass linting.')); | ||
return resolve(0); | ||
}); | ||
} | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
import * as path from 'path'; | ||
|
||
// require dependencies within the target project | ||
export function requireDependency(root: string, moduleName: string) { | ||
const packageJson = require(path.join(root, 'node_modules', moduleName, 'package.json')); | ||
const main = path.normalize(packageJson.main); | ||
return require(path.join(root, 'node_modules', moduleName, main)); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
import { ng } from '../../utils/process'; | ||
import { oneLine } from 'common-tags'; | ||
|
||
export default function () { | ||
return Promise.resolve() | ||
.then(() => ng('set', 'lint', '[]')) | ||
.then(() => ng('lint')) | ||
.then((output) => { | ||
if (!output.match(/No lint config\(s\) found\./)) { | ||
throw new Error(oneLine` | ||
Expected to match "No lint configs found." | ||
in ${output}. | ||
`); | ||
} | ||
|
||
return output; | ||
}) | ||
.then((output) => { | ||
if (!output.match(/If this is not intended, run "ng update"\./)) { | ||
throw new Error(oneLine` | ||
Expected to match "If this is not intended, run "ng update"." | ||
in ${output}. | ||
`); | ||
} | ||
|
||
return output; | ||
}); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
import { ng } from '../../utils/process'; | ||
import { readFile, writeFile } from '../../utils/fs'; | ||
|
||
export default function () { | ||
const fileName = 'src/app/foo.ts'; | ||
|
||
return Promise.resolve() | ||
.then(() => writeFile(fileName, 'const foo = "";\n')) | ||
.then(() => ng('lint', '--fix', '--force')) | ||
.then(() => readFile(fileName)) | ||
.then(content => { | ||
if (!content.match(/const foo = '';/)) { | ||
throw new Error(`Expected to match "const foo = '';" in ${content}.`); | ||
} | ||
}); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
import { ng } from '../../utils/process'; | ||
import { writeFile } from '../../utils/fs'; | ||
import { oneLine } from 'common-tags'; | ||
|
||
export default function () { | ||
const fileName = 'src/app/foo.ts'; | ||
|
||
return Promise.resolve() | ||
.then(() => writeFile(fileName, 'const foo = "";\n')) | ||
.then(() => ng('lint', '--force')) | ||
.then((output) => { | ||
if (!output.match(/" should be '/)) { | ||
throw new Error(`Expected to match "" should be '" in ${output}.`); | ||
} | ||
|
||
return output; | ||
}) | ||
.then((output) => { | ||
if (!output.match(/Lint errors found in the listed files\./)) { | ||
throw new Error(oneLine` | ||
Expected to match "Lint errors found in the listed files." | ||
in ${output}. | ||
`); | ||
} | ||
}); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
import { ng } from '../../utils/process'; | ||
import { writeFile } from '../../utils/fs'; | ||
import { oneLine } from 'common-tags'; | ||
|
||
export default function () { | ||
const fileName = 'src/app/foo.ts'; | ||
|
||
return Promise.resolve() | ||
.then(() => writeFile(fileName, 'const foo = "";\n')) | ||
.then(() => ng('lint', '--format=stylish', '--force')) | ||
.then((output) => { | ||
if (!output.match(/1:13 quotemark " should be '/)) { | ||
throw new Error(oneLine` | ||
Expected to match "1:13 quotemark " should be '" | ||
in ${output}. | ||
`); | ||
} | ||
}); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
import { ng } from '../../utils/process'; | ||
import { oneLine } from 'common-tags'; | ||
|
||
export default function () { | ||
return ng('lint') | ||
.then((output) => { | ||
if (!output.match(/All files pass linting\./)) { | ||
throw new Error(oneLine` | ||
Expected to match "All files pass linting." | ||
in ${output}. | ||
`); | ||
} | ||
}); | ||
} |
This file was deleted.
Oops, something went wrong.
please leave "lint": "ng lint" to be consistent with the rest of the script (see start, test)
it also helps if the ng-cli is only locally installed