MCPcopy Create free account
hub / github.com/colbymchenry/codegraph / resolveRelativeImport

Function resolveRelativeImport

src/resolution/import-resolver.ts:383–428  ·  view source on GitHub ↗

* Resolve a relative import

(
  importPath: string,
  fromDir: string,
  language: Language,
  context: ResolutionContext
)

Source from the content-addressed store, hash-verified

381 * Resolve a relative import
382 */
383function resolveRelativeImport(
384 importPath: string,
385 fromDir: string,
386 language: Language,
387 context: ResolutionContext
388): string | null {
389 const projectRoot = context.getProjectRoot();
390 const extensions = EXTENSION_RESOLUTION[language] || [];
391
392 // Python dotted-relative imports (`from .certs import x`, `from ..pkg.mod
393 // import y`): leading dots are PACKAGE levels (1 = current package), and the
394 // remainder is a dotted submodule path. `path.resolve(dir, '.certs')` would
395 // treat `.certs` as a literal hidden filename, so translate the Python form
396 // to a real filesystem-relative path before resolving.
397 if (language === 'python' && importPath.startsWith('.')) {
398 const dots = importPath.length - importPath.replace(/^\.+/, '').length;
399 const up = '../'.repeat(Math.max(0, dots - 1)); // 1 dot = current dir
400 const rest = importPath.slice(dots).replace(/\./g, '/'); // 'sub.mod' -> 'sub/mod'
401 const pyBase = path.resolve(fromDir, up + rest);
402 const pyRel = path.relative(projectRoot, pyBase).replace(/\\/g, '/');
403 for (const ext of extensions) {
404 if (context.fileExists(pyRel + ext)) return pyRel + ext;
405 }
406 if (pyRel && context.fileExists(pyRel)) return pyRel;
407 return null;
408 }
409
410 // Try the path as-is first
411 const basePath = path.resolve(fromDir, importPath);
412 const relativePath = path.relative(projectRoot, basePath).replace(/\\/g, '/');
413
414 // Try each extension
415 for (const ext of extensions) {
416 const candidatePath = relativePath + ext;
417 if (context.fileExists(candidatePath)) {
418 return candidatePath;
419 }
420 }
421
422 // Try without extension (might already have one)
423 if (context.fileExists(relativePath)) {
424 return relativePath;
425 }
426
427 return null;
428}
429
430/**
431 * Resolve an aliased/absolute import.

Callers 1

Calls 3

fileExistsMethod · 0.80
getProjectRootMethod · 0.65
resolveMethod · 0.65

Tested by

no test coverage detected