ucn 5.3.7 → 5.4.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/core/reporting.js CHANGED
@@ -48,6 +48,7 @@ function getStats(index, options = {}) {
48
48
  files: scopedFiles.length,
49
49
  symbols: totalSymbols, // Total symbol count, not unique names
50
50
  buildTime: index.buildTime,
51
+ buildTimeNote: 'Last index build, including discovery and graphs; excludes cache I/O and query execution. Reused when loading a cached index.',
51
52
  byLanguage: {},
52
53
  byType: {},
53
54
  ...(index.truncated && { truncated: index.truncated })
@@ -1044,6 +1045,7 @@ function orient(index, options = {}) {
1044
1045
  files: stats.files,
1045
1046
  symbols: stats.symbols,
1046
1047
  buildTime: stats.buildTime,
1048
+ buildTimeNote: stats.buildTimeNote,
1047
1049
  byLanguage: stats.byLanguage,
1048
1050
  dirs,
1049
1051
  hot: {
package/core/search.js CHANGED
@@ -727,6 +727,7 @@ function structuralSearch(index, options = {}) {
727
727
  // Auto-infer type: --receiver implies type=call
728
728
  const type = options.type || (receiver ? 'call' : undefined);
729
729
  const results = [];
730
+ const skippedTestFiles = new Set();
730
731
 
731
732
  // Validate type if provided
732
733
  if (type && !STRUCTURAL_TYPES.has(type)) {
@@ -753,7 +754,13 @@ function structuralSearch(index, options = {}) {
753
754
  if (!rp.includes(options.file) && !rp.endsWith(options.file)) return false;
754
755
  }
755
756
  if ((options.exclude && options.exclude.length > 0) || options.in) {
756
- if (!index.matchesFilters(fileEntry.relativePath, { exclude: options.exclude, in: options.in })) return false;
757
+ if (!index.matchesFilters(fileEntry.relativePath, { in: options.in })) return false;
758
+ if (!index.matchesFilters(fileEntry.relativePath, { exclude: options.exclude })) {
759
+ if (options.testExclude && !index.matchesFilters(fileEntry.relativePath, { exclude: options.testExclude })) {
760
+ skippedTestFiles.add(fileEntry.relativePath);
761
+ }
762
+ return false;
763
+ }
757
764
  }
758
765
  return true;
759
766
  };
@@ -883,7 +890,10 @@ function structuralSearch(index, options = {}) {
883
890
  // expression position — never "unused" (the deadcode
884
891
  // twin of the bodyScopedName audit skip).
885
892
  if (def.bodyScopedName) continue;
886
- index.buildCalleeIndex();
893
+ // buildCalleeIndex rebuilds the whole project. Reuse
894
+ // the eagerly built (or cache-loaded) index, including
895
+ // across every candidate in this operation.
896
+ if (!index.calleeIndex) index.buildCalleeIndex();
887
897
  // A name whose every call site is its own recursion
888
898
  // has zero callers (fix #253c — the deadcode
889
899
  // carve-out, applied here). Class-kind names are
@@ -975,6 +985,7 @@ function structuralSearch(index, options = {}) {
975
985
  }).filter(([, v]) => v !== undefined && v !== null)),
976
986
  totalMatched: total,
977
987
  shown: results.length,
988
+ filesSkipped: skippedTestFiles.size,
978
989
  ...(unused && {
979
990
  unusedScope: 'callable-symbols-only',
980
991
  unusedSafety: 'candidate-only; use deadcode before deletion',
package/core/shared.js CHANGED
@@ -50,15 +50,22 @@ function codeUnitCompare(a, b) {
50
50
  * Path-based test heuristic — matches the same patterns as `find`'s exclusion
51
51
  * logic so that `about` and `find` agree on which files are de-emphasized.
52
52
  *
53
- * Triggers when any of `test|tests|spec|__tests__|__mocks__|fixture|mock`
54
- * appears as a path segment (with word boundaries on both sides).
53
+ * Uses language-specific filename conventions plus `test|tests|__tests__|__mocks__|fixture|mock`
54
+ * as path segments (with word boundaries on both sides). `spec` is a test
55
+ * marker only for languages whose test-file conventions include it.
55
56
  *
56
57
  * Complement to `isTestFile` (filename pattern check) — together they catch
57
58
  * both `foo.test.js` (filename) AND `test/agent-benchmark.js` (directory).
58
59
  */
59
60
  function isTestPath(rp) {
60
61
  if (!rp) return false;
61
- return /(^|[/._-])(test|tests|spec|__tests__|__mocks__|fixture|mock)s?([/._-]|$)/i.test(rp);
62
+ const language = detectLanguage(rp);
63
+ const { langTraits } = require('../languages');
64
+ const specConvention = langTraits(language)?.testFileCandidates?.('sample', '')
65
+ .some(candidate => candidate.includes('.spec'));
66
+ return isTestFile(rp, language) ||
67
+ /(^|[/._-])(test|tests|__tests__|__mocks__|fixture|mock)s?([/._-]|$)/i.test(rp) ||
68
+ (!!specConvention && /(^|[/._-])specs?([/._-]|$)/i.test(rp));
62
69
  }
63
70
 
64
71
  /**
@@ -109,7 +116,9 @@ function pickBestDefinition(matches, opts = {}) {
109
116
  * Returns a new array with test patterns appended (deduplicating).
110
117
  */
111
118
  function addTestExclusions(exclude) {
112
- const testPatterns = ['test', 'spec', '__tests__', '__mocks__', 'fixture', 'mock'];
119
+ // Keep automatic test classification distinct from explicit substring
120
+ // exclusions: --exclude=spec deliberately excludes Python specs too.
121
+ const testPatterns = ['test files'];
113
122
  const existing = new Set((exclude || []).map(e => e.toLowerCase()));
114
123
  const additions = testPatterns.filter(p => !existing.has(p));
115
124
  return [...(exclude || []), ...additions];
package/core/verify.js CHANGED
@@ -808,6 +808,8 @@ function computePlanCallSites(index, name, def) {
808
808
  expression: (call.content || '').trim(),
809
809
  args: analysis.args,
810
810
  argCount: analysis.argCount,
811
+ ...(analysis.keywordArgNames && { keywordArgNames: analysis.keywordArgNames }),
812
+ ...(analysis.positionalCount != null && { positionalCount: analysis.positionalCount }),
811
813
  ...(c.calledAs && { calledAs: c.calledAs }),
812
814
  });
813
815
  }
@@ -2158,7 +2160,10 @@ function plan(index, name, options = {}) {
2158
2160
  } else if (options.defaultValue) {
2159
2161
  suggestion = `Add argument: ${options.defaultValue} (no default parameter values in ${planFileEntry?.language || 'this language'})`;
2160
2162
  } else {
2161
- suggestion = `Add argument: ${options.addParam}`;
2163
+ const keywordCall = langTraits(planLang)?.keywordArguments && site.keywordArgNames?.length > 0;
2164
+ suggestion = keywordCall
2165
+ ? `Add keyword argument: ${options.addParam}=${options.addParam} (replace the right-hand value with the intended expression; keep existing keyword arguments)`
2166
+ : `Add argument: ${options.addParam}`;
2162
2167
  }
2163
2168
  changes.push({
2164
2169
  file: site.file,
@@ -13,6 +13,7 @@ const { typeOrigin } = require('./type-evidence');
13
13
 
14
14
  const {
15
15
  traverseTree,
16
+ nodeTextWithoutComments,
16
17
  traverseTreeCached,
17
18
  nodeToLocation,
18
19
  extractJSDocstring,
@@ -989,7 +990,7 @@ function paramTypeText(param, identity) {
989
990
  const defaultValue = param.childForFieldName('default_value');
990
991
  const end = defaultValue ? defaultValue.startIndex : param.endIndex;
991
992
  if (identity.nameNode.startIndex < base || identity.nameNode.endIndex > end) return null;
992
- const text = param.text.slice(0, end - base);
993
+ const text = nodeTextWithoutComments(param).slice(0, end - base);
993
994
  const typeText = (text.slice(0, identity.nameNode.startIndex - base) +
994
995
  text.slice(identity.nameNode.endIndex - base))
995
996
  .replace(/\s+/g, ' ')
@@ -1014,10 +1015,10 @@ function structuredParams(paramsNode) {
1014
1015
  // their type text alone — the type must not double as both name and
1015
1016
  // annotation, and `void *` must not collapse into the `(void)` form.
1016
1017
  const info = {
1017
- name: identity.name || param.text.replace(/\s+/g, ' ').trim(),
1018
+ name: identity.name || nodeTextWithoutComments(param).replace(/\s+/g, ' ').trim(),
1018
1019
  };
1019
1020
  if (typeNode && identity.name) {
1020
- info.type = paramTypeText(param, identity) || typeNode.text;
1021
+ info.type = paramTypeText(param, identity) || nodeTextWithoutComments(typeNode);
1021
1022
  }
1022
1023
  if (param.type === 'optional_parameter_declaration') info.optional = true;
1023
1024
  let declaratorCursor = declarator;
@@ -1164,7 +1165,7 @@ function returnTypeOf(node) {
1164
1165
  const descriptor = (current.namedChildren || []).find(child =>
1165
1166
  child.type === 'type_descriptor') || current.namedChild(0);
1166
1167
  const type = descriptor?.childForFieldName('type') || descriptor;
1167
- return type?.text || null;
1168
+ return nodeTextWithoutComments(type) || null;
1168
1169
  }
1169
1170
  for (const child of current.namedChildren || []) {
1170
1171
  const found = findTrailing(child);
@@ -1193,7 +1194,7 @@ function returnTypeOf(node) {
1193
1194
  current = current.childForFieldName('declarator') ||
1194
1195
  (current.namedChildren || []).find(child => child.type.endsWith('_declarator'));
1195
1196
  }
1196
- return stars > 0 ? `${typeNode.text} ${'*'.repeat(stars)}` : typeNode.text;
1197
+ return stars > 0 ? `${nodeTextWithoutComments(typeNode)} ${'*'.repeat(stars)}` : nodeTextWithoutComments(typeNode);
1197
1198
  }
1198
1199
 
1199
1200
  function memberFromNode(node, className, access, lines, mode) {
@@ -1209,7 +1210,7 @@ function memberFromNode(node, className, access, lines, mode) {
1209
1210
  if (isConstructor && identity.name.startsWith('~')) modifiers.push('destructor');
1210
1211
  return {
1211
1212
  name: identity.name,
1212
- params: paramsNode ? paramsNode.text.replace(/^\(|\)$/g, '').trim() : '...',
1213
+ params: paramsNode ? nodeTextWithoutComments(paramsNode).replace(/^\(|\)$/g, '').trim() : '...',
1213
1214
  paramsStructured: structuredParams(paramsNode),
1214
1215
  returnType: isConstructor ? null :
1215
1216
  (identity.conversionType || returnTypeOf(node)),
@@ -1510,7 +1511,7 @@ function findFunctionsInTree(code, tree, mode, sourceLines = null) {
1510
1511
  : null;
1511
1512
  functions.push({
1512
1513
  name: identity.name,
1513
- params: paramsNode ? paramsNode.text.replace(/^\(|\)$/g, '').trim() : '...',
1514
+ params: paramsNode ? nodeTextWithoutComments(paramsNode).replace(/^\(|\)$/g, '').trim() : '...',
1514
1515
  paramsStructured: structuredParams(paramsNode),
1515
1516
  returnType: isConstructor ? null :
1516
1517
  (identity.conversionType || returnTypeOf(node)),
@@ -1800,7 +1801,7 @@ function findMacrosInTree(tree, lines, parser) {
1800
1801
  startLine,
1801
1802
  endLine,
1802
1803
  indent,
1803
- params: paramsNode ? paramsNode.text.replace(/^\(|\)$/g, '').trim() : undefined,
1804
+ params: paramsNode ? nodeTextWithoutComments(paramsNode).replace(/^\(|\)$/g, '').trim() : undefined,
1804
1805
  paramsStructured: paramsNode
1805
1806
  ? (paramsNode.namedChildren || [])
1806
1807
  .filter(child => child.type === 'identifier')
@@ -2,6 +2,7 @@
2
2
 
3
3
  const {
4
4
  traverseTree,
5
+ nodeTextWithoutComments,
5
6
  traverseTreeCached,
6
7
  nodeToLocation,
7
8
  extractJSDocstring,
@@ -127,7 +128,7 @@ function structuredParams(paramsNode) {
127
128
  if (nameNode) {
128
129
  recoveredParams.push({
129
130
  name: nameNode.text,
130
- ...(typeNode && { type: typeNode.text }),
131
+ ...(typeNode && { type: nodeTextWithoutComments(typeNode) }),
131
132
  rest: true,
132
133
  });
133
134
  }
@@ -138,14 +139,14 @@ function structuredParams(paramsNode) {
138
139
  const typeNode = param.childForFieldName('type');
139
140
  if (!nameNode) continue;
140
141
  const info = { name: nameNode.text };
141
- if (typeNode) info.type = typeNode.text;
142
+ if (typeNode) info.type = nodeTextWithoutComments(typeNode);
142
143
  if (modifiersOf(param).includes('this')) info.extensionReceiver = true;
143
144
  if (param.type === 'parameter_array') info.rest = true;
144
145
  const value = param.childForFieldName('value') ||
145
146
  param.namedChildren.find(child => child !== nameNode && child !== typeNode &&
146
- !['attribute_list', 'modifier'].includes(child.type));
147
+ !['attribute_list', 'modifier', 'comment'].includes(child.type));
147
148
  if (value) {
148
- info.default = value.text;
149
+ info.default = nodeTextWithoutComments(value);
149
150
  info.optional = true;
150
151
  }
151
152
  params.push(info);
@@ -208,9 +209,9 @@ function memberFromNode(node, className, lines) {
208
209
  const paramsStructured = structuredParams(paramsNode);
209
210
  return {
210
211
  name,
211
- params: paramsNode ? paramsNode.text.replace(/^\(|\)$/g, '').trim() : '...',
212
+ params: paramsNode ? nodeTextWithoutComments(paramsNode).replace(/^\(|\)$/g, '').trim() : '...',
212
213
  paramsStructured,
213
- returnType: isConstructor ? null : returnNode?.text || null,
214
+ returnType: isConstructor ? null : nodeTextWithoutComments(returnNode).trim() || null,
214
215
  startLine,
215
216
  endLine,
216
217
  indent,
@@ -263,9 +264,9 @@ function indexerMember(node, className, lines) {
263
264
  const { startLine, endLine, indent } = nodeToLocation(node, lines);
264
265
  return {
265
266
  name: 'this[]',
266
- params: paramsNode ? paramsNode.text.replace(/^\[|\]$/g, '').trim() : '...',
267
+ params: paramsNode ? nodeTextWithoutComments(paramsNode).replace(/^\[|\]$/g, '').trim() : '...',
267
268
  paramsStructured: structuredParams(paramsNode),
268
- returnType: typeNode?.text || null,
269
+ returnType: nodeTextWithoutComments(typeNode).trim() || null,
269
270
  startLine,
270
271
  endLine,
271
272
  indent,
@@ -495,9 +496,9 @@ function findFunctions(code, parser) {
495
496
  const modifiers = modifiersOf(node);
496
497
  functions.push({
497
498
  name: nameNode.text,
498
- params: paramsNode ? paramsNode.text.replace(/^\(|\)$/g, '').trim() : '...',
499
+ params: paramsNode ? nodeTextWithoutComments(paramsNode).replace(/^\(|\)$/g, '').trim() : '...',
499
500
  paramsStructured: structuredParams(paramsNode),
500
- returnType: returnNode?.text || null,
501
+ returnType: nodeTextWithoutComments(returnNode).trim() || null,
501
502
  startLine,
502
503
  endLine,
503
504
  indent,
package/languages/go.js CHANGED
@@ -10,6 +10,7 @@ const { ReceiverTypeMap, typeOrigin } = require('./type-evidence');
10
10
 
11
11
  const {
12
12
  traverseTree,
13
+ nodeTextWithoutComments,
13
14
  traverseTreeCached,
14
15
  nodeToLocation,
15
16
  parseStructuredParams,
@@ -29,7 +30,7 @@ function parseTree(parser, code) {
29
30
  function extractReturnType(node) {
30
31
  const resultNode = node.childForFieldName('result');
31
32
  if (resultNode) {
32
- return resultNode.text.trim() || null;
33
+ return nodeTextWithoutComments(resultNode).trim() || null;
33
34
  }
34
35
  return null;
35
36
  }
@@ -39,7 +40,7 @@ function extractReturnedFunctionResult(node) {
39
40
  const resultNode = node.childForFieldName('result');
40
41
  if (resultNode?.type !== 'function_type') return null;
41
42
  const innerResult = resultNode.childForFieldName('result');
42
- return innerResult?.text.trim() || null;
43
+ return nodeTextWithoutComments(innerResult).trim() || null;
43
44
  }
44
45
 
45
46
  /**
@@ -51,7 +52,7 @@ function extractGoParams(paramsNode) {
51
52
  // unknown signatures in JSON output (fix #238; the shared
52
53
  // utils.extractParams already had this fix).
53
54
  if (!paramsNode) return '...';
54
- const text = paramsNode.text;
55
+ const text = nodeTextWithoutComments(paramsNode);
55
56
  return text.replace(/^\(|\)$/g, '').trim();
56
57
  }
57
58
 
@@ -115,7 +116,7 @@ function _processFunction(node, functions, processedRanges, lines) {
115
116
  indent,
116
117
  modifiers: isExported ? ['export'] : [],
117
118
  isFunctionVariable: true,
118
- ...(resultNode?.text.trim() && { returnType: resultNode.text.trim() }),
119
+ ...(resultNode && { returnType: nodeTextWithoutComments(resultNode).trim() || null }),
119
120
  });
120
121
  }
121
122
  return true;
@@ -491,11 +492,11 @@ function extractInterfaceMembers(interfaceNode, codeOrLines) {
491
492
  } else if (sub.type === 'parameter_list') {
492
493
  hasParams = true;
493
494
  if (!paramsText) {
494
- paramsText = sub.text.slice(1, -1); // strip parens
495
+ paramsText = nodeTextWithoutComments(sub).slice(1, -1); // strip parens
495
496
  paramsNode = sub;
496
497
  } else {
497
498
  // Second parameter_list is the return type tuple
498
- returnType = sub.text;
499
+ returnType = nodeTextWithoutComments(sub);
499
500
  }
500
501
  }
501
502
  }
@@ -514,7 +515,7 @@ function extractInterfaceMembers(interfaceNode, codeOrLines) {
514
515
  for (let j = 0; j < child.namedChildCount; j++) {
515
516
  const sub = child.namedChild(j);
516
517
  if (returnTypeNodes.has(sub.type) && sub.text !== nameText) {
517
- returnType = sub.text;
518
+ returnType = nodeTextWithoutComments(sub);
518
519
  }
519
520
  }
520
521
  }
@@ -144,6 +144,7 @@ const LANGUAGES = {
144
144
  traits: {
145
145
  ...STRUCTURAL_TRAITS,
146
146
  selfParam: ['this'],
147
+ storedPromises: true,
147
148
  testFileCandidates: (base, ext) => [`${base}.test${ext}`, `${base}.spec${ext}`, `${base}.test.ts`, `${base}.test.js`, `${base}.spec.ts`, `${base}.spec.js`],
148
149
  testDirs: ['__tests__'],
149
150
  },
@@ -157,6 +158,7 @@ const LANGUAGES = {
157
158
  traits: {
158
159
  ...STRUCTURAL_TRAITS,
159
160
  selfParam: ['this'],
161
+ storedPromises: true,
160
162
  testFileCandidates: (base, ext) => [`${base}.test${ext}`, `${base}.spec${ext}`, `${base}.test.ts`, `${base}.test.js`, `${base}.spec.ts`, `${base}.spec.js`],
161
163
  testDirs: ['__tests__'],
162
164
  },
@@ -170,6 +172,7 @@ const LANGUAGES = {
170
172
  traits: {
171
173
  ...STRUCTURAL_TRAITS,
172
174
  selfParam: ['this'],
175
+ storedPromises: true,
173
176
  testFileCandidates: (base, ext) => [`${base}.test${ext}`, `${base}.spec${ext}`, `${base}.test.ts`, `${base}.test.js`, `${base}.spec.ts`, `${base}.spec.js`],
174
177
  testDirs: ['__tests__'],
175
178
  },
@@ -324,6 +327,7 @@ const LANGUAGES = {
324
327
  traits: {
325
328
  ...STRUCTURAL_TRAITS,
326
329
  selfParam: ['this'],
330
+ storedPromises: true,
327
331
  testFileCandidates: (base, ext) => [`${base}.test${ext}`, `${base}.spec${ext}`],
328
332
  },
329
333
  }
package/languages/java.js CHANGED
@@ -10,6 +10,7 @@ const { ReceiverTypeMap, typeOrigin } = require('./type-evidence');
10
10
 
11
11
  const {
12
12
  traverseTree,
13
+ nodeTextWithoutComments,
13
14
  traverseTreeCached,
14
15
  nodeToLocation,
15
16
  parseStructuredParams,
@@ -32,7 +33,7 @@ function extractJavaParams(paramsNode) {
32
33
  // unknown signatures in JSON output (fix #241; go/rust got this in #238,
33
34
  // the shared utils.extractParams already had it).
34
35
  if (!paramsNode) return '...';
35
- const text = paramsNode.text;
36
+ const text = nodeTextWithoutComments(paramsNode);
36
37
  let params = text.replace(/^\(|\)$/g, '').trim();
37
38
  return params;
38
39
  }
@@ -201,7 +202,7 @@ function stripJavaString(text) {
201
202
  function extractReturnType(node) {
202
203
  const typeNode = node.childForFieldName('type');
203
204
  if (typeNode) {
204
- return typeNode.text;
205
+ return nodeTextWithoutComments(typeNode);
205
206
  }
206
207
  return null;
207
208
  }
@@ -10,6 +10,7 @@ const { ReceiverTypeMap, typeOrigin } = require('./type-evidence');
10
10
 
11
11
  const {
12
12
  traverseTree,
13
+ nodeTextWithoutComments,
13
14
  traverseTreeCached,
14
15
  nodeToLocation,
15
16
  extractParams,
@@ -34,7 +35,7 @@ function parseTree(parser, code) {
34
35
  function extractReturnType(node) {
35
36
  const returnTypeNode = node.childForFieldName('return_type');
36
37
  if (returnTypeNode) {
37
- let text = returnTypeNode.text.trim();
38
+ let text = nodeTextWithoutComments(returnTypeNode).trim();
38
39
  if (text.startsWith(':')) {
39
40
  text = text.slice(1).trim();
40
41
  }
@@ -10,6 +10,7 @@ const { ReceiverTypeMap, typeOrigin } = require('./type-evidence');
10
10
 
11
11
  const {
12
12
  traverseTree,
13
+ nodeTextWithoutComments,
13
14
  traverseTreeCached,
14
15
  nodeToLocation,
15
16
  parseStructuredParams,
@@ -32,7 +33,7 @@ function parseTree(parser, code) {
32
33
  function extractReturnType(node) {
33
34
  const returnTypeNode = node.childForFieldName('return_type');
34
35
  if (returnTypeNode) {
35
- let text = returnTypeNode.text.trim();
36
+ let text = nodeTextWithoutComments(returnTypeNode).trim();
36
37
  if (text.startsWith('->')) {
37
38
  text = text.slice(2).trim();
38
39
  }
@@ -129,7 +130,7 @@ function extractPythonParams(paramsNode) {
129
130
  // unknown signatures in JSON output (fix #241; go/rust got this in #238,
130
131
  // the shared utils.extractParams already had it).
131
132
  if (!paramsNode) return '...';
132
- const text = paramsNode.text;
133
+ const text = nodeTextWithoutComments(paramsNode);
133
134
  let params = text.replace(/^\(|\)$/g, '').trim();
134
135
  return params;
135
136
  }
@@ -2804,7 +2805,14 @@ function findCallsInCode(code, parser) {
2804
2805
  const argsNode = node.childForFieldName('arguments');
2805
2806
  if (argsNode) {
2806
2807
  for (let i = 0; i < argsNode.namedChildCount; i++) {
2807
- const arg = argsNode.namedChild(i);
2808
+ const rawArg = argsNode.namedChild(i);
2809
+ const arg = rawArg.type === 'keyword_argument'
2810
+ ? rawArg.childForFieldName('value') : rawArg;
2811
+ if (!arg) continue;
2812
+ // Bare keyword values already belong to the reference
2813
+ // inventory/rename path; only extend the member-value
2814
+ // callback model to match its positional counterpart.
2815
+ if (rawArg.type === 'keyword_argument' && arg.type !== 'attribute') continue;
2808
2816
  if (arg.type === 'identifier' && !PYTHON_SKIP.has(arg.text) && !nonCallableNames.has(arg.text)) {
2809
2817
  calls.push({
2810
2818
  name: arg.text,
package/languages/rust.js CHANGED
@@ -10,6 +10,7 @@ const { ReceiverTypeMap, typeOrigin } = require('./type-evidence');
10
10
 
11
11
  const {
12
12
  traverseTree,
13
+ nodeTextWithoutComments,
13
14
  traverseTreeCached,
14
15
  nodeToLocation,
15
16
  parseStructuredParams,
@@ -128,7 +129,7 @@ function declarationTrees(code, parser) {
128
129
  function extractReturnType(node) {
129
130
  const returnTypeNode = node.childForFieldName('return_type');
130
131
  if (returnTypeNode) {
131
- let text = returnTypeNode.text.trim();
132
+ let text = nodeTextWithoutComments(returnTypeNode).trim();
132
133
  if (text.startsWith('->')) {
133
134
  text = text.slice(2).trim();
134
135
  }
@@ -198,7 +199,7 @@ function extractRustParams(paramsNode) {
198
199
  // unknown signatures in JSON output (fix #238; the shared
199
200
  // utils.extractParams already had this fix).
200
201
  if (!paramsNode) return '...';
201
- const text = paramsNode.text;
202
+ const text = nodeTextWithoutComments(paramsNode);
202
203
  return text.replace(/^\(|\)$/g, '').trim();
203
204
  }
204
205