eslint 4.7.2 → 4.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (139) hide show
  1. package/CHANGELOG.md +123 -0
  2. package/README.md +34 -19
  3. package/conf/default-cli-options.js +7 -4
  4. package/conf/eslint-recommended.js +2 -0
  5. package/lib/ast-utils.js +83 -42
  6. package/lib/cli-engine.js +53 -17
  7. package/lib/cli.js +17 -9
  8. package/lib/code-path-analysis/code-path-analyzer.js +8 -4
  9. package/lib/code-path-analysis/code-path-segment.js +43 -41
  10. package/lib/code-path-analysis/code-path-state.js +7 -2
  11. package/lib/config/autoconfig.js +14 -12
  12. package/lib/config/config-file.js +8 -51
  13. package/lib/config/config-initializer.js +10 -6
  14. package/lib/config/config-ops.js +21 -21
  15. package/lib/config/config-rule.js +24 -24
  16. package/lib/config/config-validator.js +38 -36
  17. package/lib/config/plugins.js +8 -35
  18. package/lib/config.js +12 -8
  19. package/lib/formatters/html-template-message.html +1 -1
  20. package/lib/formatters/html-template-page.html +3 -1
  21. package/lib/formatters/html.js +2 -1
  22. package/lib/formatters/junit.js +21 -15
  23. package/lib/formatters/tap.js +5 -3
  24. package/lib/ignored-paths.js +5 -3
  25. package/lib/linter.js +42 -42
  26. package/lib/logging.js +2 -2
  27. package/lib/options.js +12 -0
  28. package/lib/rules/.eslintrc.yml +2 -2
  29. package/lib/rules/array-bracket-newline.js +39 -25
  30. package/lib/rules/array-bracket-spacing.js +28 -28
  31. package/lib/rules/array-callback-return.js +13 -9
  32. package/lib/rules/array-element-newline.js +8 -8
  33. package/lib/rules/arrow-body-style.js +12 -6
  34. package/lib/rules/arrow-parens.js +4 -2
  35. package/lib/rules/block-spacing.js +1 -1
  36. package/lib/rules/brace-style.js +14 -14
  37. package/lib/rules/callback-return.js +2 -1
  38. package/lib/rules/capitalized-comments.js +2 -1
  39. package/lib/rules/comma-style.js +3 -1
  40. package/lib/rules/computed-property-spacing.js +22 -22
  41. package/lib/rules/consistent-return.js +4 -4
  42. package/lib/rules/consistent-this.js +4 -2
  43. package/lib/rules/curly.js +13 -9
  44. package/lib/rules/dot-notation.js +56 -35
  45. package/lib/rules/func-call-spacing.js +4 -2
  46. package/lib/rules/generator-star-spacing.js +3 -3
  47. package/lib/rules/getter-return.js +2 -1
  48. package/lib/rules/indent-legacy.js +25 -14
  49. package/lib/rules/indent.js +101 -91
  50. package/lib/rules/key-spacing.js +5 -3
  51. package/lib/rules/lines-around-comment.js +33 -4
  52. package/lib/rules/lines-around-directive.js +16 -12
  53. package/lib/rules/lines-between-class-members.js +91 -0
  54. package/lib/rules/max-len.js +2 -3
  55. package/lib/rules/max-statements-per-line.js +5 -3
  56. package/lib/rules/multiline-comment-style.js +294 -0
  57. package/lib/rules/new-cap.js +2 -1
  58. package/lib/rules/newline-after-var.js +8 -6
  59. package/lib/rules/newline-before-return.js +13 -9
  60. package/lib/rules/no-alert.js +7 -15
  61. package/lib/rules/no-await-in-loop.js +17 -9
  62. package/lib/rules/no-bitwise.js +5 -3
  63. package/lib/rules/no-catch-shadow.js +4 -2
  64. package/lib/rules/no-console.js +2 -1
  65. package/lib/rules/no-constant-condition.js +2 -2
  66. package/lib/rules/no-control-regex.js +2 -1
  67. package/lib/rules/no-else-return.js +60 -19
  68. package/lib/rules/no-empty-character-class.js +11 -11
  69. package/lib/rules/no-extra-parens.js +22 -11
  70. package/lib/rules/no-extra-semi.js +5 -3
  71. package/lib/rules/no-global-assign.js +4 -2
  72. package/lib/rules/no-implicit-coercion.js +6 -6
  73. package/lib/rules/no-implied-eval.js +2 -1
  74. package/lib/rules/no-label-var.js +4 -2
  75. package/lib/rules/no-lone-blocks.js +3 -3
  76. package/lib/rules/no-lonely-if.js +2 -1
  77. package/lib/rules/no-loop-func.js +10 -7
  78. package/lib/rules/no-mixed-requires.js +8 -4
  79. package/lib/rules/no-native-reassign.js +4 -2
  80. package/lib/rules/no-param-reassign.js +4 -2
  81. package/lib/rules/no-regex-spaces.js +1 -1
  82. package/lib/rules/no-restricted-imports.js +86 -17
  83. package/lib/rules/no-restricted-modules.js +84 -15
  84. package/lib/rules/no-restricted-properties.js +10 -10
  85. package/lib/rules/no-return-await.js +6 -6
  86. package/lib/rules/no-self-assign.js +4 -2
  87. package/lib/rules/no-sequences.js +6 -4
  88. package/lib/rules/no-trailing-spaces.js +14 -8
  89. package/lib/rules/no-unneeded-ternary.js +3 -1
  90. package/lib/rules/no-unreachable.js +4 -2
  91. package/lib/rules/no-unused-labels.js +2 -1
  92. package/lib/rules/no-use-before-define.js +13 -11
  93. package/lib/rules/no-useless-call.js +1 -25
  94. package/lib/rules/no-useless-computed-key.js +2 -1
  95. package/lib/rules/no-useless-escape.js +31 -23
  96. package/lib/rules/no-useless-return.js +14 -8
  97. package/lib/rules/no-var.js +11 -0
  98. package/lib/rules/no-whitespace-before-property.js +4 -2
  99. package/lib/rules/object-curly-newline.js +9 -2
  100. package/lib/rules/object-curly-spacing.js +20 -20
  101. package/lib/rules/object-shorthand.js +47 -35
  102. package/lib/rules/operator-assignment.js +9 -9
  103. package/lib/rules/operator-linebreak.js +15 -11
  104. package/lib/rules/padding-line-between-statements.js +6 -4
  105. package/lib/rules/prefer-arrow-callback.js +12 -10
  106. package/lib/rules/prefer-const.js +18 -10
  107. package/lib/rules/prefer-destructuring.js +4 -2
  108. package/lib/rules/prefer-numeric-literals.js +4 -2
  109. package/lib/rules/prefer-promise-reject-errors.js +16 -16
  110. package/lib/rules/prefer-rest-params.js +4 -2
  111. package/lib/rules/prefer-spread.js +1 -25
  112. package/lib/rules/prefer-template.js +33 -29
  113. package/lib/rules/quote-props.js +8 -8
  114. package/lib/rules/require-jsdoc.js +11 -18
  115. package/lib/rules/semi-style.js +44 -19
  116. package/lib/rules/semi.js +5 -3
  117. package/lib/rules/sort-imports.js +11 -6
  118. package/lib/rules/space-unary-ops.js +67 -69
  119. package/lib/rules/strict.js +8 -8
  120. package/lib/rules/valid-jsdoc.js +39 -33
  121. package/lib/rules/valid-typeof.js +4 -4
  122. package/lib/rules/wrap-iife.js +4 -4
  123. package/lib/rules/yoda.js +9 -7
  124. package/lib/testers/rule-tester.js +63 -40
  125. package/lib/token-store/backward-token-cursor.js +5 -3
  126. package/lib/token-store/forward-token-cursor.js +5 -3
  127. package/lib/token-store/utils.js +8 -4
  128. package/lib/util/apply-disable-directives.js +56 -27
  129. package/lib/util/glob.js +1 -1
  130. package/lib/util/naming.js +112 -0
  131. package/lib/util/node-event-generator.js +13 -27
  132. package/lib/util/safe-emitter.js +54 -0
  133. package/lib/util/source-code-fixer.js +4 -2
  134. package/lib/util/source-code.js +70 -65
  135. package/messages/no-config-found.txt +1 -1
  136. package/package.json +8 -8
  137. package/lib/internal-rules/.eslintrc.yml +0 -3
  138. package/lib/internal-rules/internal-consistent-docs-description.js +0 -130
  139. package/lib/internal-rules/internal-no-invalid-meta.js +0 -188
@@ -96,8 +96,10 @@ module.exports = {
96
96
 
97
97
  if (+(newPrefix + node.arguments[0].value) !== parseInt(node.arguments[0].value, node.arguments[1].value)) {
98
98
 
99
- // If the newly-produced literal would be invalid, (e.g. 0b1234),
100
- // or it would yield an incorrect parseInt result for some other reason, don't make a fix.
99
+ /*
100
+ * If the newly-produced literal would be invalid, (e.g. 0b1234),
101
+ * or it would yield an incorrect parseInt result for some other reason, don't make a fix.
102
+ */
101
103
  return null;
102
104
  }
103
105
  return fixer.replaceText(node, prefixMap[node.arguments[1].value] + node.arguments[0].value);
@@ -38,10 +38,10 @@ module.exports = {
38
38
  //----------------------------------------------------------------------
39
39
 
40
40
  /**
41
- * Checks the argument of a reject() or Promise.reject() CallExpression, and reports it if it can't be an Error
42
- * @param {ASTNode} callExpression A CallExpression node which is used to reject a Promise
43
- * @returns {void}
44
- */
41
+ * Checks the argument of a reject() or Promise.reject() CallExpression, and reports it if it can't be an Error
42
+ * @param {ASTNode} callExpression A CallExpression node which is used to reject a Promise
43
+ * @returns {void}
44
+ */
45
45
  function checkRejectCall(callExpression) {
46
46
  if (!callExpression.arguments.length && ALLOW_EMPTY_REJECT) {
47
47
  return;
@@ -59,10 +59,10 @@ module.exports = {
59
59
  }
60
60
 
61
61
  /**
62
- * Determines whether a function call is a Promise.reject() call
63
- * @param {ASTNode} node A CallExpression node
64
- * @returns {boolean} `true` if the call is a Promise.reject() call
65
- */
62
+ * Determines whether a function call is a Promise.reject() call
63
+ * @param {ASTNode} node A CallExpression node
64
+ * @returns {boolean} `true` if the call is a Promise.reject() call
65
+ */
66
66
  function isPromiseRejectCall(node) {
67
67
  return node.callee.type === "MemberExpression" &&
68
68
  node.callee.object.type === "Identifier" && node.callee.object.name === "Promise" &&
@@ -96,14 +96,14 @@ module.exports = {
96
96
  context.getDeclaredVariables(node.arguments[0])
97
97
 
98
98
  /*
99
- * Find the first variable that matches the second parameter's name.
100
- * If the first parameter has the same name as the second parameter, then the variable will actually
101
- * be "declared" when the first parameter is evaluated, but then it will be immediately overwritten
102
- * by the second parameter. It's not possible for an expression with the variable to be evaluated before
103
- * the variable is overwritten, because functions with duplicate parameters cannot have destructuring or
104
- * default assignments in their parameter lists. Therefore, it's not necessary to explicitly account for
105
- * this case.
106
- */
99
+ * Find the first variable that matches the second parameter's name.
100
+ * If the first parameter has the same name as the second parameter, then the variable will actually
101
+ * be "declared" when the first parameter is evaluated, but then it will be immediately overwritten
102
+ * by the second parameter. It's not possible for an expression with the variable to be evaluated before
103
+ * the variable is overwritten, because functions with duplicate parameters cannot have destructuring or
104
+ * default assignments in their parameter lists. Therefore, it's not necessary to explicitly account for
105
+ * this case.
106
+ */
107
107
  .find(variable => variable.name === node.arguments[0].params[1].name)
108
108
 
109
109
  // Get the references to that variable.
@@ -22,8 +22,10 @@ function getVariableOfArguments(scope) {
22
22
 
23
23
  if (variable.name === "arguments") {
24
24
 
25
- // If there was a parameter which is named "arguments", the implicit "arguments" is not defined.
26
- // So does fast return with null.
25
+ /*
26
+ * If there was a parameter which is named "arguments", the implicit "arguments" is not defined.
27
+ * So does fast return with null.
28
+ */
27
29
  return (variable.identifiers.length === 0) ? variable : null;
28
30
  }
29
31
  }
@@ -28,30 +28,6 @@ function isVariadicApplyCalling(node) {
28
28
  );
29
29
  }
30
30
 
31
- /**
32
- * Checks whether or not the tokens of two given nodes are same.
33
- * @param {ASTNode} left - A node 1 to compare.
34
- * @param {ASTNode} right - A node 2 to compare.
35
- * @param {SourceCode} sourceCode - The ESLint source code object.
36
- * @returns {boolean} the source code for the given node.
37
- */
38
- function equalTokens(left, right, sourceCode) {
39
- const tokensL = sourceCode.getTokens(left);
40
- const tokensR = sourceCode.getTokens(right);
41
-
42
- if (tokensL.length !== tokensR.length) {
43
- return false;
44
- }
45
- for (let i = 0; i < tokensL.length; ++i) {
46
- if (tokensL[i].type !== tokensR[i].type ||
47
- tokensL[i].value !== tokensR[i].value
48
- ) {
49
- return false;
50
- }
51
- }
52
-
53
- return true;
54
- }
55
31
 
56
32
  /**
57
33
  * Checks whether or not `thisArg` is not changed by `.apply()`.
@@ -64,7 +40,7 @@ function isValidThisArg(expectedThis, thisArg, context) {
64
40
  if (!expectedThis) {
65
41
  return astUtils.isNullOrUndefined(thisArg);
66
42
  }
67
- return equalTokens(expectedThis, thisArg, context);
43
+ return astUtils.equalTokens(expectedThis, thisArg, context);
68
44
  }
69
45
 
70
46
  //------------------------------------------------------------------------------
@@ -37,10 +37,10 @@ function getTopConcatBinaryExpression(node) {
37
37
  }
38
38
 
39
39
  /**
40
- * Checks whether or not a given binary expression has string literals.
41
- * @param {ASTNode} node - A node to check.
42
- * @returns {boolean} `true` if the node has string literals.
43
- */
40
+ * Checks whether or not a given binary expression has string literals.
41
+ * @param {ASTNode} node - A node to check.
42
+ * @returns {boolean} `true` if the node has string literals.
43
+ */
44
44
  function hasStringLiteral(node) {
45
45
  if (isConcatenation(node)) {
46
46
 
@@ -65,10 +65,10 @@ function hasNonStringLiteral(node) {
65
65
  }
66
66
 
67
67
  /**
68
- * Determines whether a given node will start with a template curly expression (`${}`) when being converted to a template literal.
69
- * @param {ASTNode} node The node that will be fixed to a template literal
70
- * @returns {boolean} `true` if the node will start with a template curly.
71
- */
68
+ * Determines whether a given node will start with a template curly expression (`${}`) when being converted to a template literal.
69
+ * @param {ASTNode} node The node that will be fixed to a template literal
70
+ * @returns {boolean} `true` if the node will start with a template curly.
71
+ */
72
72
  function startsWithTemplateCurly(node) {
73
73
  if (node.type === "BinaryExpression") {
74
74
  return startsWithTemplateCurly(node.left);
@@ -80,10 +80,10 @@ function startsWithTemplateCurly(node) {
80
80
  }
81
81
 
82
82
  /**
83
- * Determines whether a given node end with a template curly expression (`${}`) when being converted to a template literal.
84
- * @param {ASTNode} node The node that will be fixed to a template literal
85
- * @returns {boolean} `true` if the node will end with a template curly.
86
- */
83
+ * Determines whether a given node end with a template curly expression (`${}`) when being converted to a template literal.
84
+ * @param {ASTNode} node The node that will be fixed to a template literal
85
+ * @returns {boolean} `true` if the node will end with a template curly.
86
+ */
87
87
  function endsWithTemplateCurly(node) {
88
88
  if (node.type === "BinaryExpression") {
89
89
  return startsWithTemplateCurly(node.right);
@@ -116,11 +116,11 @@ module.exports = {
116
116
  let done = Object.create(null);
117
117
 
118
118
  /**
119
- * Gets the non-token text between two nodes, ignoring any other tokens that appear between the two tokens.
120
- * @param {ASTNode} node1 The first node
121
- * @param {ASTNode} node2 The second node
122
- * @returns {string} The text between the nodes, excluding other tokens
123
- */
119
+ * Gets the non-token text between two nodes, ignoring any other tokens that appear between the two tokens.
120
+ * @param {ASTNode} node1 The first node
121
+ * @param {ASTNode} node2 The second node
122
+ * @returns {string} The text between the nodes, excluding other tokens
123
+ */
124
124
  function getTextBetween(node1, node2) {
125
125
  const allTokens = [node1].concat(sourceCode.getTokensBetween(node1, node2)).concat(node2);
126
126
  const sourceText = sourceCode.getText();
@@ -129,19 +129,21 @@ module.exports = {
129
129
  }
130
130
 
131
131
  /**
132
- * Returns a template literal form of the given node.
133
- * @param {ASTNode} currentNode A node that should be converted to a template literal
134
- * @param {string} textBeforeNode Text that should appear before the node
135
- * @param {string} textAfterNode Text that should appear after the node
136
- * @returns {string} A string form of this node, represented as a template literal
137
- */
132
+ * Returns a template literal form of the given node.
133
+ * @param {ASTNode} currentNode A node that should be converted to a template literal
134
+ * @param {string} textBeforeNode Text that should appear before the node
135
+ * @param {string} textAfterNode Text that should appear after the node
136
+ * @returns {string} A string form of this node, represented as a template literal
137
+ */
138
138
  function getTemplateLiteral(currentNode, textBeforeNode, textAfterNode) {
139
139
  if (currentNode.type === "Literal" && typeof currentNode.value === "string") {
140
140
 
141
- // If the current node is a string literal, escape any instances of ${ or ` to prevent them from being interpreted
142
- // as a template placeholder. However, if the code already contains a backslash before the ${ or `
143
- // for some reason, don't add another backslash, because that would change the meaning of the code (it would cause
144
- // an actual backslash character to appear before the dollar sign).
141
+ /*
142
+ * If the current node is a string literal, escape any instances of ${ or ` to prevent them from being interpreted
143
+ * as a template placeholder. However, if the code already contains a backslash before the ${ or `
144
+ * for some reason, don't add another backslash, because that would change the meaning of the code (it would cause
145
+ * an actual backslash character to appear before the dollar sign).
146
+ */
145
147
  return `\`${currentNode.raw.slice(1, -1).replace(/\\*(\${|`)/g, matched => {
146
148
  if (matched.lastIndexOf("\\") % 2) {
147
149
  return `\\${matched}`;
@@ -178,8 +180,10 @@ module.exports = {
178
180
  getTemplateLiteral(currentNode.right, textBeforePlus + textAfterPlus, textAfterNode).slice(1);
179
181
  }
180
182
 
181
- // Otherwise, these nodes should not be combined into a template curly, since there is nowhere to put
182
- // the text between them.
183
+ /*
184
+ * Otherwise, these nodes should not be combined into a template curly, since there is nowhere to put
185
+ * the text between them.
186
+ */
183
187
  return `${getTemplateLiteral(currentNode.left, textBeforeNode, null)}${textBeforePlus}+${textAfterPlus}${getTemplateLiteral(currentNode.right, textAfterNode, null)}`;
184
188
  }
185
189
 
@@ -104,19 +104,19 @@ module.exports = {
104
104
  }
105
105
 
106
106
  /**
107
- * Returns a string representation of a property node with quotes removed
108
- * @param {ASTNode} key Key AST Node, which may or may not be quoted
109
- * @returns {string} A replacement string for this property
110
- */
107
+ * Returns a string representation of a property node with quotes removed
108
+ * @param {ASTNode} key Key AST Node, which may or may not be quoted
109
+ * @returns {string} A replacement string for this property
110
+ */
111
111
  function getUnquotedKey(key) {
112
112
  return key.type === "Identifier" ? key.name : key.value;
113
113
  }
114
114
 
115
115
  /**
116
- * Returns a string representation of a property node with quotes added
117
- * @param {ASTNode} key Key AST Node, which may or may not be quoted
118
- * @returns {string} A replacement string for this property
119
- */
116
+ * Returns a string representation of a property node with quotes added
117
+ * @param {ASTNode} key Key AST Node, which may or may not be quoted
118
+ * @returns {string} A replacement string for this property
119
+ */
120
120
  function getQuotedKey(key) {
121
121
  if (key.type === "Literal" && typeof key.value === "string") {
122
122
 
@@ -30,6 +30,9 @@ module.exports = {
30
30
  },
31
31
  ArrowFunctionExpression: {
32
32
  type: "boolean"
33
+ },
34
+ FunctionExpression: {
35
+ type: "boolean"
33
36
  }
34
37
  },
35
38
  additionalProperties: false
@@ -45,7 +48,9 @@ module.exports = {
45
48
  const DEFAULT_OPTIONS = {
46
49
  FunctionDeclaration: true,
47
50
  MethodDefinition: false,
48
- ClassDeclaration: false
51
+ ClassDeclaration: false,
52
+ ArrowFunctionExpression: false,
53
+ FunctionExpression: false
49
54
  };
50
55
  const options = Object.assign(DEFAULT_OPTIONS, context.options[0] && context.options[0].require || {});
51
56
 
@@ -58,21 +63,6 @@ module.exports = {
58
63
  context.report({ node, message: "Missing JSDoc comment." });
59
64
  }
60
65
 
61
- /**
62
- * Check if the jsdoc comment is present for class methods
63
- * @param {ASTNode} node node to examine
64
- * @returns {void}
65
- */
66
- function checkClassMethodJsDoc(node) {
67
- if (node.parent.type === "MethodDefinition") {
68
- const jsdocComment = source.getJSDocComment(node);
69
-
70
- if (!jsdocComment) {
71
- report(node);
72
- }
73
- }
74
- }
75
-
76
66
  /**
77
67
  * Check if the jsdoc comment is present or not.
78
68
  * @param {ASTNode} node node to examine
@@ -93,8 +83,11 @@ module.exports = {
93
83
  }
94
84
  },
95
85
  FunctionExpression(node) {
96
- if (options.MethodDefinition) {
97
- checkClassMethodJsDoc(node);
86
+ if (
87
+ (options.MethodDefinition && node.parent.type === "MethodDefinition") ||
88
+ (options.FunctionExpression && (node.parent.type === "VariableDeclarator" || (node.parent.type === "Property" && node === node.parent.value)))
89
+ ) {
90
+ checkJsDoc(node);
98
91
  }
99
92
  },
100
93
  ClassDeclaration(node) {
@@ -18,13 +18,51 @@ const astUtils = require("../ast-utils");
18
18
  const SELECTOR = `:matches(${
19
19
  [
20
20
  "BreakStatement", "ContinueStatement", "DebuggerStatement",
21
- "DoWhileStatement", "EmptyStatement", "ExportAllDeclaration",
21
+ "DoWhileStatement", "ExportAllDeclaration",
22
22
  "ExportDefaultDeclaration", "ExportNamedDeclaration",
23
23
  "ExpressionStatement", "ImportDeclaration", "ReturnStatement",
24
24
  "ThrowStatement", "VariableDeclaration"
25
25
  ].join(",")
26
26
  })`;
27
27
 
28
+ /**
29
+ * Get the child node list of a given node.
30
+ * This returns `Program#body`, `BlockStatement#body`, or `SwitchCase#consequent`.
31
+ * This is used to check whether a node is the first/last child.
32
+ * @param {Node} node A node to get child node list.
33
+ * @returns {Node[]|null} The child node list.
34
+ */
35
+ function getChildren(node) {
36
+ const t = node.type;
37
+
38
+ if (t === "BlockStatement" || t === "Program") {
39
+ return node.body;
40
+ }
41
+ if (t === "SwitchCase") {
42
+ return node.consequent;
43
+ }
44
+ return null;
45
+ }
46
+
47
+ /**
48
+ * Check whether a given node is the last statement in the parent block.
49
+ * @param {Node} node A node to check.
50
+ * @returns {boolean} `true` if the node is the last statement in the parent block.
51
+ */
52
+ function isLastChild(node) {
53
+ const t = node.parent.type;
54
+
55
+ if (t === "IfStatement" && node.parent.consequent === node && node.parent.alternate) { // before `else` keyword.
56
+ return true;
57
+ }
58
+ if (t === "DoWhileStatement") { // before `while` keyword.
59
+ return true;
60
+ }
61
+ const nodeList = getChildren(node.parent);
62
+
63
+ return nodeList !== null && nodeList[nodeList.length - 1] === node; // before `}` or etc.
64
+ }
65
+
28
66
  module.exports = {
29
67
  meta: {
30
68
  docs: {
@@ -40,23 +78,6 @@ module.exports = {
40
78
  const sourceCode = context.getSourceCode();
41
79
  const option = context.options[0] || "last";
42
80
 
43
- /**
44
- * Check whether comments exist between the given 2 tokens.
45
- * @param {Token} left The left token to check.
46
- * @param {Token} right The right token to check.
47
- * @returns {boolean} `true` if comments exist between the given 2 tokens.
48
- */
49
- function commentsExistBetween(left, right) {
50
- return sourceCode.getFirstTokenBetween(
51
- left,
52
- right,
53
- {
54
- includeComments: true,
55
- filter: astUtils.isCommentToken
56
- }
57
- ) !== null;
58
- }
59
-
60
81
  /**
61
82
  * Check the given semicolon token.
62
83
  * @param {Token} semiToken The semicolon token to check.
@@ -79,7 +100,7 @@ module.exports = {
79
100
  : "the beginning of the next line"
80
101
  },
81
102
  fix(fixer) {
82
- if (prevToken && nextToken && commentsExistBetween(prevToken, nextToken)) {
103
+ if (prevToken && nextToken && sourceCode.commentsExistBetween(prevToken, nextToken)) {
83
104
  return null;
84
105
  }
85
106
 
@@ -95,6 +116,10 @@ module.exports = {
95
116
 
96
117
  return {
97
118
  [SELECTOR](node) {
119
+ if (option === "first" && isLastChild(node)) {
120
+ return;
121
+ }
122
+
98
123
  const lastToken = sourceCode.getLastToken(node);
99
124
 
100
125
  if (astUtils.isSemicolonToken(lastToken)) {
package/lib/rules/semi.js CHANGED
@@ -93,9 +93,11 @@ module.exports = {
93
93
  loc = loc.start;
94
94
  fix = function(fixer) {
95
95
 
96
- // Expand the replacement range to include the surrounding
97
- // tokens to avoid conflicting with no-extra-semi.
98
- // https://github.com/eslint/eslint/issues/7928
96
+ /*
97
+ * Expand the replacement range to include the surrounding
98
+ * tokens to avoid conflicting with no-extra-semi.
99
+ * https://github.com/eslint/eslint/issues/7928
100
+ */
99
101
  return new FixTracker(fixer, sourceCode)
100
102
  .retainSurroundingTokens(lastToken)
101
103
  .remove(lastToken);
@@ -67,9 +67,11 @@ module.exports = {
67
67
  function usedMemberSyntax(node) {
68
68
  if (node.specifiers.length === 0) {
69
69
  return "none";
70
- } else if (node.specifiers[0].type === "ImportNamespaceSpecifier") {
70
+ }
71
+ if (node.specifiers[0].type === "ImportNamespaceSpecifier") {
71
72
  return "all";
72
- } else if (node.specifiers.length === 1) {
73
+ }
74
+ if (node.specifiers.length === 1) {
73
75
  return "single";
74
76
  }
75
77
  return "multiple";
@@ -111,9 +113,11 @@ module.exports = {
111
113
  currentLocalMemberName = currentLocalMemberName && currentLocalMemberName.toLowerCase();
112
114
  }
113
115
 
114
- // When the current declaration uses a different member syntax,
115
- // then check if the ordering is correct.
116
- // Otherwise, make a default string compare (like rule sort-vars to be consistent) of the first used local member name.
116
+ /*
117
+ * When the current declaration uses a different member syntax,
118
+ * then check if the ordering is correct.
119
+ * Otherwise, make a default string compare (like rule sort-vars to be consistent) of the first used local member name.
120
+ */
117
121
  if (currentMemberSyntaxGroupIndex !== previousMemberSyntaxGroupIndex) {
118
122
  if (currentMemberSyntaxGroupIndex < previousMemberSyntaxGroupIndex) {
119
123
  context.report({
@@ -149,7 +153,8 @@ module.exports = {
149
153
  message: "Member '{{memberName}}' of the import declaration should be sorted alphabetically.",
150
154
  data: { memberName: importSpecifiers[firstUnsortedIndex].local.name },
151
155
  fix(fixer) {
152
- if (importSpecifiers.some(specifier => sourceCode.getCommentsBefore(specifier).length || sourceCode.getCommentsAfter(specifier).length)) {
156
+ if (importSpecifiers.some(specifier =>
157
+ sourceCode.getCommentsBefore(specifier).length || sourceCode.getCommentsAfter(specifier).length)) {
153
158
 
154
159
  // If there are comments in the ImportSpecifier list, don't rearrange the specifiers.
155
160
  return null;