ember-eslint-parser 0.9.0 → 0.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ember-eslint-parser",
3
- "version": "0.9.0",
3
+ "version": "0.10.0",
4
4
  "description": "",
5
5
  "keywords": [],
6
6
  "repository": {
@@ -47,7 +47,7 @@
47
47
  "mitata": "1.0.34",
48
48
  "prettier": "^3.2.5",
49
49
  "publint": "^0.2.6",
50
- "release-plan": "^0.17.4",
50
+ "release-plan": "^0.18.0",
51
51
  "typescript": "^5.3.3",
52
52
  "vite": "^5.0.12",
53
53
  "vitest": "^1.2.2"
@@ -64,14 +64,14 @@
64
64
  "node": ">=16.0.0"
65
65
  },
66
66
  "scripts": {
67
+ "bench": "./scripts/run-bench.sh tests/parser.bench.mjs",
68
+ "bench:compare": "node scripts/bench-compare.mjs",
69
+ "bench:summary": "./scripts/local-bench-summary.sh",
67
70
  "lint": "concurrently \"npm:lint:*(!fix)\" --names \"lint:\"",
68
71
  "lint:fix": "concurrently \"npm:lint:*:fix\" --names \"fix:\"",
69
72
  "lint:js": "eslint . --max-warnings=0",
70
73
  "lint:js:fix": "eslint . --fix --max-warnings=0",
71
74
  "lint:package": "publint",
72
- "bench": "node --expose-gc tests/parser.bench.mjs",
73
- "bench:compare": "node scripts/bench-compare.mjs",
74
- "bench:summary": "./scripts/local-bench-summary.sh",
75
75
  "test": "vitest run"
76
76
  }
77
77
  }
@@ -1,5 +1,6 @@
1
1
  import * as eslintScope from 'eslint-scope';
2
2
  import { toTree, glimmerVisitorKeys, DocumentLines } from 'ember-estree';
3
+ import { registerHBSScopes } from './transforms.js';
3
4
 
4
5
  // Constant: Program + all Glimmer node types. Computed once at module load.
5
6
  const hbsVisitorKeys = { Program: ['body'], ...glimmerVisitorKeys };
@@ -64,26 +65,27 @@ export function parseForESLint(code, options) {
64
65
  },
65
66
  };
66
67
 
67
- // Build visitor keys: Program + all Glimmer node types
68
- const visitorKeys = hbsVisitorKeys;
68
+ // Analyze a stub Program then rebind the resulting global scope to the real
69
+ // Program. Analyzing the real Program directly causes infinite recursion in
70
+ // esrecurse because Glimmer subtree nodes carry parent back-links.
71
+ const stubProgram = {
72
+ type: 'Program',
73
+ body: [],
74
+ range: [0, code.length],
75
+ loc: program.loc,
76
+ };
77
+ const scopeManager = eslintScope.analyze(stubProgram, { range: true });
78
+ const globalScope = scopeManager.acquire(stubProgram);
79
+ globalScope.block = program;
80
+ scopeManager.__nodeToScope.delete(stubProgram);
81
+ scopeManager.__nodeToScope.set(program, [globalScope]);
69
82
 
70
- // Create an empty scope manager.
71
- // For HBS, all locals are assumed to be defined at runtime,
72
- // so we don't track variable references (no no-undef errors).
73
- const scopeManager = eslintScope.analyze(
74
- {
75
- type: 'Program',
76
- body: [],
77
- range: [0, code.length],
78
- loc: program.loc,
79
- },
80
- { range: true }
81
- );
83
+ registerHBSScopes({ ast: program, scopeManager, visitorKeys: hbsVisitorKeys });
82
84
 
83
85
  return {
84
86
  ast: program,
85
87
  scopeManager,
86
- visitorKeys,
88
+ visitorKeys: hbsVisitorKeys,
87
89
  services: {},
88
90
  };
89
91
  }
@@ -82,6 +82,7 @@ function isUpperCase(char) {
82
82
 
83
83
  function registerBlockParams(node, path, scopeManager, isTypescript) {
84
84
  const blockParamNodes = node.blockParamNodes || [];
85
+ if (blockParamNodes.length === 0) return;
85
86
  const upperScope = findParentScope(scopeManager, path);
86
87
  const scope = isTypescript
87
88
  ? new TypescriptScope.BlockScope(scopeManager, upperScope, node)
@@ -240,6 +241,22 @@ export function registerGlimmerScopes(result) {
240
241
  });
241
242
  }
242
243
 
244
+ /**
245
+ * Scope registration for the HBS parser. Unlike the gjs/gts path, we do not
246
+ * register references for free identifiers (`{{path}}`, `<Tag>`) — all
247
+ * template locals are treated as runtime-defined, so no-undef stays quiet.
248
+ * Only block params from `as |x|` constructs are declared.
249
+ */
250
+ export function registerHBSScopes(result) {
251
+ traverse(result.visitorKeys, result.ast, (path) => {
252
+ const node = path.node;
253
+ if (!node) return;
254
+ if ('blockParams' in node && node.type.startsWith('Glimmer')) {
255
+ registerBlockParams(node, path, result.scopeManager, false);
256
+ }
257
+ });
258
+ }
259
+
243
260
  // ── transformForLint (used by ts-patch.js) ────────────────────────────
244
261
 
245
262
  export const replaceRange = function replaceRange(s, start, end, substitute) {