diff options
author | Florian Dold <florian.dold@gmail.com> | 2017-08-14 05:01:11 +0200 |
---|---|---|
committer | Florian Dold <florian.dold@gmail.com> | 2017-08-14 05:02:09 +0200 |
commit | 363723fc84f7b8477592e0105aeb331ec9a017af (patch) | |
tree | 29f92724f34131bac64d6a318dd7e30612e631c7 /node_modules/tslint/lib/rules/semicolonRule.js | |
parent | 5634e77ad96bfe1818f6b6ee70b7379652e5487f (diff) |
node_modules
Diffstat (limited to 'node_modules/tslint/lib/rules/semicolonRule.js')
-rw-r--r-- | node_modules/tslint/lib/rules/semicolonRule.js | 385 |
1 files changed, 238 insertions, 147 deletions
diff --git a/node_modules/tslint/lib/rules/semicolonRule.js b/node_modules/tslint/lib/rules/semicolonRule.js index 747a2acd2..13e3b53f2 100644 --- a/node_modules/tslint/lib/rules/semicolonRule.js +++ b/node_modules/tslint/lib/rules/semicolonRule.js @@ -31,136 +31,119 @@ var Rule = (function (_super) { } Rule.prototype.apply = function (sourceFile) { var options = { - always: this.ruleArguments.indexOf(OPTION_NEVER) === -1, boundClassMethods: this.ruleArguments.indexOf(OPTION_IGNORE_BOUND_CLASS_METHODS) === -1, interfaces: this.ruleArguments.indexOf(OPTION_IGNORE_INTERFACES) === -1, }; - return this.applyWithWalker(new SemicolonWalker(sourceFile, this.ruleName, options)); + var Walker = this.ruleArguments.indexOf(OPTION_NEVER) === -1 ? SemicolonAlwaysWalker : SemicolonNeverWalker; + return this.applyWithWalker(new Walker(sourceFile, this.ruleName, options)); }; + /* tslint:disable:object-literal-sort-keys */ + Rule.metadata = { + ruleName: "semicolon", + description: "Enforces consistent semicolon usage at the end of every statement.", + hasFix: true, + optionsDescription: (_a = ["\n One of the following arguments must be provided:\n\n * `\"", "\"` enforces semicolons at the end of every statement.\n * `\"", "\"` disallows semicolons at the end of every statement except for when they are necessary.\n\n The following arguments may be optionally provided:\n\n * `\"", "\"` skips checking semicolons at the end of interface members.\n * `\"", "\"` skips checking semicolons at the end of bound class methods."], _a.raw = ["\n One of the following arguments must be provided:\n\n * \\`\"", "\"\\` enforces semicolons at the end of every statement.\n * \\`\"", "\"\\` disallows semicolons at the end of every statement except for when they are necessary.\n\n The following arguments may be optionally provided:\n\n * \\`\"", "\"\\` skips checking semicolons at the end of interface members.\n * \\`\"", "\"\\` skips checking semicolons at the end of bound class methods."], Lint.Utils.dedent(_a, OPTION_ALWAYS, OPTION_NEVER, OPTION_IGNORE_INTERFACES, OPTION_IGNORE_BOUND_CLASS_METHODS)), + options: { + type: "array", + items: [ + { + type: "string", + enum: [OPTION_ALWAYS, OPTION_NEVER], + }, + { + type: "string", + enum: [OPTION_IGNORE_INTERFACES], + }, + ], + additionalItems: false, + }, + optionExamples: [ + [true, OPTION_ALWAYS], + [true, OPTION_NEVER], + [true, OPTION_ALWAYS, OPTION_IGNORE_INTERFACES], + [true, OPTION_ALWAYS, OPTION_IGNORE_BOUND_CLASS_METHODS], + ], + type: "style", + typescriptOnly: false, + }; + /* tslint:enable:object-literal-sort-keys */ + Rule.FAILURE_STRING_MISSING = "Missing semicolon"; + Rule.FAILURE_STRING_COMMA = "Properties should be separated by semicolons"; + Rule.FAILURE_STRING_UNNECESSARY = "Unnecessary semicolon"; return Rule; }(Lint.Rules.AbstractRule)); -/* tslint:disable:object-literal-sort-keys */ -Rule.metadata = { - ruleName: "semicolon", - description: "Enforces consistent semicolon usage at the end of every statement.", - hasFix: true, - optionsDescription: (_a = ["\n One of the following arguments must be provided:\n\n * `\"", "\"` enforces semicolons at the end of every statement.\n * `\"", "\"` disallows semicolons at the end of every statement except for when they are necessary.\n\n The following arguments may be optionally provided:\n\n * `\"", "\"` skips checking semicolons at the end of interface members.\n * `\"", "\"` skips checking semicolons at the end of bound class methods."], _a.raw = ["\n One of the following arguments must be provided:\n\n * \\`\"", "\"\\` enforces semicolons at the end of every statement.\n * \\`\"", "\"\\` disallows semicolons at the end of every statement except for when they are necessary.\n\n The following arguments may be optionally provided:\n\n * \\`\"", "\"\\` skips checking semicolons at the end of interface members.\n * \\`\"", "\"\\` skips checking semicolons at the end of bound class methods."], Lint.Utils.dedent(_a, OPTION_ALWAYS, OPTION_NEVER, OPTION_IGNORE_INTERFACES, OPTION_IGNORE_BOUND_CLASS_METHODS)), - options: { - type: "array", - items: [ - { - type: "string", - enum: [OPTION_ALWAYS, OPTION_NEVER], - }, - { - type: "string", - enum: [OPTION_IGNORE_INTERFACES], - }, - ], - additionalItems: false, - }, - optionExamples: [ - [true, OPTION_ALWAYS], - [true, OPTION_NEVER], - [true, OPTION_ALWAYS, OPTION_IGNORE_INTERFACES], - [true, OPTION_ALWAYS, OPTION_IGNORE_BOUND_CLASS_METHODS], - ], - type: "style", - typescriptOnly: false, -}; -/* tslint:enable:object-literal-sort-keys */ -Rule.FAILURE_STRING_MISSING = "Missing semicolon"; -Rule.FAILURE_STRING_COMMA = "Properties should be separated by semicolons"; -Rule.FAILURE_STRING_UNNECESSARY = "Unnecessary semicolon"; exports.Rule = Rule; var SemicolonWalker = (function (_super) { tslib_1.__extends(SemicolonWalker, _super); function SemicolonWalker() { - var _this = _super !== null && _super.apply(this, arguments) || this; - _this.scanner = undefined; - return _this; + return _super !== null && _super.apply(this, arguments) || this; } SemicolonWalker.prototype.walk = function (sourceFile) { var _this = this; var cb = function (node) { - switch (node.kind) { - case ts.SyntaxKind.VariableStatement: - case ts.SyntaxKind.ExpressionStatement: - case ts.SyntaxKind.ReturnStatement: - case ts.SyntaxKind.BreakStatement: - case ts.SyntaxKind.ContinueStatement: - case ts.SyntaxKind.ThrowStatement: - case ts.SyntaxKind.ImportEqualsDeclaration: - case ts.SyntaxKind.DoStatement: - case ts.SyntaxKind.ExportAssignment: - _this.checkSemicolonAt(node); - break; - case ts.SyntaxKind.TypeAliasDeclaration: - case ts.SyntaxKind.ImportDeclaration: - case ts.SyntaxKind.ExportDeclaration: - case ts.SyntaxKind.DebuggerStatement: - _this.checkSemicolonOrLineBreak(node); - break; - case ts.SyntaxKind.ModuleDeclaration: - // shorthand module declaration - if (node.body === undefined) { - _this.checkSemicolonOrLineBreak(node); - } - break; - case ts.SyntaxKind.PropertyDeclaration: - _this.visitPropertyDeclaration(node); - break; - case ts.SyntaxKind.MethodDeclaration: - case ts.SyntaxKind.FunctionDeclaration: - if (node.body === undefined) { - _this.checkSemicolonOrLineBreak(node); - } - break; - case ts.SyntaxKind.InterfaceDeclaration: - if (_this.options.interfaces) { - _this.checkInterface(node); - } - break; - case ts.SyntaxKind.SemicolonClassElement: - return _this.reportUnnecessary(node.end - 1); - case ts.SyntaxKind.EmptyStatement: - return _this.checkEmptyStatement(node); - default: - } + _this.visitNode(node); return ts.forEachChild(node, cb); }; return ts.forEachChild(sourceFile, cb); }; - SemicolonWalker.prototype.visitPropertyDeclaration = function (node) { - // check if this is a multi-line arrow function - if (node.initializer !== undefined && - node.initializer.kind === ts.SyntaxKind.ArrowFunction && - !utils.isSameLine(this.sourceFile, node.getStart(this.sourceFile), node.end)) { - if (this.options.boundClassMethods) { - if (this.sourceFile.text[node.end - 1] === ";" && - this.isFollowedByLineBreak(node.end)) { - this.reportUnnecessary(node.end - 1); - } - } - } - else { - this.checkSemicolonOrLineBreak(node); + SemicolonWalker.prototype.visitNode = function (node) { + switch (node.kind) { + case ts.SyntaxKind.SemicolonClassElement: + return this.reportUnnecessary(node.end); + case ts.SyntaxKind.EmptyStatement: + return this.checkEmptyStatement(node); + case ts.SyntaxKind.PropertyDeclaration: + return this.visitPropertyDeclaration(node); } }; - SemicolonWalker.prototype.isFollowedByLineBreak = function (pos) { - var scanner = this.scanner !== undefined ? this.scanner : - (this.scanner = ts.createScanner(this.sourceFile.languageVersion, true, this.sourceFile.languageVariant, this.sourceFile.text)); - scanner.setTextPos(pos); - return scanner.scan() === ts.SyntaxKind.EndOfFileToken || scanner.hasPrecedingLineBreak(); + SemicolonWalker.prototype.reportUnnecessary = function (pos, noFix) { + this.addFailure(pos - 1, pos, Rule.FAILURE_STRING_UNNECESSARY, noFix ? undefined : Lint.Replacement.deleteText(pos - 1, 1)); }; SemicolonWalker.prototype.checkSemicolonOrLineBreak = function (node) { - var hasSemicolon = this.sourceFile.text[node.end - 1] === ";"; - if (this.options.always && !hasSemicolon) { - this.reportMissing(node.end); + if (this.sourceFile.text[node.end - 1] !== ";") { + return; + } + var nextToken = utils.getNextToken(node, this.sourceFile); + switch (nextToken.kind) { + case ts.SyntaxKind.EndOfFileToken: + case ts.SyntaxKind.CloseBraceToken: + return this.reportUnnecessary(node.end); + default: + if (!utils.isSameLine(this.sourceFile, node.end, nextToken.end)) { + this.reportUnnecessary(node.end); + } + } + }; + SemicolonWalker.prototype.checkUnnecessary = function (node) { + if (this.sourceFile.text[node.end - 1] !== ";") { + return; } - else if (!this.options.always && hasSemicolon && this.isFollowedByLineBreak(node.end)) { - // semicolon can be removed if followed by line break; - this.reportUnnecessary(node.end - 1); + var lastToken = utils.getPreviousToken(node.getLastToken(this.sourceFile), this.sourceFile); + // yield does not continue on the next line if there is no yielded expression + if (lastToken.kind === ts.SyntaxKind.YieldKeyword && lastToken.parent.kind === ts.SyntaxKind.YieldExpression || + // arrow functions with block as body don't continue on the next line + lastToken.kind === ts.SyntaxKind.CloseBraceToken && lastToken.parent.kind === ts.SyntaxKind.Block && + lastToken.parent.parent.kind === ts.SyntaxKind.ArrowFunction) { + return this.checkSemicolonOrLineBreak(node); + } + var nextToken = utils.getNextToken(node, this.sourceFile); + switch (nextToken.kind) { + case ts.SyntaxKind.OpenParenToken: + case ts.SyntaxKind.OpenBracketToken: + case ts.SyntaxKind.PlusToken: + case ts.SyntaxKind.MinusToken: + case ts.SyntaxKind.RegularExpressionLiteral: + case ts.SyntaxKind.LessThanToken: + case ts.SyntaxKind.NoSubstitutionTemplateLiteral: + case ts.SyntaxKind.TemplateHead: + break; + case ts.SyntaxKind.CloseBraceToken: + case ts.SyntaxKind.EndOfFileToken: + return this.reportUnnecessary(node.end); + default: + if (!utils.isSameLine(this.sourceFile, node.end, nextToken.end)) { + this.reportUnnecessary(node.end); + } } }; SemicolonWalker.prototype.checkEmptyStatement = function (node) { @@ -172,61 +155,169 @@ var SemicolonWalker = (function (_super) { var noFix = parentKind === ts.SyntaxKind.IfStatement || parentKind === ts.SyntaxKind.LabeledStatement || parentKind === ts.SyntaxKind.WithStatement; - this.reportUnnecessary(node.end - 1, noFix); + this.reportUnnecessary(node.end, noFix); } }; - SemicolonWalker.prototype.checkInterface = function (node) { - for (var _i = 0, _a = node.members; _i < _a.length; _i++) { - var member = _a[_i]; - var lastChar = this.sourceFile.text[member.end - 1]; - var hasSemicolon = lastChar === ";"; - if (this.options.always && !hasSemicolon) { - if (lastChar === ",") { - this.addFailureAt(member.end - 1, 1, Rule.FAILURE_STRING_COMMA, new Lint.Replacement(member.end - 1, 1, ";")); - } - else { - this.reportMissing(member.end); - } - } - else if (!this.options.always && hasSemicolon && - (member === node.members[node.members.length - 1] || this.isFollowedByLineBreak(member.end))) { - this.reportUnnecessary(member.end - 1); + SemicolonWalker.prototype.visitPropertyDeclaration = function (node) { + // check if this is a multi-line arrow function + if (node.initializer !== undefined && + node.initializer.kind === ts.SyntaxKind.ArrowFunction && + !utils.isSameLine(this.sourceFile, node.getStart(this.sourceFile), node.end)) { + if (this.options.boundClassMethods) { + this.checkUnnecessary(node); } } + else { + this.checkPropertyDeclaration(node); + } }; - SemicolonWalker.prototype.reportMissing = function (pos) { - this.addFailureAt(pos, 0, Rule.FAILURE_STRING_MISSING, Lint.Replacement.appendText(pos, ";")); + return SemicolonWalker; +}(Lint.AbstractWalker)); +var SemicolonAlwaysWalker = (function (_super) { + tslib_1.__extends(SemicolonAlwaysWalker, _super); + function SemicolonAlwaysWalker() { + return _super !== null && _super.apply(this, arguments) || this; + } + SemicolonAlwaysWalker.prototype.visitNode = function (node) { + switch (node.kind) { + case ts.SyntaxKind.VariableStatement: + case ts.SyntaxKind.ExpressionStatement: + case ts.SyntaxKind.ReturnStatement: + case ts.SyntaxKind.BreakStatement: + case ts.SyntaxKind.ContinueStatement: + case ts.SyntaxKind.ThrowStatement: + case ts.SyntaxKind.ImportEqualsDeclaration: + case ts.SyntaxKind.DoStatement: + case ts.SyntaxKind.ExportAssignment: + case ts.SyntaxKind.TypeAliasDeclaration: + case ts.SyntaxKind.ImportDeclaration: + case ts.SyntaxKind.ExportDeclaration: + case ts.SyntaxKind.DebuggerStatement: + return this.checkMissing(node); + case ts.SyntaxKind.ModuleDeclaration: + case ts.SyntaxKind.MethodDeclaration: + case ts.SyntaxKind.FunctionDeclaration: + // check shorthand module declarations and method / function signatures + if (node.body === undefined) { + this.checkMissing(node); + } + break; + case ts.SyntaxKind.InterfaceDeclaration: + if (this.options.interfaces) { + this.checkInterface(node); + } + break; + default: + return _super.prototype.visitNode.call(this, node); + } }; - SemicolonWalker.prototype.reportUnnecessary = function (pos, noFix) { - this.addFailureAt(pos, 1, Rule.FAILURE_STRING_UNNECESSARY, noFix === true ? undefined : Lint.Replacement.deleteText(pos, 1)); + SemicolonAlwaysWalker.prototype.checkPropertyDeclaration = function (node) { + return this.checkMissing(node); }; - SemicolonWalker.prototype.checkSemicolonAt = function (node) { - var hasSemicolon = this.sourceFile.text[node.end - 1] === ";"; - if (this.options.always && !hasSemicolon) { + SemicolonAlwaysWalker.prototype.checkMissing = function (node) { + if (this.sourceFile.text[node.end - 1] !== ";") { this.reportMissing(node.end); } - else if (!this.options.always && hasSemicolon) { - switch (utils.getNextToken(node, this.sourceFile).kind) { - case ts.SyntaxKind.OpenParenToken: - case ts.SyntaxKind.OpenBracketToken: - case ts.SyntaxKind.PlusToken: - case ts.SyntaxKind.MinusToken: - case ts.SyntaxKind.RegularExpressionLiteral: + }; + SemicolonAlwaysWalker.prototype.reportMissing = function (pos) { + this.addFailureAt(pos, 0, Rule.FAILURE_STRING_MISSING, Lint.Replacement.appendText(pos, ";")); + }; + SemicolonAlwaysWalker.prototype.checkInterface = function (node) { + for (var _i = 0, _a = node.members; _i < _a.length; _i++) { + var member = _a[_i]; + switch (this.sourceFile.text[member.end - 1]) { + case ";": break; + case ",": + this.addFailureAt(member.end - 1, 1, Rule.FAILURE_STRING_COMMA, new Lint.Replacement(member.end - 1, 1, ";")); break; default: - if (!this.isFollowedByStatement(node)) { - this.reportUnnecessary(node.end - 1); - } + this.reportMissing(member.end); } } }; - SemicolonWalker.prototype.isFollowedByStatement = function (node) { + return SemicolonAlwaysWalker; +}(SemicolonWalker)); +var SemicolonNeverWalker = (function (_super) { + tslib_1.__extends(SemicolonNeverWalker, _super); + function SemicolonNeverWalker() { + return _super !== null && _super.apply(this, arguments) || this; + } + SemicolonNeverWalker.prototype.visitNode = function (node) { + switch (node.kind) { + case ts.SyntaxKind.ExpressionStatement: + case ts.SyntaxKind.ThrowStatement: + case ts.SyntaxKind.ExportAssignment: + return this.checkUnnecessary(node); + case ts.SyntaxKind.VariableStatement: + return this.checkVariableStatement(node); + case ts.SyntaxKind.ReturnStatement: + if (node.expression === undefined) { + // return does not continue on the next line if the is no returned expression + return this.checkSemicolonOrLineBreak(node); + } + return this.checkUnnecessary(node); + case ts.SyntaxKind.TypeAliasDeclaration: + case ts.SyntaxKind.ImportEqualsDeclaration: + case ts.SyntaxKind.ImportDeclaration: + case ts.SyntaxKind.ExportDeclaration: + case ts.SyntaxKind.DebuggerStatement: + case ts.SyntaxKind.BreakStatement: + case ts.SyntaxKind.ContinueStatement: + case ts.SyntaxKind.DoStatement: + return this.checkSemicolonOrLineBreak(node); + case ts.SyntaxKind.ModuleDeclaration: + // shorthand module declaration + if (node.body === undefined) { + this.checkShorthandModuleDeclaration(node); + } + break; + case ts.SyntaxKind.MethodDeclaration: + // check method signature + if (node.body === undefined) { + this.checkSemicolonOrLineBreak(node); + } + break; + case ts.SyntaxKind.FunctionDeclaration: + // check function signature + if (node.body === undefined) { + this.checkSemicolonOrLineBreak(node); + } + break; + case ts.SyntaxKind.InterfaceDeclaration: + if (this.options.interfaces) { + this.checkInterface(node); + } + break; + default: + return _super.prototype.visitNode.call(this, node); + } + }; + SemicolonNeverWalker.prototype.checkPropertyDeclaration = function (node) { + if (node.initializer === undefined) { + return this.checkSemicolonOrLineBreak(node); + } + return this.checkUnnecessary(node); + }; + SemicolonNeverWalker.prototype.checkVariableStatement = function (node) { + var declarations = node.declarationList.declarations; + if (declarations[declarations.length - 1].initializer === undefined) { + // variable declaration does not continue on the next line if it has no initializer + return this.checkSemicolonOrLineBreak(node); + } + return this.checkUnnecessary(node); + }; + SemicolonNeverWalker.prototype.checkShorthandModuleDeclaration = function (node) { var nextStatement = utils.getNextStatement(node); - if (nextStatement === undefined) { - return false; + if (nextStatement === undefined || nextStatement.kind !== ts.SyntaxKind.Block) { + this.checkSemicolonOrLineBreak(node); } - return utils.isSameLine(this.sourceFile, node.end, nextStatement.getStart(this.sourceFile)); }; - return SemicolonWalker; -}(Lint.AbstractWalker)); + SemicolonNeverWalker.prototype.checkInterface = function (node) { + for (var _i = 0, _a = node.members; _i < _a.length; _i++) { + var member = _a[_i]; + this.checkSemicolonOrLineBreak(member); + } + }; + return SemicolonNeverWalker; +}(SemicolonWalker)); var _a; |