.gitignore added
[dotfiles/.git] / .config / coc / extensions / node_modules / coc-prettier / node_modules / eslint / lib / rules / no-unexpected-multiline.js
1 /**
2  * @fileoverview Rule to spot scenarios where a newline looks like it is ending a statement, but is not.
3  * @author Glen Mailer
4  */
5 "use strict";
6
7 //------------------------------------------------------------------------------
8 // Requirements
9 //------------------------------------------------------------------------------
10
11 const astUtils = require("./utils/ast-utils");
12
13 //------------------------------------------------------------------------------
14 // Rule Definition
15 //------------------------------------------------------------------------------
16
17 module.exports = {
18     meta: {
19         type: "problem",
20
21         docs: {
22             description: "disallow confusing multiline expressions",
23             category: "Possible Errors",
24             recommended: true,
25             url: "https://eslint.org/docs/rules/no-unexpected-multiline"
26         },
27
28         schema: [],
29         messages: {
30             function: "Unexpected newline between function and ( of function call.",
31             property: "Unexpected newline between object and [ of property access.",
32             taggedTemplate: "Unexpected newline between template tag and template literal.",
33             division: "Unexpected newline between numerator and division operator."
34         }
35     },
36
37     create(context) {
38
39         const REGEX_FLAG_MATCHER = /^[gimsuy]+$/u;
40
41         const sourceCode = context.getSourceCode();
42
43         /**
44          * Check to see if there is a newline between the node and the following open bracket
45          * line's expression
46          * @param {ASTNode} node The node to check.
47          * @param {string} messageId The error messageId to use.
48          * @returns {void}
49          * @private
50          */
51         function checkForBreakAfter(node, messageId) {
52             const openParen = sourceCode.getTokenAfter(node, astUtils.isNotClosingParenToken);
53             const nodeExpressionEnd = sourceCode.getTokenBefore(openParen);
54
55             if (openParen.loc.start.line !== nodeExpressionEnd.loc.end.line) {
56                 context.report({
57                     node,
58                     loc: openParen.loc,
59                     messageId
60                 });
61             }
62         }
63
64         //--------------------------------------------------------------------------
65         // Public API
66         //--------------------------------------------------------------------------
67
68         return {
69
70             MemberExpression(node) {
71                 if (!node.computed || node.optional) {
72                     return;
73                 }
74                 checkForBreakAfter(node.object, "property");
75             },
76
77             TaggedTemplateExpression(node) {
78                 const { quasi } = node;
79
80                 // handles common tags, parenthesized tags, and typescript's generic type arguments
81                 const tokenBefore = sourceCode.getTokenBefore(quasi);
82
83                 if (tokenBefore.loc.end.line !== quasi.loc.start.line) {
84                     context.report({
85                         node,
86                         loc: {
87                             start: quasi.loc.start,
88                             end: {
89                                 line: quasi.loc.start.line,
90                                 column: quasi.loc.start.column + 1
91                             }
92                         },
93                         messageId: "taggedTemplate"
94                     });
95                 }
96             },
97
98             CallExpression(node) {
99                 if (node.arguments.length === 0 || node.optional) {
100                     return;
101                 }
102                 checkForBreakAfter(node.callee, "function");
103             },
104
105             "BinaryExpression[operator='/'] > BinaryExpression[operator='/'].left"(node) {
106                 const secondSlash = sourceCode.getTokenAfter(node, token => token.value === "/");
107                 const tokenAfterOperator = sourceCode.getTokenAfter(secondSlash);
108
109                 if (
110                     tokenAfterOperator.type === "Identifier" &&
111                     REGEX_FLAG_MATCHER.test(tokenAfterOperator.value) &&
112                     secondSlash.range[1] === tokenAfterOperator.range[0]
113                 ) {
114                     checkForBreakAfter(node.left, "division");
115                 }
116             }
117         };
118
119     }
120 };