ember-eslint-parser 0.14.8 → 0.14.9

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ember-eslint-parser",
3
- "version": "0.14.8",
3
+ "version": "0.14.9",
4
4
  "description": "",
5
5
  "keywords": [],
6
6
  "repository": {
@@ -130,6 +130,20 @@ export function parseForESLint(code, options) {
130
130
  }
131
131
  }
132
132
 
133
+ // Scope analysis ran on the placeholder JS, so a write of a template
134
+ // (`const Foo = <template>`, an assignment, a default parameter) still
135
+ // has the placeholder as its writeExpr. The placeholder is out of the
136
+ // AST and never gets a `parent`, which rules read (#257).
137
+ if (result.scopeManager && result.templateInfos?.length) {
138
+ const templates = new Map(result.templateInfos.map((ti) => [ti.placeholder, ti.ast]));
139
+ for (const scope of result.scopeManager.scopes) {
140
+ for (const ref of scope.references) {
141
+ const template = ref.writeExpr && templates.get(ref.writeExpr);
142
+ if (template) ref.writeExpr = template;
143
+ }
144
+ }
145
+ }
146
+
133
147
  // Surface Glimmer template comments in program.comments as type:'Block'
134
148
  // so ESLint's inline-config scanner and plugin rules recognise them.
135
149
  if (glimmerComments.length > 0) {
@@ -15,6 +15,7 @@ const mathMLTagsSet = new Set(mathmlTagNames);
15
15
  const require = createRequire(import.meta.url);
16
16
 
17
17
  let TypescriptScope = null;
18
+ let TypescriptTemplateScope = null;
18
19
  try {
19
20
  const parserPath = require.resolve('@typescript-eslint/parser');
20
21
  // eslint-disable-next-line n/no-unpublished-require
@@ -22,6 +23,26 @@ try {
22
23
  paths: [parserPath],
23
24
  });
24
25
  TypescriptScope = require(scopeManagerPath);
26
+ TypescriptTemplateScope = class TemplateScope extends TypescriptScope.FunctionScope {
27
+ constructor(scopeManager, upperScope, block) {
28
+ // `isMethodDefinition` makes it strict without scanning the body for a
29
+ // "use strict" directive, which throws on a template's body.
30
+ super(scopeManager, upperScope, block, true);
31
+ // A template has no `arguments`, unlike the function FunctionScope models.
32
+ const args = this.set.get('arguments');
33
+ if (args) {
34
+ this.set.delete('arguments');
35
+ this.variables.splice(this.variables.indexOf(args), 1);
36
+ }
37
+ }
38
+
39
+ // Never called for a template scope: only closing a scope during analysis
40
+ // calls it, and templates get their scopes after that. The base would
41
+ // throw on a template's `body`, so guard it anyway.
42
+ isValidResolution() {
43
+ return true;
44
+ }
45
+ };
25
46
  } catch {
26
47
  // not available
27
48
  }
@@ -92,11 +113,15 @@ function createBlockScope(node, path, scopeManager, isTypescript) {
92
113
  : new Scope(scopeManager, 'block', upperScope, node);
93
114
  }
94
115
 
95
- // Give each template a scope of its own. Otherwise typescript-eslint's
96
- // no-use-before-define treats a reference in `const Foo = <template>` as
97
- // running in Foo's initializer, though a template reads its scope lazily.
116
+ // A template compiles to a closure (`scope: () => ({ Foo })`), so give it a
117
+ // function scope: its references run in an execution context of their own,
118
+ // and no-use-before-define accepts `<Foo />` in `const Foo = <template>`.
98
119
  function registerTemplateScope(node, path, scopeManager, isTypescript) {
99
- createBlockScope(node, path, scopeManager, isTypescript);
120
+ const upperScope = findParentScope(scopeManager, path);
121
+ if (isTypescript) return new TypescriptTemplateScope(scopeManager, upperScope, node);
122
+ // `isMethodDefinition` as in TemplateScope. eslint-scope's base Scope
123
+ // declares no `arguments`.
124
+ return new Scope(scopeManager, 'function', upperScope, node, true);
100
125
  }
101
126
 
102
127
  function registerBlockParams(node, path, scopeManager, isTypescript) {