From 7fff4499fd915bcea3fa93b1aa8b35f4fe7a6027 Mon Sep 17 00:00:00 2001 From: Florian Dold Date: Sun, 28 May 2017 00:38:50 +0200 Subject: add linting (and some initial fixes) --- node_modules/tslint/lib/rules/whitespaceRule.js | 238 ++++++++++++++++++++++++ 1 file changed, 238 insertions(+) create mode 100644 node_modules/tslint/lib/rules/whitespaceRule.js (limited to 'node_modules/tslint/lib/rules/whitespaceRule.js') diff --git a/node_modules/tslint/lib/rules/whitespaceRule.js b/node_modules/tslint/lib/rules/whitespaceRule.js new file mode 100644 index 000000000..b92a075e5 --- /dev/null +++ b/node_modules/tslint/lib/rules/whitespaceRule.js @@ -0,0 +1,238 @@ +"use strict"; +/** + * @license + * Copyright 2013 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. + */ +Object.defineProperty(exports, "__esModule", { value: true }); +var tslib_1 = require("tslib"); +// tslint:disable object-literal-sort-keys +var utils = require("tsutils"); +var ts = require("typescript"); +var Lint = require("../index"); +var OPTION_BRANCH = "check-branch"; +var OPTION_DECL = "check-decl"; +var OPTION_OPERATOR = "check-operator"; +var OPTION_MODULE = "check-module"; +var OPTION_SEPARATOR = "check-separator"; +var OPTION_TYPE = "check-type"; +var OPTION_TYPECAST = "check-typecast"; +var OPTION_PREBLOCK = "check-preblock"; +var Rule = (function (_super) { + tslib_1.__extends(Rule, _super); + function Rule() { + return _super !== null && _super.apply(this, arguments) || this; + } + Rule.prototype.apply = function (sourceFile) { + return this.applyWithFunction(sourceFile, walk, parseOptions(this.ruleArguments)); + }; + return Rule; +}(Lint.Rules.AbstractRule)); +Rule.metadata = { + ruleName: "whitespace", + description: "Enforces whitespace style conventions.", + rationale: "Helps maintain a readable, consistent style in your codebase.", + optionsDescription: (_a = ["\n Eight arguments may be optionally provided:\n\n * `\"check-branch\"` checks branching statements (`if`/`else`/`for`/`while`) are followed by whitespace.\n * `\"check-decl\"`checks that variable declarations have whitespace around the equals token.\n * `\"check-operator\"` checks for whitespace around operator tokens.\n * `\"check-module\"` checks for whitespace in import & export statements.\n * `\"check-separator\"` checks for whitespace after separator tokens (`,`/`;`).\n * `\"check-type\"` checks for whitespace before a variable type specification.\n * `\"check-typecast\"` checks for whitespace between a typecast and its target.\n * `\"check-preblock\"` checks for whitespace before the opening brace of a block"], _a.raw = ["\n Eight arguments may be optionally provided:\n\n * \\`\"check-branch\"\\` checks branching statements (\\`if\\`/\\`else\\`/\\`for\\`/\\`while\\`) are followed by whitespace.\n * \\`\"check-decl\"\\`checks that variable declarations have whitespace around the equals token.\n * \\`\"check-operator\"\\` checks for whitespace around operator tokens.\n * \\`\"check-module\"\\` checks for whitespace in import & export statements.\n * \\`\"check-separator\"\\` checks for whitespace after separator tokens (\\`,\\`/\\`;\\`).\n * \\`\"check-type\"\\` checks for whitespace before a variable type specification.\n * \\`\"check-typecast\"\\` checks for whitespace between a typecast and its target.\n * \\`\"check-preblock\"\\` checks for whitespace before the opening brace of a block"], Lint.Utils.dedent(_a)), + options: { + type: "array", + items: { + type: "string", + enum: ["check-branch", "check-decl", "check-operator", "check-module", + "check-separator", "check-type", "check-typecast", "check-preblock"], + }, + minLength: 0, + maxLength: 7, + }, + optionExamples: [[true, "check-branch", "check-operator", "check-typecast"]], + type: "style", + typescriptOnly: false, +}; +Rule.FAILURE_STRING = "missing whitespace"; +exports.Rule = Rule; +function parseOptions(ruleArguments) { + return { + branch: has(OPTION_BRANCH), + decl: has(OPTION_DECL), + operator: has(OPTION_OPERATOR), + module: has(OPTION_MODULE), + separator: has(OPTION_SEPARATOR), + type: has(OPTION_TYPE), + typecast: has(OPTION_TYPECAST), + preblock: has(OPTION_PREBLOCK), + }; + function has(option) { + return ruleArguments.indexOf(option) !== -1; + } +} +function walk(ctx) { + var sourceFile = ctx.sourceFile, options = ctx.options; + ts.forEachChild(sourceFile, function cb(node) { + switch (node.kind) { + case ts.SyntaxKind.ArrowFunction: + checkEqualsGreaterThanTokenInNode(node); + break; + // check for spaces between the operator symbol (except in the case of comma statements) + case ts.SyntaxKind.BinaryExpression: { + var _a = node, left = _a.left, operatorToken = _a.operatorToken, right = _a.right; + if (options.operator && operatorToken.kind !== ts.SyntaxKind.CommaToken) { + checkForTrailingWhitespace(left.getEnd()); + checkForTrailingWhitespace(right.getFullStart()); + } + break; + } + case ts.SyntaxKind.Block: + if (options.preblock) { + checkForTrailingWhitespace(node.getFullStart()); + } + break; + // check for spaces between ternary operator symbols + case ts.SyntaxKind.ConditionalExpression: + if (options.operator) { + var _b = node, condition = _b.condition, whenTrue = _b.whenTrue; + checkForTrailingWhitespace(condition.getEnd()); + checkForTrailingWhitespace(whenTrue.getFullStart()); + checkForTrailingWhitespace(whenTrue.getEnd()); + } + break; + case ts.SyntaxKind.ConstructorType: + checkEqualsGreaterThanTokenInNode(node); + break; + case ts.SyntaxKind.ExportAssignment: + if (options.module) { + var exportKeyword = node.getChildAt(0); + var position = exportKeyword.getEnd(); + checkForTrailingWhitespace(position); + } + break; + case ts.SyntaxKind.FunctionType: + checkEqualsGreaterThanTokenInNode(node); + break; + case ts.SyntaxKind.ImportDeclaration: { + var importClause = node.importClause; + if (options.module && importClause !== undefined) { + // an import clause can have _both_ named bindings and a name (the latter for the default import) + // but the named bindings always come last, so we only need to check that for whitespace + var position = void 0; + var name_1 = importClause.name, namedBindings = importClause.namedBindings; + if (namedBindings !== undefined) { + position = namedBindings.getEnd(); + } + else if (name_1 !== undefined) { + position = name_1.getEnd(); + } + if (position !== undefined) { + checkForTrailingWhitespace(position); + } + } + break; + } + case ts.SyntaxKind.ImportEqualsDeclaration: + if (options.module) { + var position = node.name.getEnd(); + checkForTrailingWhitespace(position); + } + break; + case ts.SyntaxKind.TypeAssertionExpression: + if (options.typecast) { + var position = node.expression.getFullStart(); + checkForTrailingWhitespace(position); + } + break; + case ts.SyntaxKind.VariableDeclaration: + var _c = node, name = _c.name, type = _c.type, initializer = _c.initializer; + if (options.decl && initializer !== undefined) { + checkForTrailingWhitespace((type !== undefined ? type : name).getEnd()); + } + break; + } + ts.forEachChild(node, cb); + }); + var prevTokenShouldBeFollowedByWhitespace = false; + utils.forEachTokenWithTrivia(sourceFile, function (_text, tokenKind, range, parent) { + if (tokenKind === ts.SyntaxKind.WhitespaceTrivia || + tokenKind === ts.SyntaxKind.NewLineTrivia || + tokenKind === ts.SyntaxKind.EndOfFileToken) { + prevTokenShouldBeFollowedByWhitespace = false; + return; + } + else if (prevTokenShouldBeFollowedByWhitespace) { + addMissingWhitespaceErrorAt(range.pos); + prevTokenShouldBeFollowedByWhitespace = false; + } + // check for trailing space after the given tokens + switch (tokenKind) { + case ts.SyntaxKind.CatchKeyword: + case ts.SyntaxKind.ForKeyword: + case ts.SyntaxKind.IfKeyword: + case ts.SyntaxKind.SwitchKeyword: + case ts.SyntaxKind.WhileKeyword: + case ts.SyntaxKind.WithKeyword: + if (options.branch) { + prevTokenShouldBeFollowedByWhitespace = true; + } + break; + case ts.SyntaxKind.CommaToken: + case ts.SyntaxKind.SemicolonToken: + if (options.separator) { + prevTokenShouldBeFollowedByWhitespace = true; + } + break; + case ts.SyntaxKind.EqualsToken: + if (options.decl && parent.kind !== ts.SyntaxKind.JsxAttribute) { + prevTokenShouldBeFollowedByWhitespace = true; + } + break; + case ts.SyntaxKind.ColonToken: + if (options.type) { + prevTokenShouldBeFollowedByWhitespace = true; + } + break; + case ts.SyntaxKind.ImportKeyword: + case ts.SyntaxKind.ExportKeyword: + case ts.SyntaxKind.FromKeyword: + if (options.typecast) { + prevTokenShouldBeFollowedByWhitespace = true; + } + break; + default: + break; + } + }); + function checkEqualsGreaterThanTokenInNode(node) { + if (!options.operator) { + return; + } + var equalsGreaterThanToken = Lint.childOfKind(node, ts.SyntaxKind.EqualsGreaterThanToken); + // condition so we don't crash if the arrow is somehow missing + if (equalsGreaterThanToken === undefined) { + return; + } + checkForTrailingWhitespace(equalsGreaterThanToken.getFullStart()); + checkForTrailingWhitespace(equalsGreaterThanToken.getEnd()); + } + function checkForTrailingWhitespace(position) { + if (position !== sourceFile.end && !ts.isWhiteSpaceLike(sourceFile.text.charCodeAt(position))) { + addMissingWhitespaceErrorAt(position); + } + } + function addMissingWhitespaceErrorAt(position) { + // TODO: this rule occasionally adds duplicate failures. + if (ctx.failures.some(function (f) { return f.getStartPosition().getPosition() === position; })) { + return; + } + var fix = Lint.Replacement.appendText(position, " "); + ctx.addFailureAt(position, 1, Rule.FAILURE_STRING, fix); + } +} +var _a; -- cgit v1.2.3