| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899 | /** * @fileoverview Rule to spot scenarios where a newline looks like it is ending a statement, but is not. * @author Glen Mailer */"use strict";//------------------------------------------------------------------------------// Requirements//------------------------------------------------------------------------------const astUtils = require("../ast-utils");//------------------------------------------------------------------------------// Rule Definition//------------------------------------------------------------------------------module.exports = {    meta: {        docs: {            description: "disallow confusing multiline expressions",            category: "Possible Errors",            recommended: true,            url: "https://eslint.org/docs/rules/no-unexpected-multiline"        },        schema: []    },    create(context) {        const FUNCTION_MESSAGE = "Unexpected newline between function and ( of function call.";        const PROPERTY_MESSAGE = "Unexpected newline between object and [ of property access.";        const TAGGED_TEMPLATE_MESSAGE = "Unexpected newline between template tag and template literal.";        const DIVISION_MESSAGE = "Unexpected newline between numerator and division operator.";        const REGEX_FLAG_MATCHER = /^[gimsuy]+$/;        const sourceCode = context.getSourceCode();        /**         * Check to see if there is a newline between the node and the following open bracket         * line's expression         * @param {ASTNode} node The node to check.         * @param {string} msg The error message to use.         * @returns {void}         * @private         */        function checkForBreakAfter(node, msg) {            const openParen = sourceCode.getTokenAfter(node, astUtils.isNotClosingParenToken);            const nodeExpressionEnd = sourceCode.getTokenBefore(openParen);            if (openParen.loc.start.line !== nodeExpressionEnd.loc.end.line) {                context.report({ node, loc: openParen.loc.start, message: msg, data: { char: openParen.value } });            }        }        //--------------------------------------------------------------------------        // Public API        //--------------------------------------------------------------------------        return {            MemberExpression(node) {                if (!node.computed) {                    return;                }                checkForBreakAfter(node.object, PROPERTY_MESSAGE);            },            TaggedTemplateExpression(node) {                if (node.tag.loc.end.line === node.quasi.loc.start.line) {                    return;                }                context.report({ node, loc: node.loc.start, message: TAGGED_TEMPLATE_MESSAGE });            },            CallExpression(node) {                if (node.arguments.length === 0) {                    return;                }                checkForBreakAfter(node.callee, FUNCTION_MESSAGE);            },            "BinaryExpression[operator='/'] > BinaryExpression[operator='/'].left"(node) {                const secondSlash = sourceCode.getTokenAfter(node, token => token.value === "/");                const tokenAfterOperator = sourceCode.getTokenAfter(secondSlash);                if (                    tokenAfterOperator.type === "Identifier" &&                    REGEX_FLAG_MATCHER.test(tokenAfterOperator.value) &&                    secondSlash.range[1] === tokenAfterOperator.range[0]                ) {                    checkForBreakAfter(node.left, DIVISION_MESSAGE);                }            }        };    }};
 |