( ref: UnresolvedRef, context: ResolutionContext )
| 1240 | * package_declaration namespace wrappers in the extractor. |
| 1241 | */ |
| 1242 | export function resolveJvmImport( |
| 1243 | ref: UnresolvedRef, |
| 1244 | context: ResolutionContext |
| 1245 | ): ResolvedRef | null { |
| 1246 | if (ref.referenceKind !== 'imports') return null; |
| 1247 | if (ref.language !== 'java' && ref.language !== 'kotlin') return null; |
| 1248 | |
| 1249 | const fqn = ref.referenceName; |
| 1250 | const lastDot = fqn.lastIndexOf('.'); |
| 1251 | if (lastDot <= 0) return null; |
| 1252 | const pkg = fqn.substring(0, lastDot); |
| 1253 | const sym = fqn.substring(lastDot + 1); |
| 1254 | // Wildcard imports (`com.example.*`) deliberately punt to name-matcher. |
| 1255 | if (sym === '*') return null; |
| 1256 | |
| 1257 | const candidates = context.getNodesByQualifiedName(`${pkg}::${sym}`); |
| 1258 | if (candidates.length === 0) return null; |
| 1259 | |
| 1260 | // Kotlin Multiplatform: an `expect` declaration and its `actual`s share one |
| 1261 | // FQN across source sets (commonMain / androidMain / appleMain). Taking the |
| 1262 | // first candidate let a single platform `actual` absorb every common-side |
| 1263 | // import, so the `expect` (the canonical API a commonMain file imports) |
| 1264 | // looked unused. Prefer the candidate CLOSEST to the importing file by |
| 1265 | // directory proximity — a commonMain import resolves to the commonMain |
| 1266 | // declaration — with the `expect` side as a tiebreak. |
| 1267 | const best = candidates.length === 1 ? candidates[0]! : pickClosestJvmCandidate(candidates, ref.filePath); |
| 1268 | return { |
| 1269 | original: ref, |
| 1270 | targetNodeId: best.id, |
| 1271 | confidence: 0.95, |
| 1272 | resolvedBy: 'import', |
| 1273 | }; |
| 1274 | } |
| 1275 | |
| 1276 | /** |
| 1277 | * Pick the same-FQN candidate closest to `fromPath` by shared directory |
no test coverage detected