You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							1141 lines
						
					
					
						
							44 KiB
						
					
					
				
			
		
		
	
	
							1141 lines
						
					
					
						
							44 KiB
						
					
					
				/** | 
						|
 * @fileoverview This option sets a specific tab width for your code | 
						|
 * | 
						|
 * This rule has been ported and modified from nodeca. | 
						|
 * @author Vitaly Puzrin | 
						|
 * @author Gyandeep Singh | 
						|
 */ | 
						|
 | 
						|
"use strict"; | 
						|
 | 
						|
//------------------------------------------------------------------------------ | 
						|
// Requirements | 
						|
//------------------------------------------------------------------------------ | 
						|
 | 
						|
const astUtils = require("./utils/ast-utils"); | 
						|
 | 
						|
//------------------------------------------------------------------------------ | 
						|
// Rule Definition | 
						|
//------------------------------------------------------------------------------ | 
						|
 | 
						|
/* istanbul ignore next: this rule has known coverage issues, but it's deprecated and shouldn't be updated in the future anyway. */ | 
						|
module.exports = { | 
						|
    meta: { | 
						|
        type: "layout", | 
						|
 | 
						|
        docs: { | 
						|
            description: "enforce consistent indentation", | 
						|
            category: "Stylistic Issues", | 
						|
            recommended: false, | 
						|
            url: "https://eslint.org/docs/rules/indent-legacy" | 
						|
        }, | 
						|
 | 
						|
        deprecated: true, | 
						|
 | 
						|
        replacedBy: ["indent"], | 
						|
 | 
						|
        fixable: "whitespace", | 
						|
 | 
						|
        schema: [ | 
						|
            { | 
						|
                oneOf: [ | 
						|
                    { | 
						|
                        enum: ["tab"] | 
						|
                    }, | 
						|
                    { | 
						|
                        type: "integer", | 
						|
                        minimum: 0 | 
						|
                    } | 
						|
                ] | 
						|
            }, | 
						|
            { | 
						|
                type: "object", | 
						|
                properties: { | 
						|
                    SwitchCase: { | 
						|
                        type: "integer", | 
						|
                        minimum: 0 | 
						|
                    }, | 
						|
                    VariableDeclarator: { | 
						|
                        oneOf: [ | 
						|
                            { | 
						|
                                type: "integer", | 
						|
                                minimum: 0 | 
						|
                            }, | 
						|
                            { | 
						|
                                type: "object", | 
						|
                                properties: { | 
						|
                                    var: { | 
						|
                                        type: "integer", | 
						|
                                        minimum: 0 | 
						|
                                    }, | 
						|
                                    let: { | 
						|
                                        type: "integer", | 
						|
                                        minimum: 0 | 
						|
                                    }, | 
						|
                                    const: { | 
						|
                                        type: "integer", | 
						|
                                        minimum: 0 | 
						|
                                    } | 
						|
                                } | 
						|
                            } | 
						|
                        ] | 
						|
                    }, | 
						|
                    outerIIFEBody: { | 
						|
                        type: "integer", | 
						|
                        minimum: 0 | 
						|
                    }, | 
						|
                    MemberExpression: { | 
						|
                        type: "integer", | 
						|
                        minimum: 0 | 
						|
                    }, | 
						|
                    FunctionDeclaration: { | 
						|
                        type: "object", | 
						|
                        properties: { | 
						|
                            parameters: { | 
						|
                                oneOf: [ | 
						|
                                    { | 
						|
                                        type: "integer", | 
						|
                                        minimum: 0 | 
						|
                                    }, | 
						|
                                    { | 
						|
                                        enum: ["first"] | 
						|
                                    } | 
						|
                                ] | 
						|
                            }, | 
						|
                            body: { | 
						|
                                type: "integer", | 
						|
                                minimum: 0 | 
						|
                            } | 
						|
                        } | 
						|
                    }, | 
						|
                    FunctionExpression: { | 
						|
                        type: "object", | 
						|
                        properties: { | 
						|
                            parameters: { | 
						|
                                oneOf: [ | 
						|
                                    { | 
						|
                                        type: "integer", | 
						|
                                        minimum: 0 | 
						|
                                    }, | 
						|
                                    { | 
						|
                                        enum: ["first"] | 
						|
                                    } | 
						|
                                ] | 
						|
                            }, | 
						|
                            body: { | 
						|
                                type: "integer", | 
						|
                                minimum: 0 | 
						|
                            } | 
						|
                        } | 
						|
                    }, | 
						|
                    CallExpression: { | 
						|
                        type: "object", | 
						|
                        properties: { | 
						|
                            parameters: { | 
						|
                                oneOf: [ | 
						|
                                    { | 
						|
                                        type: "integer", | 
						|
                                        minimum: 0 | 
						|
                                    }, | 
						|
                                    { | 
						|
                                        enum: ["first"] | 
						|
                                    } | 
						|
                                ] | 
						|
                            } | 
						|
                        } | 
						|
                    }, | 
						|
                    ArrayExpression: { | 
						|
                        oneOf: [ | 
						|
                            { | 
						|
                                type: "integer", | 
						|
                                minimum: 0 | 
						|
                            }, | 
						|
                            { | 
						|
                                enum: ["first"] | 
						|
                            } | 
						|
                        ] | 
						|
                    }, | 
						|
                    ObjectExpression: { | 
						|
                        oneOf: [ | 
						|
                            { | 
						|
                                type: "integer", | 
						|
                                minimum: 0 | 
						|
                            }, | 
						|
                            { | 
						|
                                enum: ["first"] | 
						|
                            } | 
						|
                        ] | 
						|
                    } | 
						|
                }, | 
						|
                additionalProperties: false | 
						|
            } | 
						|
        ], | 
						|
        messages: { | 
						|
            expected: "Expected indentation of {{expected}} but found {{actual}}." | 
						|
        } | 
						|
    }, | 
						|
 | 
						|
    create(context) { | 
						|
        const DEFAULT_VARIABLE_INDENT = 1; | 
						|
        const DEFAULT_PARAMETER_INDENT = null; // For backwards compatibility, don't check parameter indentation unless specified in the config | 
						|
        const DEFAULT_FUNCTION_BODY_INDENT = 1; | 
						|
 | 
						|
        let indentType = "space"; | 
						|
        let indentSize = 4; | 
						|
        const 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 | 
						|
            }, | 
						|
            ArrayExpression: 1, | 
						|
            ObjectExpression: 1 | 
						|
        }; | 
						|
 | 
						|
        const sourceCode = context.getSourceCode(); | 
						|
 | 
						|
        if (context.options.length) { | 
						|
            if (context.options[0] === "tab") { | 
						|
                indentSize = 1; | 
						|
                indentType = "tab"; | 
						|
            } else /* istanbul ignore else : this will be caught by options validation */ if (typeof context.options[0] === "number") { | 
						|
                indentSize = context.options[0]; | 
						|
                indentType = "space"; | 
						|
            } | 
						|
 | 
						|
            if (context.options[1]) { | 
						|
                const opts = context.options[1]; | 
						|
 | 
						|
                options.SwitchCase = opts.SwitchCase || 0; | 
						|
                const variableDeclaratorRules = opts.VariableDeclarator; | 
						|
 | 
						|
                if (typeof variableDeclaratorRules === "number") { | 
						|
                    options.VariableDeclarator = { | 
						|
                        var: variableDeclaratorRules, | 
						|
                        let: variableDeclaratorRules, | 
						|
                        const: variableDeclaratorRules | 
						|
                    }; | 
						|
                } else if (typeof variableDeclaratorRules === "object") { | 
						|
                    Object.assign(options.VariableDeclarator, variableDeclaratorRules); | 
						|
                } | 
						|
 | 
						|
                if (typeof opts.outerIIFEBody === "number") { | 
						|
                    options.outerIIFEBody = opts.outerIIFEBody; | 
						|
                } | 
						|
 | 
						|
                if (typeof opts.MemberExpression === "number") { | 
						|
                    options.MemberExpression = opts.MemberExpression; | 
						|
                } | 
						|
 | 
						|
                if (typeof opts.FunctionDeclaration === "object") { | 
						|
                    Object.assign(options.FunctionDeclaration, opts.FunctionDeclaration); | 
						|
                } | 
						|
 | 
						|
                if (typeof opts.FunctionExpression === "object") { | 
						|
                    Object.assign(options.FunctionExpression, opts.FunctionExpression); | 
						|
                } | 
						|
 | 
						|
                if (typeof opts.CallExpression === "object") { | 
						|
                    Object.assign(options.CallExpression, opts.CallExpression); | 
						|
                } | 
						|
 | 
						|
                if (typeof opts.ArrayExpression === "number" || typeof opts.ArrayExpression === "string") { | 
						|
                    options.ArrayExpression = opts.ArrayExpression; | 
						|
                } | 
						|
 | 
						|
                if (typeof opts.ObjectExpression === "number" || typeof opts.ObjectExpression === "string") { | 
						|
                    options.ObjectExpression = opts.ObjectExpression; | 
						|
                } | 
						|
            } | 
						|
        } | 
						|
 | 
						|
        const caseIndentStore = {}; | 
						|
 | 
						|
        /** | 
						|
         * Creates an error message for a line, given the expected/actual indentation. | 
						|
         * @param {int} expectedAmount The expected amount of indentation characters for this line | 
						|
         * @param {int} actualSpaces The actual number of indentation spaces that were found on this line | 
						|
         * @param {int} actualTabs The actual number of indentation tabs that were found on this line | 
						|
         * @returns {string} An error message for this line | 
						|
         */ | 
						|
        function createErrorMessageData(expectedAmount, actualSpaces, actualTabs) { | 
						|
            const expectedStatement = `${expectedAmount} ${indentType}${expectedAmount === 1 ? "" : "s"}`; // e.g. "2 tabs" | 
						|
            const foundSpacesWord = `space${actualSpaces === 1 ? "" : "s"}`; // e.g. "space" | 
						|
            const foundTabsWord = `tab${actualTabs === 1 ? "" : "s"}`; // e.g. "tabs" | 
						|
            let foundStatement; | 
						|
 | 
						|
            if (actualSpaces > 0 && actualTabs > 0) { | 
						|
                foundStatement = `${actualSpaces} ${foundSpacesWord} and ${actualTabs} ${foundTabsWord}`; // e.g. "1 space and 2 tabs" | 
						|
            } else if (actualSpaces > 0) { | 
						|
 | 
						|
                /* | 
						|
                 * Abbreviate the message if the expected indentation is also spaces. | 
						|
                 * e.g. 'Expected 4 spaces but found 2' rather than 'Expected 4 spaces but found 2 spaces' | 
						|
                 */ | 
						|
                foundStatement = indentType === "space" ? actualSpaces : `${actualSpaces} ${foundSpacesWord}`; | 
						|
            } else if (actualTabs > 0) { | 
						|
                foundStatement = indentType === "tab" ? actualTabs : `${actualTabs} ${foundTabsWord}`; | 
						|
            } else { | 
						|
                foundStatement = "0"; | 
						|
            } | 
						|
            return { | 
						|
                expected: expectedStatement, | 
						|
                actual: foundStatement | 
						|
            }; | 
						|
        } | 
						|
 | 
						|
        /** | 
						|
         * Reports a given indent violation | 
						|
         * @param {ASTNode} node Node violating the indent rule | 
						|
         * @param {int} needed Expected indentation character count | 
						|
         * @param {int} gottenSpaces Indentation space count in the actual node/code | 
						|
         * @param {int} gottenTabs Indentation tab count in the actual node/code | 
						|
         * @param {Object} [loc] Error line and column location | 
						|
         * @param {boolean} isLastNodeCheck Is the error for last node check | 
						|
         * @returns {void} | 
						|
         */ | 
						|
        function report(node, needed, gottenSpaces, gottenTabs, loc, isLastNodeCheck) { | 
						|
            if (gottenSpaces && gottenTabs) { | 
						|
 | 
						|
                // To avoid conflicts with `no-mixed-spaces-and-tabs`, don't report lines that have both spaces and tabs. | 
						|
                return; | 
						|
            } | 
						|
 | 
						|
            const desiredIndent = (indentType === "space" ? " " : "\t").repeat(needed); | 
						|
 | 
						|
            const textRange = isLastNodeCheck | 
						|
                ? [node.range[1] - node.loc.end.column, node.range[1] - node.loc.end.column + gottenSpaces + gottenTabs] | 
						|
                : [node.range[0] - node.loc.start.column, node.range[0] - node.loc.start.column + gottenSpaces + gottenTabs]; | 
						|
 | 
						|
            context.report({ | 
						|
                node, | 
						|
                loc, | 
						|
                messageId: "expected", | 
						|
                data: createErrorMessageData(needed, gottenSpaces, gottenTabs), | 
						|
                fix: fixer => fixer.replaceTextRange(textRange, desiredIndent) | 
						|
            }); | 
						|
        } | 
						|
 | 
						|
        /** | 
						|
         * Get the actual indent of node | 
						|
         * @param {ASTNode|Token} node Node to examine | 
						|
         * @param {boolean} [byLastLine=false] get indent of node's last line | 
						|
         * @returns {Object} The node's indent. Contains keys `space` and `tab`, representing the indent of each character. Also | 
						|
         * contains keys `goodChar` and `badChar`, where `goodChar` is the amount of the user's desired indentation character, and | 
						|
         * `badChar` is the amount of the other indentation character. | 
						|
         */ | 
						|
        function getNodeIndent(node, byLastLine) { | 
						|
            const token = byLastLine ? sourceCode.getLastToken(node) : sourceCode.getFirstToken(node); | 
						|
            const srcCharsBeforeNode = sourceCode.getText(token, token.loc.start.column).split(""); | 
						|
            const indentChars = srcCharsBeforeNode.slice(0, srcCharsBeforeNode.findIndex(char => char !== " " && char !== "\t")); | 
						|
            const spaces = indentChars.filter(char => char === " ").length; | 
						|
            const tabs = indentChars.filter(char => char === "\t").length; | 
						|
 | 
						|
            return { | 
						|
                space: spaces, | 
						|
                tab: tabs, | 
						|
                goodChar: indentType === "space" ? spaces : tabs, | 
						|
                badChar: indentType === "space" ? tabs : spaces | 
						|
            }; | 
						|
        } | 
						|
 | 
						|
        /** | 
						|
         * Checks node is the first in its own start line. By default it looks by start line. | 
						|
         * @param {ASTNode} node The node to check | 
						|
         * @param {boolean} [byEndLocation=false] Lookup based on start position or end | 
						|
         * @returns {boolean} true if its the first in the its start line | 
						|
         */ | 
						|
        function isNodeFirstInLine(node, byEndLocation) { | 
						|
            const firstToken = byEndLocation === true ? sourceCode.getLastToken(node, 1) : sourceCode.getTokenBefore(node), | 
						|
                startLine = byEndLocation === true ? node.loc.end.line : node.loc.start.line, | 
						|
                endLine = firstToken ? firstToken.loc.end.line : -1; | 
						|
 | 
						|
            return startLine !== endLine; | 
						|
        } | 
						|
 | 
						|
        /** | 
						|
         * Check indent for node | 
						|
         * @param {ASTNode} node Node to check | 
						|
         * @param {int} neededIndent needed indent | 
						|
         * @returns {void} | 
						|
         */ | 
						|
        function checkNodeIndent(node, neededIndent) { | 
						|
            const actualIndent = getNodeIndent(node, false); | 
						|
 | 
						|
            if ( | 
						|
                node.type !== "ArrayExpression" && | 
						|
                node.type !== "ObjectExpression" && | 
						|
                (actualIndent.goodChar !== neededIndent || actualIndent.badChar !== 0) && | 
						|
                isNodeFirstInLine(node) | 
						|
            ) { | 
						|
                report(node, neededIndent, actualIndent.space, actualIndent.tab); | 
						|
            } | 
						|
 | 
						|
            if (node.type === "IfStatement" && node.alternate) { | 
						|
                const elseToken = sourceCode.getTokenBefore(node.alternate); | 
						|
 | 
						|
                checkNodeIndent(elseToken, neededIndent); | 
						|
 | 
						|
                if (!isNodeFirstInLine(node.alternate)) { | 
						|
                    checkNodeIndent(node.alternate, neededIndent); | 
						|
                } | 
						|
            } | 
						|
 | 
						|
            if (node.type === "TryStatement" && node.handler) { | 
						|
                const catchToken = sourceCode.getFirstToken(node.handler); | 
						|
 | 
						|
                checkNodeIndent(catchToken, neededIndent); | 
						|
            } | 
						|
 | 
						|
            if (node.type === "TryStatement" && node.finalizer) { | 
						|
                const finallyToken = sourceCode.getTokenBefore(node.finalizer); | 
						|
 | 
						|
                checkNodeIndent(finallyToken, neededIndent); | 
						|
            } | 
						|
 | 
						|
            if (node.type === "DoWhileStatement") { | 
						|
                const whileToken = sourceCode.getTokenAfter(node.body); | 
						|
 | 
						|
                checkNodeIndent(whileToken, neededIndent); | 
						|
            } | 
						|
        } | 
						|
 | 
						|
        /** | 
						|
         * Check indent for nodes list | 
						|
         * @param {ASTNode[]} nodes list of node objects | 
						|
         * @param {int} indent needed indent | 
						|
         * @returns {void} | 
						|
         */ | 
						|
        function checkNodesIndent(nodes, indent) { | 
						|
            nodes.forEach(node => checkNodeIndent(node, indent)); | 
						|
        } | 
						|
 | 
						|
        /** | 
						|
         * Check last node line indent this detects, that block closed correctly | 
						|
         * @param {ASTNode} node Node to examine | 
						|
         * @param {int} lastLineIndent needed indent | 
						|
         * @returns {void} | 
						|
         */ | 
						|
        function checkLastNodeLineIndent(node, lastLineIndent) { | 
						|
            const lastToken = sourceCode.getLastToken(node); | 
						|
            const endIndent = getNodeIndent(lastToken, true); | 
						|
 | 
						|
            if ((endIndent.goodChar !== lastLineIndent || endIndent.badChar !== 0) && isNodeFirstInLine(node, true)) { | 
						|
                report( | 
						|
                    node, | 
						|
                    lastLineIndent, | 
						|
                    endIndent.space, | 
						|
                    endIndent.tab, | 
						|
                    { line: lastToken.loc.start.line, column: lastToken.loc.start.column }, | 
						|
                    true | 
						|
                ); | 
						|
            } | 
						|
        } | 
						|
 | 
						|
        /** | 
						|
         * Check last node line indent this detects, that block closed correctly | 
						|
         * This function for more complicated return statement case, where closing parenthesis may be followed by ';' | 
						|
         * @param {ASTNode} node Node to examine | 
						|
         * @param {int} firstLineIndent first line needed indent | 
						|
         * @returns {void} | 
						|
         */ | 
						|
        function checkLastReturnStatementLineIndent(node, firstLineIndent) { | 
						|
 | 
						|
            /* | 
						|
             * in case if return statement ends with ');' we have traverse back to ')' | 
						|
             * otherwise we'll measure indent for ';' and replace ')' | 
						|
             */ | 
						|
            const lastToken = sourceCode.getLastToken(node, astUtils.isClosingParenToken); | 
						|
            const textBeforeClosingParenthesis = sourceCode.getText(lastToken, lastToken.loc.start.column).slice(0, -1); | 
						|
 | 
						|
            if (textBeforeClosingParenthesis.trim()) { | 
						|
 | 
						|
                // There are tokens before the closing paren, don't report this case | 
						|
                return; | 
						|
            } | 
						|
 | 
						|
            const endIndent = getNodeIndent(lastToken, true); | 
						|
 | 
						|
            if (endIndent.goodChar !== firstLineIndent) { | 
						|
                report( | 
						|
                    node, | 
						|
                    firstLineIndent, | 
						|
                    endIndent.space, | 
						|
                    endIndent.tab, | 
						|
                    { line: lastToken.loc.start.line, column: lastToken.loc.start.column }, | 
						|
                    true | 
						|
                ); | 
						|
            } | 
						|
        } | 
						|
 | 
						|
        /** | 
						|
         * Check first node line indent is correct | 
						|
         * @param {ASTNode} node Node to examine | 
						|
         * @param {int} firstLineIndent needed indent | 
						|
         * @returns {void} | 
						|
         */ | 
						|
        function checkFirstNodeLineIndent(node, firstLineIndent) { | 
						|
            const startIndent = getNodeIndent(node, false); | 
						|
 | 
						|
            if ((startIndent.goodChar !== firstLineIndent || startIndent.badChar !== 0) && isNodeFirstInLine(node)) { | 
						|
                report( | 
						|
                    node, | 
						|
                    firstLineIndent, | 
						|
                    startIndent.space, | 
						|
                    startIndent.tab, | 
						|
                    { line: node.loc.start.line, column: node.loc.start.column } | 
						|
                ); | 
						|
            } | 
						|
        } | 
						|
 | 
						|
        /** | 
						|
         * Returns a parent node of given node based on a specified type | 
						|
         * if not present then return null | 
						|
         * @param {ASTNode} node node to examine | 
						|
         * @param {string} type type that is being looked for | 
						|
         * @param {string} stopAtList end points for the evaluating code | 
						|
         * @returns {ASTNode|void} if found then node otherwise null | 
						|
         */ | 
						|
        function getParentNodeByType(node, type, stopAtList) { | 
						|
            let parent = node.parent; | 
						|
            const stopAtSet = new Set(stopAtList || ["Program"]); | 
						|
 | 
						|
            while (parent.type !== type && !stopAtSet.has(parent.type) && parent.type !== "Program") { | 
						|
                parent = parent.parent; | 
						|
            } | 
						|
 | 
						|
            return parent.type === type ? parent : null; | 
						|
        } | 
						|
 | 
						|
        /** | 
						|
         * Returns the VariableDeclarator based on the current node | 
						|
         * if not present then return null | 
						|
         * @param {ASTNode} node node to examine | 
						|
         * @returns {ASTNode|void} if found then node otherwise null | 
						|
         */ | 
						|
        function getVariableDeclaratorNode(node) { | 
						|
            return getParentNodeByType(node, "VariableDeclarator"); | 
						|
        } | 
						|
 | 
						|
        /** | 
						|
         * Check to see if the node is part of the multi-line variable declaration. | 
						|
         * Also if its on the same line as the varNode | 
						|
         * @param {ASTNode} node node to check | 
						|
         * @param {ASTNode} varNode variable declaration node to check against | 
						|
         * @returns {boolean} True if all the above condition satisfy | 
						|
         */ | 
						|
        function isNodeInVarOnTop(node, varNode) { | 
						|
            return varNode && | 
						|
                varNode.parent.loc.start.line === node.loc.start.line && | 
						|
                varNode.parent.declarations.length > 1; | 
						|
        } | 
						|
 | 
						|
        /** | 
						|
         * Check to see if the argument before the callee node is multi-line and | 
						|
         * there should only be 1 argument before the callee node | 
						|
         * @param {ASTNode} node node to check | 
						|
         * @returns {boolean} True if arguments are multi-line | 
						|
         */ | 
						|
        function isArgBeforeCalleeNodeMultiline(node) { | 
						|
            const parent = node.parent; | 
						|
 | 
						|
            if (parent.arguments.length >= 2 && parent.arguments[1] === node) { | 
						|
                return parent.arguments[0].loc.end.line > parent.arguments[0].loc.start.line; | 
						|
            } | 
						|
 | 
						|
            return false; | 
						|
        } | 
						|
 | 
						|
        /** | 
						|
         * Check to see if the node is a file level IIFE | 
						|
         * @param {ASTNode} node The function node to check. | 
						|
         * @returns {boolean} True if the node is the outer IIFE | 
						|
         */ | 
						|
        function isOuterIIFE(node) { | 
						|
            const parent = node.parent; | 
						|
            let stmt = parent.parent; | 
						|
 | 
						|
            /* | 
						|
             * Verify that the node is an IIEF | 
						|
             */ | 
						|
            if ( | 
						|
                parent.type !== "CallExpression" || | 
						|
                parent.callee !== node) { | 
						|
 | 
						|
                return false; | 
						|
            } | 
						|
 | 
						|
            /* | 
						|
             * Navigate legal ancestors to determine whether this IIEF is outer | 
						|
             */ | 
						|
            while ( | 
						|
                stmt.type === "UnaryExpression" && ( | 
						|
                    stmt.operator === "!" || | 
						|
                    stmt.operator === "~" || | 
						|
                    stmt.operator === "+" || | 
						|
                    stmt.operator === "-") || | 
						|
                stmt.type === "AssignmentExpression" || | 
						|
                stmt.type === "LogicalExpression" || | 
						|
                stmt.type === "SequenceExpression" || | 
						|
                stmt.type === "VariableDeclarator") { | 
						|
 | 
						|
                stmt = stmt.parent; | 
						|
            } | 
						|
 | 
						|
            return (( | 
						|
                stmt.type === "ExpressionStatement" || | 
						|
                stmt.type === "VariableDeclaration") && | 
						|
                stmt.parent && stmt.parent.type === "Program" | 
						|
            ); | 
						|
        } | 
						|
 | 
						|
        /** | 
						|
         * Check indent for function block content | 
						|
         * @param {ASTNode} node A BlockStatement node that is inside of a function. | 
						|
         * @returns {void} | 
						|
         */ | 
						|
        function checkIndentInFunctionBlock(node) { | 
						|
 | 
						|
            /* | 
						|
             * Search first caller in chain. | 
						|
             * Ex.: | 
						|
             * | 
						|
             * Models <- Identifier | 
						|
             *   .User | 
						|
             *   .find() | 
						|
             *   .exec(function() { | 
						|
             *   // function body | 
						|
             * }); | 
						|
             * | 
						|
             * Looks for 'Models' | 
						|
             */ | 
						|
            const calleeNode = node.parent; // FunctionExpression | 
						|
            let indent; | 
						|
 | 
						|
            if (calleeNode.parent && | 
						|
                (calleeNode.parent.type === "Property" || | 
						|
                calleeNode.parent.type === "ArrayExpression")) { | 
						|
 | 
						|
                // If function is part of array or object, comma can be put at left | 
						|
                indent = getNodeIndent(calleeNode, false).goodChar; | 
						|
            } else { | 
						|
 | 
						|
                // If function is standalone, simple calculate indent | 
						|
                indent = getNodeIndent(calleeNode).goodChar; | 
						|
            } | 
						|
 | 
						|
            if (calleeNode.parent.type === "CallExpression") { | 
						|
                const calleeParent = calleeNode.parent; | 
						|
 | 
						|
                if (calleeNode.type !== "FunctionExpression" && calleeNode.type !== "ArrowFunctionExpression") { | 
						|
                    if (calleeParent && calleeParent.loc.start.line < node.loc.start.line) { | 
						|
                        indent = getNodeIndent(calleeParent).goodChar; | 
						|
                    } | 
						|
                } else { | 
						|
                    if (isArgBeforeCalleeNodeMultiline(calleeNode) && | 
						|
                        calleeParent.callee.loc.start.line === calleeParent.callee.loc.end.line && | 
						|
                        !isNodeFirstInLine(calleeNode)) { | 
						|
                        indent = getNodeIndent(calleeParent).goodChar; | 
						|
                    } | 
						|
                } | 
						|
            } | 
						|
 | 
						|
            /* | 
						|
             * function body indent should be indent + indent size, unless this | 
						|
             * is a FunctionDeclaration, FunctionExpression, or outer IIFE and the corresponding options are enabled. | 
						|
             */ | 
						|
            let functionOffset = indentSize; | 
						|
 | 
						|
            if (options.outerIIFEBody !== null && isOuterIIFE(calleeNode)) { | 
						|
                functionOffset = options.outerIIFEBody * indentSize; | 
						|
            } else if (calleeNode.type === "FunctionExpression") { | 
						|
                functionOffset = options.FunctionExpression.body * indentSize; | 
						|
            } else if (calleeNode.type === "FunctionDeclaration") { | 
						|
                functionOffset = options.FunctionDeclaration.body * indentSize; | 
						|
            } | 
						|
            indent += functionOffset; | 
						|
 | 
						|
            // check if the node is inside a variable | 
						|
            const parentVarNode = getVariableDeclaratorNode(node); | 
						|
 | 
						|
            if (parentVarNode && isNodeInVarOnTop(node, parentVarNode)) { | 
						|
                indent += indentSize * options.VariableDeclarator[parentVarNode.parent.kind]; | 
						|
            } | 
						|
 | 
						|
            if (node.body.length > 0) { | 
						|
                checkNodesIndent(node.body, indent); | 
						|
            } | 
						|
 | 
						|
            checkLastNodeLineIndent(node, indent - functionOffset); | 
						|
        } | 
						|
 | 
						|
 | 
						|
        /** | 
						|
         * Checks if the given node starts and ends on the same line | 
						|
         * @param {ASTNode} node The node to check | 
						|
         * @returns {boolean} Whether or not the block starts and ends on the same line. | 
						|
         */ | 
						|
        function isSingleLineNode(node) { | 
						|
            const lastToken = sourceCode.getLastToken(node), | 
						|
                startLine = node.loc.start.line, | 
						|
                endLine = lastToken.loc.end.line; | 
						|
 | 
						|
            return startLine === endLine; | 
						|
        } | 
						|
 | 
						|
        /** | 
						|
         * Check to see if the first element inside an array is an object and on the same line as the node | 
						|
         * If the node is not an array then it will return false. | 
						|
         * @param {ASTNode} node node to check | 
						|
         * @returns {boolean} success/failure | 
						|
         */ | 
						|
        function isFirstArrayElementOnSameLine(node) { | 
						|
            if (node.type === "ArrayExpression" && node.elements[0]) { | 
						|
                return node.elements[0].loc.start.line === node.loc.start.line && node.elements[0].type === "ObjectExpression"; | 
						|
            } | 
						|
            return false; | 
						|
 | 
						|
        } | 
						|
 | 
						|
        /** | 
						|
         * Check indent for array block content or object block content | 
						|
         * @param {ASTNode} node node to examine | 
						|
         * @returns {void} | 
						|
         */ | 
						|
        function checkIndentInArrayOrObjectBlock(node) { | 
						|
 | 
						|
            // Skip inline | 
						|
            if (isSingleLineNode(node)) { | 
						|
                return; | 
						|
            } | 
						|
 | 
						|
            let elements = (node.type === "ArrayExpression") ? node.elements : node.properties; | 
						|
 | 
						|
            // filter out empty elements example would be [ , 2] so remove first element as espree considers it as null | 
						|
            elements = elements.filter(elem => elem !== null); | 
						|
 | 
						|
            let nodeIndent; | 
						|
            let elementsIndent; | 
						|
            const parentVarNode = getVariableDeclaratorNode(node); | 
						|
 | 
						|
            // TODO - come up with a better strategy in future | 
						|
            if (isNodeFirstInLine(node)) { | 
						|
                const parent = node.parent; | 
						|
 | 
						|
                nodeIndent = getNodeIndent(parent).goodChar; | 
						|
                if (!parentVarNode || parentVarNode.loc.start.line !== node.loc.start.line) { | 
						|
                    if (parent.type !== "VariableDeclarator" || parentVarNode === parentVarNode.parent.declarations[0]) { | 
						|
                        if (parent.type === "VariableDeclarator" && parentVarNode.loc.start.line === parent.loc.start.line) { | 
						|
                            nodeIndent += (indentSize * options.VariableDeclarator[parentVarNode.parent.kind]); | 
						|
                        } else if (parent.type === "ObjectExpression" || parent.type === "ArrayExpression") { | 
						|
                            const parentElements = node.parent.type === "ObjectExpression" ? node.parent.properties : node.parent.elements; | 
						|
 | 
						|
                            if (parentElements[0] && | 
						|
                                    parentElements[0].loc.start.line === parent.loc.start.line && | 
						|
                                    parentElements[0].loc.end.line !== parent.loc.start.line) { | 
						|
 | 
						|
                                /* | 
						|
                                 * If the first element of the array spans multiple lines, don't increase the expected indentation of the rest. | 
						|
                                 * e.g. [{ | 
						|
                                 *        foo: 1 | 
						|
                                 *      }, | 
						|
                                 *      { | 
						|
                                 *        bar: 1 | 
						|
                                 *      }] | 
						|
                                 * the second object is not indented. | 
						|
                                 */ | 
						|
                            } else if (typeof options[parent.type] === "number") { | 
						|
                                nodeIndent += options[parent.type] * indentSize; | 
						|
                            } else { | 
						|
                                nodeIndent = parentElements[0].loc.start.column; | 
						|
                            } | 
						|
                        } else if (parent.type === "CallExpression" || parent.type === "NewExpression") { | 
						|
                            if (typeof options.CallExpression.arguments === "number") { | 
						|
                                nodeIndent += options.CallExpression.arguments * indentSize; | 
						|
                            } else if (options.CallExpression.arguments === "first") { | 
						|
                                if (parent.arguments.indexOf(node) !== -1) { | 
						|
                                    nodeIndent = parent.arguments[0].loc.start.column; | 
						|
                                } | 
						|
                            } else { | 
						|
                                nodeIndent += indentSize; | 
						|
                            } | 
						|
                        } else if (parent.type === "LogicalExpression" || parent.type === "ArrowFunctionExpression") { | 
						|
                            nodeIndent += indentSize; | 
						|
                        } | 
						|
                    } | 
						|
                } else if (!parentVarNode && !isFirstArrayElementOnSameLine(parent) && parent.type !== "MemberExpression" && parent.type !== "ExpressionStatement" && parent.type !== "AssignmentExpression" && parent.type !== "Property") { | 
						|
                    nodeIndent += indentSize; | 
						|
                } | 
						|
 | 
						|
                checkFirstNodeLineIndent(node, nodeIndent); | 
						|
            } else { | 
						|
                nodeIndent = getNodeIndent(node).goodChar; | 
						|
            } | 
						|
 | 
						|
            if (options[node.type] === "first") { | 
						|
                elementsIndent = elements.length ? elements[0].loc.start.column : 0; // If there are no elements, elementsIndent doesn't matter. | 
						|
            } else { | 
						|
                elementsIndent = nodeIndent + indentSize * options[node.type]; | 
						|
            } | 
						|
 | 
						|
            /* | 
						|
             * Check if the node is a multiple variable declaration; if so, then | 
						|
             * make sure indentation takes that into account. | 
						|
             */ | 
						|
            if (isNodeInVarOnTop(node, parentVarNode)) { | 
						|
                elementsIndent += indentSize * options.VariableDeclarator[parentVarNode.parent.kind]; | 
						|
            } | 
						|
 | 
						|
            checkNodesIndent(elements, elementsIndent); | 
						|
 | 
						|
            if (elements.length > 0) { | 
						|
 | 
						|
                // Skip last block line check if last item in same line | 
						|
                if (elements[elements.length - 1].loc.end.line === node.loc.end.line) { | 
						|
                    return; | 
						|
                } | 
						|
            } | 
						|
 | 
						|
            checkLastNodeLineIndent(node, nodeIndent + | 
						|
                (isNodeInVarOnTop(node, parentVarNode) ? options.VariableDeclarator[parentVarNode.parent.kind] * indentSize : 0)); | 
						|
        } | 
						|
 | 
						|
        /** | 
						|
         * Check if the node or node body is a BlockStatement or not | 
						|
         * @param {ASTNode} node node to test | 
						|
         * @returns {boolean} True if it or its body is a block statement | 
						|
         */ | 
						|
        function isNodeBodyBlock(node) { | 
						|
            return node.type === "BlockStatement" || node.type === "ClassBody" || (node.body && node.body.type === "BlockStatement") || | 
						|
                (node.consequent && node.consequent.type === "BlockStatement"); | 
						|
        } | 
						|
 | 
						|
        /** | 
						|
         * Check indentation for blocks | 
						|
         * @param {ASTNode} node node to check | 
						|
         * @returns {void} | 
						|
         */ | 
						|
        function blockIndentationCheck(node) { | 
						|
 | 
						|
            // Skip inline blocks | 
						|
            if (isSingleLineNode(node)) { | 
						|
                return; | 
						|
            } | 
						|
 | 
						|
            if (node.parent && ( | 
						|
                node.parent.type === "FunctionExpression" || | 
						|
                node.parent.type === "FunctionDeclaration" || | 
						|
                node.parent.type === "ArrowFunctionExpression") | 
						|
            ) { | 
						|
                checkIndentInFunctionBlock(node); | 
						|
                return; | 
						|
            } | 
						|
 | 
						|
            let indent; | 
						|
            let nodesToCheck = []; | 
						|
 | 
						|
            /* | 
						|
             * For this statements we should check indent from statement beginning, | 
						|
             * not from the beginning of the block. | 
						|
             */ | 
						|
            const statementsWithProperties = [ | 
						|
                "IfStatement", "WhileStatement", "ForStatement", "ForInStatement", "ForOfStatement", "DoWhileStatement", "ClassDeclaration", "TryStatement" | 
						|
            ]; | 
						|
 | 
						|
            if (node.parent && statementsWithProperties.indexOf(node.parent.type) !== -1 && isNodeBodyBlock(node)) { | 
						|
                indent = getNodeIndent(node.parent).goodChar; | 
						|
            } else if (node.parent && node.parent.type === "CatchClause") { | 
						|
                indent = getNodeIndent(node.parent.parent).goodChar; | 
						|
            } else { | 
						|
                indent = getNodeIndent(node).goodChar; | 
						|
            } | 
						|
 | 
						|
            if (node.type === "IfStatement" && node.consequent.type !== "BlockStatement") { | 
						|
                nodesToCheck = [node.consequent]; | 
						|
            } else if (Array.isArray(node.body)) { | 
						|
                nodesToCheck = node.body; | 
						|
            } else { | 
						|
                nodesToCheck = [node.body]; | 
						|
            } | 
						|
 | 
						|
            if (nodesToCheck.length > 0) { | 
						|
                checkNodesIndent(nodesToCheck, indent + indentSize); | 
						|
            } | 
						|
 | 
						|
            if (node.type === "BlockStatement") { | 
						|
                checkLastNodeLineIndent(node, indent); | 
						|
            } | 
						|
        } | 
						|
 | 
						|
        /** | 
						|
         * Filter out the elements which are on the same line of each other or the node. | 
						|
         * basically have only 1 elements from each line except the variable declaration line. | 
						|
         * @param {ASTNode} node Variable declaration node | 
						|
         * @returns {ASTNode[]} Filtered elements | 
						|
         */ | 
						|
        function filterOutSameLineVars(node) { | 
						|
            return node.declarations.reduce((finalCollection, elem) => { | 
						|
                const lastElem = finalCollection[finalCollection.length - 1]; | 
						|
 | 
						|
                if ((elem.loc.start.line !== node.loc.start.line && !lastElem) || | 
						|
                    (lastElem && lastElem.loc.start.line !== elem.loc.start.line)) { | 
						|
                    finalCollection.push(elem); | 
						|
                } | 
						|
 | 
						|
                return finalCollection; | 
						|
            }, []); | 
						|
        } | 
						|
 | 
						|
        /** | 
						|
         * Check indentation for variable declarations | 
						|
         * @param {ASTNode} node node to examine | 
						|
         * @returns {void} | 
						|
         */ | 
						|
        function checkIndentInVariableDeclarations(node) { | 
						|
            const elements = filterOutSameLineVars(node); | 
						|
            const nodeIndent = getNodeIndent(node).goodChar; | 
						|
            const lastElement = elements[elements.length - 1]; | 
						|
 | 
						|
            const elementsIndent = nodeIndent + indentSize * options.VariableDeclarator[node.kind]; | 
						|
 | 
						|
            checkNodesIndent(elements, elementsIndent); | 
						|
 | 
						|
            // Only check the last line if there is any token after the last item | 
						|
            if (sourceCode.getLastToken(node).loc.end.line <= lastElement.loc.end.line) { | 
						|
                return; | 
						|
            } | 
						|
 | 
						|
            const tokenBeforeLastElement = sourceCode.getTokenBefore(lastElement); | 
						|
 | 
						|
            if (tokenBeforeLastElement.value === ",") { | 
						|
 | 
						|
                // Special case for comma-first syntax where the semicolon is indented | 
						|
                checkLastNodeLineIndent(node, getNodeIndent(tokenBeforeLastElement).goodChar); | 
						|
            } else { | 
						|
                checkLastNodeLineIndent(node, elementsIndent - indentSize); | 
						|
            } | 
						|
        } | 
						|
 | 
						|
        /** | 
						|
         * Check and decide whether to check for indentation for blockless nodes | 
						|
         * Scenarios are for or while statements without braces around them | 
						|
         * @param {ASTNode} node node to examine | 
						|
         * @returns {void} | 
						|
         */ | 
						|
        function blockLessNodes(node) { | 
						|
            if (node.body.type !== "BlockStatement") { | 
						|
                blockIndentationCheck(node); | 
						|
            } | 
						|
        } | 
						|
 | 
						|
        /** | 
						|
         * Returns the expected indentation for the case statement | 
						|
         * @param {ASTNode} node node to examine | 
						|
         * @param {int} [providedSwitchIndent] indent for switch statement | 
						|
         * @returns {int} indent size | 
						|
         */ | 
						|
        function expectedCaseIndent(node, providedSwitchIndent) { | 
						|
            const switchNode = (node.type === "SwitchStatement") ? node : node.parent; | 
						|
            const switchIndent = typeof providedSwitchIndent === "undefined" | 
						|
                ? getNodeIndent(switchNode).goodChar | 
						|
                : providedSwitchIndent; | 
						|
            let caseIndent; | 
						|
 | 
						|
            if (caseIndentStore[switchNode.loc.start.line]) { | 
						|
                return caseIndentStore[switchNode.loc.start.line]; | 
						|
            } | 
						|
 | 
						|
            if (switchNode.cases.length > 0 && options.SwitchCase === 0) { | 
						|
                caseIndent = switchIndent; | 
						|
            } else { | 
						|
                caseIndent = switchIndent + (indentSize * options.SwitchCase); | 
						|
            } | 
						|
 | 
						|
            caseIndentStore[switchNode.loc.start.line] = caseIndent; | 
						|
            return caseIndent; | 
						|
 | 
						|
        } | 
						|
 | 
						|
        /** | 
						|
         * Checks wether a return statement is wrapped in () | 
						|
         * @param {ASTNode} node node to examine | 
						|
         * @returns {boolean} the result | 
						|
         */ | 
						|
        function isWrappedInParenthesis(node) { | 
						|
            const regex = /^return\s*?\(\s*?\);*?/u; | 
						|
 | 
						|
            const statementWithoutArgument = sourceCode.getText(node).replace( | 
						|
                sourceCode.getText(node.argument), "" | 
						|
            ); | 
						|
 | 
						|
            return regex.test(statementWithoutArgument); | 
						|
        } | 
						|
 | 
						|
        return { | 
						|
            Program(node) { | 
						|
                if (node.body.length > 0) { | 
						|
 | 
						|
                    // Root nodes should have no indent | 
						|
                    checkNodesIndent(node.body, getNodeIndent(node).goodChar); | 
						|
                } | 
						|
            }, | 
						|
 | 
						|
            ClassBody: blockIndentationCheck, | 
						|
 | 
						|
            BlockStatement: blockIndentationCheck, | 
						|
 | 
						|
            WhileStatement: blockLessNodes, | 
						|
 | 
						|
            ForStatement: blockLessNodes, | 
						|
 | 
						|
            ForInStatement: blockLessNodes, | 
						|
 | 
						|
            ForOfStatement: blockLessNodes, | 
						|
 | 
						|
            DoWhileStatement: blockLessNodes, | 
						|
 | 
						|
            IfStatement(node) { | 
						|
                if (node.consequent.type !== "BlockStatement" && node.consequent.loc.start.line > node.loc.start.line) { | 
						|
                    blockIndentationCheck(node); | 
						|
                } | 
						|
            }, | 
						|
 | 
						|
            VariableDeclaration(node) { | 
						|
                if (node.declarations[node.declarations.length - 1].loc.start.line > node.declarations[0].loc.start.line) { | 
						|
                    checkIndentInVariableDeclarations(node); | 
						|
                } | 
						|
            }, | 
						|
 | 
						|
            ObjectExpression(node) { | 
						|
                checkIndentInArrayOrObjectBlock(node); | 
						|
            }, | 
						|
 | 
						|
            ArrayExpression(node) { | 
						|
                checkIndentInArrayOrObjectBlock(node); | 
						|
            }, | 
						|
 | 
						|
            MemberExpression(node) { | 
						|
 | 
						|
                if (typeof options.MemberExpression === "undefined") { | 
						|
                    return; | 
						|
                } | 
						|
 | 
						|
                if (isSingleLineNode(node)) { | 
						|
                    return; | 
						|
                } | 
						|
 | 
						|
                /* | 
						|
                 * The typical layout of variable declarations and assignments | 
						|
                 * alter the expectation of correct indentation. Skip them. | 
						|
                 * TODO: Add appropriate configuration options for variable | 
						|
                 * declarations and assignments. | 
						|
                 */ | 
						|
                if (getParentNodeByType(node, "VariableDeclarator", ["FunctionExpression", "ArrowFunctionExpression"])) { | 
						|
                    return; | 
						|
                } | 
						|
 | 
						|
                if (getParentNodeByType(node, "AssignmentExpression", ["FunctionExpression"])) { | 
						|
                    return; | 
						|
                } | 
						|
 | 
						|
                const propertyIndent = getNodeIndent(node).goodChar + indentSize * options.MemberExpression; | 
						|
 | 
						|
                const checkNodes = [node.property]; | 
						|
 | 
						|
                const dot = sourceCode.getTokenBefore(node.property); | 
						|
 | 
						|
                if (dot.type === "Punctuator" && dot.value === ".") { | 
						|
                    checkNodes.push(dot); | 
						|
                } | 
						|
 | 
						|
                checkNodesIndent(checkNodes, propertyIndent); | 
						|
            }, | 
						|
 | 
						|
            SwitchStatement(node) { | 
						|
 | 
						|
                // Switch is not a 'BlockStatement' | 
						|
                const switchIndent = getNodeIndent(node).goodChar; | 
						|
                const caseIndent = expectedCaseIndent(node, switchIndent); | 
						|
 | 
						|
                checkNodesIndent(node.cases, caseIndent); | 
						|
 | 
						|
 | 
						|
                checkLastNodeLineIndent(node, switchIndent); | 
						|
            }, | 
						|
 | 
						|
            SwitchCase(node) { | 
						|
 | 
						|
                // Skip inline cases | 
						|
                if (isSingleLineNode(node)) { | 
						|
                    return; | 
						|
                } | 
						|
                const caseIndent = expectedCaseIndent(node); | 
						|
 | 
						|
                checkNodesIndent(node.consequent, caseIndent + indentSize); | 
						|
            }, | 
						|
 | 
						|
            FunctionDeclaration(node) { | 
						|
                if (isSingleLineNode(node)) { | 
						|
                    return; | 
						|
                } | 
						|
                if (options.FunctionDeclaration.parameters === "first" && node.params.length) { | 
						|
                    checkNodesIndent(node.params.slice(1), node.params[0].loc.start.column); | 
						|
                } else if (options.FunctionDeclaration.parameters !== null) { | 
						|
                    checkNodesIndent(node.params, getNodeIndent(node).goodChar + indentSize * options.FunctionDeclaration.parameters); | 
						|
                } | 
						|
            }, | 
						|
 | 
						|
            FunctionExpression(node) { | 
						|
                if (isSingleLineNode(node)) { | 
						|
                    return; | 
						|
                } | 
						|
                if (options.FunctionExpression.parameters === "first" && node.params.length) { | 
						|
                    checkNodesIndent(node.params.slice(1), node.params[0].loc.start.column); | 
						|
                } else if (options.FunctionExpression.parameters !== null) { | 
						|
                    checkNodesIndent(node.params, getNodeIndent(node).goodChar + indentSize * options.FunctionExpression.parameters); | 
						|
                } | 
						|
            }, | 
						|
 | 
						|
            ReturnStatement(node) { | 
						|
                if (isSingleLineNode(node)) { | 
						|
                    return; | 
						|
                } | 
						|
 | 
						|
                const firstLineIndent = getNodeIndent(node).goodChar; | 
						|
 | 
						|
                // in case if return statement is wrapped in parenthesis | 
						|
                if (isWrappedInParenthesis(node)) { | 
						|
                    checkLastReturnStatementLineIndent(node, firstLineIndent); | 
						|
                } else { | 
						|
                    checkNodeIndent(node, firstLineIndent); | 
						|
                } | 
						|
            }, | 
						|
 | 
						|
            CallExpression(node) { | 
						|
                if (isSingleLineNode(node)) { | 
						|
                    return; | 
						|
                } | 
						|
                if (options.CallExpression.arguments === "first" && node.arguments.length) { | 
						|
                    checkNodesIndent(node.arguments.slice(1), node.arguments[0].loc.start.column); | 
						|
                } else if (options.CallExpression.arguments !== null) { | 
						|
                    checkNodesIndent(node.arguments, getNodeIndent(node).goodChar + indentSize * options.CallExpression.arguments); | 
						|
                } | 
						|
            } | 
						|
 | 
						|
        }; | 
						|
 | 
						|
    } | 
						|
};
 | 
						|
 |