1
0

types.ts 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. /**
  2. * Reference Resolution Types
  3. *
  4. * Types for the reference resolution system.
  5. */
  6. import { EdgeKind, Language, Node } from '../types';
  7. /**
  8. * An unresolved reference from extraction
  9. */
  10. export interface UnresolvedRef {
  11. /** ID of the source node containing the reference */
  12. fromNodeId: string;
  13. /** The name being referenced */
  14. referenceName: string;
  15. /** Type of reference */
  16. referenceKind: EdgeKind;
  17. /** Line where reference occurs */
  18. line: number;
  19. /** Column where reference occurs */
  20. column: number;
  21. /** File path where reference occurs */
  22. filePath: string;
  23. /** Language of the source file */
  24. language: Language;
  25. /** Possible qualified names it might resolve to */
  26. candidates?: string[];
  27. }
  28. /**
  29. * A resolved reference
  30. */
  31. export interface ResolvedRef {
  32. /** Original unresolved reference */
  33. original: UnresolvedRef;
  34. /** ID of the target node */
  35. targetNodeId: string;
  36. /** Confidence score (0-1) */
  37. confidence: number;
  38. /** How it was resolved */
  39. resolvedBy: 'exact-match' | 'import' | 'qualified-name' | 'framework' | 'fuzzy' | 'instance-method' | 'file-path';
  40. }
  41. /**
  42. * Result of resolution attempt
  43. */
  44. export interface ResolutionResult {
  45. /** Successfully resolved references */
  46. resolved: ResolvedRef[];
  47. /** References that couldn't be resolved */
  48. unresolved: UnresolvedRef[];
  49. /** Statistics */
  50. stats: {
  51. total: number;
  52. resolved: number;
  53. unresolved: number;
  54. byMethod: Record<string, number>;
  55. };
  56. }
  57. /**
  58. * Context for resolution - provides access to the graph
  59. */
  60. export interface ResolutionContext {
  61. /** Get all nodes in a file */
  62. getNodesInFile(filePath: string): Node[];
  63. /** Get all nodes by name */
  64. getNodesByName(name: string): Node[];
  65. /** Get all nodes by qualified name */
  66. getNodesByQualifiedName(qualifiedName: string): Node[];
  67. /** Get all nodes of a kind */
  68. getNodesByKind(kind: Node['kind']): Node[];
  69. /** Check if a file exists */
  70. fileExists(filePath: string): boolean;
  71. /** Read file content */
  72. readFile(filePath: string): string | null;
  73. /** Get project root */
  74. getProjectRoot(): string;
  75. /** Get all files */
  76. getAllFiles(): string[];
  77. /** Get nodes by lowercase name (O(1) lookup for fuzzy matching) */
  78. getNodesByLowerName(lowerName: string): Node[];
  79. /** Get cached import mappings for a file */
  80. getImportMappings(filePath: string, language: Language): ImportMapping[];
  81. /**
  82. * Project import-path aliases (tsconfig/jsconfig `paths`). Returns
  83. * `null` when the project doesn't define any. Cached per resolver
  84. * instance — safe to call from any resolver code path. Optional so
  85. * existing test fixtures and external context implementations
  86. * compile without modification; production resolver implements it.
  87. */
  88. getProjectAliases?(): import('./path-aliases').AliasMap | null;
  89. /**
  90. * Re-exports declared by a file (`export { x } from './other'`,
  91. * `export * from './other'`). Empty array when the file has none.
  92. * Optional so older callers compile; the import resolver follows
  93. * re-export chains when this is provided.
  94. */
  95. getReExports?(filePath: string, language: Language): ReExport[];
  96. /**
  97. * List immediate subdirectories of `relativePath` (relative to the
  98. * project root). Returns an empty array when the path doesn't exist
  99. * or isn't a directory. Used by framework resolvers that need to
  100. * walk build-system metadata (e.g. Cargo workspace globs). Optional
  101. * so external context implementations and test fixtures compile
  102. * without modification.
  103. */
  104. listDirectories?(relativePath: string): string[];
  105. }
  106. /**
  107. * Result of framework-specific file extraction.
  108. */
  109. export interface FrameworkExtractionResult {
  110. /** Framework-specific nodes (e.g. routes) */
  111. nodes: Node[];
  112. /** Framework-specific unresolved references (e.g. route -> handler) */
  113. references: UnresolvedRef[];
  114. }
  115. /**
  116. * Framework-specific resolver
  117. */
  118. export interface FrameworkResolver {
  119. /** Framework name */
  120. name: string;
  121. /** Languages this framework applies to. If omitted, applies to all languages. */
  122. languages?: Language[];
  123. /** Detect if project uses this framework (project-level, called once at startup) */
  124. detect(context: ResolutionContext): boolean;
  125. /** Resolve a reference using framework-specific patterns */
  126. resolve(ref: UnresolvedRef, context: ResolutionContext): ResolvedRef | null;
  127. /**
  128. * Opt a reference NAME through the resolver's name-exists pre-filter, even when
  129. * no node is named that. Needed for dynamic dispatch where the call target is
  130. * an attribute/descriptor, not a declared symbol (e.g. Django's
  131. * `self._iterable_class(...)`, React effect callbacks). Returning true lets the
  132. * ref reach `resolve()` instead of being dropped for having no name match.
  133. */
  134. claimsReference?(name: string): boolean;
  135. /**
  136. * Extract framework-specific nodes and references from a file.
  137. *
  138. * Returns route nodes, middleware nodes, etc., plus unresolved references
  139. * that link those nodes to handlers (view classes, controller methods,
  140. * included modules). Unresolved references flow into the normal resolution
  141. * pipeline; the framework's own `resolve()` is one of the strategies tried.
  142. */
  143. extract?(filePath: string, content: string): FrameworkExtractionResult;
  144. }
  145. /**
  146. * Import mapping from a file
  147. */
  148. export interface ImportMapping {
  149. /** Local name used in the file */
  150. localName: string;
  151. /** Original exported name (may differ due to aliasing) */
  152. exportedName: string;
  153. /** Source module/path */
  154. source: string;
  155. /** Whether it's a default import */
  156. isDefault: boolean;
  157. /** Whether it's a namespace import (import * as X) */
  158. isNamespace: boolean;
  159. /** Resolved file path (if local) */
  160. resolvedPath?: string;
  161. }
  162. /**
  163. * Re-export from a file: `export { x } from './other'` or
  164. * `export * from './other'`. Used by the resolver to chase
  165. * symbols through barrel files.
  166. */
  167. export type ReExport =
  168. | {
  169. kind: 'named';
  170. /** Name as exported by THIS file. */
  171. exportedName: string;
  172. /** Name in the upstream module (differs when renamed: `as`). */
  173. originalName: string;
  174. /** Module specifier of the upstream module. */
  175. source: string;
  176. }
  177. | {
  178. kind: 'wildcard';
  179. /** Module specifier of the upstream module. */
  180. source: string;
  181. };