ucn 3.8.7 → 3.8.8
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/core/entrypoints.js +62 -35
- package/core/output.js +1 -0
- package/languages/go.js +31 -2
- package/package.json +1 -1
package/core/entrypoints.js
CHANGED
|
@@ -209,15 +209,15 @@ const FRAMEWORK_PATTERNS = [
|
|
|
209
209
|
// ── Go Framework Patterns ─────────────────────────────────────────
|
|
210
210
|
|
|
211
211
|
// Cobra CLI framework — RunE, Run, PreRunE etc. assigned to cobra.Command struct fields
|
|
212
|
-
// Detected via
|
|
212
|
+
// Detected via composite literal: &cobra.Command{RunE: handler}
|
|
213
213
|
{
|
|
214
214
|
id: 'cobra-command',
|
|
215
215
|
languages: new Set(['go']),
|
|
216
216
|
type: 'cli',
|
|
217
217
|
framework: 'cobra',
|
|
218
|
-
detection: '
|
|
219
|
-
|
|
220
|
-
|
|
218
|
+
detection: 'compositePattern',
|
|
219
|
+
typePattern: /^cobra\.Command$/,
|
|
220
|
+
fieldPattern: /^(Run|RunE|PreRun|PreRunE|PostRun|PostRunE|PersistentPreRun|PersistentPreRunE|PersistentPostRun|PersistentPostRunE)$/,
|
|
221
221
|
},
|
|
222
222
|
|
|
223
223
|
// Go goroutine launch — go func() or go handler()
|
|
@@ -289,50 +289,77 @@ function matchDecoratorOrModifier(symbol, language) {
|
|
|
289
289
|
*/
|
|
290
290
|
function buildCallbackEntrypointMap(index) {
|
|
291
291
|
const callPatterns = FRAMEWORK_PATTERNS.filter(p => p.detection === 'callPattern');
|
|
292
|
-
|
|
292
|
+
const compositePatterns = FRAMEWORK_PATTERNS.filter(p => p.detection === 'compositePattern');
|
|
293
|
+
if (callPatterns.length === 0 && compositePatterns.length === 0) return new Map();
|
|
293
294
|
|
|
294
295
|
const result = new Map(); // name -> info
|
|
295
296
|
|
|
296
297
|
for (const [filePath, fileEntry] of index.files) {
|
|
297
298
|
const lang = fileEntry.language;
|
|
298
|
-
const relevantPatterns = callPatterns.filter(p => p.languages.has(lang));
|
|
299
|
-
if (relevantPatterns.length === 0) continue;
|
|
300
299
|
|
|
301
300
|
const calls = getCachedCalls(index, filePath);
|
|
302
301
|
if (!calls) continue;
|
|
303
302
|
|
|
304
|
-
// Pass 1:
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
for (const
|
|
310
|
-
if (
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
303
|
+
// Pass 1+2: call-pattern detection (e.g., app.GET("/", handler))
|
|
304
|
+
const relevantCallPatterns = callPatterns.filter(p => p.languages.has(lang));
|
|
305
|
+
if (relevantCallPatterns.length > 0) {
|
|
306
|
+
// Pass 1: find route-registration calls, index by line
|
|
307
|
+
const routeLines = new Map(); // line -> { pattern, call }
|
|
308
|
+
for (const call of calls) {
|
|
309
|
+
if (!call.receiver) continue;
|
|
310
|
+
for (const pattern of relevantCallPatterns) {
|
|
311
|
+
if (pattern.receiverPattern.test(call.receiver) &&
|
|
312
|
+
pattern.methodPattern.test(call.name)) {
|
|
313
|
+
routeLines.set(call.line, { pattern, call });
|
|
314
|
+
break;
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
if (routeLines.size > 0) {
|
|
320
|
+
// Pass 2: find callbacks on route-registration lines
|
|
321
|
+
for (const call of calls) {
|
|
322
|
+
if (!call.isFunctionReference && !call.isPotentialCallback) continue;
|
|
323
|
+
const route = routeLines.get(call.line);
|
|
324
|
+
if (!route) continue;
|
|
325
|
+
|
|
326
|
+
if (!result.has(call.name)) {
|
|
327
|
+
result.set(call.name, {
|
|
328
|
+
framework: route.pattern.framework,
|
|
329
|
+
type: route.pattern.type,
|
|
330
|
+
patternId: route.pattern.id,
|
|
331
|
+
method: route.call.name.toUpperCase(),
|
|
332
|
+
file: filePath,
|
|
333
|
+
line: call.line,
|
|
334
|
+
});
|
|
335
|
+
}
|
|
314
336
|
}
|
|
315
337
|
}
|
|
316
338
|
}
|
|
317
339
|
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
340
|
+
// Pass 3: composite literal patterns (e.g., &cobra.Command{RunE: handler})
|
|
341
|
+
const relevantCompositePatterns = compositePatterns.filter(p => p.languages.has(lang));
|
|
342
|
+
if (relevantCompositePatterns.length > 0) {
|
|
343
|
+
for (const call of calls) {
|
|
344
|
+
if (!call.compositeType) continue;
|
|
345
|
+
if (!call.isPotentialCallback && !call.isFunctionReference) continue;
|
|
346
|
+
|
|
347
|
+
for (const pattern of relevantCompositePatterns) {
|
|
348
|
+
if (pattern.typePattern.test(call.compositeType) &&
|
|
349
|
+
pattern.fieldPattern.test(call.fieldName)) {
|
|
350
|
+
if (!result.has(call.name)) {
|
|
351
|
+
result.set(call.name, {
|
|
352
|
+
framework: pattern.framework,
|
|
353
|
+
type: pattern.type,
|
|
354
|
+
patternId: pattern.id,
|
|
355
|
+
method: call.fieldName,
|
|
356
|
+
file: filePath,
|
|
357
|
+
line: call.line,
|
|
358
|
+
});
|
|
359
|
+
}
|
|
360
|
+
break;
|
|
361
|
+
}
|
|
362
|
+
}
|
|
336
363
|
}
|
|
337
364
|
}
|
|
338
365
|
}
|
package/core/output.js
CHANGED
package/languages/go.js
CHANGED
|
@@ -954,6 +954,31 @@ function findCallsInCode(code, parser, options = {}) {
|
|
|
954
954
|
valueNode = valueNode.namedChildCount > 0 ? valueNode.namedChild(0) : null;
|
|
955
955
|
}
|
|
956
956
|
if (valueNode) {
|
|
957
|
+
// Extract field name (the key) and parent composite literal type
|
|
958
|
+
let keyNode = node.namedChildCount >= 1 ? node.namedChild(0) : null;
|
|
959
|
+
if (keyNode && keyNode.type === 'literal_element') {
|
|
960
|
+
keyNode = keyNode.namedChildCount > 0 ? keyNode.namedChild(0) : null;
|
|
961
|
+
}
|
|
962
|
+
const fieldName = keyNode ? keyNode.text : undefined;
|
|
963
|
+
|
|
964
|
+
let compositeType;
|
|
965
|
+
let compositeLit = node.parent; // literal_value
|
|
966
|
+
if (compositeLit && compositeLit.type === 'literal_value') {
|
|
967
|
+
compositeLit = compositeLit.parent; // composite_literal
|
|
968
|
+
}
|
|
969
|
+
if (compositeLit && compositeLit.type === 'composite_literal') {
|
|
970
|
+
const typeNode = compositeLit.childForFieldName('type');
|
|
971
|
+
if (typeNode) {
|
|
972
|
+
if (typeNode.type === 'qualified_type') {
|
|
973
|
+
const pkg = typeNode.childForFieldName('package')?.text;
|
|
974
|
+
const typeName = typeNode.childForFieldName('name')?.text;
|
|
975
|
+
compositeType = pkg && typeName ? `${pkg}.${typeName}` : typeNode.text;
|
|
976
|
+
} else if (typeNode.type === 'type_identifier') {
|
|
977
|
+
compositeType = typeNode.text;
|
|
978
|
+
}
|
|
979
|
+
}
|
|
980
|
+
}
|
|
981
|
+
|
|
957
982
|
if (valueNode.type === 'identifier') {
|
|
958
983
|
const name = valueNode.text;
|
|
959
984
|
if (!GO_SKIP_IDENTS.has(name) && !GO_BUILTINS.has(name) && !importAliases.has(name) && /^[a-zA-Z]/.test(name)) {
|
|
@@ -965,7 +990,9 @@ function findCallsInCode(code, parser, options = {}) {
|
|
|
965
990
|
isFunctionReference: true,
|
|
966
991
|
isPotentialCallback: true,
|
|
967
992
|
enclosingFunction,
|
|
968
|
-
uncertain: false
|
|
993
|
+
uncertain: false,
|
|
994
|
+
...(compositeType && { compositeType }),
|
|
995
|
+
...(fieldName && { fieldName }),
|
|
969
996
|
});
|
|
970
997
|
}
|
|
971
998
|
}
|
|
@@ -984,7 +1011,9 @@ function findCallsInCode(code, parser, options = {}) {
|
|
|
984
1011
|
...(receiverType && { receiverType }),
|
|
985
1012
|
enclosingFunction,
|
|
986
1013
|
isPotentialCallback: true,
|
|
987
|
-
uncertain: false
|
|
1014
|
+
uncertain: false,
|
|
1015
|
+
...(compositeType && { compositeType }),
|
|
1016
|
+
...(fieldName && { fieldName }),
|
|
988
1017
|
});
|
|
989
1018
|
}
|
|
990
1019
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ucn",
|
|
3
|
-
"version": "3.8.
|
|
3
|
+
"version": "3.8.8",
|
|
4
4
|
"mcpName": "io.github.mleoca/ucn",
|
|
5
5
|
"description": "Code intelligence toolkit for AI agents — extract functions, trace call chains, find callers, detect dead code without reading entire files. Works as MCP server, CLI, or agent skill. Supports JS/TS, Python, Go, Rust, Java.",
|
|
6
6
|
"main": "index.js",
|