code-graph-context 2.0.0 → 2.0.1
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.
|
@@ -84,6 +84,38 @@ function extractInjectionToken(node) {
|
|
|
84
84
|
}
|
|
85
85
|
return null;
|
|
86
86
|
}
|
|
87
|
+
/**
|
|
88
|
+
* Extract constructor parameter types and @Inject tokens for edge detection.
|
|
89
|
+
* This allows INJECTS detection to work without AST access (for cross-chunk detection).
|
|
90
|
+
*/
|
|
91
|
+
function extractConstructorParamTypes(node) {
|
|
92
|
+
const types = [];
|
|
93
|
+
const injectTokens = new Map();
|
|
94
|
+
const constructors = node.getConstructors();
|
|
95
|
+
if (constructors.length === 0)
|
|
96
|
+
return { types, injectTokens };
|
|
97
|
+
const constructor = constructors[0];
|
|
98
|
+
const parameters = constructor.getParameters();
|
|
99
|
+
for (const param of parameters) {
|
|
100
|
+
const typeNode = param.getTypeNode();
|
|
101
|
+
if (typeNode) {
|
|
102
|
+
const typeName = typeNode.getText();
|
|
103
|
+
types.push(typeName);
|
|
104
|
+
// Check for @Inject decorator
|
|
105
|
+
const decorators = param.getDecorators();
|
|
106
|
+
for (const decorator of decorators) {
|
|
107
|
+
if (decorator.getName() === 'Inject') {
|
|
108
|
+
const args = decorator.getArguments();
|
|
109
|
+
if (args.length > 0) {
|
|
110
|
+
const token = args[0].getText().replace(/['"]/g, '');
|
|
111
|
+
injectTokens.set(typeName, token);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
return { types, injectTokens };
|
|
118
|
+
}
|
|
87
119
|
function hasDynamicMethods(node) {
|
|
88
120
|
const methods = node.getMethods();
|
|
89
121
|
const dynamicMethods = ['forRoot', 'forFeature', 'forRootAsync', 'forFeatureAsync'];
|
|
@@ -262,59 +294,39 @@ function detectDependencyInjection(sourceNode, targetNode) {
|
|
|
262
294
|
return false;
|
|
263
295
|
if (targetNode.properties?.coreType !== CoreNodeType.CLASS_DECLARATION)
|
|
264
296
|
return false;
|
|
265
|
-
const constructors = sourceNode.sourceNode?.getConstructors();
|
|
266
|
-
if (!constructors || constructors.length === 0)
|
|
267
|
-
return false;
|
|
268
|
-
const constructor = constructors[0];
|
|
269
|
-
const parameters = constructor.getParameters();
|
|
270
297
|
const targetName = targetNode.properties?.name;
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
return token === targetName;
|
|
282
|
-
}
|
|
283
|
-
}
|
|
284
|
-
return false;
|
|
285
|
-
});
|
|
286
|
-
});
|
|
298
|
+
if (!targetName)
|
|
299
|
+
return false;
|
|
300
|
+
// Use pre-extracted constructor params from context (works after AST cleanup)
|
|
301
|
+
const constructorParamTypes = sourceNode.properties?.context?.constructorParamTypes ?? [];
|
|
302
|
+
const injectTokens = sourceNode.properties?.context?.injectTokens ?? {};
|
|
303
|
+
// Check if target is in constructor params by type
|
|
304
|
+
if (constructorParamTypes.includes(targetName))
|
|
305
|
+
return true;
|
|
306
|
+
// Check if target is referenced via @Inject token
|
|
307
|
+
return Object.values(injectTokens).includes(targetName);
|
|
287
308
|
}
|
|
288
309
|
function extractInjectionTokenFromRelation(sourceNode, targetNode) {
|
|
289
|
-
const
|
|
290
|
-
if (!
|
|
310
|
+
const targetName = targetNode.properties?.name;
|
|
311
|
+
if (!targetName)
|
|
291
312
|
return null;
|
|
292
|
-
|
|
293
|
-
const
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
const args = decorator.getArguments();
|
|
299
|
-
if (args.length > 0) {
|
|
300
|
-
return args[0].getText().replace(/['"]/g, '');
|
|
301
|
-
}
|
|
302
|
-
}
|
|
313
|
+
// Use pre-extracted inject tokens from context (works after AST cleanup)
|
|
314
|
+
const injectTokens = sourceNode.properties?.context?.injectTokens ?? {};
|
|
315
|
+
// Find the token that maps to the target
|
|
316
|
+
for (const [typeName, token] of Object.entries(injectTokens)) {
|
|
317
|
+
if (token === targetName || typeName === targetName) {
|
|
318
|
+
return token;
|
|
303
319
|
}
|
|
304
320
|
}
|
|
305
321
|
return null;
|
|
306
322
|
}
|
|
307
323
|
function findParameterIndex(sourceNode, targetNode) {
|
|
308
|
-
const constructors = sourceNode.sourceNode?.getConstructors();
|
|
309
|
-
if (!constructors || constructors.length === 0)
|
|
310
|
-
return 0;
|
|
311
|
-
const constructor = constructors[0];
|
|
312
|
-
const parameters = constructor.getParameters();
|
|
313
324
|
const targetName = targetNode.properties?.name;
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
325
|
+
if (!targetName)
|
|
326
|
+
return -1;
|
|
327
|
+
// Use pre-extracted constructor params from context (works after AST cleanup)
|
|
328
|
+
const constructorParamTypes = sourceNode.properties?.context?.constructorParamTypes ?? [];
|
|
329
|
+
return constructorParamTypes.indexOf(targetName);
|
|
318
330
|
}
|
|
319
331
|
function computeFullPathFromNodes(sourceNode, targetNode) {
|
|
320
332
|
const basePath = sourceNode.properties?.context?.basePath ?? '';
|
|
@@ -791,6 +803,8 @@ export const NESTJS_FRAMEWORK_SCHEMA = {
|
|
|
791
803
|
const node = parsedNode.sourceNode;
|
|
792
804
|
if (!node)
|
|
793
805
|
return {};
|
|
806
|
+
// Extract constructor param types for INJECTS edge detection
|
|
807
|
+
const { types, injectTokens } = extractConstructorParamTypes(node);
|
|
794
808
|
return {
|
|
795
809
|
isAbstract: node.getAbstractKeyword() != null,
|
|
796
810
|
isDefaultExport: node.isDefaultExport(),
|
|
@@ -800,6 +814,9 @@ export const NESTJS_FRAMEWORK_SCHEMA = {
|
|
|
800
814
|
methodCount: node.getMethods().length,
|
|
801
815
|
propertyCount: node.getProperties().length,
|
|
802
816
|
constructorParameterCount: countConstructorParameters(node),
|
|
817
|
+
// Pre-extracted for cross-chunk edge detection
|
|
818
|
+
constructorParamTypes: types,
|
|
819
|
+
injectTokens: Object.fromEntries(injectTokens),
|
|
803
820
|
};
|
|
804
821
|
},
|
|
805
822
|
priority: 1,
|
|
@@ -876,13 +876,12 @@ export class TypeScriptParser {
|
|
|
876
876
|
}
|
|
877
877
|
async applyEdgeEnhancement(edgeEnhancement) {
|
|
878
878
|
try {
|
|
879
|
-
// Combine parsed nodes and existing nodes for
|
|
880
|
-
//
|
|
879
|
+
// Combine parsed nodes and existing nodes for edge matching
|
|
880
|
+
// Detection patterns should use pre-extracted context, not raw AST
|
|
881
881
|
const allTargetNodes = new Map([...this.parsedNodes, ...this.existingNodes]);
|
|
882
882
|
for (const [sourceId, sourceNode] of this.parsedNodes) {
|
|
883
|
-
//
|
|
884
|
-
|
|
885
|
-
continue;
|
|
883
|
+
// Note: sourceNode.sourceNode may be undefined after AST cleanup
|
|
884
|
+
// Detection patterns should use pre-extracted context from node.properties.context
|
|
886
885
|
for (const [targetId, targetNode] of allTargetNodes) {
|
|
887
886
|
if (sourceId === targetId)
|
|
888
887
|
continue;
|
|
@@ -174,10 +174,11 @@ export class WorkspaceParser {
|
|
|
174
174
|
for (const [nodeId, parsedNode] of innerParsedNodes) {
|
|
175
175
|
this.accumulatedParsedNodes.set(nodeId, {
|
|
176
176
|
id: parsedNode.id,
|
|
177
|
+
coreType: parsedNode.coreType, // Needed for detection patterns
|
|
177
178
|
semanticType: parsedNode.semanticType,
|
|
178
179
|
properties: {
|
|
179
180
|
name: parsedNode.properties.name,
|
|
180
|
-
context: parsedNode.properties.context, // Contains propertyTypes
|
|
181
|
+
context: parsedNode.properties.context, // Contains propertyTypes, dependencies
|
|
181
182
|
},
|
|
182
183
|
});
|
|
183
184
|
}
|
package/package.json
CHANGED