UNPKG

tslint-eslint-rules

Version:

Improve your TSLint with the missing ESLint Rules

915 lines (914 loc) 90.3 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var tslib_1 = require("tslib"); var ts = require("typescript"); var Lint = require("tslint"); var RULE_NAME = 'ter-indent'; var DEFAULT_VARIABLE_INDENT = 1; var DEFAULT_PARAMETER_INDENT = null; var DEFAULT_FUNCTION_BODY_INDENT = 1; var indentType = 'space'; var indentSize = 4; var OPTIONS; function assign(target) { var sources = []; for (var _i = 1; _i < arguments.length; _i++) { sources[_i - 1] = arguments[_i]; } sources.forEach(function (source) { if (source !== undefined && source !== null) { for (var nextKey in source) { if (source.hasOwnProperty(nextKey)) { target[nextKey] = source[nextKey]; } } } }); return target; } function isKind(node, kind) { return node.kind === ts.SyntaxKind[kind]; } function isOneOf(node, kinds) { return kinds.some(function (kind) { return node.kind === ts.SyntaxKind[kind]; }); } var Rule = (function (_super) { tslib_1.__extends(Rule, _super); function Rule() { return _super !== null && _super.apply(this, arguments) || this; } Rule.prototype.apply = function (sourceFile) { var walker = new IndentWalker(sourceFile, this.getOptions()); return this.applyWithWalker(walker); }; Rule.metadata = { ruleName: RULE_NAME, hasFix: true, description: 'enforce consistent indentation', rationale: Lint.Utils.dedent(templateObject_1 || (templateObject_1 = tslib_1.__makeTemplateObject(["\n Using only one of tabs or spaces for indentation leads to more consistent editor behavior,\n cleaner diffs in version control, and easier programmatic manipulation.\n "], ["\n Using only one of tabs or spaces for indentation leads to more consistent editor behavior,\n cleaner diffs in version control, and easier programmatic manipulation.\n "]))), optionsDescription: Lint.Utils.dedent(templateObject_2 || (templateObject_2 = tslib_1.__makeTemplateObject(["\n The string 'tab' or an integer indicating the number of spaces to use per tab.\n\n An object may be provided to fine tune the indentation rules:\n\n * `\"SwitchCase\"` (default: 0) enforces indentation level for `case` clauses in\n `switch` statements\n * `\"VariableDeclarator\"` (default: 1) enforces indentation level for `var` declarators;\n can also take an object to define separate rules for `var`,\n `let` and `const` declarations.\n * `\"outerIIFEBody\"` (default: 1) enforces indentation level for file-level IIFEs.\n * `\"MemberExpression\"` (off by default) enforces indentation level for multi-line\n property chains (except in variable declarations and assignments)\n * `\"FunctionDeclaration\"` takes an object to define rules for function declarations.\n * `\"parameters\"` (off by default) enforces indentation level for parameters in a\n function declaration. This can either be a number indicating\n indentation level, or the string `\"first\"` indicating that all\n parameters of the declaration must be aligned with the first parameter.\n * `\"body\"` (default: 1) enforces indentation level for the body of a function expression.\n * `\"FunctionExpression\"` takes an object to define rules for function declarations.\n * `\"parameters\"` (off by default) enforces indentation level for parameters in a\n function declaration. This can either be a number indicating\n indentation level, or the string `\"first\"` indicating that all\n parameters of the declaration must be aligned with the first parameter.\n * `\"body\"` (default: 1) enforces indentation level for the body of a function expression.\n * `\"CallExpression\"` takes an object to define rules for function call expressions.\n * `\"arguments\"` (off by default) enforces indentation level for arguments in a call\n expression. This can either be a number indicating indentation level,\n or the string `\"first\"` indicating that all arguments of the\n expression must be aligned with the first argument.\n "], ["\n The string 'tab' or an integer indicating the number of spaces to use per tab.\n\n An object may be provided to fine tune the indentation rules:\n\n * \\`\"SwitchCase\"\\` (default: 0) enforces indentation level for \\`case\\` clauses in\n \\`switch\\` statements\n * \\`\"VariableDeclarator\"\\` (default: 1) enforces indentation level for \\`var\\` declarators;\n can also take an object to define separate rules for \\`var\\`,\n \\`let\\` and \\`const\\` declarations.\n * \\`\"outerIIFEBody\"\\` (default: 1) enforces indentation level for file-level IIFEs.\n * \\`\"MemberExpression\"\\` (off by default) enforces indentation level for multi-line\n property chains (except in variable declarations and assignments)\n * \\`\"FunctionDeclaration\"\\` takes an object to define rules for function declarations.\n * \\`\"parameters\"\\` (off by default) enforces indentation level for parameters in a\n function declaration. This can either be a number indicating\n indentation level, or the string \\`\"first\"\\` indicating that all\n parameters of the declaration must be aligned with the first parameter.\n * \\`\"body\"\\` (default: 1) enforces indentation level for the body of a function expression.\n * \\`\"FunctionExpression\"\\` takes an object to define rules for function declarations.\n * \\`\"parameters\"\\` (off by default) enforces indentation level for parameters in a\n function declaration. This can either be a number indicating\n indentation level, or the string \\`\"first\"\\` indicating that all\n parameters of the declaration must be aligned with the first parameter.\n * \\`\"body\"\\` (default: 1) enforces indentation level for the body of a function expression.\n * \\`\"CallExpression\"\\` takes an object to define rules for function call expressions.\n * \\`\"arguments\"\\` (off by default) enforces indentation level for arguments in a call\n expression. This can either be a number indicating indentation level,\n or the string \\`\"first\"\\` indicating that all arguments of the\n expression must be aligned with the first argument.\n "]))), options: { type: 'array', items: [{ type: 'number', minimum: '0' }, { type: 'string', enum: ['tab'] }, { type: 'object', properties: { SwitchCase: { type: 'number', minimum: 0 }, VariableDeclarator: { type: 'object', properties: { var: { type: 'number', minimum: 0 }, let: { type: 'number', minimum: 0 }, const: { type: 'number', minimum: 0 } } }, outerIIFEBody: { type: 'number' }, FunctionDeclaration: { type: 'object', properties: { parameters: { type: 'number', minimum: 0 }, body: { type: 'number', minimum: 0 } } }, FunctionExpression: { type: 'object', properties: { parameters: { type: 'number', minimum: 0 }, body: { type: 'number', minimum: 0 } } }, MemberExpression: { type: 'number' }, CallExpression: { type: 'object', properties: { arguments: { type: 'number', minimum: 0 } } } }, additionalProperties: false }], minLength: 1, maxLength: 2 }, optionExamples: [ Lint.Utils.dedent(templateObject_3 || (templateObject_3 = tslib_1.__makeTemplateObject(["\n \"", "\": [true, \"tab\"]\n "], ["\n \"", "\": [true, \"tab\"]\n "])), RULE_NAME), Lint.Utils.dedent(templateObject_4 || (templateObject_4 = tslib_1.__makeTemplateObject(["\n \"", "\": [true, 2]\n "], ["\n \"", "\": [true, 2]\n "])), RULE_NAME), Lint.Utils.dedent(templateObject_5 || (templateObject_5 = tslib_1.__makeTemplateObject(["\n \"", "\": [\n true,\n 2,\n {\n \"FunctionExpression\": {\n \"parameters\": 1,\n \"body\": 1\n }\n }\n ]\n "], ["\n \"", "\": [\n true,\n 2,\n {\n \"FunctionExpression\": {\n \"parameters\": 1,\n \"body\": 1\n }\n }\n ]\n "])), RULE_NAME) ], typescriptOnly: false, type: 'maintainability' }; return Rule; }(Lint.Rules.AbstractRule)); exports.Rule = Rule; var IndentWalker = (function (_super) { tslib_1.__extends(IndentWalker, _super); function IndentWalker(sourceFile, options) { var _this = _super.call(this, sourceFile, options) || this; _this.caseIndentStore = {}; _this.varIndentStore = {}; OPTIONS = { SwitchCase: 0, VariableDeclarator: { var: DEFAULT_VARIABLE_INDENT, let: DEFAULT_VARIABLE_INDENT, const: DEFAULT_VARIABLE_INDENT }, outerIIFEBody: null, FunctionDeclaration: { parameters: DEFAULT_PARAMETER_INDENT, body: DEFAULT_FUNCTION_BODY_INDENT }, FunctionExpression: { parameters: DEFAULT_PARAMETER_INDENT, body: DEFAULT_FUNCTION_BODY_INDENT }, CallExpression: { arguments: DEFAULT_PARAMETER_INDENT } }; var firstParam = _this.getOptions()[0]; if (firstParam === 'tab') { indentSize = 1; indentType = 'tab'; } else { indentSize = firstParam || 4; indentType = 'space'; } var userOptions = _this.getOptions()[1]; if (userOptions) { OPTIONS.SwitchCase = userOptions.SwitchCase || 0; if (typeof userOptions.VariableDeclarator === 'number') { OPTIONS.VariableDeclarator = { var: userOptions.VariableDeclarator, let: userOptions.VariableDeclarator, const: userOptions.VariableDeclarator }; } else if (typeof userOptions.VariableDeclarator === 'object') { assign(OPTIONS.VariableDeclarator, userOptions.VariableDeclarator); } if (typeof userOptions.outerIIFEBody === 'number') { OPTIONS.outerIIFEBody = userOptions.outerIIFEBody; } if (typeof userOptions.MemberExpression === 'number') { OPTIONS.MemberExpression = userOptions.MemberExpression; } if (typeof userOptions.FunctionDeclaration === 'object') { assign(OPTIONS.FunctionDeclaration, userOptions.FunctionDeclaration); } if (typeof userOptions.FunctionExpression === 'object') { assign(OPTIONS.FunctionExpression, userOptions.FunctionExpression); } if (typeof userOptions.CallExpression === 'object') { assign(OPTIONS.CallExpression, userOptions.CallExpression); } } _this.srcFile = sourceFile; _this.srcText = sourceFile.getFullText(); return _this; } IndentWalker.prototype.getSourceSubstr = function (start, end) { return this.srcText.substr(start, end - start); }; IndentWalker.prototype.getLineAndCharacter = function (node, byEndLocation) { if (byEndLocation === void 0) { byEndLocation = false; } var index = byEndLocation ? node.getEnd() : node.getStart(); return this.srcFile.getLineAndCharacterOfPosition(index); }; IndentWalker.prototype.getLine = function (node, byEndLocation) { if (byEndLocation === void 0) { byEndLocation = false; } return this.getLineAndCharacter(node, byEndLocation).line; }; IndentWalker.prototype.createErrorMessage = function (expectedAmount, actualSpaces, actualTabs) { var expectedStatement = expectedAmount + " " + indentType + (expectedAmount === 1 ? '' : 's'); var foundSpacesWord = "space" + (actualSpaces === 1 ? '' : 's'); var foundTabsWord = "tab" + (actualTabs === 1 ? '' : 's'); var foundStatement; if (actualSpaces > 0 && actualTabs > 0) { foundStatement = actualSpaces + " " + foundSpacesWord + " and " + actualTabs + " " + foundTabsWord; } else if (actualSpaces > 0) { foundStatement = indentType === 'space' ? actualSpaces : actualSpaces + " " + foundSpacesWord; } else if (actualTabs > 0) { foundStatement = indentType === 'tab' ? actualTabs : actualTabs + " " + foundTabsWord; } else { foundStatement = '0'; } return "Expected indentation of " + expectedStatement + " but found " + foundStatement + "."; }; IndentWalker.prototype.report = function (node, needed, gottenSpaces, gottenTabs, loc) { if (gottenSpaces && gottenTabs) { return; } var msg = this.createErrorMessage(needed, gottenSpaces, gottenTabs); var width = gottenSpaces + gottenTabs; var start = (loc !== undefined ? loc : node.getStart()) - width; var desiredIndent = (indentType === 'space' ? ' ' : '\t').repeat(needed); var fix = this.createReplacement(start, width, desiredIndent); this.addFailure(this.createFailure(start, width, msg, fix)); }; IndentWalker.prototype.isNodeFirstInLine = function (node, byEndLocation) { if (byEndLocation === void 0) { byEndLocation = false; } var token = byEndLocation ? node.getLastToken() : node.getFirstToken(); var pos = token.getStart() - 1; while ([' ', '\t'].indexOf(this.srcText.charAt(pos)) !== -1) { pos -= 1; } return this.srcText.charAt(pos) === '\n' || this._firstInLineCommentHelper(node); }; IndentWalker.prototype._firstInLineCommentHelper = function (node) { var pos; var firstInLine = false; var comments = ts.getLeadingCommentRanges(node.getFullText(), 0); if (comments && comments.length) { var offset = node.getFullStart(); var lastComment = comments[comments.length - 1]; var comment = this.getSourceSubstr(lastComment.pos + offset, lastComment.end + offset); if (comment.indexOf('\n') !== -1) { firstInLine = true; } else { pos = lastComment.pos + offset; while (pos > 0 && this.srcText.charAt(pos) !== '\n') { pos -= 1; } var content = this.getSourceSubstr(pos + 1, lastComment.pos + offset); if (content.trim() === '') { firstInLine = true; } } } return firstInLine; }; IndentWalker.prototype.getNodeIndent = function (node) { if (node === this.getSourceFile()) { return { contentStart: 0, firstInLine: true, space: 0, tab: 0, goodChar: 0, badChar: 0 }; } if (node.kind === ts.SyntaxKind.SyntaxList && node.parent) { return this.getNodeIndent(node.parent); } var endIndex = node.getStart(this.srcFile); var pos = endIndex - 1; while (pos > 0 && this.srcText.charAt(pos) !== '\n') { pos -= 1; } var str = this.getSourceSubstr(pos + 1, endIndex); var whiteSpace = (str.match(/^\s+/) || [''])[0]; var indentChars = whiteSpace.split(''); var spaces = indentChars.filter(function (char) { return char === ' '; }).length; var tabs = indentChars.filter(function (char) { return char === '\t'; }).length; return { contentStart: pos + spaces + tabs + 1, firstInLine: spaces + tabs === str.length || this._firstInLineCommentHelper(node), space: spaces, tab: tabs, goodChar: indentType === 'space' ? spaces : tabs, badChar: indentType === 'space' ? tabs : spaces }; }; IndentWalker.prototype.checkNodeIndent = function (node, neededIndent) { var actualIndent = this.getNodeIndent(node); if (!isKind(node, 'ArrayLiteralExpression') && !isKind(node, 'ObjectLiteralExpression') && (actualIndent.goodChar !== neededIndent || actualIndent.badChar !== 0) && actualIndent.firstInLine) { this.report(node, neededIndent, actualIndent.space, actualIndent.tab, actualIndent.contentStart); } if (isKind(node, 'IfStatement')) { var elseStatement = node.elseStatement; if (elseStatement) { var elseKeyword = node.getChildren().filter(function (ch) { return isKind(ch, 'ElseKeyword'); }).shift(); this.checkNodeIndent(elseKeyword, neededIndent); if (!this.isNodeFirstInLine(elseStatement)) { this.checkNodeIndent(elseStatement, neededIndent); } } } else if (isKind(node, 'TryStatement')) { var handler = node.catchClause; if (handler) { var catchKeyword = handler.getChildren().filter(function (ch) { return isKind(ch, 'CatchKeyword'); }).shift(); this.checkNodeIndent(catchKeyword, neededIndent); if (!this.isNodeFirstInLine(handler)) { this.checkNodeIndent(handler, neededIndent); } } var finalizer = node.finallyBlock; if (finalizer) { var finallyKeyword = node.getChildren().filter(function (ch) { return isKind(ch, 'FinallyKeyword'); }).shift(); this.checkNodeIndent(finallyKeyword, neededIndent); } } else if (isKind(node, 'DoStatement')) { var whileKeyword = node.getChildren().filter(function (ch) { return isKind(ch, 'WhileKeyword'); }).shift(); this.checkNodeIndent(whileKeyword, neededIndent); } }; IndentWalker.prototype.isSingleLineNode = function (node) { var text = node.kind === ts.SyntaxKind.SyntaxList ? node.getFullText() : node.getText(); return text.indexOf('\n') === -1; }; IndentWalker.prototype.blockIndentationCheck = function (node) { if (this.isSingleLineNode(node)) { return; } var functionLike = [ 'FunctionExpression', 'FunctionDeclaration', 'MethodDeclaration', 'Constructor', 'ArrowFunction' ]; if (node.parent && isOneOf(node.parent, functionLike)) { this.checkIndentInFunctionBlock(node); return; } var indent; var nodesToCheck = []; var statementsWithProperties = [ 'IfStatement', 'WhileStatement', 'ForStatement', 'ForInStatement', 'ForOfStatement', 'DoStatement', 'ClassDeclaration', 'ClassExpression', 'InterfaceDeclaration', 'TypeLiteral', 'TryStatement', 'SourceFile' ]; if (node.parent && isOneOf(node.parent, statementsWithProperties) && this.isNodeBodyBlock(node)) { indent = this.getNodeIndent(node.parent).goodChar; } else if (node.parent && isKind(node.parent, 'CatchClause')) { indent = this.getNodeIndent(node.parent.parent).goodChar; } else { indent = this.getNodeIndent(node).goodChar; } if (isKind(node, 'IfStatement') && !isKind(node.thenStatement, 'Block')) { nodesToCheck = [node.thenStatement]; } else { if (isKind(node, 'Block')) { nodesToCheck = node.getChildren()[1].getChildren(); } else if (node.parent && isOneOf(node.parent, [ 'ClassDeclaration', 'ClassExpression', 'InterfaceDeclaration', 'TypeLiteral' ])) { nodesToCheck = node.getChildren(); } else { nodesToCheck = [node.statement]; } } this.checkNodeIndent(node, indent); if (nodesToCheck.length > 0) { this.checkNodesIndent(nodesToCheck, indent + indentSize); } if (isKind(node, 'Block')) { this.checkLastNodeLineIndent(node, indent); } else if (node.parent && this.isNodeBodyBlock(node)) { this.checkLastNodeLineIndent(node.parent, indent); } }; IndentWalker.prototype.isAssignment = function (node) { if (!isKind(node, 'BinaryExpression')) { return false; } return node.operatorToken.getText() === '='; }; IndentWalker.prototype.isNodeBodyBlock = function (node) { var hasBlock = [ 'ClassDeclaration', 'ClassExpression', 'InterfaceDeclaration', 'TypeLiteral' ]; return isKind(node, 'Block') || (isKind(node, 'SyntaxList') && isOneOf(node.parent, hasBlock)); }; IndentWalker.prototype.checkFirstNodeLineIndent = function (node, firstLineIndent) { var startIndent = this.getNodeIndent(node); var firstInLine = startIndent.firstInLine; if (firstInLine && (startIndent.goodChar !== firstLineIndent || startIndent.badChar !== 0)) { this.report(node, firstLineIndent, startIndent.space, startIndent.tab, startIndent.contentStart); } }; IndentWalker.prototype.checkLastNodeLineIndent = function (node, lastLineIndent) { var lastToken = node.getLastToken(); var endIndent = this.getNodeIndent(lastToken); var firstInLine = endIndent.firstInLine; if (firstInLine && (endIndent.goodChar !== lastLineIndent || endIndent.badChar !== 0)) { this.report(lastToken, lastLineIndent, endIndent.space, endIndent.tab); } }; IndentWalker.prototype.isOuterIIFE = function (node) { if (!node.parent) return false; var parent = node.parent; var expressionIsNode = parent.expression !== node; if (isKind(parent, 'ParenthesizedExpression')) { parent = parent.parent; } if (!isKind(parent, 'CallExpression') || expressionIsNode) { return false; } var stmt = parent; var condition; do { stmt = stmt.parent; condition = (isKind(stmt, 'PrefixUnaryExpression') && (stmt.operator === ts.SyntaxKind.ExclamationToken || stmt.operator === ts.SyntaxKind.TildeToken || stmt.operator === ts.SyntaxKind.PlusToken || stmt.operator === ts.SyntaxKind.MinusToken) || isKind(stmt, 'BinaryExpression') || isKind(stmt, 'SyntaxList') || isKind(stmt, 'VariableDeclaration') || isKind(stmt, 'VariableDeclarationList') || isKind(stmt, 'ParenthesizedExpression')); } while (condition); return ((isKind(stmt, 'ExpressionStatement') || isKind(stmt, 'VariableStatement')) && !!stmt.parent && isKind(stmt.parent, 'SourceFile')); }; IndentWalker.prototype.isArgBeforeCalleeNodeMultiline = function (node) { var parent = node.parent; if (parent && parent['arguments'].length >= 2 && parent['arguments'][1] === node) { var firstArg = parent['arguments'][0]; return this.getLine(firstArg, true) > this.getLine(firstArg); } return false; }; IndentWalker.prototype.checkIndentInFunctionBlock = function (node) { var calleeNode = node.parent; var indent = this.getNodeIndent(calleeNode).goodChar; if (calleeNode.parent && calleeNode.parent.kind === ts.SyntaxKind.CallExpression) { var calleeParent = calleeNode.parent; if (calleeNode.kind !== ts.SyntaxKind.FunctionExpression && calleeNode.kind !== ts.SyntaxKind.ArrowFunction) { if (calleeParent && this.getLine(calleeParent) < this.getLine(node)) { indent = this.getNodeIndent(calleeParent).goodChar; } } else { var callee = calleeParent.expression; if (this.isArgBeforeCalleeNodeMultiline(calleeNode) && this.getLine(callee) === this.getLine(callee, true) && !this.isNodeFirstInLine(calleeNode)) { indent = this.getNodeIndent(calleeParent).goodChar; } } } var functionOffset = indentSize; if (OPTIONS.outerIIFEBody !== null && this.isOuterIIFE(calleeNode)) { functionOffset = OPTIONS.outerIIFEBody * indentSize; } else if (calleeNode.kind === ts.SyntaxKind.FunctionExpression) { functionOffset = OPTIONS.FunctionExpression.body * indentSize; } else if (calleeNode.kind === ts.SyntaxKind.FunctionDeclaration) { functionOffset = OPTIONS.FunctionDeclaration.body * indentSize; } else if (isOneOf(calleeNode, ['MethodDeclaration', 'Constructor'])) { functionOffset = OPTIONS.FunctionExpression.body * indentSize; } indent += functionOffset; var parentVarNode = this.getVariableDeclaratorNode(node); if (parentVarNode && this.isNodeInVarOnTop(node, parentVarNode) && parentVarNode.parent) { var varKind = parentVarNode.parent.getFirstToken().getText(); indent += indentSize * OPTIONS.VariableDeclarator[varKind]; } this.checkFirstNodeLineIndent(node, indent - functionOffset); if (node.statements.length) { this.checkNodesIndent(node.statements, indent); } this.checkLastNodeLineIndent(node, indent - functionOffset); }; IndentWalker.prototype.checkNodesIndent = function (nodes, indent) { var _this = this; nodes.forEach(function (node) { return _this.checkNodeIndent(node, indent); }); }; IndentWalker.prototype.expectedCaseIndent = function (node, switchIndent) { var switchNode = (node.kind === ts.SyntaxKind.SwitchStatement) ? node : node.parent; var line = this.getLine(switchNode); var caseIndent; if (this.caseIndentStore[line]) { return this.caseIndentStore[line]; } else { if (typeof switchIndent === 'undefined') { switchIndent = this.getNodeIndent(switchNode).goodChar; } caseIndent = switchIndent + (indentSize * OPTIONS.SwitchCase); this.caseIndentStore[line] = caseIndent; return caseIndent; } }; IndentWalker.prototype.expectedVarIndent = function (node, varIndent) { var varNode = node.parent; var line = this.getLine(varNode); var indent; if (this.varIndentStore[line]) { return this.varIndentStore[line]; } else { if (typeof varIndent === 'undefined') { varIndent = this.getNodeIndent(varNode).goodChar; } var varKind = varNode.getFirstToken().getText(); indent = varIndent + (indentSize * OPTIONS.VariableDeclarator[varKind]); this.varIndentStore[line] = indent; return indent; } }; IndentWalker.prototype.getParentNodeByType = function (node, kind, stopAtList) { if (stopAtList === void 0) { stopAtList = [ts.SyntaxKind.SourceFile]; } var parent = node.parent; while (parent && parent.kind !== kind && stopAtList.indexOf(parent.kind) === -1 && parent.kind !== ts.SyntaxKind.SourceFile) { parent = parent.parent; } return parent && parent.kind === kind ? parent : null; }; IndentWalker.prototype.getVariableDeclaratorNode = function (node) { return this.getParentNodeByType(node, ts.SyntaxKind.VariableDeclaration); }; IndentWalker.prototype.getBinaryExpressionNode = function (node) { return this.getParentNodeByType(node, ts.SyntaxKind.BinaryExpression); }; IndentWalker.prototype.checkIndentInArrayOrObjectBlock = function (node) { if (this.isSingleLineNode(node)) { return; } var elements = isKind(node, 'ObjectLiteralExpression') ? node['properties'] : node['elements']; elements = elements.filter(function (elem) { return elem.getText() !== ''; }); var nodeLine = this.getLine(node); var nodeEndLine = this.getLine(node, true); var nodeIndent; var elementsIndent; var varKind; var parentVarNode = this.getVariableDeclaratorNode(node); if (this.isNodeFirstInLine(node) && node.parent) { var parent = node.parent; nodeIndent = this.getNodeIndent(parent).goodChar; if (parentVarNode && this.getLine(parentVarNode) !== nodeLine) { if (!isKind(parent, 'VariableDeclaration') || parentVarNode === parentVarNode.parent.declarations[0]) { var parentVarLine = this.getLine(parentVarNode); var parentLine = this.getLine(parent); if (isKind(parent, 'VariableDeclaration') && parentVarLine === parentLine && parentVarNode.parent) { varKind = parentVarNode.parent.getFirstToken().getText(); nodeIndent = nodeIndent + (indentSize * OPTIONS.VariableDeclarator[varKind]); } else if (isOneOf(parent, [ 'ObjectLiteralExpression', 'ArrayLiteralExpression', 'CallExpression', 'ArrowFunction', 'NewExpression', 'BinaryExpression' ])) { nodeIndent = nodeIndent + indentSize; } } } else if (!parentVarNode && !this.isFirstArrayElementOnSameLine(parent) && parent.kind !== ts.SyntaxKind.PropertyAccessExpression && parent.kind !== ts.SyntaxKind.ExpressionStatement && parent.kind !== ts.SyntaxKind.PropertyAssignment && !(this.isAssignment(parent))) { nodeIndent = nodeIndent + indentSize; } elementsIndent = nodeIndent + indentSize; this.checkFirstNodeLineIndent(node, nodeIndent); } else { nodeIndent = this.getNodeIndent(node).goodChar; elementsIndent = nodeIndent + indentSize; } if (parentVarNode && this.isNodeInVarOnTop(node, parentVarNode) && parentVarNode.parent) { varKind = parentVarNode.parent.getFirstToken().getText(); elementsIndent += indentSize * OPTIONS.VariableDeclarator[varKind]; } this.checkNodesIndent(elements, elementsIndent); if (elements.length > 0) { var lastLine = this.getLine(elements[elements.length - 1], true); if (lastLine === nodeEndLine) { return; } } this.checkLastNodeLineIndent(node, elementsIndent - indentSize); }; IndentWalker.prototype.isFirstArrayElementOnSameLine = function (node) { if (isKind(node, 'ArrayLiteralExpression')) { var ele = node.elements[0]; if (ele) { return isKind(ele, 'ObjectLiteralExpression') && this.getLine(ele) === this.getLine(node); } } return false; }; IndentWalker.prototype.isNodeInVarOnTop = function (node, varNode) { var nodeLine = this.getLine(node); var parentLine = this.getLine(varNode.parent); return varNode && parentLine === nodeLine && varNode.parent.declarations.length > 1; }; IndentWalker.prototype.blockLessNodes = function (node) { if (!isKind(node.statement, 'Block')) { this.blockIndentationCheck(node); } }; IndentWalker.prototype.checkIndentInVariableDeclarations = function (node) { var indent = this.expectedVarIndent(node); this.checkNodeIndent(node, indent); }; IndentWalker.prototype.visitCase = function (node) { if (this.isSingleLineNode(node)) { return; } var caseIndent = this.expectedCaseIndent(node); this.checkNodesIndent(node.statements, caseIndent + indentSize); }; IndentWalker.prototype.checkLastReturnStatementLineIndent = function (node, firstLineIndent) { if (!node.expression) { return; } var lastToken = node.expression.getLastToken(); var endIndex = lastToken.getStart(); var pos = endIndex - 1; while (pos > 0 && this.srcText.charAt(pos) !== '\n') { pos -= 1; } var textBeforeClosingParenthesis = this.getSourceSubstr(pos + 1, endIndex); if (textBeforeClosingParenthesis.trim()) { return; } var endIndent = this.getNodeIndent(lastToken); if (endIndent.goodChar !== firstLineIndent) { this.report(node, firstLineIndent, endIndent.space, endIndent.tab, lastToken.getStart()); } }; IndentWalker.prototype.visitClassDeclaration = function (node) { var len = node.getChildCount(); this.blockIndentationCheck(node.getChildAt(len - 2)); _super.prototype.visitClassDeclaration.call(this, node); }; IndentWalker.prototype.visitClassExpression = function (node) { var len = node.getChildCount(); this.blockIndentationCheck(node.getChildAt(len - 2)); _super.prototype.visitClassExpression.call(this, node); }; IndentWalker.prototype.visitInterfaceDeclaration = function (node) { var len = node.getChildCount(); this.blockIndentationCheck(node.getChildAt(len - 2)); _super.prototype.visitInterfaceDeclaration.call(this, node); }; IndentWalker.prototype.visitTypeLiteral = function (node) { var len = node.getChildCount(); this.blockIndentationCheck(node.getChildAt(len - 2)); _super.prototype.visitTypeLiteral.call(this, node); }; IndentWalker.prototype.visitBlock = function (node) { this.blockIndentationCheck(node); _super.prototype.visitBlock.call(this, node); }; IndentWalker.prototype.visitIfStatement = function (node) { var thenLine = this.getLine(node.thenStatement); var line = this.getLine(node); if (!isKind(node.thenStatement, 'Block') && thenLine > line) { this.blockIndentationCheck(node); } _super.prototype.visitIfStatement.call(this, node); }; IndentWalker.prototype.visitObjectLiteralExpression = function (node) { this.checkIndentInArrayOrObjectBlock(node); _super.prototype.visitObjectLiteralExpression.call(this, node); }; IndentWalker.prototype.visitArrayLiteralExpression = function (node) { this.checkIndentInArrayOrObjectBlock(node); _super.prototype.visitArrayLiteralExpression.call(this, node); }; IndentWalker.prototype.visitSwitchStatement = function (node) { var switchIndent = this.getNodeIndent(node).goodChar; var caseIndent = this.expectedCaseIndent(node, switchIndent); this.checkNodesIndent(node.caseBlock.clauses, caseIndent); this.checkLastNodeLineIndent(node, switchIndent); _super.prototype.visitSwitchStatement.call(this, node); }; IndentWalker.prototype.visitCaseClause = function (node) { this.visitCase(node); _super.prototype.visitCaseClause.call(this, node); }; IndentWalker.prototype.visitDefaultClause = function (node) { this.visitCase(node); _super.prototype.visitDefaultClause.call(this, node); }; IndentWalker.prototype.visitWhileStatement = function (node) { this.blockLessNodes(node); _super.prototype.visitWhileStatement.call(this, node); }; IndentWalker.prototype.visitForStatement = function (node) { this.blockLessNodes(node); _super.prototype.visitForStatement.call(this, node); }; IndentWalker.prototype.visitForInStatement = function (node) { this.blockLessNodes(node); _super.prototype.visitForInStatement.call(this, node); }; IndentWalker.prototype.visitDoStatement = function (node) { this.blockLessNodes(node); _super.prototype.visitDoStatement.call(this, node); }; IndentWalker.prototype.visitVariableDeclaration = function (node) { this.checkIndentInVariableDeclarations(node); _super.prototype.visitVariableDeclaration.call(this, node); }; IndentWalker.prototype.visitVariableStatement = function (node) { _super.prototype.visitVariableStatement.call(this, node); var list = node.getChildAt(0).getChildAt(1); if (!list) { return; } var len = list.getChildCount(); if (len === 0) { return; } var lastElement = list.getChildAt(len - 1); var lastToken = node.getLastToken(); var lastTokenLine = this.getLine(lastToken, true); var lastElementLine = this.getLine(lastElement, true); if (lastTokenLine <= lastElementLine) { return; } var tokenBeforeLastElement = list.getChildAt(len - 2); if (tokenBeforeLastElement && isKind(tokenBeforeLastElement, 'CommaToken')) { this.checkLastNodeLineIndent(node, this.getNodeIndent(tokenBeforeLastElement).goodChar); } else { var nodeIndent = this.getNodeIndent(node).goodChar; var varKind = node.getFirstToken().getText(); var declaratorIndent = typeof OPTIONS.VariableDeclarator[varKind] === 'number' ? OPTIONS.VariableDeclarator[varKind] : DEFAULT_VARIABLE_INDENT; var elementsIndent = nodeIndent + indentSize * declaratorIndent; this.checkLastNodeLineIndent(node, elementsIndent - indentSize); } }; IndentWalker.prototype.visitFunctionDeclaration = function (node) { if (this.isSingleLineNode(node)) { return; } if (OPTIONS.FunctionDeclaration.parameters === 'first' && node.parameters.length) { var indent = this.getLineAndCharacter(node.parameters[0]).character; this.checkNodesIndent(node.parameters.slice(1), indent); } else if (OPTIONS.FunctionDeclaration.parameters !== null) { var nodeIndent = this.getNodeIndent(node).goodChar; this.checkNodesIndent(node.parameters, nodeIndent + indentSize * OPTIONS.FunctionDeclaration.parameters); var closingParen = node.getChildAt(node.getChildCount() - 2); this.checkNodeIndent(closingParen, nodeIndent); } _super.prototype.visitFunctionDeclaration.call(this, node); }; IndentWalker.prototype.checkFunctionMethodExpression = function (node) { if (OPTIONS.FunctionExpression.parameters === 'first' && node.parameters.length) { var indent = this.getLineAndCharacter(node.parameters[0]).character; this.checkNodesIndent(node.parameters.slice(1), indent); } else if (OPTIONS.FunctionExpression.parameters !== null) { var nodeIndent = this.getNodeIndent(node).goodChar; this.checkNodesIndent(node.parameters, nodeIndent + indentSize * OPTIONS.FunctionExpression.parameters); var closingParen = node.getChildAt(node.getChildCount() - 2); this.checkNodeIndent(closingParen, nodeIndent); } }; IndentWalker.prototype.visitFunctionExpression = function (node) { if (this.isSingleLineNode(node)) { return; } this.checkFunctionMethodExpression(node); _super.prototype.visitFunctionExpression.call(this, node); }; IndentWalker.prototype.visitMethodDeclaration = function (node) { if (this.isSingleLineNode(node)) { return; } this.checkFunctionMethodExpression(node); _super.prototype.visitMethodDeclaration.call(this, node); }; IndentWalker.prototype.visitConstructorDeclaration = function (node) { if (this.isSingleLineNode(node)) { return; } this.checkFunctionMethodExpression(node); _super.prototype.visitConstructorDeclaration.call(this, node); }; IndentWalker.prototype.visitCallExpression = function (node) { if (this.isSingleLineNode(node)) { return; } if (OPTIONS.CallExpression.arguments === 'first' && node.arguments.length) { var indent = this.getLineAndCharacter(node.arguments[0]).character; this.checkNodesIndent(node.arguments.slice(1), indent); } else if (OPTIONS.CallExpression.arguments !== null) { var openParen = node.getChildAt(node.getChildCount(this.srcFile) - 3, this.srcFile); var openParenIndent = this.getNodeIndent(openParen); this.checkNodesIndent(node.arguments, openParenIndent.goodChar + indentSize * OPTIONS.CallExpression.arguments); } _super.prototype.visitCallExpression.call(this, node); }; IndentWalker.prototype.visitPropertyAccessExpression = function (node) { if (this.isSingleLineNode(node)) { return; } var varDec = ts.SyntaxKind.VariableDeclaration; var funcKind = [ts.SyntaxKind.FunctionExpression, ts.SyntaxKind.ArrowFunction]; if (this.getParentNodeByType(node, varDec, funcKind)) { return; } var binExp = ts.SyntaxKind.BinaryExpression; var funcExp = ts.SyntaxKind.FunctionExpression; var binaryNode = this.getParentNodeByType(node, binExp, [funcExp]); if (binaryNode && this.isAssignment(binaryNode)) { return; } _super.prototype.visitPropertyAccessExpression.call(this, node); if (typeof OPTIONS.MemberExpression === 'undefined') { return; } var propertyIndent = this.getNodeIndent(node).goodChar + indentSize * OPTIONS.MemberExpression; var dotToken = node.getChildAt(1); var checkNodes = [node.name, dotToken]; this.checkNodesIndent(checkNodes, propertyIndent); }; IndentWalker.prototype.visitReturnStatement = function (node) { if (this.isSingleLineNode(node) || !node.expression) { return; } var firstLineIndent = this.getNodeIndent(node).goodChar; if (isKind(node.expression, 'ParenthesizedExpression')) { this.checkLastReturnStatementLineIndent(node, firstLineIndent); } else { this.checkNodeIndent(node, firstLineIndent); } _super.prototype.visitReturnStatement.call(this, node); }; IndentWalker.prototype.visitSourceFile = function (node) { this.checkNodesIndent(node.statements, 0); _super.prototype.visitSourceFile.call(this, node); }; return IndentWalker; }(Lint.RuleWalker)); var templateObject_1, templateObject_2, templateObject_3, templateObject_4, templateObject_5; //# sourceMappingURL=data:application/json;charset=utf8;base64,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