eslint 9.9.1 → 9.10.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.
@@ -20,7 +20,7 @@ const
20
20
 
21
21
  CodePathAnalyzer = require("../../../linter/code-path-analysis/code-path-analyzer"),
22
22
  createEmitter = require("../../../linter/safe-emitter"),
23
- ConfigCommentParser = require("../../../linter/config-comment-parser"),
23
+ { ConfigCommentParser, VisitNodeStep, CallMethodStep } = require("@eslint/plugin-kit"),
24
24
 
25
25
  eslintScope = require("eslint-scope");
26
26
 
@@ -316,65 +316,6 @@ function markExportedVariables(globalScope, variables) {
316
316
 
317
317
  }
318
318
 
319
- const STEP_KIND = {
320
- visit: 1,
321
- call: 2
322
- };
323
-
324
- /**
325
- * A class to represent a step in the traversal process.
326
- */
327
- class TraversalStep {
328
-
329
- /**
330
- * The type of the step.
331
- * @type {string}
332
- */
333
- type;
334
-
335
- /**
336
- * The kind of the step. Represents the same data as the `type` property
337
- * but it's a number for performance.
338
- * @type {number}
339
- */
340
- kind;
341
-
342
- /**
343
- * The target of the step.
344
- * @type {ASTNode|string}
345
- */
346
- target;
347
-
348
- /**
349
- * The phase of the step.
350
- * @type {number|undefined}
351
- */
352
- phase;
353
-
354
- /**
355
- * The arguments of the step.
356
- * @type {Array<any>}
357
- */
358
- args;
359
-
360
- /**
361
- * Creates a new instance.
362
- * @param {Object} options The options for the step.
363
- * @param {string} options.type The type of the step.
364
- * @param {ASTNode|string} options.target The target of the step.
365
- * @param {number|undefined} [options.phase] The phase of the step.
366
- * @param {Array<any>} options.args The arguments of the step.
367
- * @returns {void}
368
- */
369
- constructor({ type, target, phase, args }) {
370
- this.type = type;
371
- this.kind = STEP_KIND[type];
372
- this.target = target;
373
- this.phase = phase;
374
- this.args = args;
375
- }
376
- }
377
-
378
319
  /**
379
320
  * A class to represent a directive comment.
380
321
  * @implements {IDirective}
@@ -1002,16 +943,18 @@ class SourceCode extends TokenStore {
1002
943
  return false;
1003
944
  }
1004
945
 
1005
- const { directivePart } = commentParser.extractDirectiveComment(comment.value);
946
+ const directive = commentParser.parseDirective(comment.value);
1006
947
 
1007
- const directiveMatch = directivesPattern.exec(directivePart);
948
+ if (!directive) {
949
+ return false;
950
+ }
1008
951
 
1009
- if (!directiveMatch) {
952
+ if (!directivesPattern.test(directive.label)) {
1010
953
  return false;
1011
954
  }
1012
955
 
1013
956
  // only certain comment types are supported as line comments
1014
- return comment.type !== "Line" || !!/^eslint-disable-(next-)?line$/u.test(directiveMatch[1]);
957
+ return comment.type !== "Line" || !!/^eslint-disable-(next-)?line$/u.test(directive.label);
1015
958
  });
1016
959
 
1017
960
  this[caches].set("configNodes", configNodes);
@@ -1038,27 +981,24 @@ class SourceCode extends TokenStore {
1038
981
  const directives = [];
1039
982
 
1040
983
  this.getInlineConfigNodes().forEach(comment => {
1041
- const { directivePart, justificationPart } = commentParser.extractDirectiveComment(comment.value);
1042
984
 
1043
- // Step 1: Extract the directive text
1044
- const match = directivesPattern.exec(directivePart);
1045
-
1046
- if (!match) {
1047
- return;
1048
- }
1049
-
1050
- const directiveText = match[1];
985
+ // Step 1: Parse the directive
986
+ const {
987
+ label,
988
+ value,
989
+ justification: justificationPart
990
+ } = commentParser.parseDirective(comment.value);
1051
991
 
1052
992
  // Step 2: Extract the directive value
1053
- const lineCommentSupported = /^eslint-disable-(next-)?line$/u.test(directiveText);
993
+ const lineCommentSupported = /^eslint-disable-(next-)?line$/u.test(label);
1054
994
 
1055
995
  if (comment.type === "Line" && !lineCommentSupported) {
1056
996
  return;
1057
997
  }
1058
998
 
1059
999
  // Step 3: Validate the directive does not span multiple lines
1060
- if (directiveText === "eslint-disable-line" && comment.loc.start.line !== comment.loc.end.line) {
1061
- const message = `${directiveText} comment should not span multiple lines.`;
1000
+ if (label === "eslint-disable-line" && comment.loc.start.line !== comment.loc.end.line) {
1001
+ const message = `${label} comment should not span multiple lines.`;
1062
1002
 
1063
1003
  problems.push({
1064
1004
  ruleId: null,
@@ -1069,19 +1009,17 @@ class SourceCode extends TokenStore {
1069
1009
  }
1070
1010
 
1071
1011
  // Step 4: Extract the directive value and create the Directive object
1072
- const directiveValue = directivePart.slice(match.index + directiveText.length);
1073
-
1074
- switch (directiveText) {
1012
+ switch (label) {
1075
1013
  case "eslint-disable":
1076
1014
  case "eslint-enable":
1077
1015
  case "eslint-disable-next-line":
1078
1016
  case "eslint-disable-line": {
1079
- const directiveType = directiveText.slice("eslint-".length);
1017
+ const directiveType = label.slice("eslint-".length);
1080
1018
 
1081
1019
  directives.push(new Directive({
1082
1020
  type: directiveType,
1083
1021
  node: comment,
1084
- value: directiveValue,
1022
+ value,
1085
1023
  justification: justificationPart
1086
1024
  }));
1087
1025
  }
@@ -1136,20 +1074,20 @@ class SourceCode extends TokenStore {
1136
1074
 
1137
1075
  this.getInlineConfigNodes().forEach(comment => {
1138
1076
 
1139
- const { directiveText, directiveValue } = commentParser.parseDirective(comment);
1077
+ const { label, value } = commentParser.parseDirective(comment.value);
1140
1078
 
1141
- switch (directiveText) {
1079
+ switch (label) {
1142
1080
  case "exported":
1143
- Object.assign(exportedVariables, commentParser.parseListConfig(directiveValue, comment));
1081
+ Object.assign(exportedVariables, commentParser.parseListConfig(value));
1144
1082
  break;
1145
1083
 
1146
1084
  case "globals":
1147
1085
  case "global":
1148
- for (const [id, { value }] of Object.entries(commentParser.parseStringConfig(directiveValue, comment))) {
1086
+ for (const [id, idSetting] of Object.entries(commentParser.parseStringConfig(value))) {
1149
1087
  let normalizedValue;
1150
1088
 
1151
1089
  try {
1152
- normalizedValue = normalizeConfigGlobal(value);
1090
+ normalizedValue = normalizeConfigGlobal(idSetting);
1153
1091
  } catch (err) {
1154
1092
  problems.push({
1155
1093
  ruleId: null,
@@ -1172,9 +1110,9 @@ class SourceCode extends TokenStore {
1172
1110
  break;
1173
1111
 
1174
1112
  case "eslint": {
1175
- const parseResult = commentParser.parseJsonConfig(directiveValue);
1113
+ const parseResult = commentParser.parseJSONLikeConfig(value);
1176
1114
 
1177
- if (parseResult.success) {
1115
+ if (parseResult.ok) {
1178
1116
  configs.push({
1179
1117
  config: {
1180
1118
  rules: parseResult.config
@@ -1251,16 +1189,14 @@ class SourceCode extends TokenStore {
1251
1189
  const emitter = createEmitter();
1252
1190
  let analyzer = {
1253
1191
  enterNode(node) {
1254
- steps.push(new TraversalStep({
1255
- type: "visit",
1192
+ steps.push(new VisitNodeStep({
1256
1193
  target: node,
1257
1194
  phase: 1,
1258
1195
  args: [node, node.parent]
1259
1196
  }));
1260
1197
  },
1261
1198
  leaveNode(node) {
1262
- steps.push(new TraversalStep({
1263
- type: "visit",
1199
+ steps.push(new VisitNodeStep({
1264
1200
  target: node,
1265
1201
  phase: 2,
1266
1202
  args: [node, node.parent]
@@ -1283,8 +1219,7 @@ class SourceCode extends TokenStore {
1283
1219
 
1284
1220
  CODE_PATH_EVENTS.forEach(eventName => {
1285
1221
  emitter.on(eventName, (...args) => {
1286
- steps.push(new TraversalStep({
1287
- type: "call",
1222
+ steps.push(new CallMethodStep({
1288
1223
  target: eventName,
1289
1224
  args
1290
1225
  }));
@@ -60,34 +60,23 @@ function groupByParentDirective(directives) {
60
60
  /**
61
61
  * Creates removal details for a set of directives within the same comment.
62
62
  * @param {Directive[]} directives Unused directives to be removed.
63
- * @param {Token} node The backing Comment token.
63
+ * @param {{node: Token, value: string}} parentDirective Data about the backing directive.
64
64
  * @param {SourceCode} sourceCode The source code object for the file being linted.
65
65
  * @returns {{ description, fix, unprocessedDirective }[]} Details for later creation of output Problems.
66
66
  */
67
- function createIndividualDirectivesRemoval(directives, node, sourceCode) {
68
-
69
- const range = sourceCode.getRange(node);
70
-
71
- /*
72
- * `node.value` starts right after `//` or `/*`.
73
- * All calculated offsets will be relative to this index.
74
- */
75
- const commentValueStart = range[0] + "//".length;
76
-
77
- // Find where the list of rules starts. `\S+` matches with the directive name (e.g. `eslint-disable-line`)
78
- const listStartOffset = /^\s*\S+\s+/u.exec(node.value)[0].length;
67
+ function createIndividualDirectivesRemoval(directives, parentDirective, sourceCode) {
79
68
 
80
69
  /*
81
- * Get the list text without any surrounding whitespace. In order to preserve the original
70
+ * Get the list of the rules text without any surrounding whitespace. In order to preserve the original
82
71
  * formatting, we don't want to change that whitespace.
83
72
  *
84
73
  * // eslint-disable-line rule-one , rule-two , rule-three -- comment
85
74
  * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
86
75
  */
87
- const listText = node.value
88
- .slice(listStartOffset) // remove directive name and all whitespace before the list
89
- .split(/\s-{2,}\s/u)[0] // remove `-- comment`, if it exists
90
- .trimEnd(); // remove all whitespace after the list
76
+ const listText = parentDirective.value.trim();
77
+
78
+ // Calculate where it starts in the source code text
79
+ const listStart = sourceCode.text.indexOf(listText, sourceCode.getRange(parentDirective.node)[0]);
91
80
 
92
81
  /*
93
82
  * We can assume that `listText` contains multiple elements.
@@ -101,13 +90,13 @@ function createIndividualDirectivesRemoval(directives, node, sourceCode) {
101
90
  const regex = new RegExp(String.raw`(?:^|\s*,\s*)(?<quote>['"]?)${escapeRegExp(ruleId)}\k<quote>(?:\s*,\s*|$)`, "u");
102
91
  const match = regex.exec(listText);
103
92
  const matchedText = match[0];
104
- const matchStartOffset = listStartOffset + match.index;
105
- const matchEndOffset = matchStartOffset + matchedText.length;
93
+ const matchStart = listStart + match.index;
94
+ const matchEnd = matchStart + matchedText.length;
106
95
 
107
96
  const firstIndexOfComma = matchedText.indexOf(",");
108
97
  const lastIndexOfComma = matchedText.lastIndexOf(",");
109
98
 
110
- let removalStartOffset, removalEndOffset;
99
+ let removalStart, removalEnd;
111
100
 
112
101
  if (firstIndexOfComma !== lastIndexOfComma) {
113
102
 
@@ -123,8 +112,8 @@ function createIndividualDirectivesRemoval(directives, node, sourceCode) {
123
112
  * // eslint-disable-line rule-one , rule-two , rule-three -- comment
124
113
  * ^^^^^^^^^^^
125
114
  */
126
- removalStartOffset = matchStartOffset + firstIndexOfComma;
127
- removalEndOffset = matchStartOffset + lastIndexOfComma;
115
+ removalStart = matchStart + firstIndexOfComma;
116
+ removalEnd = matchStart + lastIndexOfComma;
128
117
 
129
118
  } else {
130
119
 
@@ -146,16 +135,16 @@ function createIndividualDirectivesRemoval(directives, node, sourceCode) {
146
135
  * // eslint-disable-line rule-one , rule-two , rule-three -- comment
147
136
  * ^^^^^^^^^^^^^
148
137
  */
149
- removalStartOffset = matchStartOffset;
150
- removalEndOffset = matchEndOffset;
138
+ removalStart = matchStart;
139
+ removalEnd = matchEnd;
151
140
  }
152
141
 
153
142
  return {
154
143
  description: `'${ruleId}'`,
155
144
  fix: {
156
145
  range: [
157
- commentValueStart + removalStartOffset,
158
- commentValueStart + removalEndOffset
146
+ removalStart,
147
+ removalEnd
159
148
  ],
160
149
  text: ""
161
150
  },
@@ -206,7 +195,7 @@ function processUnusedDirectives(allDirectives, sourceCode) {
206
195
  }
207
196
 
208
197
  return remainingRuleIds.size
209
- ? createIndividualDirectivesRemoval(directives, parentDirective.node, sourceCode)
198
+ ? createIndividualDirectivesRemoval(directives, parentDirective, sourceCode)
210
199
  : [createDirectiveRemoval(directives, parentDirective.node, sourceCode)];
211
200
  }
212
201
  );
@@ -0,0 +1,134 @@
1
+ /**
2
+ * @fileoverview The FileContext class.
3
+ * @author Nicholas C. Zakas
4
+ */
5
+
6
+ "use strict";
7
+
8
+ /**
9
+ * Represents a file context that the linter can use to lint a file.
10
+ */
11
+ class FileContext {
12
+
13
+ /**
14
+ * The current working directory.
15
+ * @type {string}
16
+ */
17
+ cwd;
18
+
19
+ /**
20
+ * The filename of the file being linted.
21
+ * @type {string}
22
+ */
23
+ filename;
24
+
25
+ /**
26
+ * The physical filename of the file being linted.
27
+ * @type {string}
28
+ */
29
+ physicalFilename;
30
+
31
+ /**
32
+ * The source code of the file being linted.
33
+ * @type {SourceCode}
34
+ */
35
+ sourceCode;
36
+
37
+ /**
38
+ * The parser options for the file being linted.
39
+ * @type {Record<string, unknown>}
40
+ * @deprecated Use `languageOptions` instead.
41
+ */
42
+ parserOptions;
43
+
44
+ /**
45
+ * The path to the parser used to parse this file.
46
+ * @type {string}
47
+ * @deprecated No longer supported.
48
+ */
49
+ parserPath;
50
+
51
+ /**
52
+ * The language options used when parsing this file.
53
+ * @type {Record<string, unknown>}
54
+ */
55
+ languageOptions;
56
+
57
+ /**
58
+ * The settings for the file being linted.
59
+ * @type {Record<string, unknown>}
60
+ */
61
+ settings;
62
+
63
+ /**
64
+ * Creates a new instance.
65
+ * @param {Object} config The configuration object for the file context.
66
+ * @param {string} config.cwd The current working directory.
67
+ * @param {string} config.filename The filename of the file being linted.
68
+ * @param {string} config.physicalFilename The physical filename of the file being linted.
69
+ * @param {SourceCode} config.sourceCode The source code of the file being linted.
70
+ * @param {Record<string, unknown>} config.parserOptions The parser options for the file being linted.
71
+ * @param {string} config.parserPath The path to the parser used to parse this file.
72
+ * @param {Record<string, unknown>} config.languageOptions The language options used when parsing this file.
73
+ * @param {Record<string, unknown>} config.settings The settings for the file being linted.
74
+ */
75
+ constructor({
76
+ cwd,
77
+ filename,
78
+ physicalFilename,
79
+ sourceCode,
80
+ parserOptions,
81
+ parserPath,
82
+ languageOptions,
83
+ settings
84
+ }) {
85
+ this.cwd = cwd;
86
+ this.filename = filename;
87
+ this.physicalFilename = physicalFilename;
88
+ this.sourceCode = sourceCode;
89
+ this.parserOptions = parserOptions;
90
+ this.parserPath = parserPath;
91
+ this.languageOptions = languageOptions;
92
+ this.settings = settings;
93
+
94
+ Object.freeze(this);
95
+ }
96
+
97
+ /**
98
+ * Gets the current working directory.
99
+ * @returns {string} The current working directory.
100
+ * @deprecated Use `cwd` instead.
101
+ */
102
+ getCwd() {
103
+ return this.cwd;
104
+ }
105
+
106
+ /**
107
+ * Gets the filename of the file being linted.
108
+ * @returns {string} The filename of the file being linted.
109
+ * @deprecated Use `filename` instead.
110
+ */
111
+ getFilename() {
112
+ return this.filename;
113
+ }
114
+
115
+ /**
116
+ * Gets the physical filename of the file being linted.
117
+ * @returns {string} The physical filename of the file being linted.
118
+ * @deprecated Use `physicalFilename` instead.
119
+ */
120
+ getPhysicalFilename() {
121
+ return this.physicalFilename;
122
+ }
123
+
124
+ /**
125
+ * Gets the source code of the file being linted.
126
+ * @returns {SourceCode} The source code of the file being linted.
127
+ * @deprecated Use `sourceCode` instead.
128
+ */
129
+ getSourceCode() {
130
+ return this.sourceCode;
131
+ }
132
+ }
133
+
134
+ exports.FileContext = FileContext;
@@ -17,9 +17,6 @@ const
17
17
  espree = require("espree"),
18
18
  merge = require("lodash.merge"),
19
19
  pkg = require("../../package.json"),
20
- {
21
- directivesPattern
22
- } = require("../shared/directives"),
23
20
  {
24
21
  Legacy: {
25
22
  ConfigOps,
@@ -30,7 +27,7 @@ const
30
27
  Traverser = require("../shared/traverser"),
31
28
  { SourceCode } = require("../languages/js/source-code"),
32
29
  applyDisableDirectives = require("./apply-disable-directives"),
33
- ConfigCommentParser = require("./config-comment-parser"),
30
+ { ConfigCommentParser } = require("@eslint/plugin-kit"),
34
31
  NodeEventGenerator = require("./node-event-generator"),
35
32
  createReportTranslator = require("./report-translator"),
36
33
  Rules = require("./rules"),
@@ -56,6 +53,7 @@ const parserSymbol = Symbol.for("eslint.RuleTester.parser");
56
53
  const { LATEST_ECMA_VERSION } = require("../../conf/ecma-version");
57
54
  const { VFile } = require("./vfile");
58
55
  const { ParserService } = require("../services/parser-service");
56
+ const { FileContext } = require("./file-context");
59
57
  const STEP_KIND_VISIT = 1;
60
58
  const STEP_KIND_CALL = 2;
61
59
 
@@ -334,7 +332,7 @@ function createDisableDirectives({ type, value, justification, node }, ruleMappe
334
332
  directives: [], // valid disable directives
335
333
  directiveProblems: [] // problems in directives
336
334
  };
337
- const parentDirective = { node, ruleIds };
335
+ const parentDirective = { node, value, ruleIds };
338
336
 
339
337
  for (const ruleId of directiveRules) {
340
338
 
@@ -402,15 +400,20 @@ function getDirectiveComments(sourceCode, ruleMapper, warnInlineConfig, config)
402
400
  });
403
401
 
404
402
  sourceCode.getInlineConfigNodes().filter(token => token.type !== "Shebang").forEach(comment => {
405
- const { directivePart, justificationPart } = commentParser.extractDirectiveComment(comment.value);
406
403
 
407
- const match = directivesPattern.exec(directivePart);
404
+ const directive = commentParser.parseDirective(comment.value);
408
405
 
409
- if (!match) {
406
+ if (!directive) {
410
407
  return;
411
408
  }
412
- const directiveText = match[1];
413
- const lineCommentSupported = /^eslint-disable-(next-)?line$/u.test(directiveText);
409
+
410
+ const {
411
+ label,
412
+ value,
413
+ justification: justificationPart
414
+ } = directive;
415
+
416
+ const lineCommentSupported = /^eslint-disable-(next-)?line$/u.test(label);
414
417
 
415
418
  if (comment.type === "Line" && !lineCommentSupported) {
416
419
  return;
@@ -419,7 +422,7 @@ function getDirectiveComments(sourceCode, ruleMapper, warnInlineConfig, config)
419
422
  const loc = sourceCode.getLoc(comment);
420
423
 
421
424
  if (warnInlineConfig) {
422
- const kind = comment.type === "Block" ? `/*${directiveText}*/` : `//${directiveText}`;
425
+ const kind = comment.type === "Block" ? `/*${label}*/` : `//${label}`;
423
426
 
424
427
  problems.push(createLintingProblem({
425
428
  ruleId: null,
@@ -430,8 +433,8 @@ function getDirectiveComments(sourceCode, ruleMapper, warnInlineConfig, config)
430
433
  return;
431
434
  }
432
435
 
433
- if (directiveText === "eslint-disable-line" && loc.start.line !== loc.end.line) {
434
- const message = `${directiveText} comment should not span multiple lines.`;
436
+ if (label === "eslint-disable-line" && loc.start.line !== loc.end.line) {
437
+ const message = `${label} comment should not span multiple lines.`;
435
438
 
436
439
  problems.push(createLintingProblem({
437
440
  ruleId: null,
@@ -441,17 +444,15 @@ function getDirectiveComments(sourceCode, ruleMapper, warnInlineConfig, config)
441
444
  return;
442
445
  }
443
446
 
444
- const directiveValue = directivePart.slice(match.index + directiveText.length);
445
-
446
- switch (directiveText) {
447
+ switch (label) {
447
448
  case "eslint-disable":
448
449
  case "eslint-enable":
449
450
  case "eslint-disable-next-line":
450
451
  case "eslint-disable-line": {
451
- const directiveType = directiveText.slice("eslint-".length);
452
+ const directiveType = label.slice("eslint-".length);
452
453
  const { directives, directiveProblems } = createDisableDirectives({
453
454
  type: directiveType,
454
- value: directiveValue,
455
+ value,
455
456
  justification: justificationPart,
456
457
  node: comment
457
458
  }, ruleMapper, jslang, sourceCode);
@@ -462,16 +463,16 @@ function getDirectiveComments(sourceCode, ruleMapper, warnInlineConfig, config)
462
463
  }
463
464
 
464
465
  case "exported":
465
- Object.assign(exportedVariables, commentParser.parseListConfig(directiveValue, comment));
466
+ Object.assign(exportedVariables, commentParser.parseListConfig(value));
466
467
  break;
467
468
 
468
469
  case "globals":
469
470
  case "global":
470
- for (const [id, { value }] of Object.entries(commentParser.parseStringConfig(directiveValue, comment))) {
471
+ for (const [id, idSetting] of Object.entries(commentParser.parseStringConfig(value))) {
471
472
  let normalizedValue;
472
473
 
473
474
  try {
474
- normalizedValue = ConfigOps.normalizeConfigGlobal(value);
475
+ normalizedValue = ConfigOps.normalizeConfigGlobal(idSetting);
475
476
  } catch (err) {
476
477
  problems.push(createLintingProblem({
477
478
  ruleId: null,
@@ -494,9 +495,9 @@ function getDirectiveComments(sourceCode, ruleMapper, warnInlineConfig, config)
494
495
  break;
495
496
 
496
497
  case "eslint": {
497
- const parseResult = commentParser.parseJsonConfig(directiveValue);
498
+ const parseResult = commentParser.parseJSONLikeConfig(value);
498
499
 
499
- if (parseResult.success) {
500
+ if (parseResult.ok) {
500
501
  Object.keys(parseResult.config).forEach(name => {
501
502
  const rule = ruleMapper(name);
502
503
  const ruleValue = parseResult.config[name];
@@ -713,7 +714,7 @@ function findEslintEnv(text) {
713
714
  if (match[0].endsWith("*/")) {
714
715
  retv = Object.assign(
715
716
  retv || {},
716
- commentParser.parseListConfig(commentParser.extractDirectiveComment(match[1]).directivePart)
717
+ commentParser.parseListConfig(commentParser.parseDirective(match[0].slice(2, -2)).value)
717
718
  );
718
719
  }
719
720
  }
@@ -979,24 +980,18 @@ function runRules(
979
980
  * All rule contexts will inherit from this object. This avoids the performance penalty of copying all the
980
981
  * properties once for each rule.
981
982
  */
982
- const sharedTraversalContext = Object.freeze(
983
- {
984
- getCwd: () => cwd,
985
- cwd,
986
- getFilename: () => filename,
987
- filename,
988
- getPhysicalFilename: () => physicalFilename || filename,
989
- physicalFilename: physicalFilename || filename,
990
- getSourceCode: () => sourceCode,
991
- sourceCode,
992
- parserOptions: {
993
- ...languageOptions.parserOptions
994
- },
995
- parserPath: parserName,
996
- languageOptions,
997
- settings
998
- }
999
- );
983
+ const sharedTraversalContext = new FileContext({
984
+ cwd,
985
+ filename,
986
+ physicalFilename: physicalFilename || filename,
987
+ sourceCode,
988
+ parserOptions: {
989
+ ...languageOptions.parserOptions
990
+ },
991
+ parserPath: parserName,
992
+ languageOptions,
993
+ settings
994
+ });
1000
995
 
1001
996
  const lintingProblems = [];
1002
997
 
@@ -117,6 +117,7 @@ module.exports = {
117
117
  return properties && !parent.computed && parent.key.name === node.name;
118
118
  },
119
119
  ImportDefaultSpecifier: true,
120
+ ImportNamespaceSpecifier: true,
120
121
  RestElement: true,
121
122
  FunctionExpression: true,
122
123
  ArrowFunctionExpression: true,