From 8759afdb953b13e80500e913358c1216ff64d9a7 Mon Sep 17 00:00:00 2001 From: Klaus Meinhardt Date: Sat, 13 May 2017 18:35:40 +0200 Subject: [PATCH 1/2] CLI: handle directories passed with -p Search for tsconfig.json in specified directory. Exit with error if there is none. Ref: #2692 [enhancement] cli: `-p` option handles directories --- src/runner.ts | 19 ++++++++++++++----- src/tslint-cli.ts | 8 +++++++- test/executable/executableTests.ts | 23 +++++++++++++++++++++++ 3 files changed, 44 insertions(+), 6 deletions(-) diff --git a/src/runner.ts b/src/runner.ts index 427f361de18..a99f59cfb13 100644 --- a/src/runner.ts +++ b/src/runner.ts @@ -146,11 +146,14 @@ export class Runner { let program: ts.Program | undefined; if (this.options.project != null) { - if (!fs.existsSync(this.options.project)) { + let project: string; + try { + project = findTsconfig(this.options.project); + } catch (e) { console.error("Invalid option for project: " + this.options.project); return onComplete(1); } - program = Linter.createProgram(this.options.project); + program = Linter.createProgram(project); if (files.length === 0) { files = Linter.getFileNames(program); } @@ -175,9 +178,6 @@ export class Runner { // if not type checking, we don't need to pass in a program object program = undefined; } - } else if (this.options.typeCheck) { - console.error("--project must be specified in order to enable type checking."); - return onComplete(1); } let ignorePatterns: string[] = []; @@ -257,3 +257,12 @@ export class Runner { }); } } + +function findTsconfig(project: string): string { + const stats = fs.statSync(project); + if (stats.isDirectory()) { + project = path.join(project, "tsconfig.json"); + fs.accessSync(project); + } + return project; +} diff --git a/src/tslint-cli.ts b/src/tslint-cli.ts index b53d4995e17..79585133537 100644 --- a/src/tslint-cli.ts +++ b/src/tslint-cli.ts @@ -54,6 +54,12 @@ const processed = optimist throw "Missing files"; } + // tslint:disable-next-line strict-boolean-expressions + if (argv["type-check"] && !argv.project) { + // tslint:disable-next-line:no-string-throw + throw "--project must be specified in order to enable type checking."; + } + // tslint:disable-next-line strict-boolean-expressions if (argv.f) { // throw a string, otherwise a call stack is printed for this message @@ -214,7 +220,7 @@ tslint accepts the following commandline options: this can be used to test custom rules. -p, --project: - The location of a tsconfig.json file that will be used to determine which + The path or directory containing a tsconfig.json file that will be used to determine which files will be linted. --type-check diff --git a/test/executable/executableTests.ts b/test/executable/executableTests.ts index b11046416e4..9e7db3b1ca2 100644 --- a/test/executable/executableTests.ts +++ b/test/executable/executableTests.ts @@ -251,6 +251,29 @@ describe("Executable", function(this: Mocha.ISuiteCallbackContext) { }); }); + it("can be passed a directory and defaults to tsconfig.json", (done) => { + execCli(["-c", "test/files/tsconfig-test/tslint.json", "--project", "test/files/tsconfig-test"], (err) => { + assert.isNull(err, "process should exit without an error"); + done(); + }); + }); + + it("exits with error if passed a directory and there is not tsconfig.json", (done) => { + execCli(["-c", "test/files/tsconfig-test/tslint.json", "--project", "test/files"], (err) => { + assert.isNotNull(err, "process should exit with an error"); + assert.strictEqual(err.code, 1, "error code should be 1"); + done(); + }); + }); + + it("exits with error if passed directory does not exist", (done) => { + execCli(["-c", "test/files/tsconfig-test/tslint.json", "--project", "test/files/non-existant"], (err) => { + assert.isNotNull(err, "process should exit with an error"); + assert.strictEqual(err.code, 1, "error code should be 1"); + done(); + }); + }); + it("exits with code 2 if both `tsconfig.json` and files arguments are passed and files contain lint errors", (done) => { execCli( [ From f4676e5960b5b596f7316ee8fc71151b3a5b9d6b Mon Sep 17 00:00:00 2001 From: Klaus Meinhardt Date: Sat, 13 May 2017 21:16:57 +0200 Subject: [PATCH 2/2] move exception handling --- src/runner.ts | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/src/runner.ts b/src/runner.ts index a99f59cfb13..ac5e9ee38be 100644 --- a/src/runner.ts +++ b/src/runner.ts @@ -146,10 +146,8 @@ export class Runner { let program: ts.Program | undefined; if (this.options.project != null) { - let project: string; - try { - project = findTsconfig(this.options.project); - } catch (e) { + const project = findTsconfig(this.options.project); + if (project === undefined) { console.error("Invalid option for project: " + this.options.project); return onComplete(1); } @@ -258,11 +256,15 @@ export class Runner { } } -function findTsconfig(project: string): string { - const stats = fs.statSync(project); - if (stats.isDirectory()) { - project = path.join(project, "tsconfig.json"); - fs.accessSync(project); +function findTsconfig(project: string): string | undefined { + try { + const stats = fs.statSync(project); // throws if file does not exist + if (stats.isDirectory()) { + project = path.join(project, "tsconfig.json"); + fs.accessSync(project); // throws if file does not exist + } + } catch (e) { + return undefined; } return project; }