gitnexus 1.6.6-rc.54 → 1.6.6-rc.55
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.
|
@@ -293,6 +293,9 @@ export function populatePhpNamespaceSiblings(parsedFiles, indexes, inputs) {
|
|
|
293
293
|
//
|
|
294
294
|
// Additionally, mirror from files that are imported via `use` (different
|
|
295
295
|
// namespace) so return types from dependencies are chain-followable too.
|
|
296
|
+
const parsedByPath = new Map();
|
|
297
|
+
for (const p of parsedFiles)
|
|
298
|
+
parsedByPath.set(p.filePath, p);
|
|
296
299
|
for (const parsed of parsedFiles) {
|
|
297
300
|
const moduleScope = parsed.scopes.find((s) => s.kind === 'Module');
|
|
298
301
|
if (moduleScope === undefined)
|
|
@@ -328,7 +331,7 @@ export function populatePhpNamespaceSiblings(parsedFiles, indexes, inputs) {
|
|
|
328
331
|
}
|
|
329
332
|
// Mirror return-type bindings from accessible files.
|
|
330
333
|
for (const srcFilePath of accessibleFiles) {
|
|
331
|
-
const srcParsed =
|
|
334
|
+
const srcParsed = parsedByPath.get(srcFilePath);
|
|
332
335
|
if (srcParsed === undefined)
|
|
333
336
|
continue;
|
|
334
337
|
const srcModuleScope = srcParsed.scopes.find((s) => s.kind === 'Module');
|
|
@@ -78,9 +78,11 @@ export type ScopeExtractorHooks = Pick<LanguageProvider, 'resolveScopeKind' | 'b
|
|
|
78
78
|
* Drive the five extraction passes and return a `ParsedFile`.
|
|
79
79
|
*
|
|
80
80
|
* Throws `ScopeTreeInvariantError` (from #912) when the provider emits
|
|
81
|
-
* captures that violate structural scope invariants.
|
|
82
|
-
*
|
|
83
|
-
*
|
|
84
|
-
*
|
|
81
|
+
* captures that violate structural scope invariants (e.g., overlapping
|
|
82
|
+
* sibling scopes). When no `@scope.module` capture is present, a
|
|
83
|
+
* synthetic Module scope is created spanning all captures, and orphan
|
|
84
|
+
* non-Module scopes are re-parented under it. This enables indexing of
|
|
85
|
+
* files where tree-sitter produces an ERROR root (e.g., complex .phtml
|
|
86
|
+
* templates with mixed PHP/HTML/JS).
|
|
85
87
|
*/
|
|
86
88
|
export declare function extract(matches: readonly CaptureMatch[], filePath: string, provider: ScopeExtractorHooks): ParsedFile;
|
|
@@ -65,17 +65,28 @@ import { extractTemplateArguments } from './utils/template-arguments.js';
|
|
|
65
65
|
* Drive the five extraction passes and return a `ParsedFile`.
|
|
66
66
|
*
|
|
67
67
|
* Throws `ScopeTreeInvariantError` (from #912) when the provider emits
|
|
68
|
-
* captures that violate structural scope invariants.
|
|
69
|
-
*
|
|
70
|
-
*
|
|
71
|
-
*
|
|
68
|
+
* captures that violate structural scope invariants (e.g., overlapping
|
|
69
|
+
* sibling scopes). When no `@scope.module` capture is present, a
|
|
70
|
+
* synthetic Module scope is created spanning all captures, and orphan
|
|
71
|
+
* non-Module scopes are re-parented under it. This enables indexing of
|
|
72
|
+
* files where tree-sitter produces an ERROR root (e.g., complex .phtml
|
|
73
|
+
* templates with mixed PHP/HTML/JS).
|
|
72
74
|
*/
|
|
73
75
|
export function extract(matches, filePath, provider) {
|
|
74
76
|
// Partition matches by topic up front — one linear pass over the input.
|
|
75
77
|
const partitioned = partitionByTopic(matches);
|
|
76
78
|
// ── Pass 1: build the scope tree ─────────────────────────────────────
|
|
77
79
|
const scopeDrafts = pass1BuildScopes(partitioned.scope, filePath, provider);
|
|
78
|
-
const moduleScope = ensureModuleScope(scopeDrafts,
|
|
80
|
+
const moduleScope = ensureModuleScope(scopeDrafts, filePath, matches);
|
|
81
|
+
// Re-parent orphan drafts (parent === null, non-Module) under the
|
|
82
|
+
// Module scope. Replaces drafts with new ones carrying the correct
|
|
83
|
+
// parent — runs before content passes so bindings/ownedDefs are empty.
|
|
84
|
+
for (let i = 0; i < scopeDrafts.length; i++) {
|
|
85
|
+
const d = scopeDrafts[i];
|
|
86
|
+
if (d.parent === null && d.kind !== 'Module') {
|
|
87
|
+
scopeDrafts[i] = makeDraft(d.id, moduleScope.id, d.kind, d.range, d.filePath);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
79
90
|
const scopes = scopeDrafts.map(draftToScope);
|
|
80
91
|
// buildScopeTree validates invariants (throws on violation) and exposes
|
|
81
92
|
// the lookup contract consumed by Passes 2-5.
|
|
@@ -171,18 +182,29 @@ function topicOf(match) {
|
|
|
171
182
|
}
|
|
172
183
|
return 'unknown';
|
|
173
184
|
}
|
|
174
|
-
function ensureModuleScope(scopeDrafts,
|
|
185
|
+
function ensureModuleScope(scopeDrafts, filePath, allMatches) {
|
|
175
186
|
const moduleScope = scopeDrafts.find((s) => s.kind === 'Module');
|
|
176
187
|
if (moduleScope !== undefined)
|
|
177
188
|
return moduleScope;
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
189
|
+
// Synthesize a Module scope spanning all captures in the file.
|
|
190
|
+
// Computed from ALL captures (scope, declaration, reference, etc.)
|
|
191
|
+
// so the range covers top-level references that appear after the
|
|
192
|
+
// last inner scope — not just inner Function/Class scopes.
|
|
193
|
+
let endLine = 0;
|
|
194
|
+
let endCol = 0;
|
|
195
|
+
for (const match of allMatches) {
|
|
196
|
+
for (const capture of Object.values(match)) {
|
|
197
|
+
if (capture.range.endLine > endLine ||
|
|
198
|
+
(capture.range.endLine === endLine && capture.range.endCol > endCol)) {
|
|
199
|
+
endLine = capture.range.endLine;
|
|
200
|
+
endCol = capture.range.endCol;
|
|
201
|
+
}
|
|
202
|
+
}
|
|
183
203
|
}
|
|
184
|
-
|
|
185
|
-
|
|
204
|
+
const range = { startLine: 0, startCol: 0, endLine, endCol };
|
|
205
|
+
const synthetic = makeDraft(makeScopeId({ filePath, range, kind: 'Module' }), null, 'Module', range, filePath);
|
|
206
|
+
scopeDrafts.push(synthetic);
|
|
207
|
+
return synthetic;
|
|
186
208
|
}
|
|
187
209
|
function draftToScope(draft) {
|
|
188
210
|
const frozenBindings = new Map();
|
package/package.json
CHANGED