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 #635 from palantir/release-2.5.0-beta
Browse files Browse the repository at this point in the history
Prepare release v2.5.0-beta
  • Loading branch information
adidahiya committed Sep 3, 2015
2 parents f1e4aa6 + cae6344 commit 4294795
Show file tree
Hide file tree
Showing 33 changed files with 945 additions and 430 deletions.
29 changes: 29 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,35 @@
Change Log
===

v2.5.0-beta
---
* Use TypeScript compiler `v1.6.0-beta`
* [bugfix] Fix `no-internal-module` false positives on nested namespaces (#600)
* [docs] Add documentation for `sort-object-literal-keys` rule

v2.5.0-dev.5
---
* Upgrade TypeScript compiler to `v1.7.0-dev.20150828`
* [bugfix] Handle .tsx files appropriately (#597, #558)

v2.5.0-dev.4
---
* Upgrade TypeScript compiler to `v1.6.0-dev.20150825`

v2.5.0-dev.3
---
* Upgrade TypeScript compiler to `v1.6.0-dev.20150821`

v2.5.0-dev.2
---
* Upgrade TypeScript compiler to `v1.6.0-dev.20150811`
* [bug] fix `whitespace` false positive in JSX elements (#559)

v2.5.0-dev.1
---
* Upgrade TypeScript compiler to `v1.6.0-dev.20150805`
* [enhancement] Support `.tsx` syntax (#490)

v2.4.5
---
* [bugfix] fix false positives on `no-shadowed-variable` rule (#500)
Expand Down
4 changes: 2 additions & 2 deletions Gruntfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ module.exports = function (grunt) {
// jscs:disable requireCamelCaseOrUpperCaseIdentifiers
grunt.initConfig({
pkg: grunt.file.readJSON("package.json"),
typescriptBin: "node_modules/typescript/bin/typescriptServices.js",
typescriptBin: "node_modules/typescript/lib/typescriptServices.js",

clean: {
bin: ["bin/tslint-cli.js"],
Expand Down Expand Up @@ -78,6 +78,7 @@ module.exports = function (grunt) {

ts: {
options: {
noImplicitAny: true,
sourceMap: false,
target: "es5"
},
Expand All @@ -97,7 +98,6 @@ module.exports = function (grunt) {

core: {
options: {
noImplicitAny: true,
declaration: true,
module: "commonjs"
},
Expand Down
5 changes: 4 additions & 1 deletion lib/tslint.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ declare module Lint {
protected visitImportEqualsDeclaration(node: ts.ImportEqualsDeclaration): void;
protected visitIndexSignatureDeclaration(node: ts.IndexSignatureDeclaration): void;
protected visitInterfaceDeclaration(node: ts.InterfaceDeclaration): void;
protected visitJsxElement(node: ts.JsxElement): void;
protected visitJsxSelfClosingElement(node: ts.JsxSelfClosingElement): void;
protected visitLabeledStatement(node: ts.LabeledStatement): void;
protected visitMethodDeclaration(node: ts.MethodDeclaration): void;
protected visitMethodSignature(node: ts.SignatureDeclaration): void;
Expand Down Expand Up @@ -114,6 +116,7 @@ declare module Lint {
}
declare module Lint {
function createLanguageServiceHost(fileName: string, source: string): ts.LanguageServiceHost;
function createLanguageService(fileName: string, source: string): ts.LanguageService;
}
declare module Lint.Rules {
class AbstractRule implements Lint.IRule {
Expand Down Expand Up @@ -206,7 +209,7 @@ declare module Lint {
protected visitRegularExpressionLiteral(node: ts.Node): void;
protected visitIdentifier(node: ts.Identifier): void;
protected visitTemplateExpression(node: ts.TemplateExpression): void;
private addTokenToSkipFromNode(node);
protected addTokenToSkipFromNode(node: ts.Node): void;
}
}
declare module Lint.Configuration {
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": "2.4.5",
"version": "2.5.0-beta",
"description": "a static analysis linter for TypeScript",
"bin": {
"tslint": "./bin/tslint"
Expand Down Expand Up @@ -36,7 +36,7 @@
"grunt-tslint": "latest",
"mocha": "^2.2.5",
"tslint": "latest",
"typescript": "latest"
"typescript": "1.6.0-beta"
},
"license": "Apache-2.0"
}
3 changes: 2 additions & 1 deletion src/enableDisableRules.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ module Lint {

public visitSourceFile(node: ts.SourceFile) {
super.visitSourceFile(node);
Lint.scanAllTokens(ts.createScanner(ts.ScriptTarget.ES5, false, node.text), (scanner: ts.Scanner) => {
const scan = ts.createScanner(ts.ScriptTarget.ES5, false, ts.LanguageVariant.Standard, node.text);
Lint.scanAllTokens(scan, (scanner: ts.Scanner) => {
const startPos = scanner.getStartPos();
if (this.tokensToSkipStartEndMap[startPos] != null) {
// tokens to skip are places where the scanner gets confused about what the token is, without the proper context
Expand Down
16 changes: 7 additions & 9 deletions src/language/languageServiceHost.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,19 +21,17 @@ module Lint {
getCurrentDirectory: () => "",
getDefaultLibFileName: () => "lib.d.ts",
getScriptFileNames: () => [fileName],
getScriptIsOpen: () => true,
getScriptSnapshot: () => {
return {
getChangeRange: (oldSnapshot) => undefined,
getLength: () => source.length,
getLineStartPositions: () => ts.computeLineStarts(source),
getText: (start, end) => source.substring(start, end)
};
},
getScriptSnapshot: () => ts.ScriptSnapshot.fromString(source),
getScriptVersion: () => "1",
log: (message) => { /* */ }
};

return host;
}

export function createLanguageService(fileName: string, source: string) {
const documentRegistry = ts.createDocumentRegistry();
const languageServiceHost = Lint.createLanguageServiceHost(fileName, source);
return ts.createLanguageService(languageServiceHost, documentRegistry);
}
}
2 changes: 2 additions & 0 deletions src/language/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ module Lint {
const compilerOptions = createCompilerOptions();

const compilerHost: ts.CompilerHost = {
fileExists: () => true,
getCanonicalFileName: (filename: string) => filename,
getCurrentDirectory: () => "",
getDefaultLibFileName: () => "lib.d.ts",
Expand All @@ -31,6 +32,7 @@ module Lint {
return ts.createSourceFile(filenameToGet, source, compilerOptions.target, true);
}
},
readFile: () => null,
useCaseSensitiveFileNames: () => true,
writeFile: () => null
};
Expand Down
2 changes: 1 addition & 1 deletion src/language/walker/skippableTokenAwareRuleWalker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ module Lint {
super.visitTemplateExpression(node);
}

private addTokenToSkipFromNode(node: ts.Node) {
protected addTokenToSkipFromNode(node: ts.Node) {
if (node.getStart() < node.getEnd()) {
// only add to the map nodes whose end comes after their start, to prevent infinite loops
this.tokensToSkipStartEndMap[node.getStart()] = node.getEnd();
Expand Down
16 changes: 16 additions & 0 deletions src/language/walker/syntaxWalker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,14 @@ module Lint {
this.walkChildren(node);
}

protected visitJsxElement(node: ts.JsxElement) {
this.walkChildren(node);
}

protected visitJsxSelfClosingElement(node: ts.JsxSelfClosingElement) {
this.walkChildren(node);
}

protected visitLabeledStatement(node: ts.LabeledStatement) {
this.walkChildren(node);
}
Expand Down Expand Up @@ -410,6 +418,14 @@ module Lint {
this.visitInterfaceDeclaration(<ts.InterfaceDeclaration> node);
break;

case ts.SyntaxKind.JsxElement:
this.visitJsxElement(<ts.JsxElement> node);
break;

case ts.SyntaxKind.JsxSelfClosingElement:
this.visitJsxSelfClosingElement(<ts.JsxSelfClosingElement> node);
break;

case ts.SyntaxKind.LabeledStatement:
this.visitLabeledStatement(<ts.LabeledStatement> node);
break;
Expand Down
2 changes: 1 addition & 1 deletion src/rules/commentFormatRule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ export class Rule extends Lint.Rules.AbstractRule {
class CommentWalker extends Lint.SkippableTokenAwareRuleWalker {
public visitSourceFile(node: ts.SourceFile) {
super.visitSourceFile(node);
Lint.scanAllTokens(ts.createScanner(ts.ScriptTarget.ES5, false, node.text), (scanner: ts.Scanner) => {
Lint.scanAllTokens(ts.createScanner(ts.ScriptTarget.ES5, false, ts.LanguageVariant.Standard, node.text), (scanner: ts.Scanner) => {
const startPos = scanner.getStartPos();
if (this.tokensToSkipStartEndMap[startPos] != null) {
// tokens to skip are places where the scanner gets confused about what the token is, without the proper context
Expand Down
2 changes: 1 addition & 1 deletion src/rules/indentRule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ class IndentWalker extends Lint.RuleWalker {
}

let endOfComment = -1;
const scanner = ts.createScanner(ts.ScriptTarget.ES5, false, node.text);
const scanner = ts.createScanner(ts.ScriptTarget.ES5, false, ts.LanguageVariant.Standard, node.text);
for (let lineStart of node.getLineStarts()) {
if (lineStart < endOfComment) {
// skip checking lines inside multi-line comments
Expand Down
2 changes: 1 addition & 1 deletion src/rules/jsdocFormatRule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ export class Rule extends Lint.Rules.AbstractRule {
class JsdocWalker extends Lint.SkippableTokenAwareRuleWalker {
public visitSourceFile(node: ts.SourceFile) {
super.visitSourceFile(node);
Lint.scanAllTokens(ts.createScanner(ts.ScriptTarget.ES5, false, node.text), (scanner: ts.Scanner) => {
Lint.scanAllTokens(ts.createScanner(ts.ScriptTarget.ES5, false, ts.LanguageVariant.Standard, node.text), (scanner: ts.Scanner) => {
const startPos = scanner.getStartPos();
if (this.tokensToSkipStartEndMap[startPos] != null) {
// tokens to skip are places where the scanner gets confused about what the token is, without the proper context
Expand Down
2 changes: 1 addition & 1 deletion src/rules/noConsecutiveBlankLinesRule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ class BlankLinesWalker extends Lint.SkippableTokenAwareRuleWalker {

// starting with 1 to cover the case where the file starts with two blank lines
let newLinesInARowSeenSoFar = 1;
Lint.scanAllTokens(ts.createScanner(ts.ScriptTarget.ES5, false, node.text), (scanner: ts.Scanner) => {
Lint.scanAllTokens(ts.createScanner(ts.ScriptTarget.ES5, false, ts.LanguageVariant.Standard, node.text), (scanner: ts.Scanner) => {
const startPos = scanner.getStartPos();
if (this.tokensToSkipStartEndMap[startPos] != null) {
// tokens to skip are places where the scanner gets confused about what the token is, without the proper context
Expand Down
19 changes: 15 additions & 4 deletions src/rules/noInternalModuleRule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,23 @@ export class Rule extends Lint.Rules.AbstractRule {

class NoInternalModuleWalker extends Lint.RuleWalker {
public visitModuleDeclaration(node: ts.ModuleDeclaration) {
if (Lint.isNodeFlagSet(node, ts.NodeFlags.Namespace)) {
// ok namespace
} else if (node.name.kind === ts.SyntaxKind.Identifier) {
// for external modules, node.name will be a LiteralExpression instead of Identifier
if (this.isInternalModuleDeclaration(node)) {
this.addFailure(this.createFailure(node.getStart(), node.getWidth(), Rule.FAILURE_STRING));
}
super.visitModuleDeclaration(node);
}

private isInternalModuleDeclaration(node: ts.ModuleDeclaration) {
// an internal module declaration is not a namespace or a nested declaration
// for external modules, node.name.kind will be a LiteralExpression instead of Identifier
return !Lint.isNodeFlagSet(node, ts.NodeFlags.Namespace)
&& !this.isNestedDeclaration(node)
&& node.name.kind === ts.SyntaxKind.Identifier;
}

private isNestedDeclaration(node: ts.ModuleDeclaration) {
// in a declaration expression like 'module a.b.c' - 'a' is the top level module declaration node and 'b' and 'c' are nested
// therefore we can depend that a node's position will only match with its name's position for nested nodes
return node.name.pos === node.pos;
}
}
2 changes: 1 addition & 1 deletion src/rules/noStringLiteralRule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ class NoStringLiteralWalker extends Lint.RuleWalker {
}

private isValidIdentifier(token: string) {
const scanner = ts.createScanner(ts.ScriptTarget.ES5, true, token);
const scanner = ts.createScanner(ts.ScriptTarget.ES5, false, ts.LanguageVariant.Standard, token);
scanner.scan();
// if we scanned to the end of the token, we can check if the scanned item was an identifier
return scanner.getTokenText() === token && scanner.isIdentifier();
Expand Down
2 changes: 1 addition & 1 deletion src/rules/noTrailingWhitespaceRule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ class NoTrailingWhitespaceWalker extends Lint.SkippableTokenAwareRuleWalker {
super.visitSourceFile(node);
let lastSeenWasWhitespace = false;
let lastSeenWhitespacePosition = 0;
Lint.scanAllTokens(ts.createScanner(ts.ScriptTarget.ES5, false, node.text), (scanner: ts.Scanner) => {
Lint.scanAllTokens(ts.createScanner(ts.ScriptTarget.ES5, false, ts.LanguageVariant.Standard, node.text), (scanner: ts.Scanner) => {
const startPos = scanner.getStartPos();
if (this.tokensToSkipStartEndMap[startPos] != null) {
// tokens to skip are places where the scanner gets confused about what the token is, without the proper context
Expand Down
14 changes: 6 additions & 8 deletions src/rules/noUnusedVariableRule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,25 +20,22 @@ export class Rule extends Lint.Rules.AbstractRule {
public static FAILURE_STRING = "unused variable: ";

public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] {
const documentRegistry = ts.createDocumentRegistry();
const languageServiceHost = Lint.createLanguageServiceHost("file.ts", sourceFile.getFullText());
const languageService = ts.createLanguageService(languageServiceHost, documentRegistry);

const languageService = Lint.createLanguageService(sourceFile.fileName, sourceFile.getFullText());
return this.applyWithWalker(new NoUnusedVariablesWalker(sourceFile, this.getOptions(), languageService));
}
}

class NoUnusedVariablesWalker extends Lint.RuleWalker {
private languageService: ts.LanguageService;
private skipBindingElement: boolean;
private skipParameterDeclaration: boolean;
private skipVariableDeclaration: boolean;
private languageService: ts.LanguageService;

constructor(sourceFile: ts.SourceFile, options: Lint.IOptions, languageService: ts.LanguageService) {
super(sourceFile, options);
this.languageService = languageService;
this.skipVariableDeclaration = false;
this.skipParameterDeclaration = false;
this.languageService = languageService;
}

public visitBindingElement(node: ts.BindingElement) {
Expand Down Expand Up @@ -200,8 +197,9 @@ class NoUnusedVariablesWalker extends Lint.RuleWalker {
}

private validateReferencesForVariable(name: string, position: number) {
const highlights = this.languageService.getDocumentHighlights("file.ts", position, ["file.ts"]);
if (highlights[0].highlightSpans.length <= 1) {
const fileName = this.getSourceFile().fileName;
const highlights = this.languageService.getDocumentHighlights(fileName, position, [fileName]);
if (highlights == null || highlights[0].highlightSpans.length <= 1) {
this.addFailure(this.createFailure(position, name.length, `${Rule.FAILURE_STRING}'${name}'`));
}
}
Expand Down
8 changes: 3 additions & 5 deletions src/rules/noUseBeforeDeclareRule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,7 @@ export class Rule extends Lint.Rules.AbstractRule {
public static FAILURE_STRING_POSTFIX = "' used before declaration";

public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] {
const documentRegistry = ts.createDocumentRegistry();
const languageServiceHost = Lint.createLanguageServiceHost("file.ts", sourceFile.getFullText());
const languageService = ts.createLanguageService(languageServiceHost, documentRegistry);

const languageService = Lint.createLanguageService(sourceFile.fileName, sourceFile.getFullText());
return this.applyWithWalker(new NoUseBeforeDeclareWalker(sourceFile, this.getOptions(), languageService));
}
}
Expand Down Expand Up @@ -101,7 +98,8 @@ class NoUseBeforeDeclareWalker extends Lint.ScopeAwareRuleWalker<VisitedVariable
}

private validateUsageForVariable(name: string, position: number) {
const highlights = this.languageService.getDocumentHighlights("file.ts", position, ["file.ts"]);
const fileName = this.getSourceFile().fileName;
const highlights = this.languageService.getDocumentHighlights(fileName, position, [fileName]);
for (let highlight of highlights) {
for (let highlightSpan of highlight.highlightSpans) {
const referencePosition = highlightSpan.textSpan.start;
Expand Down
1 change: 0 additions & 1 deletion src/rules/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
"../../lib/tslint.d.ts",
"../../typings/node.d.ts",
"../../typings/typescriptServices.d.ts",
"../../typings/typescriptServicesScanner.d.ts",
"./alignRule.ts",
"./banRule.ts",
"./classNameRule.ts",
Expand Down
2 changes: 1 addition & 1 deletion src/rules/typedefWhitespaceRule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ class TypedefWhitespaceWalker extends Lint.RuleWalker {

public checkSpace(option: string, node: ts.Node, typeNode: ts.TypeNode | ts.StringLiteral, positionBeforeColon: number) {
if (this.hasOption(option) && typeNode != null && positionBeforeColon != null) {
const scanner = ts.createScanner(ts.ScriptTarget.ES5, false, node.getText());
const scanner = ts.createScanner(ts.ScriptTarget.ES5, false, ts.LanguageVariant.Standard, node.getText());
let hasLeadingWhitespace: boolean;

scanner.setTextPos(positionBeforeColon - node.getStart());
Expand Down

0 comments on commit 4294795

Please sign in to comment.