2015-08-26 03:37:52 +02:00
|
|
|
/// <reference path="../../node_modules/tslint/typings/typescriptServices.d.ts" />
|
2015-08-26 03:09:32 +02:00
|
|
|
/// <reference path="../../node_modules/tslint/lib/tslint.d.ts" />
|
|
|
|
|
|
|
|
const OPTION_CATCH = "check-catch";
|
|
|
|
const OPTION_ELSE = "check-else";
|
|
|
|
|
|
|
|
export class Rule extends Lint.Rules.AbstractRule {
|
|
|
|
public static CATCH_FAILURE_STRING = "'catch' should be on the line following the previous block's ending curly brace";
|
|
|
|
public static ELSE_FAILURE_STRING = "'else' should be on the line following the previous block's ending curly brace";
|
|
|
|
|
|
|
|
public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] {
|
|
|
|
return this.applyWithWalker(new NextLineWalker(sourceFile, this.getOptions()));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
class NextLineWalker extends Lint.RuleWalker {
|
|
|
|
public visitIfStatement(node: ts.IfStatement) {
|
|
|
|
const sourceFile = node.getSourceFile();
|
|
|
|
const thenStatement = node.thenStatement;
|
|
|
|
|
|
|
|
const elseStatement = node.elseStatement;
|
|
|
|
if (!!elseStatement) {
|
|
|
|
// find the else keyword
|
|
|
|
const elseKeyword = getFirstChildOfKind(node, ts.SyntaxKind.ElseKeyword);
|
|
|
|
if (this.hasOption(OPTION_ELSE) && !!elseKeyword) {
|
|
|
|
const thenStatementEndLoc = sourceFile.getLineAndCharacterOfPosition(thenStatement.getEnd());
|
2015-09-17 23:29:52 +02:00
|
|
|
const elseKeywordLoc = sourceFile.getLineAndCharacterOfPosition(elseKeyword.getStart(sourceFile));
|
2015-08-26 03:09:32 +02:00
|
|
|
if (thenStatementEndLoc.line !== (elseKeywordLoc.line - 1)) {
|
2015-09-17 23:29:52 +02:00
|
|
|
const failure = this.createFailure(elseKeyword.getStart(sourceFile), elseKeyword.getWidth(sourceFile), Rule.ELSE_FAILURE_STRING);
|
2015-08-26 03:09:32 +02:00
|
|
|
this.addFailure(failure);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
super.visitIfStatement(node);
|
|
|
|
}
|
|
|
|
|
|
|
|
public visitTryStatement(node: ts.TryStatement) {
|
|
|
|
const sourceFile = node.getSourceFile();
|
|
|
|
const catchClause = node.catchClause;
|
|
|
|
|
|
|
|
// "visit" try block
|
|
|
|
const tryBlock = node.tryBlock;
|
|
|
|
|
|
|
|
if (this.hasOption(OPTION_CATCH) && !!catchClause) {
|
2015-09-17 23:29:52 +02:00
|
|
|
const tryClosingBrace = tryBlock.getLastToken(sourceFile);
|
|
|
|
const catchKeyword = catchClause.getFirstToken(sourceFile);
|
2015-08-26 03:09:32 +02:00
|
|
|
const tryClosingBraceLoc = sourceFile.getLineAndCharacterOfPosition(tryClosingBrace.getEnd());
|
2015-09-17 23:29:52 +02:00
|
|
|
const catchKeywordLoc = sourceFile.getLineAndCharacterOfPosition(catchKeyword.getStart(sourceFile));
|
2015-08-26 03:09:32 +02:00
|
|
|
if (tryClosingBraceLoc.line !== (catchKeywordLoc.line - 1)) {
|
2015-09-17 23:29:52 +02:00
|
|
|
const failure = this.createFailure(catchKeyword.getStart(sourceFile), catchKeyword.getWidth(sourceFile), Rule.CATCH_FAILURE_STRING);
|
2015-08-26 03:09:32 +02:00
|
|
|
this.addFailure(failure);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
super.visitTryStatement(node);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function getFirstChildOfKind(node: ts.Node, kind: ts.SyntaxKind) {
|
|
|
|
return node.getChildren().filter((child) => child.kind === kind)[0];
|
|
|
|
}
|