eslint 4.15.0 → 4.18.1

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 (90) hide show
  1. package/CHANGELOG.md +56 -0
  2. package/lib/config/config-validator.js +9 -2
  3. package/lib/linter.js +38 -19
  4. package/lib/options.js +7 -7
  5. package/lib/report-translator.js +28 -37
  6. package/lib/rules/accessor-pairs.js +7 -3
  7. package/lib/rules/array-bracket-newline.js +11 -5
  8. package/lib/rules/array-bracket-spacing.js +11 -5
  9. package/lib/rules/array-callback-return.js +11 -5
  10. package/lib/rules/array-element-newline.js +8 -3
  11. package/lib/rules/arrow-body-style.js +16 -8
  12. package/lib/rules/arrow-parens.js +13 -9
  13. package/lib/rules/arrow-spacing.js +13 -5
  14. package/lib/rules/block-scoped-var.js +6 -2
  15. package/lib/rules/block-spacing.js +13 -6
  16. package/lib/rules/brace-style.js +16 -14
  17. package/lib/rules/callback-return.js +6 -2
  18. package/lib/rules/camelcase.js +6 -2
  19. package/lib/rules/capitalized-comments.js +11 -8
  20. package/lib/rules/class-methods-use-this.js +7 -3
  21. package/lib/rules/comma-dangle.js +7 -4
  22. package/lib/rules/comma-spacing.js +13 -10
  23. package/lib/rules/comma-style.js +16 -5
  24. package/lib/rules/complexity.js +6 -2
  25. package/lib/rules/computed-property-spacing.js +13 -5
  26. package/lib/rules/consistent-return.js +12 -7
  27. package/lib/rules/consistent-this.js +9 -4
  28. package/lib/rules/constructor-super.js +17 -8
  29. package/lib/rules/curly.js +59 -80
  30. package/lib/rules/default-case.js +6 -2
  31. package/lib/rules/dot-location.js +8 -3
  32. package/lib/rules/dot-notation.js +10 -5
  33. package/lib/rules/eol-last.js +7 -3
  34. package/lib/rules/eqeqeq.js +6 -2
  35. package/lib/rules/guard-for-in.js +35 -7
  36. package/lib/rules/indent.js +4 -4
  37. package/lib/rules/key-spacing.js +3 -2
  38. package/lib/rules/keyword-spacing.js +6 -1
  39. package/lib/rules/no-alert.js +19 -18
  40. package/lib/rules/no-array-constructor.js +6 -2
  41. package/lib/rules/no-await-in-loop.js +75 -57
  42. package/lib/rules/no-bitwise.js +6 -2
  43. package/lib/rules/no-buffer-constructor.js +6 -3
  44. package/lib/rules/no-caller.js +6 -2
  45. package/lib/rules/no-case-declarations.js +6 -2
  46. package/lib/rules/no-catch-shadow.js +6 -2
  47. package/lib/rules/no-class-assign.js +6 -2
  48. package/lib/rules/no-compare-neg-zero.js +5 -2
  49. package/lib/rules/no-cond-assign.js +10 -4
  50. package/lib/rules/no-confusing-arrow.js +6 -2
  51. package/lib/rules/no-console.js +6 -2
  52. package/lib/rules/no-const-assign.js +6 -2
  53. package/lib/rules/no-constant-condition.js +6 -3
  54. package/lib/rules/no-continue.js +6 -2
  55. package/lib/rules/no-control-regex.js +7 -3
  56. package/lib/rules/no-debugger.js +5 -2
  57. package/lib/rules/no-delete-var.js +6 -2
  58. package/lib/rules/no-div-regex.js +6 -2
  59. package/lib/rules/no-dupe-args.js +6 -2
  60. package/lib/rules/no-dupe-class-members.js +6 -2
  61. package/lib/rules/no-dupe-keys.js +6 -2
  62. package/lib/rules/no-duplicate-case.js +6 -2
  63. package/lib/rules/no-else-return.js +7 -2
  64. package/lib/rules/no-empty-character-class.js +6 -2
  65. package/lib/rules/no-empty-function.js +6 -2
  66. package/lib/rules/no-empty-pattern.js +7 -3
  67. package/lib/rules/no-empty.js +7 -3
  68. package/lib/rules/no-eq-null.js +6 -2
  69. package/lib/rules/no-eval.js +6 -2
  70. package/lib/rules/no-ex-assign.js +6 -2
  71. package/lib/rules/no-extend-native.js +6 -2
  72. package/lib/rules/no-extra-bind.js +6 -2
  73. package/lib/rules/no-extra-boolean-cast.js +8 -3
  74. package/lib/rules/no-extra-label.js +6 -2
  75. package/lib/rules/no-extra-parens.js +5 -1
  76. package/lib/rules/no-extra-semi.js +6 -2
  77. package/lib/rules/no-self-assign.js +3 -1
  78. package/lib/rules/no-unused-vars.js +1 -1
  79. package/lib/rules/object-curly-newline.js +67 -19
  80. package/lib/rules/object-property-newline.js +8 -2
  81. package/lib/rules/object-shorthand.js +9 -7
  82. package/lib/rules/padding-line-between-statements.js +6 -0
  83. package/lib/rules/prefer-destructuring.js +4 -2
  84. package/lib/rules/require-await.js +5 -0
  85. package/lib/rules/rest-spread-spacing.js +6 -0
  86. package/lib/rules/space-unary-ops.js +1 -10
  87. package/lib/rules/valid-jsdoc.js +89 -28
  88. package/lib/util/glob-util.js +17 -4
  89. package/lib/util/npm-util.js +1 -1
  90. package/package.json +2 -2
@@ -34,7 +34,12 @@ module.exports = {
34
34
  },
35
35
  additionalProperties: false
36
36
  }],
37
- fixable: "code"
37
+
38
+ fixable: "code",
39
+
40
+ messages: {
41
+ unexpected: "Unnecessary 'else' after 'return'."
42
+ }
38
43
  },
39
44
 
40
45
  create(context) {
@@ -52,7 +57,7 @@ module.exports = {
52
57
  function displayReport(node) {
53
58
  context.report({
54
59
  node,
55
- message: "Unnecessary 'else' after 'return'.",
60
+ messageId: "unexpected",
56
61
  fix: fixer => {
57
62
  const sourceCode = context.getSourceCode();
58
63
  const startToken = sourceCode.getFirstToken(node);
@@ -36,7 +36,11 @@ module.exports = {
36
36
  url: "https://eslint.org/docs/rules/no-empty-character-class"
37
37
  },
38
38
 
39
- schema: []
39
+ schema: [],
40
+
41
+ messages: {
42
+ unexpected: "Empty class."
43
+ }
40
44
  },
41
45
 
42
46
  create(context) {
@@ -48,7 +52,7 @@ module.exports = {
48
52
  const token = sourceCode.getFirstToken(node);
49
53
 
50
54
  if (token.type === "RegularExpression" && !regex.test(token.value)) {
51
- context.report({ node, message: "Empty class." });
55
+ context.report({ node, messageId: "unexpected" });
52
56
  }
53
57
  }
54
58
 
@@ -109,7 +109,11 @@ module.exports = {
109
109
  },
110
110
  additionalProperties: false
111
111
  }
112
- ]
112
+ ],
113
+
114
+ messages: {
115
+ unexpected: "Unexpected empty {{name}}."
116
+ }
113
117
  },
114
118
 
115
119
  create(context) {
@@ -146,7 +150,7 @@ module.exports = {
146
150
  context.report({
147
151
  node,
148
152
  loc: node.body.loc.start,
149
- message: "Unexpected empty {{name}}.",
153
+ messageId: "unexpected",
150
154
  data: { name }
151
155
  });
152
156
  }
@@ -17,19 +17,23 @@ module.exports = {
17
17
  url: "https://eslint.org/docs/rules/no-empty-pattern"
18
18
  },
19
19
 
20
- schema: []
20
+ schema: [],
21
+
22
+ messages: {
23
+ unexpected: "Unexpected empty {{type}} pattern."
24
+ }
21
25
  },
22
26
 
23
27
  create(context) {
24
28
  return {
25
29
  ObjectPattern(node) {
26
30
  if (node.properties.length === 0) {
27
- context.report({ node, message: "Unexpected empty object pattern." });
31
+ context.report({ node, messageId: "unexpected", data: { type: "object" } });
28
32
  }
29
33
  },
30
34
  ArrayPattern(node) {
31
35
  if (node.elements.length === 0) {
32
- context.report({ node, message: "Unexpected empty array pattern." });
36
+ context.report({ node, messageId: "unexpected", data: { type: "array" } });
33
37
  }
34
38
  }
35
39
  };
@@ -33,7 +33,11 @@ module.exports = {
33
33
  },
34
34
  additionalProperties: false
35
35
  }
36
- ]
36
+ ],
37
+
38
+ messages: {
39
+ unexpected: "Empty {{type}} statement."
40
+ }
37
41
  },
38
42
 
39
43
  create(context) {
@@ -64,13 +68,13 @@ module.exports = {
64
68
  return;
65
69
  }
66
70
 
67
- context.report({ node, message: "Empty block statement." });
71
+ context.report({ node, messageId: "unexpected", data: { type: "block" } });
68
72
  },
69
73
 
70
74
  SwitchStatement(node) {
71
75
 
72
76
  if (typeof node.cases === "undefined" || node.cases.length === 0) {
73
- context.report({ node, message: "Empty switch statement." });
77
+ context.report({ node, messageId: "unexpected", data: { type: "switch" } });
74
78
  }
75
79
  }
76
80
  };
@@ -19,7 +19,11 @@ module.exports = {
19
19
  url: "https://eslint.org/docs/rules/no-eq-null"
20
20
  },
21
21
 
22
- schema: []
22
+ schema: [],
23
+
24
+ messages: {
25
+ unexpected: "Use '===' to compare with null."
26
+ }
23
27
  },
24
28
 
25
29
  create(context) {
@@ -31,7 +35,7 @@ module.exports = {
31
35
 
32
36
  if (node.right.type === "Literal" && node.right.raw === "null" && badOperator ||
33
37
  node.left.type === "Literal" && node.left.raw === "null" && badOperator) {
34
- context.report({ node, message: "Use ‘===’ to compare with ‘null’." });
38
+ context.report({ node, messageId: "unexpected" });
35
39
  }
36
40
  }
37
41
  };
@@ -91,7 +91,11 @@ module.exports = {
91
91
  },
92
92
  additionalProperties: false
93
93
  }
94
- ]
94
+ ],
95
+
96
+ messages: {
97
+ unexpected: "eval can be harmful."
98
+ }
95
99
  },
96
100
 
97
101
  create(context) {
@@ -160,7 +164,7 @@ module.exports = {
160
164
  context.report({
161
165
  node,
162
166
  loc: locationNode.loc.start,
163
- message: "eval can be harmful."
167
+ messageId: "unexpected"
164
168
  });
165
169
  }
166
170
 
@@ -20,7 +20,11 @@ module.exports = {
20
20
  url: "https://eslint.org/docs/rules/no-ex-assign"
21
21
  },
22
22
 
23
- schema: []
23
+ schema: [],
24
+
25
+ messages: {
26
+ unexpected: "Do not assign to the exception parameter."
27
+ }
24
28
  },
25
29
 
26
30
  create(context) {
@@ -32,7 +36,7 @@ module.exports = {
32
36
  */
33
37
  function checkVariable(variable) {
34
38
  astUtils.getModifyingReferences(variable.references).forEach(reference => {
35
- context.report({ node: reference.identifier, message: "Do not assign to the exception parameter." });
39
+ context.report({ node: reference.identifier, messageId: "unexpected" });
36
40
  });
37
41
  }
38
42
 
@@ -45,7 +45,11 @@ module.exports = {
45
45
  },
46
46
  additionalProperties: false
47
47
  }
48
- ]
48
+ ],
49
+
50
+ messages: {
51
+ unexpected: "{{builtin}} prototype is read only, properties should not be added."
52
+ }
49
53
  },
50
54
 
51
55
  create(context) {
@@ -67,7 +71,7 @@ module.exports = {
67
71
  function reportNode(node, builtin) {
68
72
  context.report({
69
73
  node,
70
- message: "{{builtin}} prototype is read only, properties should not be added.",
74
+ messageId: "unexpected",
71
75
  data: {
72
76
  builtin
73
77
  }
@@ -25,7 +25,11 @@ module.exports = {
25
25
 
26
26
  schema: [],
27
27
 
28
- fixable: "code"
28
+ fixable: "code",
29
+
30
+ messages: {
31
+ unexpected: "The function binding is unnecessary."
32
+ }
29
33
  },
30
34
 
31
35
  create(context) {
@@ -41,7 +45,7 @@ module.exports = {
41
45
  function report(node) {
42
46
  context.report({
43
47
  node: node.parent.parent,
44
- message: "The function binding is unnecessary.",
48
+ messageId: "unexpected",
45
49
  loc: node.parent.property.loc.start,
46
50
  fix(fixer) {
47
51
  const firstTokenToRemove = context.getSourceCode()
@@ -26,7 +26,12 @@ module.exports = {
26
26
 
27
27
  schema: [],
28
28
 
29
- fixable: "code"
29
+ fixable: "code",
30
+
31
+ messages: {
32
+ unexpectedCall: "Redundant Boolean call.",
33
+ unexpectedNegation: "Redundant double negation."
34
+ }
30
35
  },
31
36
 
32
37
  create(context) {
@@ -82,7 +87,7 @@ module.exports = {
82
87
  ) {
83
88
  context.report({
84
89
  node,
85
- message: "Redundant double negation.",
90
+ messageId: "unexpectedNegation",
86
91
  fix: fixer => fixer.replaceText(parent, sourceCode.getText(node.argument))
87
92
  });
88
93
  }
@@ -97,7 +102,7 @@ module.exports = {
97
102
  if (isInBooleanContext(node, parent)) {
98
103
  context.report({
99
104
  node,
100
- message: "Redundant Boolean call.",
105
+ messageId: "unexpectedCall",
101
106
  fix: fixer => {
102
107
  if (!node.arguments.length) {
103
108
  return fixer.replaceText(parent, "true");
@@ -26,7 +26,11 @@ module.exports = {
26
26
 
27
27
  schema: [],
28
28
 
29
- fixable: "code"
29
+ fixable: "code",
30
+
31
+ messages: {
32
+ unexpected: "This label '{{name}}' is unnecessary."
33
+ }
30
34
  },
31
35
 
32
36
  create(context) {
@@ -109,7 +113,7 @@ module.exports = {
109
113
  if (info.breakable && info.label && info.label.name === labelNode.name) {
110
114
  context.report({
111
115
  node: labelNode,
112
- message: "This label '{{name}}' is unnecessary.",
116
+ messageId: "unexpected",
113
117
  data: labelNode,
114
118
  fix: fixer => fixer.removeRange([sourceCode.getFirstToken(node).range[1], labelNode.range[1]])
115
119
  });
@@ -55,6 +55,10 @@ module.exports = {
55
55
  maxItems: 2
56
56
  }
57
57
  ]
58
+ },
59
+
60
+ messages: {
61
+ unexpected: "Gratuitous parentheses around expression."
58
62
  }
59
63
  },
60
64
 
@@ -312,7 +316,7 @@ module.exports = {
312
316
  context.report({
313
317
  node,
314
318
  loc: leftParenToken.loc.start,
315
- message: "Gratuitous parentheses around expression.",
319
+ messageId: "unexpected",
316
320
  fix(fixer) {
317
321
  const parenthesizedSource = sourceCode.text.slice(leftParenToken.range[1], rightParenToken.range[0]);
318
322
 
@@ -26,7 +26,11 @@ module.exports = {
26
26
  },
27
27
 
28
28
  fixable: "code",
29
- schema: []
29
+ schema: [],
30
+
31
+ messages: {
32
+ unexpected: "Unnecessary semicolon."
33
+ }
30
34
  },
31
35
 
32
36
  create(context) {
@@ -40,7 +44,7 @@ module.exports = {
40
44
  function report(nodeOrToken) {
41
45
  context.report({
42
46
  node: nodeOrToken,
43
- message: "Unnecessary semicolon.",
47
+ messageId: "unexpected",
44
48
  fix(fixer) {
45
49
 
46
50
  /*
@@ -121,7 +121,9 @@ function eachSelfAssignment(left, right, props, report) {
121
121
  let startJ = 0;
122
122
 
123
123
  for (let i = right.properties.length - 1; i >= 0; --i) {
124
- if (right.properties[i].type === "ExperimentalSpreadProperty") {
124
+ const propType = right.properties[i].type;
125
+
126
+ if (propType === "SpreadElement" || propType === "ExperimentalSpreadProperty") {
125
127
  startJ = i + 1;
126
128
  break;
127
129
  }
@@ -65,7 +65,7 @@ module.exports = {
65
65
  create(context) {
66
66
  const sourceCode = context.getSourceCode();
67
67
 
68
- const REST_PROPERTY_TYPE = /^(?:Experimental)?RestProperty$/;
68
+ const REST_PROPERTY_TYPE = /^(?:RestElement|(?:Experimental)?RestProperty)$/;
69
69
 
70
70
  const config = {
71
71
  vars: "all",
@@ -10,6 +10,7 @@
10
10
  //------------------------------------------------------------------------------
11
11
 
12
12
  const astUtils = require("../ast-utils");
13
+ const lodash = require("lodash");
13
14
 
14
15
  //------------------------------------------------------------------------------
15
16
  // Helpers
@@ -73,19 +74,57 @@ function normalizeOptionValue(value) {
73
74
  * Normalizes a given option value.
74
75
  *
75
76
  * @param {string|Object|undefined} options - An option value to parse.
76
- * @returns {{ObjectExpression: {multiline: boolean, minProperties: number}, ObjectPattern: {multiline: boolean, minProperties: number}}} Normalized option object.
77
+ * @returns {{
78
+ * ObjectExpression: {multiline: boolean, minProperties: number, consistent: boolean},
79
+ * ObjectPattern: {multiline: boolean, minProperties: number, consistent: boolean},
80
+ * ImportDeclaration: {multiline: boolean, minProperties: number, consistent: boolean},
81
+ * ExportNamedDeclaration : {multiline: boolean, minProperties: number, consistent: boolean}
82
+ * }} Normalized option object.
77
83
  */
78
84
  function normalizeOptions(options) {
79
- if (options && (options.ObjectExpression || options.ObjectPattern)) {
85
+ const isNodeSpecificOption = lodash.overSome([lodash.isPlainObject, lodash.isString]);
86
+
87
+ if (lodash.isPlainObject(options) && lodash.some(options, isNodeSpecificOption)) {
80
88
  return {
81
89
  ObjectExpression: normalizeOptionValue(options.ObjectExpression),
82
- ObjectPattern: normalizeOptionValue(options.ObjectPattern)
90
+ ObjectPattern: normalizeOptionValue(options.ObjectPattern),
91
+ ImportDeclaration: normalizeOptionValue(options.ImportDeclaration),
92
+ ExportNamedDeclaration: normalizeOptionValue(options.ExportDeclaration)
83
93
  };
84
94
  }
85
95
 
86
96
  const value = normalizeOptionValue(options);
87
97
 
88
- return { ObjectExpression: value, ObjectPattern: value };
98
+ return { ObjectExpression: value, ObjectPattern: value, ImportDeclaration: value, ExportNamedDeclaration: value };
99
+ }
100
+
101
+ /**
102
+ * Determines if ObjectExpression, ObjectPattern, ImportDeclaration or ExportNamedDeclaration
103
+ * node needs to be checked for missing line breaks
104
+ *
105
+ * @param {ASTNode} node - Node under inspection
106
+ * @param {Object} options - option specific to node type
107
+ * @param {Token} first - First object property
108
+ * @param {Token} last - Last object property
109
+ * @returns {boolean} `true` if node needs to be checked for missing line breaks
110
+ */
111
+ function areLineBreaksRequired(node, options, first, last) {
112
+ let objectProperties;
113
+
114
+ if (node.type === "ObjectExpression" || node.type === "ObjectPattern") {
115
+ objectProperties = node.properties;
116
+ } else {
117
+
118
+ // is ImportDeclaration or ExportNamedDeclaration
119
+ objectProperties = node.specifiers;
120
+ }
121
+
122
+ return objectProperties.length >= options.minProperties ||
123
+ (
124
+ options.multiline &&
125
+ objectProperties.length > 0 &&
126
+ first.loc.start.line !== last.loc.end.line
127
+ );
89
128
  }
90
129
 
91
130
  //------------------------------------------------------------------------------
@@ -109,7 +148,9 @@ module.exports = {
109
148
  type: "object",
110
149
  properties: {
111
150
  ObjectExpression: OPTION_VALUE,
112
- ObjectPattern: OPTION_VALUE
151
+ ObjectPattern: OPTION_VALUE,
152
+ ImportDeclaration: OPTION_VALUE,
153
+ ExportDeclaration: OPTION_VALUE
113
154
  },
114
155
  additionalProperties: false,
115
156
  minProperties: 1
@@ -125,32 +166,37 @@ module.exports = {
125
166
 
126
167
  /**
127
168
  * Reports a given node if it violated this rule.
128
- *
129
- * @param {ASTNode} node - A node to check. This is an ObjectExpression node or an ObjectPattern node.
130
- * @param {{multiline: boolean, minProperties: number}} options - An option object.
169
+ * @param {ASTNode} node - A node to check. This is an ObjectExpression, ObjectPattern, ImportDeclaration or ExportNamedDeclaration node.
170
+ * @param {{multiline: boolean, minProperties: number, consistent: boolean}} options - An option object.
131
171
  * @returns {void}
132
172
  */
133
173
  function check(node) {
134
174
  const options = normalizedOptions[node.type];
175
+
176
+ if (
177
+ (node.type === "ImportDeclaration" &&
178
+ !node.specifiers.some(specifier => specifier.type === "ImportSpecifier")) ||
179
+ (node.type === "ExportNamedDeclaration" &&
180
+ !node.specifiers.some(specifier => specifier.type === "ExportSpecifier"))
181
+ ) {
182
+ return;
183
+ }
184
+
135
185
  const openBrace = sourceCode.getFirstToken(node, token => token.value === "{");
186
+
136
187
  let closeBrace;
137
188
 
138
189
  if (node.typeAnnotation) {
139
190
  closeBrace = sourceCode.getTokenBefore(node.typeAnnotation);
140
191
  } else {
141
- closeBrace = sourceCode.getLastToken(node);
192
+ closeBrace = sourceCode.getLastToken(node, token => token.value === "}");
142
193
  }
143
194
 
144
195
  let first = sourceCode.getTokenAfter(openBrace, { includeComments: true });
145
196
  let last = sourceCode.getTokenBefore(closeBrace, { includeComments: true });
146
- const needsLinebreaks = (
147
- node.properties.length >= options.minProperties ||
148
- (
149
- options.multiline &&
150
- node.properties.length > 0 &&
151
- first.loc.start.line !== last.loc.end.line
152
- )
153
- );
197
+
198
+ const needsLineBreaks = areLineBreaksRequired(node, options, first, last);
199
+
154
200
  const hasCommentsFirstToken = astUtils.isCommentToken(first);
155
201
  const hasCommentsLastToken = astUtils.isCommentToken(last);
156
202
 
@@ -165,7 +211,7 @@ module.exports = {
165
211
  first = sourceCode.getTokenAfter(openBrace);
166
212
  last = sourceCode.getTokenBefore(closeBrace);
167
213
 
168
- if (needsLinebreaks) {
214
+ if (needsLineBreaks) {
169
215
  if (astUtils.isTokenOnSameLine(openBrace, first)) {
170
216
  context.report({
171
217
  message: "Expected a line break after this opening brace.",
@@ -244,7 +290,9 @@ module.exports = {
244
290
 
245
291
  return {
246
292
  ObjectExpression: check,
247
- ObjectPattern: check
293
+ ObjectPattern: check,
294
+ ImportDeclaration: check,
295
+ ExportNamedDeclaration: check
248
296
  };
249
297
  }
250
298
  };
@@ -22,7 +22,10 @@ module.exports = {
22
22
  {
23
23
  type: "object",
24
24
  properties: {
25
- allowMultiplePropertiesPerLine: {
25
+ allowAllPropertiesOnSameLine: {
26
+ type: "boolean"
27
+ },
28
+ allowMultiplePropertiesPerLine: { // Deprecated
26
29
  type: "boolean"
27
30
  }
28
31
  },
@@ -34,7 +37,10 @@ module.exports = {
34
37
  },
35
38
 
36
39
  create(context) {
37
- const allowSameLine = context.options[0] && Boolean(context.options[0].allowMultiplePropertiesPerLine);
40
+ const allowSameLine = context.options[0] && (
41
+ Boolean(context.options[0].allowAllPropertiesOnSameLine) ||
42
+ Boolean(context.options[0].allowMultiplePropertiesPerLine) // Deprecated
43
+ );
38
44
  const errorMessage = allowSameLine
39
45
  ? "Object properties must go on a new line if they aren't all on the same line."
40
46
  : "Object properties must go on a new line.";
@@ -131,7 +131,7 @@ module.exports = {
131
131
  *
132
132
  */
133
133
  function canHaveShorthand(property) {
134
- return (property.kind !== "set" && property.kind !== "get" && property.type !== "SpreadProperty" && property.type !== "ExperimentalSpreadProperty");
134
+ return (property.kind !== "set" && property.kind !== "get" && property.type !== "SpreadElement" && property.type !== "SpreadProperty" && property.type !== "ExperimentalSpreadProperty");
135
135
  }
136
136
 
137
137
  /**
@@ -233,10 +233,11 @@ module.exports = {
233
233
  const keyText = sourceCode.text.slice(firstKeyToken.range[0], lastKeyToken.range[1]);
234
234
  let keyPrefix = "";
235
235
 
236
+ if (node.value.async) {
237
+ keyPrefix += "async ";
238
+ }
236
239
  if (node.value.generator) {
237
- keyPrefix = "*";
238
- } else if (node.value.async) {
239
- keyPrefix = "async ";
240
+ keyPrefix += "*";
240
241
  }
241
242
 
242
243
  if (node.value.type === "FunctionExpression") {
@@ -273,10 +274,11 @@ module.exports = {
273
274
  const keyText = sourceCode.text.slice(firstKeyToken.range[0], lastKeyToken.range[1]);
274
275
  let functionHeader = "function";
275
276
 
277
+ if (node.value.async) {
278
+ functionHeader = `async ${functionHeader}`;
279
+ }
276
280
  if (node.value.generator) {
277
- functionHeader = "function*";
278
- } else if (node.value.async) {
279
- functionHeader = "async function";
281
+ functionHeader = `${functionHeader}*`;
280
282
  }
281
283
 
282
284
  return fixer.replaceTextRange([node.range[0], lastKeyToken.range[1]], `${keyText}: ${functionHeader}`);
@@ -358,6 +358,12 @@ const StatementTypes = {
358
358
  node.loc.start.line !== node.loc.end.line &&
359
359
  isBlockLikeStatement(sourceCode, node)
360
360
  },
361
+ "multiline-expression": {
362
+ test: (node, sourceCode) =>
363
+ node.loc.start.line !== node.loc.end.line &&
364
+ node.type === "ExpressionStatement" &&
365
+ !isDirectivePrologue(node, sourceCode)
366
+ },
361
367
 
362
368
  block: newNodeTypeTester("BlockStatement"),
363
369
  empty: newNodeTypeTester("EmptyStatement"),
@@ -165,8 +165,10 @@ module.exports = {
165
165
  if (shouldCheck(reportNode.type, "object")) {
166
166
  const property = rightNode.property;
167
167
 
168
- if ((property.type === "Literal" && leftNode.name === property.value) || (property.type === "Identifier" &&
169
- leftNode.name === property.name)) {
168
+ if (
169
+ (property.type === "Literal" && leftNode.name === property.value) ||
170
+ (property.type === "Identifier" && leftNode.name === property.name && !rightNode.computed)
171
+ ) {
170
172
  report(reportNode, "object");
171
173
  }
172
174
  }
@@ -90,6 +90,11 @@ module.exports = {
90
90
 
91
91
  AwaitExpression() {
92
92
  scopeInfo.hasAwait = true;
93
+ },
94
+ ForOfStatement(node) {
95
+ if (node.await) {
96
+ scopeInfo.hasAwait = true;
97
+ }
93
98
  }
94
99
  };
95
100
  }
@@ -47,9 +47,15 @@ module.exports = {
47
47
  switch (node.type) {
48
48
  case "SpreadElement":
49
49
  type = "spread";
50
+ if (node.parent.type === "ObjectExpression") {
51
+ type += " property";
52
+ }
50
53
  break;
51
54
  case "RestElement":
52
55
  type = "rest";
56
+ if (node.parent.type === "ObjectPattern") {
57
+ type += " property";
58
+ }
53
59
  break;
54
60
  case "ExperimentalSpreadProperty":
55
61
  type = "spread property";
@@ -66,15 +66,6 @@ module.exports = {
66
66
  node.argument && node.argument.type === "UnaryExpression" && node.argument.operator === "!";
67
67
  }
68
68
 
69
- /**
70
- * Check if the node's child argument is an "ObjectExpression"
71
- * @param {ASTnode} node AST node
72
- * @returns {boolean} Whether or not the argument's type is "ObjectExpression"
73
- */
74
- function isArgumentObjectExpression(node) {
75
- return node.argument && node.argument.type && node.argument.type === "ObjectExpression";
76
- }
77
-
78
69
  /**
79
70
  * Checks if an override exists for a given operator.
80
71
  * @param {string} operator Operator
@@ -125,7 +116,7 @@ module.exports = {
125
116
  * @returns {void}
126
117
  */
127
118
  function verifyWordDoesntHaveSpaces(node, firstToken, secondToken, word) {
128
- if (isArgumentObjectExpression(node)) {
119
+ if (astUtils.canTokensBeAdjacent(firstToken, secondToken)) {
129
120
  if (secondToken.range[0] > firstToken.range[1]) {
130
121
  context.report({
131
122
  node,