gitnexus 1.6.13-rc.56 → 1.6.13-rc.58

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.
Files changed (39) hide show
  1. package/dist/_shared/scope-resolution/types.d.ts +2 -0
  2. package/dist/_shared/scope-resolution/types.d.ts.map +1 -1
  3. package/dist/cli/i18n/en.d.ts +1 -1
  4. package/dist/cli/i18n/en.js +1 -1
  5. package/dist/cli/i18n/resources.d.ts +1 -1
  6. package/dist/cli/i18n/zh-CN.js +1 -1
  7. package/dist/cli/index.js +1 -1
  8. package/dist/cli/tool.js +2 -0
  9. package/dist/core/group/extractors/http-patterns/python.js +23 -4
  10. package/dist/core/ingestion/call-processor.d.ts +5 -0
  11. package/dist/core/ingestion/call-processor.js +22 -8
  12. package/dist/core/ingestion/language-provider.d.ts +28 -1
  13. package/dist/core/ingestion/languages/go/import-binding.d.ts +3 -0
  14. package/dist/core/ingestion/languages/go/import-binding.js +16 -0
  15. package/dist/core/ingestion/languages/go/import-decomposer.js +2 -1
  16. package/dist/core/ingestion/languages/go/import-package-name.d.ts +2 -0
  17. package/dist/core/ingestion/languages/go/import-package-name.js +7 -0
  18. package/dist/core/ingestion/languages/go/interpret.js +7 -1
  19. package/dist/core/ingestion/languages/go/route-bindings.d.ts +25 -0
  20. package/dist/core/ingestion/languages/go/route-bindings.js +194 -0
  21. package/dist/core/ingestion/languages/go/route-handler.d.ts +19 -0
  22. package/dist/core/ingestion/languages/go/route-handler.js +146 -0
  23. package/dist/core/ingestion/languages/go/scope-resolver.js +2 -0
  24. package/dist/core/ingestion/languages/go.js +5 -0
  25. package/dist/core/ingestion/pipeline-phases/parse-impl.js +53 -15
  26. package/dist/core/ingestion/route-extractors/fastapi-router-bindings.d.ts +19 -15
  27. package/dist/core/ingestion/route-extractors/fastapi-router-bindings.js +43 -21
  28. package/dist/core/ingestion/route-extractors/fastapi-router-prefixes.d.ts +21 -0
  29. package/dist/core/ingestion/route-extractors/fastapi-router-prefixes.js +153 -0
  30. package/dist/core/ingestion/route-extractors/go-gin-echo.d.ts +29 -0
  31. package/dist/core/ingestion/route-extractors/go-gin-echo.js +374 -0
  32. package/dist/core/ingestion/scope-resolution/contract/scope-resolver.d.ts +5 -0
  33. package/dist/core/ingestion/scope-resolution/pipeline/run.js +15 -0
  34. package/dist/core/ingestion/workers/parse-worker.d.ts +20 -0
  35. package/dist/mcp/local/local-backend.js +50 -0
  36. package/dist/mcp/tools.js +1 -0
  37. package/dist/storage/index-lock.js +9 -1
  38. package/dist/storage/parse-cache.js +8 -1
  39. package/package.json +1 -1
@@ -279,6 +279,8 @@ type ParsedImportSyntax =
279
279
  */
280
280
  | {
281
281
  readonly kind: 'namespace';
282
+ /** The source omitted a local alias; the imported module declares its binding name. */
283
+ readonly implicitLocalName?: boolean;
282
284
  /** Scope-visible handle (e.g. `np` in `import numpy as np`; `numpy` when unaliased). */
283
285
  readonly localName: string;
284
286
  /** Module being aliased (e.g. `numpy` in `import numpy as np`). */
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/scope-resolution/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/scope-resolution/types.ts"],"names":[],"mappings":"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"}
@@ -287,7 +287,7 @@ export declare const en: {
287
287
  readonly 'help.option.impact.direction': 'upstream (dependants) or downstream (dependencies)';
288
288
  readonly 'help.option.impact.depth': 'Max relationship depth (default: 3)';
289
289
  readonly 'help.option.impact.includeTests': 'Include test files in results';
290
- readonly 'help.option.impact.limit': 'Max symbols per depth level and affected processes/modules to return (default: 100)';
290
+ readonly 'help.option.impact.limit': 'Max symbols per depth level (default: 100); explicit --limit also caps affected processes/modules/routes';
291
291
  readonly 'help.option.impact.offset': 'Skip N symbols per depth level for pagination';
292
292
  readonly 'help.option.impact.summaryOnly': 'Return counts and risk only, omit symbol list';
293
293
  readonly 'help.option.trace.fromUid': 'Source symbol UID (zero-ambiguity lookup)';
@@ -289,7 +289,7 @@ export const en = {
289
289
  'help.option.impact.direction': 'upstream (dependants) or downstream (dependencies)',
290
290
  'help.option.impact.depth': 'Max relationship depth (default: 3)',
291
291
  'help.option.impact.includeTests': 'Include test files in results',
292
- 'help.option.impact.limit': 'Max symbols per depth level and affected processes/modules to return (default: 100)',
292
+ 'help.option.impact.limit': 'Max symbols per depth level (default: 100); explicit --limit also caps affected processes/modules/routes',
293
293
  'help.option.impact.offset': 'Skip N symbols per depth level for pagination',
294
294
  'help.option.impact.summaryOnly': 'Return counts and risk only, omit symbol list',
295
295
  'help.option.trace.fromUid': 'Source symbol UID (zero-ambiguity lookup)',
@@ -288,7 +288,7 @@ export declare const cliResources: {
288
288
  readonly 'help.option.impact.direction': 'upstream (dependants) or downstream (dependencies)';
289
289
  readonly 'help.option.impact.depth': 'Max relationship depth (default: 3)';
290
290
  readonly 'help.option.impact.includeTests': 'Include test files in results';
291
- readonly 'help.option.impact.limit': 'Max symbols per depth level and affected processes/modules to return (default: 100)';
291
+ readonly 'help.option.impact.limit': 'Max symbols per depth level (default: 100); explicit --limit also caps affected processes/modules/routes';
292
292
  readonly 'help.option.impact.offset': 'Skip N symbols per depth level for pagination';
293
293
  readonly 'help.option.impact.summaryOnly': 'Return counts and risk only, omit symbol list';
294
294
  readonly 'help.option.trace.fromUid': 'Source symbol UID (zero-ambiguity lookup)';
@@ -287,7 +287,7 @@ export const zhCN = {
287
287
  'help.option.impact.direction': 'upstream(依赖它的项)或 downstream(它依赖的项)',
288
288
  'help.option.impact.depth': '最大关系遍历深度(默认:3)',
289
289
  'help.option.impact.includeTests': '在结果中包含测试文件',
290
- 'help.option.impact.limit': '每层深度最大符号数及最多返回的受影响流程/模块数(默认:100)',
290
+ 'help.option.impact.limit': '每层深度最大符号数(默认:100);显式指定 --limit 时,也限制受影响流程/模块/路由数',
291
291
  'help.option.impact.offset': '每层深度跳过 N 个符号(分页用)',
292
292
  'help.option.impact.summaryOnly': '仅返回计数和风险等级,省略符号列表',
293
293
  'help.option.trace.fromUid': '源符号 UID(零歧义查找)',
package/dist/cli/index.js CHANGED
@@ -315,7 +315,7 @@ program
315
315
  .option('--kind <kind>', 'Kind filter to disambiguate common names (e.g. Function, Class, Method)')
316
316
  .option('--depth <n>', 'Max relationship depth (default: 3)')
317
317
  .option('--include-tests', 'Include test files in results')
318
- .option('-l, --limit <n>', 'Max symbols per depth level and affected processes/modules to return (default: 100)')
318
+ .option('-l, --limit <n>', 'Max symbols per depth level (default: 100); explicit --limit also caps affected processes/modules/routes')
319
319
  .option('--offset <n>', 'Skip N symbols per depth level for pagination')
320
320
  .option('--summary-only', 'Return counts and risk only, omit symbol list')
321
321
  .action(createLbugLazyAction(() => import('./tool.js'), 'impactCommand'));
package/dist/cli/tool.js CHANGED
@@ -237,6 +237,8 @@ export async function impactCommand(target, options) {
237
237
  result.affected_processes = result.affected_processes.slice(0, parsedLimit);
238
238
  if (Array.isArray(result.affected_modules))
239
239
  result.affected_modules = result.affected_modules.slice(0, parsedLimit);
240
+ if (Array.isArray(result.affected_routes))
241
+ result.affected_routes = result.affected_routes.slice(0, parsedLimit);
240
242
  }
241
243
  output(result);
242
244
  }
@@ -1,6 +1,8 @@
1
1
  import Python from 'tree-sitter-python';
2
2
  import { compilePatterns, runCompiledPatterns, unquoteLiteral, } from '../tree-sitter-scanner.js';
3
3
  import { normalizeExtractedRoutePath } from '../../../ingestion/route-extractors/route-path.js';
4
+ import { extractFastAPIRouterBindings, } from '../../../ingestion/route-extractors/fastapi-router-bindings.js';
5
+ import { mergeMountPrefixes, resolveFastAPIRouterPrefixes, } from '../../../ingestion/route-extractors/fastapi-router-prefixes.js';
4
6
  import { extractPythonModuleConstants, parseConstOperands, resolveOperands, } from '../../../ingestion/route-extractors/python-const-resolver.js';
5
7
  /**
6
8
  * Python HTTP plugin. Handles:
@@ -883,6 +885,10 @@ const NONLITERAL_ROUTE_DECORATOR_RE = /@\s*(?:app|router)\s*\.\s*(?:get|post|put
883
885
  function buildPythonRepoContext(files, parser, readFile, parseSource) {
884
886
  const prefixesByLongKey = new Map();
885
887
  const prefixesByShortKey = new Map();
888
+ const routerIncludes = [];
889
+ const routerImports = [];
890
+ const routerModuleAliases = [];
891
+ const routerConstructorPrefixes = [];
886
892
  // Single read pass (#2393): slurp every `.py` file's content ONCE. This used to
887
893
  // be two passes — the include_router pre-pass below and the #2391 constant cost
888
894
  // gate each re-read every `.py` file. The composed-route cost gate is computed
@@ -900,6 +906,15 @@ function buildPythonRepoContext(files, parser, readFile, parseSource) {
900
906
  if (!hasComposedRoute && NONLITERAL_ROUTE_DECORATOR_RE.test(src))
901
907
  hasComposedRoute = true;
902
908
  }
909
+ for (const [rel, src] of pyContents) {
910
+ if (src.includes('include_router')) {
911
+ extractFastAPIRouterBindings(rel, src, routerIncludes, routerImports, routerModuleAliases, routerConstructorPrefixes);
912
+ }
913
+ }
914
+ // Resolve against every repo path, empty files included, so module
915
+ // ambiguity matches ingestion (which passes all scanned paths).
916
+ const { prefixesByFile, resolvedIncludes } = resolveFastAPIRouterPrefixes(files, routerIncludes, routerImports, routerModuleAliases, routerConstructorPrefixes);
917
+ const resolvedIncludeKeys = new Set([...resolvedIncludes].map((inc) => JSON.stringify([inc.filePath, inc.routerExpr, inc.prefix])));
903
918
  // Single PARSE pass (#2391): parse each `.py` at most once and feed BOTH the
904
919
  // include_router prefix pre-pass and the composed-constant map below. This used
905
920
  // to be two loops, so an include_router file in a composed repo was parsed
@@ -968,6 +983,8 @@ function buildPythonRepoContext(files, parser, readFile, parseSource) {
968
983
  if (prefix === null)
969
984
  continue;
970
985
  const moduleShort = modNode.text;
986
+ if (resolvedIncludeKeys.has(JSON.stringify([rel, `${moduleShort}.router`, prefix])))
987
+ continue;
971
988
  const aliasLong = localNameToModuleAlias.get(moduleShort);
972
989
  const sameFileImport = localNameToModule.get(moduleShort);
973
990
  const longKey = aliasLong ?? sameFileImport?.moduleLong;
@@ -993,6 +1010,8 @@ function buildPythonRepoContext(files, parser, readFile, parseSource) {
993
1010
  const prefix = unquoteLiteral(prefixNode.text);
994
1011
  if (prefix === null)
995
1012
  continue;
1013
+ if (resolvedIncludeKeys.has(JSON.stringify([rel, nameNode.text, prefix])))
1014
+ continue;
996
1015
  if (localImp.moduleLong) {
997
1016
  recordPrefix(prefixesByLongKey, localImp.moduleLong, prefix);
998
1017
  }
@@ -1013,6 +1032,7 @@ function buildPythonRepoContext(files, parser, readFile, parseSource) {
1013
1032
  }
1014
1033
  }
1015
1034
  return {
1035
+ prefixesByFile,
1016
1036
  prefixesByLongKey,
1017
1037
  prefixesByShortKey,
1018
1038
  constantsByFile,
@@ -1145,14 +1165,13 @@ export const PYTHON_HTTP_PLUGIN = {
1145
1165
  // by the literal and the #2391 non-literal (resolved) router loops so both
1146
1166
  // stack prefixes identically.
1147
1167
  const emitRouterProvider = (httpMethod, rawPath, line) => {
1148
- // Long key first (precise, package-aware), short key as fallback.
1149
- // Mirrors the ingestion-side resolution in parse-impl.ts so the
1150
- // graph nodes and group contracts agree on which prefix applies.
1168
+ // Exact file matches plus the legacy long/short fallback. This mirrors
1169
+ // ingestion so graph Route nodes and contracts agree on mounted paths.
1151
1170
  const longKey = fileRel ? fileLongKey(fileRel) : '';
1152
1171
  const longPrefixes = longKey ? ctx?.prefixesByLongKey.get(longKey) : undefined;
1153
1172
  const shortKey = fileRel ? fileShortKey(fileRel) : '';
1154
1173
  const shortPrefixes = longPrefixes || !shortKey ? undefined : ctx?.prefixesByShortKey.get(shortKey);
1155
- const prefixSet = longPrefixes ?? shortPrefixes;
1174
+ const prefixSet = mergeMountPrefixes(fileRel ? ctx?.prefixesByFile.get(fileRel.replace(/\\/g, '/')) : undefined, longPrefixes ?? shortPrefixes);
1156
1175
  // Stack the same-file APIRouter(prefix=...) under any cross-file
1157
1176
  // include_router prefix.
1158
1177
  const localPath = constructorPrefix ? joinPrefix(constructorPrefix, rawPath) : rawPath;
@@ -19,6 +19,7 @@ import type { SemanticModel, SymbolTableReader } from './model/index.js';
19
19
  import type { ParsedImport, SymbolDefinition } from '../../_shared/index.js';
20
20
  import type { ExtractedRoute, ExtractedFetchCall } from './workers/parse-worker.js';
21
21
  import type { ExtractedDecoratorRoute } from './workers/parse-worker.js';
22
+ import type { LanguageProvider } from './language-provider.js';
22
23
  /** Per-file resolved type bindings for exported symbols.
23
24
  * Consumed by the cross-file re-resolution / enrichment pass. */
24
25
  export type ExportedTypeMap = Map<string, Map<string, string>>;
@@ -30,6 +31,10 @@ interface RouteResolutionFile {
30
31
  interface RouteHandlerResolutionContext {
31
32
  readonly files: readonly RouteResolutionFile[];
32
33
  readonly resolveImportTarget: (parsedImport: ParsedImport, fromFile: string) => string | null;
34
+ /** Every file an import resolves to (an import may name a whole directory of files). */
35
+ readonly resolveImportTargets?: (parsedImport: ParsedImport, fromFile: string) => readonly string[];
36
+ /** The route file's `LanguageProvider.resolveRouteHandler`, when it defines one. */
37
+ readonly providerRouteHandler?: (filePath: string) => LanguageProvider['resolveRouteHandler'];
33
38
  readonly isExportedSymbol: (nodeId: string) => boolean;
34
39
  /** 0-based graph-node startLine for same-name tRPC handler disambiguation. */
35
40
  readonly nodeStartLine?: (nodeId: string) => number | undefined;
@@ -441,16 +441,30 @@ export function resolveRouteHandlerSymbols(model, extractedRoutes, decoratorRout
441
441
  }
442
442
  dataHandlersByIdentity.set(key, state);
443
443
  }
444
+ // A language that resolves its own handlers sees only this seam: the
445
+ // model, and the workspace files an import local name resolves to.
446
+ const importTargetsFor = (fromFile, localName) => {
447
+ const parsedImport = uniqueImport(fromFile, localName);
448
+ if (parsedImport === undefined || routeContext?.resolveImportTargets === undefined)
449
+ return [];
450
+ return routeContext.resolveImportTargets(parsedImport, fromFile);
451
+ };
452
+ const providerContext = { model, importTargetsFor };
453
+ const decoratorHandlerId = (dr) => {
454
+ if (dr.source === DATA_ROUTE_TABLE_SOURCE)
455
+ return dataHandlerByRoute.get(dr);
456
+ const providerHandler = routeContext?.providerRouteHandler?.(dr.filePath);
457
+ if (providerHandler)
458
+ return providerHandler(dr, providerContext);
459
+ return dr.handlerName ? uniqueSymbolId(dr.filePath, dr.handlerName) : undefined;
460
+ };
444
461
  // Decorator routes (Spring / FastAPI / generic) — the decorated handler in
445
- // the route's own file. Data tables additionally suppress an identity when
446
- // duplicate entries resolve to different handlers: recording either one
447
- // would invent a single-winner dispatch that the loop does not prove.
462
+ // the route's own file, unless the route's language resolves its own
463
+ // handlers. Data tables additionally suppress an identity when duplicate
464
+ // entries resolve to different handlers: recording either one would invent a
465
+ // single-winner dispatch that the loop does not prove.
448
466
  for (const dr of decoratorRoutes) {
449
- const handlerId = dr.source === DATA_ROUTE_TABLE_SOURCE
450
- ? dataHandlerByRoute.get(dr)
451
- : dr.handlerName
452
- ? uniqueSymbolId(dr.filePath, dr.handlerName)
453
- : undefined;
467
+ const handlerId = decoratorHandlerId(dr);
454
468
  // An unproven data-table entry never becomes a Route node, so it must not
455
469
  // reserve the identity and suppress a later, valid framework declaration.
456
470
  if (dr.source === DATA_ROUTE_TABLE_SOURCE && handlerId === undefined)
@@ -27,6 +27,18 @@ import type { SharedSpringType } from './route-extractors/spring-shared.js';
27
27
  import type { ModuleConstants, Operand, RepoConstants } from './route-extractors/constant-resolver.js';
28
28
  import type Parser from 'tree-sitter';
29
29
  import type { ExtractedDecoratorRoute } from './workers/parse-worker.js';
30
+ import type { SemanticModel } from './model/semantic-model.js';
31
+ /** What a provider's {@link LanguageProviderConfig.resolveRouteHandler} can see. */
32
+ export interface RouteHandlerResolutionHookContext {
33
+ /** The model after every file has been parsed; scope resolution has not run. */
34
+ readonly model: SemanticModel;
35
+ /**
36
+ * Every workspace file the import bound to `localName` in `fromFile` resolves
37
+ * to. `[]` when the name is not a unique import binding or the import does
38
+ * not resolve inside the workspace (stdlib, third-party).
39
+ */
40
+ readonly importTargetsFor: (fromFile: string, localName: string) => readonly string[];
41
+ }
30
42
  import type { SpringNonHttpHandlerFact } from './frameworks/spring/non-http-handlers.js';
31
43
  import type { SpringMessageProducerFact } from './frameworks/spring/message-producers.js';
32
44
  /** One file's captured Spring async messaging facts, in both directions. */
@@ -429,7 +441,8 @@ interface LanguageProviderConfig {
429
441
  * Decorators are the common case and the reason for the name, but not the only
430
442
  * shape: JS/TS uses this hook for hand-rolled dispatch guards
431
443
  * (`route-extractors/dispatch-guard.ts`), where a raw `node:http` server
432
- * declares a route by comparing the request path to a literal. Anything that
444
+ * declares a route by comparing the request path to a literal, and Go uses it
445
+ * for gin/echo verb calls (`route-extractors/go-gin-echo.ts`). Anything that
433
446
  * yields a `(path, verb, handler)` triple from one file's AST belongs here —
434
447
  * set `ExtractedDecoratorRoute.source` when the provenance is not a decorator,
435
448
  * so the `HANDLES_ROUTE` edge does not claim one.
@@ -458,6 +471,20 @@ interface LanguageProviderConfig {
458
471
  * Default: undefined (no handler name from generic decorator captures).
459
472
  */
460
473
  readonly decoratorRouteHandlerName?: (decoratorNode: SyntaxNode) => string | undefined;
474
+ /**
475
+ * Resolve a route's `handlerName` to a symbol node id, for routes this
476
+ * language extracted. When defined, the routes phase asks this hook instead of
477
+ * looking the name up in the route's own file — for languages whose handlers
478
+ * routinely live in other files of the same package or module, and whose
479
+ * visibility rules only the language knows.
480
+ *
481
+ * Return a node id only when exactly one definition matches; `undefined`
482
+ * leaves the route without `handlerSymbolId` (fail-open, never a wrong
483
+ * handler).
484
+ *
485
+ * Default: undefined (same-file lookup by name).
486
+ */
487
+ readonly resolveRouteHandler?: (route: ExtractedDecoratorRoute, context: RouteHandlerResolutionHookContext) => string | undefined;
461
488
  /**
462
489
  * Collect a project-wide, language-agnostic view of route-defining
463
490
  * class/interface declarations (`SharedSpringType`) from a parsed file.
@@ -0,0 +1,3 @@
1
+ import type { ParsedImport } from '../../../../_shared/index.js';
2
+ /** An omitted alias binds the imported package clause, never its path spelling. */
3
+ export declare function resolveGoImportBinding(parsedImport: ParsedImport, resolveTargetFiles: () => readonly string[], sourceTextFor: (filePath: string) => string | undefined): ParsedImport;
@@ -0,0 +1,16 @@
1
+ import { inferGoPackageName } from './package-clause.js';
2
+ /** An omitted alias binds the imported package clause, never its path spelling. */
3
+ export function resolveGoImportBinding(parsedImport, resolveTargetFiles, sourceTextFor) {
4
+ if (parsedImport.kind !== 'namespace' || !parsedImport.implicitLocalName)
5
+ return parsedImport;
6
+ const targetFiles = resolveTargetFiles();
7
+ if (targetFiles.length === 0)
8
+ return parsedImport;
9
+ const names = new Set(targetFiles.map((file) => inferGoPackageName(sourceTextFor(file) ?? '')));
10
+ const name = names.size === 1 ? names.values().next().value : undefined;
11
+ if (!name) {
12
+ // Keep the dependency without inventing a scope-visible package qualifier.
13
+ return { kind: 'side-effect', targetRaw: parsedImport.targetRaw };
14
+ }
15
+ return { ...parsedImport, localName: name, importedName: name };
16
+ }
@@ -1,3 +1,4 @@
1
+ import { goImportPackageName } from './import-package-name.js';
1
2
  import { syntheticCapture } from '../../utils/ast-helpers.js';
2
3
  export function splitGoImportStatement(node) {
3
4
  if (node.type === 'import_declaration') {
@@ -24,7 +25,7 @@ export function splitGoImportStatement(node) {
24
25
  const rawPath = pathNode.text.replace(/^"|"$/g, '').replace(/^`|`$/g, '');
25
26
  const nameNode = node.childForFieldName('name');
26
27
  const alias = nameNode?.text;
27
- const leaf = rawPath.split('/').filter(Boolean).pop() ?? rawPath;
28
+ const leaf = goImportPackageName(rawPath);
28
29
  const kind = alias === '.' ? 'dot' : alias === '_' ? 'blank' : alias === undefined ? 'namespace' : 'alias';
29
30
  // Blank imports (import _ "pkg") are dropped in V1 — they represent
30
31
  // side-effect registrations (e.g. database drivers), but emitting
@@ -0,0 +1,2 @@
1
+ /** Conventional package qualifier; semantic-version suffixes name modules, not packages. */
2
+ export declare function goImportPackageName(importPath: string): string;
@@ -0,0 +1,7 @@
1
+ /** Conventional package qualifier; semantic-version suffixes name modules, not packages. */
2
+ export function goImportPackageName(importPath) {
3
+ const segments = importPath.split('/').filter(Boolean);
4
+ const leaf = segments.at(-1) ?? importPath;
5
+ const name = /^v\d+$/.test(leaf) && segments.length > 1 ? segments[segments.length - 2] : leaf;
6
+ return name.replace(/\.v\d+$/, '');
7
+ }
@@ -15,7 +15,13 @@ export function interpretGoImport(captures) {
15
15
  if (kind === 'namespace') {
16
16
  if (name === undefined)
17
17
  return null;
18
- return { kind: 'namespace', localName: name, importedName: name, targetRaw: source };
18
+ return {
19
+ kind: 'namespace',
20
+ localName: name,
21
+ importedName: name,
22
+ targetRaw: source,
23
+ implicitLocalName: true,
24
+ };
19
25
  }
20
26
  return null;
21
27
  }
@@ -0,0 +1,25 @@
1
+ import type { SyntaxNode } from 'tree-sitter';
2
+ /** A declaration, shared by every use and assignment that resolves to it. */
3
+ export interface GoRouteBinding {
4
+ readonly visibleFrom: number;
5
+ readonly ownerFunction: SyntaxNode;
6
+ readonly type: SyntaxNode | null;
7
+ readonly isInputParameter: boolean;
8
+ readonly values: (SyntaxNode | null)[];
9
+ capturedWrite: boolean;
10
+ }
11
+ /**
12
+ * Route-local binding evidence. Declaration identity and visibility follow Go
13
+ * blocks; value inference deliberately remains conservative across all writes.
14
+ * Nested functions are visited so writes to captured locals cannot leave stale
15
+ * proofs. Their own declarations remain separate from the captured bindings.
16
+ */
17
+ export declare class GoRouteBindings {
18
+ private readonly scopes;
19
+ constructor(root: SyntaxNode);
20
+ private collectNode;
21
+ lookup(node: SyntaxNode): GoRouteBinding | undefined;
22
+ private declare;
23
+ private parameters;
24
+ private pairedValue;
25
+ }
@@ -0,0 +1,194 @@
1
+ const FUNCTIONS = new Set(['function_declaration', 'method_declaration', 'func_literal']);
2
+ const SCOPES = new Set([
3
+ 'block',
4
+ 'if_statement',
5
+ 'for_statement',
6
+ 'expression_switch_statement',
7
+ 'type_switch_statement',
8
+ 'select_statement',
9
+ 'expression_case',
10
+ 'type_case',
11
+ 'communication_case',
12
+ 'default_case',
13
+ ]);
14
+ const BINDING_NODES = new Set([
15
+ 'short_var_declaration',
16
+ 'var_spec',
17
+ 'const_spec',
18
+ 'assignment_statement',
19
+ 'range_clause',
20
+ 'receive_statement',
21
+ 'type_switch_statement',
22
+ 'type_spec',
23
+ 'type_alias',
24
+ ]);
25
+ function enclosingGoFunction(node) {
26
+ for (let current = node; current; current = current.parent) {
27
+ if (FUNCTIONS.has(current.type))
28
+ return current;
29
+ }
30
+ return undefined;
31
+ }
32
+ function lexicalScope(node) {
33
+ for (let current = node.parent; current; current = current.parent) {
34
+ if (SCOPES.has(current.type))
35
+ return current;
36
+ if (FUNCTIONS.has(current.type))
37
+ return current.childForFieldName('body') ?? undefined;
38
+ }
39
+ return undefined;
40
+ }
41
+ /**
42
+ * Route-local binding evidence. Declaration identity and visibility follow Go
43
+ * blocks; value inference deliberately remains conservative across all writes.
44
+ * Nested functions are visited so writes to captured locals cannot leave stale
45
+ * proofs. Their own declarations remain separate from the captured bindings.
46
+ */
47
+ export class GoRouteBindings {
48
+ scopes = new Map();
49
+ constructor(root) {
50
+ const assignments = [];
51
+ const stack = [root];
52
+ while (stack.length > 0) {
53
+ const node = stack.pop();
54
+ if (!node)
55
+ break;
56
+ if (FUNCTIONS.has(node.type))
57
+ this.parameters(node);
58
+ this.collectNode(node, assignments);
59
+ for (let i = node.namedChildCount - 1; i >= 0; i--) {
60
+ const child = node.namedChild(i);
61
+ if (child)
62
+ stack.push(child);
63
+ }
64
+ }
65
+ // Resolve writes after collecting declarations, but at each write's source
66
+ // position. A short declaration's LHS can refer to its newly declared name;
67
+ // its initializer still sees the previous scope through ordinary lookup.
68
+ for (const { name, value } of assignments) {
69
+ const parent = name.parent?.type === 'expression_list' ? name.parent.parent : name.parent;
70
+ const declaration = parent?.type === 'short_var_declaration';
71
+ const scope = declaration && parent ? lexicalScope(parent) : undefined;
72
+ const binding = scope ? this.scopes.get(scope.id)?.get(name.text) : this.lookup(name);
73
+ if (!binding)
74
+ continue;
75
+ binding.values.push(value);
76
+ if (enclosingGoFunction(name)?.id !== binding.ownerFunction.id)
77
+ binding.capturedWrite = true;
78
+ }
79
+ }
80
+ collectNode(node, assignments) {
81
+ if (!BINDING_NODES.has(node.type))
82
+ return;
83
+ const scope = lexicalScope(node);
84
+ if (!scope)
85
+ return;
86
+ if (node.type === 'short_var_declaration') {
87
+ const names = node.childForFieldName('left')?.namedChildren ?? [];
88
+ const values = node.childForFieldName('right')?.namedChildren ?? [];
89
+ names.forEach((name, index) => {
90
+ if (name.type !== 'identifier' || name.text === '_')
91
+ return;
92
+ const existing = this.scopes.get(scope.id)?.get(name.text);
93
+ if (!existing)
94
+ this.declare(name, scope, node.endIndex);
95
+ assignments.push({ name, value: this.pairedValue(values, names.length, index) });
96
+ });
97
+ }
98
+ else if (node.type === 'var_spec' || node.type === 'const_spec') {
99
+ const names = node.childrenForFieldName('name');
100
+ const values = node.childForFieldName('value')?.namedChildren ?? [];
101
+ for (const [index, name] of names.entries()) {
102
+ const binding = this.declare(name, scope, node.endIndex, node.childForFieldName('type'));
103
+ if (binding && values.length > 0) {
104
+ binding.values.push(this.pairedValue(values, names.length, index));
105
+ }
106
+ }
107
+ }
108
+ else if (node.type === 'assignment_statement') {
109
+ const names = node.childForFieldName('left')?.namedChildren ?? [];
110
+ const values = node.childForFieldName('right')?.namedChildren ?? [];
111
+ names.forEach((name, index) => {
112
+ if (name.type === 'identifier') {
113
+ assignments.push({ name, value: this.pairedValue(values, names.length, index) });
114
+ }
115
+ });
116
+ }
117
+ else if (node.type === 'range_clause' || node.type === 'receive_statement') {
118
+ const declares = node.children.some((child) => child.type === ':=');
119
+ for (const name of node.childForFieldName('left')?.namedChildren ?? []) {
120
+ if (name.type !== 'identifier')
121
+ continue;
122
+ if (declares)
123
+ this.declare(name, scope, node.endIndex)?.values.push(null);
124
+ else
125
+ assignments.push({ name, value: null });
126
+ }
127
+ }
128
+ else if (node.type === 'type_switch_statement') {
129
+ for (const name of node.childForFieldName('alias')?.namedChildren ?? []) {
130
+ this.declare(name, node, name.endIndex)?.values.push(null);
131
+ }
132
+ }
133
+ else if (node.type === 'type_spec' || node.type === 'type_alias') {
134
+ const name = node.childForFieldName('name');
135
+ if (name)
136
+ this.declare(name, scope, name.endIndex);
137
+ }
138
+ }
139
+ lookup(node) {
140
+ for (let current = node; current; current = current.parent) {
141
+ const binding = this.scopes.get(current.id)?.get(node.text);
142
+ if (binding && binding.visibleFrom <= node.startIndex)
143
+ return binding;
144
+ }
145
+ return undefined;
146
+ }
147
+ declare(name, scope, visibleFrom, type = null, isInputParameter = false) {
148
+ if (name.text === '_')
149
+ return undefined;
150
+ const ownerFunction = enclosingGoFunction(scope);
151
+ if (!ownerFunction)
152
+ return undefined;
153
+ let names = this.scopes.get(scope.id);
154
+ if (!names) {
155
+ names = new Map();
156
+ this.scopes.set(scope.id, names);
157
+ }
158
+ const binding = {
159
+ visibleFrom,
160
+ ownerFunction,
161
+ type,
162
+ isInputParameter,
163
+ values: [],
164
+ capturedWrite: false,
165
+ };
166
+ names.set(name.text, binding);
167
+ return binding;
168
+ }
169
+ parameters(fn) {
170
+ const body = fn.childForFieldName('body');
171
+ if (!body)
172
+ return;
173
+ for (const parameter of fn.childForFieldName('type_parameters')?.namedChildren ?? []) {
174
+ for (const name of parameter.childrenForFieldName('name')) {
175
+ this.declare(name, fn, name.endIndex);
176
+ }
177
+ }
178
+ for (const field of ['receiver', 'parameters', 'result']) {
179
+ for (const parameter of fn.childForFieldName(field)?.namedChildren ?? []) {
180
+ if (parameter.type !== 'parameter_declaration' &&
181
+ parameter.type !== 'variadic_parameter_declaration')
182
+ continue;
183
+ const fixed = parameter.type === 'parameter_declaration';
184
+ for (const name of parameter.childrenForFieldName('name')) {
185
+ this.declare(name, body, body.startIndex, fixed ? parameter.childForFieldName('type') : null, fixed && field !== 'result');
186
+ }
187
+ }
188
+ }
189
+ }
190
+ pairedValue(values, count, index) {
191
+ // A multi-result call proves only the first result's constructor hint.
192
+ return (values.length === count ? values[index] : index === 0 ? values[0] : null) ?? null;
193
+ }
194
+ }
@@ -0,0 +1,19 @@
1
+ import type { RouteHandlerResolutionHookContext } from '../../language-provider.js';
2
+ import type { ExtractedDecoratorRoute } from '../../workers/parse-worker.js';
3
+ /**
4
+ * Resolve a gin/echo handler designator (`Login`, `pkg.Login`, `h.Login`) to a
5
+ * symbol, looking across the files of a Go package — a package is a directory,
6
+ * so a handler registered in `router.go` is usually a method declared in a
7
+ * sibling file (#3402).
8
+ *
9
+ * Every step is unique-or-decline, and nothing falls back to a name-only match:
10
+ * with the router and the handlers in different packages, a same-named method
11
+ * in the router's own directory belongs to an unrelated type.
12
+ *
13
+ * Runs at the end of the parse phase, before scope resolution, so a Method's
14
+ * `ownerId` is still the worker's `Struct:<methodFile>:<Receiver>` id — keyed on
15
+ * the METHOD's file, which is not the struct's node id when the struct is
16
+ * declared in another file of the package. Ownership is therefore matched on
17
+ * either id.
18
+ */
19
+ export declare function resolveGoRouteHandler(route: ExtractedDecoratorRoute, context: RouteHandlerResolutionHookContext): string | undefined;