Skip to content
This repository has been archived by the owner on Mar 25, 2021. It is now read-only.

Extend cli options #2322

Merged
merged 5 commits into from
Mar 10, 2017
Merged
Show file tree
Hide file tree
Changes from 4 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
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ Options:
-h, --help display detailed help
-i, --init generate a tslint.json config file in the current working directory
-o, --out output file
--project tsconfig.json file
-p, --project tsconfig.json file
-r, --rules-dir rules directory
-s, --formatters-dir formatters directory
-t, --format output format (prose, json, stylish, verbose, pmd, msbuild, checkstyle, vso, fileslist) [default: "prose"]
Expand Down Expand Up @@ -200,7 +200,7 @@ tslint accepts the following command-line options:
the tests. See the full tslint documentation for more details on how
this can be used to test custom rules.

--project:
-p, --project:
The location of a tsconfig.json file that will be used to determine which
files will be linted.

Expand Down
4 changes: 2 additions & 2 deletions docs/usage/cli/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ Options:
-h, --help display detailed help
-i, --init generate a tslint.json config file in the current working directory
-o, --out output file
--project tsconfig.json file
-p, --project tsconfig.json file
-r, --rules-dir rules directory
-s, --formatters-dir formatters directory
-t, --format output format (prose, json, stylish, verbose, pmd, msbuild, checkstyle, vso, fileslist, codeFrame) [default: "prose"]
Expand Down Expand Up @@ -115,7 +115,7 @@ tslint accepts the following command-line options:
specified directory as the configuration file for the tests. See the
full tslint documentation for more details on how this can be used to test custom rules.

--project:
-p, --project:
The location of a tsconfig.json file that will be used to determine which
files will be linted.

Expand Down
39 changes: 18 additions & 21 deletions src/runner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -112,35 +112,30 @@ export class Runner {
public run(onComplete: (status: number) => void) {
if (this.options.version) {
this.outputStream.write(Linter.VERSION + "\n");
onComplete(0);
return;
return onComplete(0);
}

if (this.options.init) {
if (fs.existsSync(CONFIG_FILENAME)) {
console.error(`Cannot generate ${CONFIG_FILENAME}: file already exists`);
onComplete(1);
return;
return onComplete(1);
}

const tslintJSON = JSON.stringify(DEFAULT_CONFIG, undefined, " ");
fs.writeFileSync(CONFIG_FILENAME, tslintJSON);
onComplete(0);
return;
return onComplete(0);
}

if (this.options.test) {
const results = runTests(this.options.test, this.options.rulesDirectory);
const results = runTests((this.options.files || []).map(Runner.trimSingleQuotes), this.options.rulesDirectory);
const didAllTestsPass = consoleTestResultsHandler(results);
onComplete(didAllTestsPass ? 0 : 1);
return;
return onComplete(didAllTestsPass ? 0 : 1);
}

// when provided, it should point to an existing location
if (this.options.config && !fs.existsSync(this.options.config)) {
console.error("Invalid option for configuration: " + this.options.config);
onComplete(1);
return;
return onComplete(1);
}

// if both files and tsconfig are present, use files
Expand All @@ -150,8 +145,7 @@ export class Runner {
if (this.options.project != null) {
if (!fs.existsSync(this.options.project)) {
console.error("Invalid option for project: " + this.options.project);
onComplete(1);
return;
return onComplete(1);
}
program = Linter.createProgram(this.options.project, path.dirname(this.options.project));
if (files.length === 0) {
Expand All @@ -171,12 +165,16 @@ export class Runner {
message += " " + ts.flattenDiagnosticMessageText(diag.messageText, "\n");
return message;
});
throw new Error(messages.join("\n"));
console.error(messages.join("\n"));
return onComplete(this.options.force ? 0 : 1);
}
} else {
// 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[] = [];
Expand All @@ -197,7 +195,7 @@ export class Runner {
} catch (error) {
if (error.name === FatalError.NAME) {
console.error(error.message);
onComplete(1);
return onComplete(1);
}
// rethrow unhandled error
throw error;
Expand All @@ -218,23 +216,22 @@ export class Runner {
for (const file of files) {
if (!fs.existsSync(file)) {
console.error(`Unable to open file: ${file}`);
onComplete(1);
return;
return onComplete(1);
}

const buffer = new Buffer(256);
buffer.fill(0);
const fd = fs.openSync(file, "r");
try {
fs.readSync(fd, buffer, 0, 256, 0);
if (buffer.readInt8(0) === 0x47 && buffer.readInt8(188) === 0x47) {
if (buffer.readInt8(0, true) === 0x47 && buffer.readInt8(188, true) === 0x47) {
// MPEG transport streams use the '.ts' file extension. They use 0x47 as the frame
// separator, repeating every 188 bytes. It is unlikely to find that pattern in
// TypeScript source, so tslint ignores files with the specific pattern.
console.warn(`${file}: ignoring MPEG transport stream`);
return;
fs.closeSync(fd);
continue;
}
} finally {
} catch (e) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why is this in a catch instead of a finally? The file descriptor should be closed regardless of what happens. Line 231 can be removed too

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good catch, I thought finally would not be executed when leaving the try block with return or continue. Will revert that change

fs.closeSync(fd);
}

Expand Down
9 changes: 6 additions & 3 deletions src/test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,12 @@ export interface TestResult {
};
}

export function runTests(pattern: string, rulesDirectory?: string | string[]): TestResult[] {
return glob.sync(`${pattern}/tslint.json`)
.map((directory: string): TestResult => runTest(path.dirname(directory), rulesDirectory));
export function runTests(patterns: string[], rulesDirectory?: string | string[]): TestResult[] {
const files: string[] = [];
for (const pattern of patterns) {
files.push(...glob.sync(`${pattern}/tslint.json`));
}
return files.map((directory: string): TestResult => runTest(path.dirname(directory), rulesDirectory));
}

export function runTest(testDirectory: string, rulesDirectory?: string | string[]): TestResult {
Expand Down
9 changes: 5 additions & 4 deletions src/tslint-cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,8 @@ const processed = optimist
describe: "output file",
type: "string",
},
"project": {
"p": {
alias: "project",
describe: "tsconfig.json file",
type: "string",
},
Expand All @@ -92,7 +93,7 @@ const processed = optimist
},
"test": {
describe: "test that tslint produces the correct output for the specified directory",
type: "string",
type: "boolean",
},
"type-check": {
describe: "enable type checking when linting a project",
Expand Down Expand Up @@ -186,7 +187,7 @@ tslint accepts the following commandline options:
the tests. See the full tslint documentation for more details on how
this can be used to test custom rules.

--project:
-p, --project:
The location of a tsconfig.json file that will be used to determine which
files will be linted.

Expand All @@ -213,7 +214,7 @@ const options: IRunnerOptions = {
formattersDirectory: argv.s,
init: argv.init,
out: argv.out,
project: argv.project,
project: argv.p,
rulesDirectory: argv.r,
test: argv.test,
typeCheck: argv["type-check"],
Expand Down
21 changes: 20 additions & 1 deletion test/executable/executableTests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,15 @@ describe("Executable", function(this: Mocha.ISuiteCallbackContext) {
done();
});
});

it("can be used with multiple paths", (done) => {
// pass a failing test as second path to make sure it gets executed
execCli(["--test", "test/files/custom-rule-rule-test", "test/files/incorrect-fixes-test"], (err) => {
assert.isNotNull(err, "process should exit with error");
assert.strictEqual(err.code, 1, "error code should be 1");
done();
});
});
});

describe("tsconfig.json", () => {
Expand All @@ -230,14 +239,24 @@ describe("Executable", function(this: Mocha.ISuiteCallbackContext) {
});

it("exits with code 0 if `tsconfig.json` is passed but it includes no ts files", (done) => {
execCli(["-c", "test/files/tsconfig-no-ts-files/tslint.json", "--project", "test/files/tsconfig-no-ts-files/tsconfig.json"],
execCli(["-c", "test/files/tsconfig-no-ts-files/tslint.json", "-p", "test/files/tsconfig-no-ts-files/tsconfig.json"],
(err) => {
assert.isNull(err, "process should exit without an error");
done();
});
});
});

describe("--type-check", () => {
it("exits with code 1 if --project is not passed", (done) => {
execCli(["--type-check"], (err) => {
assert.isNotNull(err, "process should exit with error");
assert.strictEqual(err.code, 2, "error code should be 2");
done();
});
});
});

describe("--init flag", () => {
// remove temp file before calling tslint --init
beforeEach(cleanTempInitFile);
Expand Down