Skip to content

Commit

Permalink
feat(@angular/cli): add ability to exclude files and directories (#4437)
Browse files Browse the repository at this point in the history
Fixes #4350
  • Loading branch information
delasteve authored and hansl committed Feb 9, 2017
1 parent 9548d90 commit 6e3186d
Show file tree
Hide file tree
Showing 4 changed files with 111 additions and 27 deletions.
1 change: 1 addition & 0 deletions packages/@angular/cli/blueprints/ng2/files/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
"ng": "ng",
"start": "ng serve",
"test": "ng test",
"lint": "ng lint",
"pree2e": "webdriver-manager update --standalone false --gecko false",
"e2e": "protractor"
},
Expand Down
32 changes: 30 additions & 2 deletions packages/@angular/cli/lib/config/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -181,18 +181,46 @@
"type": "object",
"properties": {
"files": {
"type": "string"
"description": "File glob(s) to lint.",
"oneOf": [
{
"type": "string"
},
{
"type": "array",
"items": {
"type": "string"
}
}
],
"default": []
},
"project": {
"description": "Location of the tsconfig.json project file. Will also use as files to lint if 'files' property not present.",
"type": "string"
},
"tslintConfig": {
"description": "Location of the tslint.json configuration.",
"type": "string",
"default": "tslint.json"
},
"exclude": {
"description": "File glob(s) to ignore.",
"oneOf": [
{
"type": "string"
},
{
"type": "array",
"items": {
"type": "string"
}
}
],
"default": []
}
},
"required": [
"files",
"project"
],
"additionalProperties": false
Expand Down
85 changes: 60 additions & 25 deletions packages/@angular/cli/tasks/lint.ts
Original file line number Diff line number Diff line change
@@ -1,36 +1,46 @@
const Task = require('../ember-cli/lib/models/task');
import * as chalk from 'chalk';
import * as path from 'path';
import * as glob from 'glob';
import * as ts from 'typescript';
import { requireDependency } from '../utilities/require-project-module';
import { CliConfig } from '../models/config';
import { LintCommandOptions } from '../commands/lint';
import { oneLine } from 'common-tags';

interface CliLintConfig {
files?: (string | string[]);
project?: string;
tslintConfig?: string;
exclude?: (string | string[]);
}

export default Task.extend({
run: function (commandOptions: LintCommandOptions) {
const ui = this.ui;
const projectRoot = this.project.root;
const lintConfigs: CliLintConfig[] = CliConfig.fromProject().config.lint || [];

return new Promise(function (resolve, reject) {
const tslint = requireDependency(projectRoot, 'tslint');
const Linter = tslint.Linter;
const Configuration = tslint.Configuration;
if (lintConfigs.length === 0) {
ui.writeLine(chalk.yellow(oneLine`
No lint config(s) found.
If this is not intended, run "ng update".
`));

const lintConfigs = CliConfig.fromProject().config.lint || [];
return Promise.resolve(0);
}

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);
}
const tslint = requireDependency(projectRoot, 'tslint');
const Linter = tslint.Linter;
const Configuration = tslint.Configuration;

let errors = 0;
let errors = 0;
let results = '';

lintConfigs.forEach((config) => {
const program = Linter.createProgram(config.project);
const files: string[] = Linter.getFileNames(program);
lintConfigs
.forEach((config) => {
const program: ts.Program = Linter.createProgram(config.project);
const files = getFilesToLint(program, config, Linter);

const linter = new Linter({
fix: commandOptions.fix,
Expand All @@ -45,17 +55,42 @@ export default Task.extend({

const result = linter.getResult();
errors += result.failureCount;

ui.writeLine(result.output.trim().concat('\n'));
results = results.concat(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);
}
if (errors > 0) {
ui.writeLine(results.trim());
ui.writeLine(chalk.red('Lint errors found in the listed files.'));
return commandOptions.force ? Promise.resolve(0) : Promise.resolve(2);
}

ui.writeLine(chalk.green('All files pass linting.'));
return resolve(0);
});
ui.writeLine(chalk.green('All files pass linting.'));
return Promise.resolve(0);
}
});

function getFilesToLint(program: ts.Program, lintConfig: CliLintConfig, Linter: any): string[] {
let files: string[] = [];

if (lintConfig.files !== null) {
files = Array.isArray(lintConfig.files) ? lintConfig.files : [lintConfig.files];
} else {
files = Linter.getFileNames(program);
}

let globOptions = {};

if (lintConfig.exclude !== null) {
const excludePatterns = Array.isArray(lintConfig.exclude)
? lintConfig.exclude
: [lintConfig.exclude];

globOptions = { ignore: excludePatterns, nodir: true };
}

files = files
.map((file: string) => glob.sync(file, globOptions))
.reduce((a: string[], b: string[]) => a.concat(b), []);

return files;
}
20 changes: 20 additions & 0 deletions tests/e2e/tests/lint/lint-with-exclude.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
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(() => ng('set', 'lint.0.exclude', '"**/foo.ts"'))
.then(() => writeFile(fileName, 'const foo = "";\n'))
.then(() => ng('lint'))
.then((output) => {
if (!output.match(/All files pass linting\./)) {
throw new Error(oneLine`
Expected to match "All files pass linting."
in ${output}.
`);
}
});
}

0 comments on commit 6e3186d

Please sign in to comment.