gitnexus 1.6.6-rc.144 → 1.6.6-rc.145
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/dist/core/ingestion/languages/java/captures.js +95 -1
- package/dist/core/ingestion/languages/java/interpret.js +12 -6
- package/dist/core/ingestion/languages/java/query.js +16 -1
- package/dist/core/ingestion/scope-resolution/graph-bridge/ids.js +15 -3
- package/dist/core/ingestion/scope-resolution/graph-bridge/node-lookup.js +13 -4
- package/package.json +1 -1
|
@@ -161,7 +161,101 @@ export function emitJavaScopeCaptures(sourceText, _filePath, cachedTree) {
|
|
|
161
161
|
}
|
|
162
162
|
out.push(grouped);
|
|
163
163
|
}
|
|
164
|
-
return [
|
|
164
|
+
return [
|
|
165
|
+
...resolveVarTypeBindings(out),
|
|
166
|
+
...synthesizeJavaInheritanceReferences(tree.rootNode),
|
|
167
|
+
...synthesizeJavaExplicitConstructorReferences(tree.rootNode),
|
|
168
|
+
];
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* Synthesize `@reference.call.constructor` captures for explicit constructor
|
|
172
|
+
* invocations — `super(...)` and `this(...)` (F38 #1928). tree-sitter-java
|
|
173
|
+
* models these as `explicit_constructor_invocation` nodes, which the scope
|
|
174
|
+
* query does not match, so the chained-constructor CALLS edges (subclass ctor →
|
|
175
|
+
* superclass ctor; ctor → sibling overload) were silently dropped.
|
|
176
|
+
*
|
|
177
|
+
* The grammar gives no constructor *name* at the call site (the child is a bare
|
|
178
|
+
* `(super)` / `(this)` token), so the target name is resolved structurally:
|
|
179
|
+
* - `this(...)` → the enclosing type's own simple name (constructor symbols
|
|
180
|
+
* are keyed by the declaring class name).
|
|
181
|
+
* - `super(...)` → the enclosing class's superclass simple-name tail (reusing
|
|
182
|
+
* `javaBaseLookupNameNode` so qualified/generic supers reduce
|
|
183
|
+
* to the bare class name, matching the EXTENDS synth). An
|
|
184
|
+
* implicit `Object` super (no `superclass` field) has no
|
|
185
|
+
* in-graph symbol, so it is skipped rather than emitting a
|
|
186
|
+
* dangling reference.
|
|
187
|
+
* Arity is attached so overloaded constructors disambiguate downstream, mirroring
|
|
188
|
+
* the call-site arity synthesized for `new X(...)`.
|
|
189
|
+
*/
|
|
190
|
+
function synthesizeJavaExplicitConstructorReferences(root) {
|
|
191
|
+
const out = [];
|
|
192
|
+
const stack = [root];
|
|
193
|
+
while (stack.length > 0) {
|
|
194
|
+
const node = stack.pop();
|
|
195
|
+
if (node.type === 'explicit_constructor_invocation') {
|
|
196
|
+
emitJavaExplicitConstructorRef(out, node);
|
|
197
|
+
}
|
|
198
|
+
for (let i = 0; i < node.namedChildCount; i++) {
|
|
199
|
+
const child = node.namedChild(i);
|
|
200
|
+
if (child !== null)
|
|
201
|
+
stack.push(child);
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
return out;
|
|
205
|
+
}
|
|
206
|
+
const TYPE_DECL_NODE_TYPES = new Set([
|
|
207
|
+
'class_declaration',
|
|
208
|
+
'enum_declaration',
|
|
209
|
+
'record_declaration',
|
|
210
|
+
]);
|
|
211
|
+
function emitJavaExplicitConstructorRef(out, node) {
|
|
212
|
+
const ctor = node.childForFieldName('constructor');
|
|
213
|
+
if (ctor === null)
|
|
214
|
+
return;
|
|
215
|
+
const enclosingType = findEnclosingTypeDeclaration(node);
|
|
216
|
+
if (enclosingType === null)
|
|
217
|
+
return;
|
|
218
|
+
let targetNameNode = null;
|
|
219
|
+
if (ctor.type === 'this') {
|
|
220
|
+
targetNameNode = enclosingType.childForFieldName('name');
|
|
221
|
+
}
|
|
222
|
+
else if (ctor.type === 'super') {
|
|
223
|
+
// Only class_declaration carries a `superclass` field; enum/record cannot
|
|
224
|
+
// declare an explicit superclass, so `super(...)` there has no resolvable
|
|
225
|
+
// target symbol.
|
|
226
|
+
const superclass = enclosingType.childForFieldName('superclass');
|
|
227
|
+
if (superclass === null)
|
|
228
|
+
return;
|
|
229
|
+
for (const base of superclass.namedChildren) {
|
|
230
|
+
if (base === null)
|
|
231
|
+
continue;
|
|
232
|
+
const nameNode = javaBaseLookupNameNode(base);
|
|
233
|
+
if (nameNode !== null) {
|
|
234
|
+
targetNameNode = nameNode;
|
|
235
|
+
break;
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
if (targetNameNode === null)
|
|
240
|
+
return;
|
|
241
|
+
const argList = node.childForFieldName('arguments');
|
|
242
|
+
const args = argList === null
|
|
243
|
+
? []
|
|
244
|
+
: argList.namedChildren.filter((c) => c !== null && c.type !== 'block_comment' && c.type !== 'line_comment');
|
|
245
|
+
out.push({
|
|
246
|
+
'@reference.call.constructor': nodeToCapture('@reference.call.constructor', node),
|
|
247
|
+
'@reference.name': nodeToCapture('@reference.name', targetNameNode),
|
|
248
|
+
'@reference.arity': syntheticCapture('@reference.arity', node, String(args.length)),
|
|
249
|
+
});
|
|
250
|
+
}
|
|
251
|
+
function findEnclosingTypeDeclaration(node) {
|
|
252
|
+
let cur = node.parent;
|
|
253
|
+
while (cur !== null) {
|
|
254
|
+
if (TYPE_DECL_NODE_TYPES.has(cur.type))
|
|
255
|
+
return cur;
|
|
256
|
+
cur = cur.parent;
|
|
257
|
+
}
|
|
258
|
+
return null;
|
|
165
259
|
}
|
|
166
260
|
/**
|
|
167
261
|
* Synthesize `@reference.inherits` captures from Java class heritage so the
|
|
@@ -67,10 +67,14 @@ export function interpretJavaTypeBinding(captures) {
|
|
|
67
67
|
const typeCap = captures['@type-binding.type'];
|
|
68
68
|
if (nameCap === undefined || typeCap === undefined)
|
|
69
69
|
return null;
|
|
70
|
-
// Strip
|
|
71
|
-
// `
|
|
72
|
-
//
|
|
73
|
-
|
|
70
|
+
// Strip generics BEFORE the qualifier (F41 #1928). Stripping the qualifier
|
|
71
|
+
// first uses `lastIndexOf('.')`, which for a qualified *type argument*
|
|
72
|
+
// (`Map<String, com.example.User>`) cuts inside the generic and yields a
|
|
73
|
+
// corrupted `User>`. Unwrapping generics first reduces the string to a single
|
|
74
|
+
// (possibly qualified) class name, then the qualifier strip leaves the bare
|
|
75
|
+
// simple name. `stripGeneric`'s erasure fallback is qualifier-tolerant so a
|
|
76
|
+
// qualified generic base (`com.example.BaseModel<T>`) still reduces correctly.
|
|
77
|
+
const rawType = stripQualifier(stripGeneric(typeCap.text.trim()));
|
|
74
78
|
// Skip `var` — tree-sitter-java parses `var` as type_identifier with
|
|
75
79
|
// text "var". When used without a constructor initializer, there's no
|
|
76
80
|
// concrete type to bind.
|
|
@@ -120,8 +124,10 @@ function stripGeneric(text) {
|
|
|
120
124
|
// `BaseModel<T>` → `BaseModel`, `Builder<Self>` → `Builder`.
|
|
121
125
|
// This mirrors JVM type erasure — the raw class name is the resolvable symbol.
|
|
122
126
|
// The pattern matches up to the first `<` to handle nested generics safely
|
|
123
|
-
// (e.g. `BaseModel<List<String>>` → `BaseModel`).
|
|
124
|
-
|
|
127
|
+
// (e.g. `BaseModel<List<String>>` → `BaseModel`). The base is allowed to be
|
|
128
|
+
// qualified (`com.example.BaseModel<T>` → `com.example.BaseModel`) since the
|
|
129
|
+
// caller strips the qualifier afterwards (F41 #1928).
|
|
130
|
+
const fallback = text.match(/^((?:[A-Za-z_$][A-Za-z0-9_$]*\.)*[A-Za-z_$][A-Za-z0-9_$]*)<.+>$/s);
|
|
125
131
|
if (fallback !== null)
|
|
126
132
|
return fallback[1].trim();
|
|
127
133
|
return text;
|
|
@@ -212,8 +212,23 @@ const JAVA_SCOPE_QUERY = `
|
|
|
212
212
|
type: (generic_type
|
|
213
213
|
(type_identifier) @reference.name)) @reference.call.constructor
|
|
214
214
|
|
|
215
|
+
;; References — qualified constructor calls: new pkg.Foo(), new a.b.Foo() (F35 #1928)
|
|
216
|
+
;; tree-sitter-java parses \`pkg.Foo\` as a scoped_type_identifier whose final
|
|
217
|
+
;; child is the simple type. Bind that tail as @reference.name (trailing \`.\`
|
|
218
|
+
;; anchor = last child) so resolution targets \`Foo\`, not the raw \`pkg.Foo\` text.
|
|
219
|
+
;; Mirrors the TS/JS new-expression qualified-constructor capture.
|
|
215
220
|
(object_creation_expression
|
|
216
|
-
type: (scoped_type_identifier
|
|
221
|
+
type: (scoped_type_identifier
|
|
222
|
+
(type_identifier) @reference.name .) @reference.call.constructor.qualified) @reference.call.constructor
|
|
223
|
+
|
|
224
|
+
;; References — qualified + generic constructor calls: new pkg.Box<T>() (F35 #1928)
|
|
225
|
+
;; The base is a generic_type whose first child is a scoped_type_identifier, so
|
|
226
|
+
;; neither the simple-generic nor the plain-scoped arm above matches it. Bind the
|
|
227
|
+
;; scoped tail as @reference.name.
|
|
228
|
+
(object_creation_expression
|
|
229
|
+
type: (generic_type
|
|
230
|
+
(scoped_type_identifier
|
|
231
|
+
(type_identifier) @reference.name .) @reference.call.constructor.qualified)) @reference.call.constructor
|
|
217
232
|
|
|
218
233
|
;; References — method references: User::getName, obj::method
|
|
219
234
|
(method_reference
|
|
@@ -48,6 +48,15 @@ function isCallerAnchorLabel(label) {
|
|
|
48
48
|
label === 'Struct' ||
|
|
49
49
|
label === 'Enum');
|
|
50
50
|
}
|
|
51
|
+
/**
|
|
52
|
+
* Callables whose same-name overloads occupy distinct graph nodes keyed by
|
|
53
|
+
* parameter types / shape. Must mirror `isOverloadableCallable` in
|
|
54
|
+
* `node-lookup.ts` so registration and lookup agree (Constructor included —
|
|
55
|
+
* #1928 F38).
|
|
56
|
+
*/
|
|
57
|
+
function isOverloadableCallable(label) {
|
|
58
|
+
return label === 'Function' || label === 'Method' || label === 'Constructor';
|
|
59
|
+
}
|
|
51
60
|
/**
|
|
52
61
|
* Look up a `SymbolDefinition` in the graph node lookup.
|
|
53
62
|
*
|
|
@@ -83,7 +92,7 @@ export function resolveDefGraphId(filePath, def, nodeLookup) {
|
|
|
83
92
|
if (cHit !== undefined)
|
|
84
93
|
return cHit;
|
|
85
94
|
}
|
|
86
|
-
if ((def.type
|
|
95
|
+
if (isOverloadableCallable(def.type) &&
|
|
87
96
|
def.parameterTypes !== undefined &&
|
|
88
97
|
def.parameterTypeClasses !== undefined) {
|
|
89
98
|
const shapeTag = parameterShapeIdTag(def.parameterTypes, def.parameterTypeClasses);
|
|
@@ -96,8 +105,11 @@ export function resolveDefGraphId(filePath, def, nodeLookup) {
|
|
|
96
105
|
}
|
|
97
106
|
// Overload disambiguation: when the def carries parameter types,
|
|
98
107
|
// try the parameter-typed key first so same-name same-arity
|
|
99
|
-
// overloads route to their distinct graph nodes.
|
|
100
|
-
|
|
108
|
+
// overloads route to their distinct graph nodes. Constructors are
|
|
109
|
+
// included so a `this(int)`/`super(int)` chain or `new Foo(int)`
|
|
110
|
+
// resolves to the matching ctor overload instead of first-wins
|
|
111
|
+
// collapsing onto another `Foo` ctor (a self-loop) — #1928 F38.
|
|
112
|
+
if (isOverloadableCallable(def.type) &&
|
|
101
113
|
def.parameterTypes !== undefined &&
|
|
102
114
|
def.parameterTypes.length > 0) {
|
|
103
115
|
const pKey = qualifiedKey(filePath, def.type, `${qn}~${def.parameterTypes.join(',')}`);
|
|
@@ -87,9 +87,7 @@ export function buildGraphNodeLookup(graph) {
|
|
|
87
87
|
// a parameter-types-suffixed key so resolveDefGraphId can find
|
|
88
88
|
// the right overload by matching its def's parameterTypes.
|
|
89
89
|
const pTypes = props.parameterTypes;
|
|
90
|
-
if (pTypes !== undefined &&
|
|
91
|
-
pTypes.length > 0 &&
|
|
92
|
-
(node.label === 'Function' || node.label === 'Method')) {
|
|
90
|
+
if (pTypes !== undefined && pTypes.length > 0 && isOverloadableCallable(node.label)) {
|
|
93
91
|
const pKey = qualifiedKey(props.filePath, node.label, `${keyQualified}~${pTypes.join(',')}`);
|
|
94
92
|
// Each overload is unique — set unconditionally.
|
|
95
93
|
if (!lookup.has(pKey))
|
|
@@ -98,7 +96,7 @@ export function buildGraphNodeLookup(graph) {
|
|
|
98
96
|
const pClasses = props
|
|
99
97
|
.parameterTypeClasses;
|
|
100
98
|
const shapeTag = parameterShapeIdTag(pTypes, pClasses);
|
|
101
|
-
if (shapeTag !== '' && (node.label
|
|
99
|
+
if (shapeTag !== '' && isOverloadableCallable(node.label)) {
|
|
102
100
|
const shapeKey = qualifiedKey(props.filePath, node.label, `${keyQualified}${shapeTag}`);
|
|
103
101
|
if (!lookup.has(shapeKey))
|
|
104
102
|
lookup.set(shapeKey, node.id);
|
|
@@ -136,6 +134,17 @@ export function buildGraphNodeLookup(graph) {
|
|
|
136
134
|
}
|
|
137
135
|
return lookup;
|
|
138
136
|
}
|
|
137
|
+
/**
|
|
138
|
+
* Callables whose same-name overloads must route to distinct graph nodes via
|
|
139
|
+
* the parameter-types / shape key. Constructors belong here too: a class with
|
|
140
|
+
* `Foo()` and `Foo(int)` mints distinct `#0`/`#1` Constructor nodes, and a
|
|
141
|
+
* `this(...)`/`super(...)` edge (or any `new Foo(args)`) must reach the right
|
|
142
|
+
* one. Without the overload key both ctor nodes collapse onto the first-wins
|
|
143
|
+
* qualified/simple key, turning a `this()` chain into a self-loop (#1928 F38).
|
|
144
|
+
*/
|
|
145
|
+
function isOverloadableCallable(label) {
|
|
146
|
+
return label === 'Function' || label === 'Method' || label === 'Constructor';
|
|
147
|
+
}
|
|
139
148
|
export function isLinkableLabel(label) {
|
|
140
149
|
return (label === 'Function' ||
|
|
141
150
|
label === 'Method' ||
|
package/package.json
CHANGED