go-module.ts 1.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647
  1. /**
  2. * Go module path detection.
  3. *
  4. * A Go monorepo's cross-package calls (`pkga.FuncX(...)`) only resolve when
  5. * the resolver knows the project's module path (the `module ...` directive
  6. * in `go.mod`). Without it, `isExternalImport` treats every in-module import
  7. * — `github.com/example/myproject/pkga` — as a third-party package, so
  8. * resolution falls through to name-matching with path proximity and returns
  9. * a tiny fraction of the real call sites. See issue #388.
  10. */
  11. import * as fs from 'fs';
  12. import * as path from 'path';
  13. export interface GoModule {
  14. /** The module path declared in `go.mod`, e.g. `github.com/example/myproject` */
  15. modulePath: string;
  16. /** Absolute path to the directory containing the `go.mod` file. */
  17. rootDir: string;
  18. }
  19. /**
  20. * Read the `go.mod` file at the project root and extract the module path.
  21. * Returns `null` if no `go.mod` exists or it has no `module` directive.
  22. *
  23. * Limitation: only the project-root `go.mod` is read. Nested `go.mod` files
  24. * (Go workspaces, monorepos with multiple modules) are not yet resolved —
  25. * a follow-up if a real repro shows up.
  26. */
  27. export function loadGoModule(projectRoot: string): GoModule | null {
  28. const goModPath = path.join(projectRoot, 'go.mod');
  29. let content: string;
  30. try {
  31. content = fs.readFileSync(goModPath, 'utf-8');
  32. } catch {
  33. return null;
  34. }
  35. // `module <path>` is the first non-comment directive in any valid go.mod.
  36. // Strip line comments so a `// module foo` doesn't false-match.
  37. const stripped = content.replace(/\/\/[^\n]*/g, '');
  38. const match = stripped.match(/^\s*module\s+(\S+)\s*$/m);
  39. if (!match) return null;
  40. // Strip optional quoting around the module path.
  41. const modulePath = match[1]!.replace(/^["']|["']$/g, '');
  42. if (!modulePath) return null;
  43. return { modulePath, rootDir: projectRoot };
  44. }