diff --git a/internal/loader/loader.go b/internal/loader/loader.go index 8ae1a96..b96f447 100644 --- a/internal/loader/loader.go +++ b/internal/loader/loader.go @@ -4,6 +4,7 @@ import ( "fmt" "io/ioutil" "os" + "path/filepath" "strings" "github.com/charmbracelet/log" @@ -248,7 +249,8 @@ func normalizePackage(opts *config.IndexOpts, pkg *packages.Package) *packages.P } if pkg.Module.Version == "" { - if sameRepoRoot(pkg.Module.Path, opts.ModulePath) { + if hasSameRepoRoot(pkg.Module.Path, opts.ModulePath) || + isNestedDir(pkg.Module.Dir, opts.ModuleRoot) { pkg.Module.Version = opts.ModuleVersion } else { // Only panic when running in debug mode. @@ -286,9 +288,9 @@ func normalizePackage(opts *config.IndexOpts, pkg *packages.Package) *packages.P return pkg } -// sameRepoRoot returns true if a and b resolve to the same VCS repository root. -// This is used to detect sibling modules in a monorepo. -func sameRepoRoot(pathA, pathB string) bool { +// hasSameRepoRoot returns true if a and b resolve to the same VCS repository +// root. This is used to detect sibling modules in a monorepo. +func hasSameRepoRoot(pathA, pathB string) bool { if pathA == pathB { return true } @@ -299,3 +301,19 @@ func sameRepoRoot(pathA, pathB string) bool { } return rootA.Root == rootB.Root } + +// isNestedDir returns true if either directory is a subdirectory of the other. +// This detects workspace sibling modules (e.g. go.work) that live in the same +// repository but have different VCS import paths. +func isNestedDir(dirA, dirB string) bool { + if dirA == "" || dirB == "" { + return false + } + if rel, err := filepath.Rel(dirA, dirB); err == nil && filepath.IsLocal(rel) { + return true + } + if rel, err := filepath.Rel(dirB, dirA); err == nil && filepath.IsLocal(rel) { + return true + } + return false +} diff --git a/internal/modules/modules.go b/internal/modules/modules.go index a0a4d08..705e475 100644 --- a/internal/modules/modules.go +++ b/internal/modules/modules.go @@ -7,8 +7,8 @@ import ( "strings" "github.com/charmbracelet/log" - "github.com/sourcegraph/scip-go/internal/command" "github.com/sourcegraph/scip-go/internal/output" + "golang.org/x/mod/modfile" "golang.org/x/tools/go/vcs" ) @@ -21,17 +21,18 @@ func ModuleName(dir, repo, inName string) (moduleName string, isStdLib bool, err moduleName = repo - if !isModule(dir) { + goModPath := filepath.Join(dir, "go.mod") + data, readErr := os.ReadFile(goModPath) + if readErr != nil { log.Warn("No go.mod file found in current directory.") - } else { - if moduleName, err = command.Run(dir, "go", "list", "-mod=readonly", "-m"); err != nil { - return fmt.Errorf("failed to list modules: %v\n%s", err, moduleName) - } - + moduleName, isStdLib, err = resolveModuleName(repo, moduleName) return nil } - - moduleName, isStdLib, err = resolveModuleName(repo, moduleName) + parsed, parseErr := modfile.ParseLax(goModPath, data, nil) + if parseErr != nil { + return fmt.Errorf("failed to parse go.mod: %v", parseErr) + } + moduleName = parsed.Module.Mod.Path return nil } @@ -74,8 +75,3 @@ func resolveModuleName(repo, name string) (string, bool, error) { return name, name == "std", nil } -// isModule returns true if there is a go.mod file in the given directory. -func isModule(dir string) bool { - _, err := os.Stat(filepath.Join(dir, "go.mod")) - return err == nil -} diff --git a/internal/testdata/snapshots/output/alias/main.go b/internal/testdata/snapshots/output/alias/main.go index 7f3971d..5b0d722 100755 --- a/internal/testdata/snapshots/output/alias/main.go +++ b/internal/testdata/snapshots/output/alias/main.go @@ -1,5 +1,5 @@ package main -// ^^^^ definition github.com/sourcegraph/scip-go . `github.com/sourcegraph/scip-go/internal/testdata/snapshots/input/alias`/ +// ^^^^ definition github.com/sourcegraph/scip-go 0.1.test `github.com/sourcegraph/scip-go/internal/testdata/snapshots/input/alias`/ // documentation // > package main @@ -7,7 +7,7 @@ // Copied from https://github.com/golang/go/issues/68877#issuecomment-2290000187 type ( T struct{} -// ^ definition github.com/sourcegraph/scip-go . `github.com/sourcegraph/scip-go/internal/testdata/snapshots/input/alias`/T# +// ^ definition github.com/sourcegraph/scip-go 0.1.test `github.com/sourcegraph/scip-go/internal/testdata/snapshots/input/alias`/T# // documentation // > ```go // > type T struct @@ -20,7 +20,7 @@ // > struct{} // > ``` U = T -// ^ definition github.com/sourcegraph/scip-go . `github.com/sourcegraph/scip-go/internal/testdata/snapshots/input/alias`/U# +// ^ definition github.com/sourcegraph/scip-go 0.1.test `github.com/sourcegraph/scip-go/internal/testdata/snapshots/input/alias`/U# // documentation // > ```go // > type U = T @@ -32,9 +32,9 @@ // > ```go // > struct{} // > ``` -// ^ reference github.com/sourcegraph/scip-go . `github.com/sourcegraph/scip-go/internal/testdata/snapshots/input/alias`/T# +// ^ reference github.com/sourcegraph/scip-go 0.1.test `github.com/sourcegraph/scip-go/internal/testdata/snapshots/input/alias`/T# V = U -// ^ definition github.com/sourcegraph/scip-go . `github.com/sourcegraph/scip-go/internal/testdata/snapshots/input/alias`/V# +// ^ definition github.com/sourcegraph/scip-go 0.1.test `github.com/sourcegraph/scip-go/internal/testdata/snapshots/input/alias`/V# // documentation // > ```go // > type V = U @@ -46,9 +46,9 @@ // > ```go // > struct{} // > ``` -// ^ reference github.com/sourcegraph/scip-go . `github.com/sourcegraph/scip-go/internal/testdata/snapshots/input/alias`/U# +// ^ reference github.com/sourcegraph/scip-go 0.1.test `github.com/sourcegraph/scip-go/internal/testdata/snapshots/input/alias`/U# S U -// ^ definition github.com/sourcegraph/scip-go . `github.com/sourcegraph/scip-go/internal/testdata/snapshots/input/alias`/S# +// ^ definition github.com/sourcegraph/scip-go 0.1.test `github.com/sourcegraph/scip-go/internal/testdata/snapshots/input/alias`/S# // documentation // > ```go // > type S struct @@ -60,9 +60,9 @@ // > ```go // > struct{} // > ``` -// ^ reference github.com/sourcegraph/scip-go . `github.com/sourcegraph/scip-go/internal/testdata/snapshots/input/alias`/U# +// ^ reference github.com/sourcegraph/scip-go 0.1.test `github.com/sourcegraph/scip-go/internal/testdata/snapshots/input/alias`/U# Z int32 -// ^ definition github.com/sourcegraph/scip-go . `github.com/sourcegraph/scip-go/internal/testdata/snapshots/input/alias`/Z# +// ^ definition github.com/sourcegraph/scip-go 0.1.test `github.com/sourcegraph/scip-go/internal/testdata/snapshots/input/alias`/Z# // documentation // > Check that we don't panic // > Copied from https://github.com/golang/go/issues/68877#issuecomment-2290000187 @@ -72,14 +72,14 @@ // > ``` ) -//⌄ enclosing_range_start github.com/sourcegraph/scip-go . `github.com/sourcegraph/scip-go/internal/testdata/snapshots/input/alias`/f(). +//⌄ enclosing_range_start github.com/sourcegraph/scip-go 0.1.test `github.com/sourcegraph/scip-go/internal/testdata/snapshots/input/alias`/f(). func f(u U) {} -// ^ definition github.com/sourcegraph/scip-go . `github.com/sourcegraph/scip-go/internal/testdata/snapshots/input/alias`/f(). +// ^ definition github.com/sourcegraph/scip-go 0.1.test `github.com/sourcegraph/scip-go/internal/testdata/snapshots/input/alias`/f(). // documentation // > ```go // > func f(u U) // > ``` // ^ definition local 0 -// ^ reference github.com/sourcegraph/scip-go . `github.com/sourcegraph/scip-go/internal/testdata/snapshots/input/alias`/U# -// ⌃ enclosing_range_end github.com/sourcegraph/scip-go . `github.com/sourcegraph/scip-go/internal/testdata/snapshots/input/alias`/f(). +// ^ reference github.com/sourcegraph/scip-go 0.1.test `github.com/sourcegraph/scip-go/internal/testdata/snapshots/input/alias`/U# +// ⌃ enclosing_range_end github.com/sourcegraph/scip-go 0.1.test `github.com/sourcegraph/scip-go/internal/testdata/snapshots/input/alias`/f(). diff --git a/internal/testdata/snapshots/output/package-documentation/primary.go b/internal/testdata/snapshots/output/package-documentation/primary.go index e3ccebf..b6294ed 100755 --- a/internal/testdata/snapshots/output/package-documentation/primary.go +++ b/internal/testdata/snapshots/output/package-documentation/primary.go @@ -1,15 +1,15 @@ // This is documentation for this package. package packagedocumentation -// ^^^^^^^^^^^^^^^^^^^^ definition github.com/sourcegraph/scip-go . `github.com/sourcegraph/scip-go/internal/testdata/snapshots/input/package-documentation`/ +// ^^^^^^^^^^^^^^^^^^^^ definition github.com/sourcegraph/scip-go 0.1.test `github.com/sourcegraph/scip-go/internal/testdata/snapshots/input/package-documentation`/ // documentation // > This is documentation for this package. -//⌄ enclosing_range_start github.com/sourcegraph/scip-go . `github.com/sourcegraph/scip-go/internal/testdata/snapshots/input/package-documentation`/Exported(). +//⌄ enclosing_range_start github.com/sourcegraph/scip-go 0.1.test `github.com/sourcegraph/scip-go/internal/testdata/snapshots/input/package-documentation`/Exported(). func Exported() {} -// ^^^^^^^^ definition github.com/sourcegraph/scip-go . `github.com/sourcegraph/scip-go/internal/testdata/snapshots/input/package-documentation`/Exported(). +// ^^^^^^^^ definition github.com/sourcegraph/scip-go 0.1.test `github.com/sourcegraph/scip-go/internal/testdata/snapshots/input/package-documentation`/Exported(). // documentation // > ```go // > func Exported() // > ``` -// ⌃ enclosing_range_end github.com/sourcegraph/scip-go . `github.com/sourcegraph/scip-go/internal/testdata/snapshots/input/package-documentation`/Exported(). +// ⌃ enclosing_range_end github.com/sourcegraph/scip-go 0.1.test `github.com/sourcegraph/scip-go/internal/testdata/snapshots/input/package-documentation`/Exported(). diff --git a/internal/testdata/snapshots/output/package-documentation/secondary.go b/internal/testdata/snapshots/output/package-documentation/secondary.go index dda5e1f..d8a9c68 100755 --- a/internal/testdata/snapshots/output/package-documentation/secondary.go +++ b/internal/testdata/snapshots/output/package-documentation/secondary.go @@ -1,12 +1,12 @@ package packagedocumentation -// ^^^^^^^^^^^^^^^^^^^^ reference github.com/sourcegraph/scip-go . `github.com/sourcegraph/scip-go/internal/testdata/snapshots/input/package-documentation`/ +// ^^^^^^^^^^^^^^^^^^^^ reference github.com/sourcegraph/scip-go 0.1.test `github.com/sourcegraph/scip-go/internal/testdata/snapshots/input/package-documentation`/ -//⌄ enclosing_range_start github.com/sourcegraph/scip-go . `github.com/sourcegraph/scip-go/internal/testdata/snapshots/input/package-documentation`/AlsoExporter(). +//⌄ enclosing_range_start github.com/sourcegraph/scip-go 0.1.test `github.com/sourcegraph/scip-go/internal/testdata/snapshots/input/package-documentation`/AlsoExporter(). func AlsoExporter() {} -// ^^^^^^^^^^^^ definition github.com/sourcegraph/scip-go . `github.com/sourcegraph/scip-go/internal/testdata/snapshots/input/package-documentation`/AlsoExporter(). +// ^^^^^^^^^^^^ definition github.com/sourcegraph/scip-go 0.1.test `github.com/sourcegraph/scip-go/internal/testdata/snapshots/input/package-documentation`/AlsoExporter(). // documentation // > ```go // > func AlsoExporter() // > ``` -// ⌃ enclosing_range_end github.com/sourcegraph/scip-go . `github.com/sourcegraph/scip-go/internal/testdata/snapshots/input/package-documentation`/AlsoExporter(). +// ⌃ enclosing_range_end github.com/sourcegraph/scip-go 0.1.test `github.com/sourcegraph/scip-go/internal/testdata/snapshots/input/package-documentation`/AlsoExporter().