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 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
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
36 changes: 16 additions & 20 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,21 +216,19 @@ 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;
continue;
}
} finally {
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