Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit cd390fd

Browse filesBrowse files
committed
Merge branch 'master' of https://github.com/Microsoft/TypeScript
2 parents 1e0b9ca + e813963 commit cd390fd
Copy full SHA for cd390fd

7 files changed

+222-5Lines changed: 222 additions & 5 deletions

File tree

Expand file treeCollapse file tree
Open diff view settings
Filter options
Expand file treeCollapse file tree
Open diff view settings
Collapse file

‎Jakefile.js‎

Copy file name to clipboardExpand all lines: Jakefile.js
+21-2Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -780,17 +780,36 @@ task("update-sublime", ["local", serverFile], function() {
780780
jake.cpR(serverFile + ".map", "../TypeScript-Sublime-Plugin/tsserver/");
781781
});
782782

783+
var tslintRuleDir = "scripts/tslint";
784+
var tslintRules = ([
785+
"nextLineRule",
786+
"noInferrableTypesRule",
787+
"noNullRule",
788+
"booleanTriviaRule"
789+
]);
790+
var tslintRulesFiles = tslintRules.map(function(p) {
791+
return path.join(tslintRuleDir, p + ".ts");
792+
});
793+
var tslintRulesOutFiles = tslintRules.map(function(p) {
794+
return path.join(builtLocalDirectory, "tslint", p + ".js");
795+
});
796+
desc("Compiles tslint rules to js");
797+
task("build-rules", tslintRulesOutFiles);
798+
tslintRulesFiles.forEach(function(ruleFile, i) {
799+
compileFile(tslintRulesOutFiles[i], [ruleFile], [ruleFile], [], /*useBuiltCompiler*/ true, /*noOutFile*/ true, /*generateDeclarations*/ false, path.join(builtLocalDirectory, "tslint"));
800+
});
801+
783802
// if the codebase were free of linter errors we could make jake runtests
784803
// run this task automatically
785804
desc("Runs tslint on the compiler sources");
786-
task("lint", [], function() {
805+
task("lint", ["build-rules"], function() {
787806
function success(f) { return function() { console.log('SUCCESS: No linter errors in ' + f + '\n'); }};
788807
function failure(f) { return function() { console.log('FAILURE: Please fix linting errors in ' + f + '\n') }};
789808

790809
var lintTargets = compilerSources.concat(harnessCoreSources);
791810
for (var i in lintTargets) {
792811
var f = lintTargets[i];
793-
var cmd = 'tslint -c tslint.json ' + f;
812+
var cmd = 'tslint --rules-dir built/local/tslint -c tslint.json ' + f;
794813
exec(cmd, success(f), failure(f));
795814
}
796815
}, { async: true });
Collapse file
+50Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
/// <reference path="../../node_modules/tslint/typings/typescriptServices.d.ts" />
2+
/// <reference path="../../node_modules/tslint/lib/tslint.d.ts" />
3+
4+
5+
export class Rule extends Lint.Rules.AbstractRule {
6+
public static FAILURE_STRING_FACTORY = (name: string, currently: string) => `Tag boolean argument as '${name}' (currently '${currently}')`;
7+
8+
public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] {
9+
const program = ts.createProgram([sourceFile.fileName], Lint.createCompilerOptions());
10+
const checker = program.getTypeChecker();
11+
return this.applyWithWalker(new BooleanTriviaWalker(checker, program.getSourceFile(sourceFile.fileName), this.getOptions()));
12+
}
13+
}
14+
15+
class BooleanTriviaWalker extends Lint.RuleWalker {
16+
constructor(private checker: ts.TypeChecker, file: ts.SourceFile, opts: Lint.IOptions) {
17+
super(file, opts);
18+
}
19+
20+
visitCallExpression(node: ts.CallExpression) {
21+
super.visitCallExpression(node);
22+
if (node.arguments) {
23+
const targetCallSignature = this.checker.getResolvedSignature(node);
24+
if (!!targetCallSignature) {
25+
const targetParameters = targetCallSignature.getParameters();
26+
const source = this.getSourceFile();
27+
for (let index = 0; index < targetParameters.length; index++) {
28+
const param = targetParameters[index];
29+
const arg = node.arguments[index];
30+
if (!(arg && param)) continue;
31+
32+
const argType = this.checker.getContextualType(arg);
33+
if (argType && (argType.getFlags() & ts.TypeFlags.Boolean)) {
34+
if (arg.kind !== ts.SyntaxKind.TrueKeyword && arg.kind !== ts.SyntaxKind.FalseKeyword) {
35+
continue;
36+
}
37+
let triviaContent: string;
38+
const ranges = ts.getLeadingCommentRanges(arg.getFullText(), 0);
39+
if (ranges && ranges.length === 1 && ranges[0].kind === ts.SyntaxKind.MultiLineCommentTrivia) {
40+
triviaContent = arg.getFullText().slice(ranges[0].pos + 2, ranges[0].end - 2); //+/-2 to remove /**/
41+
}
42+
if (triviaContent !== param.getName()) {
43+
this.addFailure(this.createFailure(arg.getStart(source), arg.getWidth(source), Rule.FAILURE_STRING_FACTORY(param.getName(), triviaContent)));
44+
}
45+
}
46+
}
47+
}
48+
}
49+
}
50+
}
Collapse file

‎scripts/tslint/nextLineRule.ts‎

Copy file name to clipboard
+61Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
/// <reference path="../../node_modules/tslint/typings/typescriptServices.d.ts" />
2+
/// <reference path="../../node_modules/tslint/lib/tslint.d.ts" />
3+
4+
const OPTION_CATCH = "check-catch";
5+
const OPTION_ELSE = "check-else";
6+
7+
export class Rule extends Lint.Rules.AbstractRule {
8+
public static CATCH_FAILURE_STRING = "'catch' should be on the line following the previous block's ending curly brace";
9+
public static ELSE_FAILURE_STRING = "'else' should be on the line following the previous block's ending curly brace";
10+
11+
public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] {
12+
return this.applyWithWalker(new NextLineWalker(sourceFile, this.getOptions()));
13+
}
14+
}
15+
16+
class NextLineWalker extends Lint.RuleWalker {
17+
public visitIfStatement(node: ts.IfStatement) {
18+
const sourceFile = node.getSourceFile();
19+
const thenStatement = node.thenStatement;
20+
21+
const elseStatement = node.elseStatement;
22+
if (!!elseStatement) {
23+
// find the else keyword
24+
const elseKeyword = getFirstChildOfKind(node, ts.SyntaxKind.ElseKeyword);
25+
if (this.hasOption(OPTION_ELSE) && !!elseKeyword) {
26+
const thenStatementEndLoc = sourceFile.getLineAndCharacterOfPosition(thenStatement.getEnd());
27+
const elseKeywordLoc = sourceFile.getLineAndCharacterOfPosition(elseKeyword.getStart(sourceFile));
28+
if (thenStatementEndLoc.line !== (elseKeywordLoc.line - 1)) {
29+
const failure = this.createFailure(elseKeyword.getStart(sourceFile), elseKeyword.getWidth(sourceFile), Rule.ELSE_FAILURE_STRING);
30+
this.addFailure(failure);
31+
}
32+
}
33+
}
34+
35+
super.visitIfStatement(node);
36+
}
37+
38+
public visitTryStatement(node: ts.TryStatement) {
39+
const sourceFile = node.getSourceFile();
40+
const catchClause = node.catchClause;
41+
42+
// "visit" try block
43+
const tryBlock = node.tryBlock;
44+
45+
if (this.hasOption(OPTION_CATCH) && !!catchClause) {
46+
const tryClosingBrace = tryBlock.getLastToken(sourceFile);
47+
const catchKeyword = catchClause.getFirstToken(sourceFile);
48+
const tryClosingBraceLoc = sourceFile.getLineAndCharacterOfPosition(tryClosingBrace.getEnd());
49+
const catchKeywordLoc = sourceFile.getLineAndCharacterOfPosition(catchKeyword.getStart(sourceFile));
50+
if (tryClosingBraceLoc.line !== (catchKeywordLoc.line - 1)) {
51+
const failure = this.createFailure(catchKeyword.getStart(sourceFile), catchKeyword.getWidth(sourceFile), Rule.CATCH_FAILURE_STRING);
52+
this.addFailure(failure);
53+
}
54+
}
55+
super.visitTryStatement(node);
56+
}
57+
}
58+
59+
function getFirstChildOfKind(node: ts.Node, kind: ts.SyntaxKind) {
60+
return node.getChildren().filter((child) => child.kind === kind)[0];
61+
}
Collapse file
+49Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
/// <reference path="../../node_modules/tslint/typings/typescriptServices.d.ts" />
2+
/// <reference path="../../node_modules/tslint/lib/tslint.d.ts" />
3+
4+
5+
export class Rule extends Lint.Rules.AbstractRule {
6+
public static FAILURE_STRING_FACTORY = (type: string) => `LHS type (${type}) inferred by RHS expression, remove type annotation`;
7+
8+
public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] {
9+
return this.applyWithWalker(new InferrableTypeWalker(sourceFile, this.getOptions()));
10+
}
11+
}
12+
13+
class InferrableTypeWalker extends Lint.RuleWalker {
14+
visitVariableStatement(node: ts.VariableStatement) {
15+
node.declarationList.declarations.forEach(e => {
16+
if ((!!e.type) && (!!e.initializer)) {
17+
let failure: string;
18+
switch (e.type.kind) {
19+
case ts.SyntaxKind.BooleanKeyword:
20+
if (e.initializer.kind === ts.SyntaxKind.TrueKeyword || e.initializer.kind === ts.SyntaxKind.FalseKeyword) {
21+
failure = 'boolean';
22+
}
23+
break;
24+
case ts.SyntaxKind.NumberKeyword:
25+
if (e.initializer.kind === ts.SyntaxKind.NumericLiteral) {
26+
failure = 'number';
27+
}
28+
break;
29+
case ts.SyntaxKind.StringKeyword:
30+
switch (e.initializer.kind) {
31+
case ts.SyntaxKind.StringLiteral:
32+
case ts.SyntaxKind.NoSubstitutionTemplateLiteral:
33+
case ts.SyntaxKind.TemplateExpression:
34+
failure = 'string';
35+
break;
36+
default:
37+
break;
38+
}
39+
break;
40+
}
41+
if (failure) {
42+
this.addFailure(this.createFailure(e.type.getStart(), e.type.getWidth(), Rule.FAILURE_STRING_FACTORY(failure)));
43+
}
44+
}
45+
});
46+
47+
super.visitVariableStatement(node);
48+
}
49+
}
Collapse file

‎scripts/tslint/noNullRule.ts‎

Copy file name to clipboard
+20Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
/// <reference path="../../node_modules/tslint/typings/typescriptServices.d.ts" />
2+
/// <reference path="../../node_modules/tslint/lib/tslint.d.ts" />
3+
4+
5+
export class Rule extends Lint.Rules.AbstractRule {
6+
public static FAILURE_STRING = "Don't use the 'null' keyword - use 'undefined' for missing values instead";
7+
8+
public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] {
9+
return this.applyWithWalker(new NullWalker(sourceFile, this.getOptions()));
10+
}
11+
}
12+
13+
class NullWalker extends Lint.RuleWalker {
14+
visitNode(node: ts.Node) {
15+
super.visitNode(node);
16+
if (node.kind === ts.SyntaxKind.NullKeyword) {
17+
this.addFailure(this.createFailure(node.getStart(), node.getWidth(), Rule.FAILURE_STRING));
18+
}
19+
}
20+
}
Collapse file

‎scripts/tslint/tsconfig.json‎

Copy file name to clipboard
+7Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"compilerOptions": {
3+
"noImplicitAny": true,
4+
"module": "commonjs",
5+
"outDir": "../../built/local/tslint"
6+
}
7+
}
Collapse file

‎tslint.json‎

Copy file name to clipboardExpand all lines: tslint.json
+14-3Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@
88
"spaces"
99
],
1010
"one-line": [true,
11-
"check-open-brace"
11+
"check-open-brace",
12+
"check-whitespace"
1213
],
1314
"no-unreachable": true,
1415
"no-use-before-declare": true,
@@ -21,14 +22,24 @@
2122
"check-branch",
2223
"check-operator",
2324
"check-separator",
24-
"check-type"
25+
"check-type",
26+
"check-module"
2527
],
2628
"typedef-whitespace": [true, {
2729
"call-signature": "nospace",
2830
"index-signature": "nospace",
2931
"parameter": "nospace",
3032
"property-declaration": "nospace",
3133
"variable-declaration": "nospace"
32-
}]
34+
}],
35+
"next-line": [true,
36+
"check-catch",
37+
"check-else"
38+
],
39+
"no-internal-module": true,
40+
"no-trailing-whitespace": true,
41+
"no-inferrable-types": true,
42+
"no-null": true,
43+
"boolean-trivia": true
3344
}
3445
}

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.