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

Commit

Permalink
Merge pull request #1395 from palantir/release/3.14.0-dev.0
Browse files Browse the repository at this point in the history
Prepare release v3.14.0-dev.0
  • Loading branch information
adidahiya authored Jul 14, 2016
2 parents cfd608b + c74afed commit 32fc15d
Show file tree
Hide file tree
Showing 116 changed files with 583 additions and 87 deletions.
11 changes: 11 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,17 @@
Change Log
===

v3.14.0-dev.0
---
* [enhancement] Add optional type information to rules (#1323)

Thanks to our contributors!
* @ScottSWu

v3.13.0
---
* Stable release containing changes from the last dev release (v3.13.0-dev.0)

v3.13.0-dev.0
---
* [new-rule] `ordered-imports` rule (#1325)
Expand Down
28 changes: 28 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,8 @@ Options:
-e, --exclude exclude globs from path expansion
-t, --format output format (prose, json, verbose, pmd, msbuild, checkstyle) [default: "prose"]
--test test that tslint produces the correct output for the specified directory
--project path to tsconfig.json file
--type-check enable type checking when linting a project
-v, --version current version
```

Expand Down Expand Up @@ -182,6 +184,14 @@ 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:
The location of a tsconfig.json file that will be used to determine which
files will be linted.
--type-check
Enables the type checker when running linting rules. --project must be
specified in order to enable type checking.
-v, --version:
The current version of tslint.
Expand Down Expand Up @@ -214,6 +224,23 @@ const linter = new Linter(fileName, fileContents, options);
const result = linter.lint();
```

#### Type Checking

To enable rules that work with the type checker, a TypeScript program object must be passed to the linter when using the programmatic API. Helper functions are provided to create a program from a `tsconfig.json` file. A project directory can be specified if project files do not lie in the same directory as the `tsconfig.json` file.

```javascript
const program = Linter.createProgram("tsconfig.json", "projectDir/");
const files = Linter.getFileNames(program);
const results = files.map(file => {
const fileContents = program.getSourceFile(file).getFullText();
const linter = new Linter(file, fileContents, options, program);
return result.lint();
});
```

When using the CLI, the `--project` flag will automatically create a program from the specified `tsconfig.json` file. Adding `--type-check` then enables rules that require the type checker.


Core Rules
-----
<sup>[back to ToC &uarr;](#table-of-contents)</sup>
Expand Down Expand Up @@ -313,6 +340,7 @@ Core rules are included in the `tslint` package.
* `"jsx-double"` enforces double quotes for JSX attributes.
* `"avoid-escape"` allows you to use the "other" quotemark in cases where escaping would normally be required. For example, `[true, "double", "avoid-escape"]` would not report a failure on the string literal `'Hello "World"'`.
* `radix` enforces the radix parameter of `parseInt`.
* `restrict-plus-operands` enforces the type of addition operands to be both `string` or both `number` (requires type checking).
* `semicolon` enforces consistent semicolon usage at the end of every statement. Rule options:
* `"always"` enforces semicolons at the end of every statement.
* `"never"` disallows semicolons at the end of every statement except for when they are necessary.
Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "tslint",
"version": "3.13.0-dev.0",
"version": "3.14.0-dev.0",
"description": "An extensible static analysis linter for the TypeScript language",
"bin": {
"tslint": "./bin/tslint"
Expand Down Expand Up @@ -43,7 +43,7 @@
"mocha": "^2.2.5",
"tslint": "next",
"tslint-test-config-non-relative": "file:test/external/tslint-test-config-non-relative",
"typescript": "next"
"typescript": ">=2.0.0-dev"
},
"peerDependencies": {
"typescript": ">=1.7.3 || >=1.8.0-dev || >=1.9.0-dev || >=2.0.0-dev || >=2.1.0-dev"
Expand Down
5 changes: 3 additions & 2 deletions scripts/buildDocs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,11 @@

import * as fs from "fs";
import * as glob from "glob";
import * as path from "path";
import * as yaml from "js-yaml";
import {IRuleMetadata} from "../lib/language/rule/rule";
import * as path from "path";

import {AbstractRule} from "../lib/language/rule/abstractRule";
import {IRuleMetadata} from "../lib/language/rule/rule";

const DOCS_DIR = "../../tslint-gh-pages";
const DOCS_RULE_DIR = path.join(DOCS_DIR, "rules");
Expand Down
2 changes: 1 addition & 1 deletion src/configuration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@
* limitations under the License.
*/

import findup = require("findup-sync");
import * as fs from "fs";
import * as path from "path";
import * as findup from "findup-sync";
import * as resolve from "resolve";

import {arrayify, objectify, stripComments} from "./utils";
Expand Down
16 changes: 15 additions & 1 deletion src/enableDisableRules.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
*/

import * as ts from "typescript";

import {scanAllTokens} from "./language/utils";
import {SkippableTokenAwareRuleWalker} from "./language/walker/skippableTokenAwareRuleWalker";
import {IEnableDisablePosition} from "./ruleLoader";
Expand Down Expand Up @@ -64,10 +65,23 @@ export class EnableDisableRulesWalker extends SkippableTokenAwareRuleWalker {
const isEnabled = enableOrDisableMatch[1] === "enable";
const isCurrentLine = enableOrDisableMatch[3] === "line";
const isNextLine = enableOrDisableMatch[3] === "next-line";

let rulesList = ["all"];
if (commentTextParts.length > 2) {

if (commentTextParts.length === 2) {
// an implicit whitespace separator is used for the rules list.
rulesList = commentTextParts[1].split(/\s+/).slice(1);

// remove empty items and potential comment end.
rulesList = rulesList.filter(item => !!item && item.indexOf("*/") === -1);

// potentially there were no items, so default to `all`.
rulesList = rulesList.length > 0 ? rulesList : ["all"];
} else if (commentTextParts.length > 2) {
// an explicit separator was specified for the rules list.
rulesList = commentTextParts[2].split(/\s+/);
}

for (const ruleToAdd of rulesList) {
if (!(ruleToAdd in this.enableDisableRuleMap)) {
this.enableDisableRuleMap[ruleToAdd] = [];
Expand Down
1 change: 1 addition & 0 deletions src/language/languageServiceHost.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
*/

import * as ts from "typescript";

import {createCompilerOptions} from "./utils";

export function createLanguageServiceHost(fileName: string, source: string): ts.LanguageServiceHost {
Expand Down
7 changes: 3 additions & 4 deletions src/language/rule/abstractRule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,23 +16,22 @@
*/

import * as ts from "typescript";

import {IOptions} from "../../lint";
import {RuleWalker} from "../walker/ruleWalker";
import {IRule, IRuleMetadata, IDisabledInterval, RuleFailure} from "./rule";
import {IDisabledInterval, IRule, IRuleMetadata, RuleFailure} from "./rule";

export abstract class AbstractRule implements IRule {
public static metadata: IRuleMetadata;
private value: any;
private options: IOptions;

constructor(ruleName: string, value: any, disabledIntervals: IDisabledInterval[]) {
constructor(ruleName: string, private value: any, disabledIntervals: IDisabledInterval[]) {
let ruleArguments: any[] = [];

if (Array.isArray(value) && value.length > 1) {
ruleArguments = value.slice(1);
}

this.value = value;
this.options = {
disabledIntervals: disabledIntervals,
ruleArguments: ruleArguments,
Expand Down
25 changes: 10 additions & 15 deletions src/language/rule/rule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
*/

import * as ts from "typescript";

import {RuleWalker} from "../walker/ruleWalker";

export interface IRuleMetadata {
Expand Down Expand Up @@ -61,6 +62,11 @@ export interface IRuleMetadata {
* An explanation of why the rule is useful.
*/
rationale?: string;

/**
* Whether or not the rule requires type info to run.
*/
requiresTypeInfo?: boolean;
}

export type RuleType = "functionality" | "maintainability" | "style" | "typescript";
Expand All @@ -84,12 +90,7 @@ export interface IRule {
}

export class RuleFailurePosition {
private position: number;
private lineAndCharacter: ts.LineAndCharacter;

constructor(position: number, lineAndCharacter: ts.LineAndCharacter) {
this.position = position;
this.lineAndCharacter = lineAndCharacter;
constructor(private position: number, private lineAndCharacter: ts.LineAndCharacter) {
}

public getPosition() {
Expand Down Expand Up @@ -119,25 +120,19 @@ export class RuleFailurePosition {
}

export class RuleFailure {
private sourceFile: ts.SourceFile;
private fileName: string;
private startPosition: RuleFailurePosition;
private endPosition: RuleFailurePosition;
private failure: string;
private ruleName: string;

constructor(sourceFile: ts.SourceFile,
constructor(private sourceFile: ts.SourceFile,
start: number,
end: number,
failure: string,
ruleName: string) {
private failure: string,
private ruleName: string) {

this.sourceFile = sourceFile;
this.fileName = sourceFile.fileName;
this.startPosition = this.createFailurePosition(start);
this.endPosition = this.createFailurePosition(end);
this.failure = failure;
this.ruleName = ruleName;
}

public getFileName() {
Expand Down
30 changes: 30 additions & 0 deletions src/language/rule/typedRule.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/**
* @license
* Copyright 2016 Palantir Technologies, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

import * as ts from "typescript";

import {AbstractRule} from "./abstractRule";
import {RuleFailure} from "./rule";

export abstract class TypedRule extends AbstractRule {
public apply(sourceFile: ts.SourceFile): RuleFailure[] {
// if no program is given to the linter, throw an error
throw new Error(`${this.getOptions().ruleName} requires type checking`);
}

public abstract applyWithProgram(sourceFile: ts.SourceFile, program: ts.Program): RuleFailure[];
}
1 change: 1 addition & 0 deletions src/language/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

import * as path from "path";
import * as ts from "typescript";

import {IDisabledInterval, RuleFailure} from "./rule/rule";

export function getSourceFile(fileName: string, source: string): ts.SourceFile {
Expand Down
1 change: 1 addition & 0 deletions src/language/walker/blockScopeAwareRuleWalker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
*/

import * as ts from "typescript";

import {ScopeAwareRuleWalker} from "./scopeAwareRuleWalker";

/**
Expand Down
1 change: 1 addition & 0 deletions src/language/walker/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
*/

export * from "./blockScopeAwareRuleWalker";
export * from "./programAwareRuleWalker";
export * from "./ruleWalker";
export * from "./scopeAwareRuleWalker";
export * from "./skippableTokenAwareRuleWalker";
Expand Down
39 changes: 39 additions & 0 deletions src/language/walker/programAwareRuleWalker.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/**
* @license
* Copyright 2016 Palantir Technologies, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

import * as ts from "typescript";

import {IOptions} from "../../lint";
import {RuleWalker} from "./ruleWalker";

export class ProgramAwareRuleWalker extends RuleWalker {
private typeChecker: ts.TypeChecker;

constructor(sourceFile: ts.SourceFile, options: IOptions, private program: ts.Program) {
super(sourceFile, options);

this.typeChecker = program.getTypeChecker();
}

public getProgram(): ts.Program {
return this.program;
}

public getTypeChecker(): ts.TypeChecker {
return this.typeChecker;
}
}
5 changes: 2 additions & 3 deletions src/language/walker/ruleWalker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
*/

import * as ts from "typescript";

import {IOptions} from "../../lint";
import {IDisabledInterval, RuleFailure} from "../rule/rule";
import {doesIntersect} from "../utils";
Expand All @@ -26,17 +27,15 @@ export class RuleWalker extends SyntaxWalker {
private position: number;
private options: any[];
private failures: RuleFailure[];
private sourceFile: ts.SourceFile;
private disabledIntervals: IDisabledInterval[];
private ruleName: string;

constructor(sourceFile: ts.SourceFile, options: IOptions) {
constructor(private sourceFile: ts.SourceFile, options: IOptions) {
super();

this.position = 0;
this.failures = [];
this.options = options.ruleArguments;
this.sourceFile = sourceFile;
this.limit = this.sourceFile.getFullWidth();
this.disabledIntervals = options.disabledIntervals;
this.ruleName = options.ruleName;
Expand Down
1 change: 1 addition & 0 deletions src/language/walker/scopeAwareRuleWalker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
*/

import * as ts from "typescript";

import {RuleWalker} from "./ruleWalker";

export abstract class ScopeAwareRuleWalker<T> extends RuleWalker {
Expand Down
1 change: 1 addition & 0 deletions src/language/walker/skippableTokenAwareRuleWalker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
*/

import * as ts from "typescript";

import {IOptions} from "../../lint";
import {RuleWalker} from "./ruleWalker";

Expand Down
4 changes: 2 additions & 2 deletions src/lint.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,11 @@

import * as configuration from "./configuration";
import * as formatters from "./formatters";
import * as linter from "./tslint";
import {RuleFailure} from "./language/rule/rule";
import * as rules from "./rules";
import * as test from "./test";
import * as linter from "./tslint";
import * as utils from "./utils";
import {RuleFailure} from "./language/rule/rule";

export * from "./language/rule/rule";
export * from "./enableDisableRules";
Expand Down
Loading

0 comments on commit 32fc15d

Please sign in to comment.