feat(nix/buildGo): add the import position to errmsg

When a foreign dep is missing a dependency, it is good to have a
context.

e.g. the `github.com/charmbracelet/bubblegum` package has a lot of
dependencies that are only used in its `examples/` dir; this is not
obvious, unless we also print where the imports come from.

New error message:

```
error: missing foreign dependency 'github.com/containerd/console' in 'github.com/charmbracelet/bubbletea, imported at /nix/store/0cry4sg6bzxqwk5zl2nxhas6k5663svg-source/tea.go:22:2'
```

Change-Id: If34a3c62b9d77d4aea108b5e011e16fbd03e8554
Reviewed-on: https://cl.tvl.fyi/c/depot/+/2852
Tested-by: BuildkiteCI
Reviewed-by: tazjin <mail@tazj.in>
This commit is contained in:
Profpatsch 2021-04-05 11:41:37 +02:00
parent 77c09076ec
commit 2224731e0d
2 changed files with 22 additions and 11 deletions

View file

@ -56,8 +56,8 @@ let
throw "missing local dependency '${lib.concatStringsSep "." d}' in '${path}'" throw "missing local dependency '${lib.concatStringsSep "." d}' in '${path}'"
) self) entry.localDeps; ) self) entry.localDeps;
foreignDeps = map (d: lib.attrByPath [ d ] ( foreignDeps = map (d: lib.attrByPath [ d.path ] (
throw "missing foreign dependency '${d}' in '${path}'" throw "missing foreign dependency '${d.path}' in '${path}, imported at ${d.position}'"
) depMap) entry.foreignDeps; ) depMap) entry.foreignDeps;
args = { args = {

View file

@ -29,13 +29,19 @@ var stdlibList string
// Return information includes the local (relative from project root) // Return information includes the local (relative from project root)
// and external (none-stdlib) dependencies of this package. // and external (none-stdlib) dependencies of this package.
type pkg struct { type pkg struct {
Name string `json:"name"` Name string `json:"name"`
Locator []string `json:"locator"` Locator []string `json:"locator"`
Files []string `json:"files"` Files []string `json:"files"`
SFiles []string `json:"sfiles"` SFiles []string `json:"sfiles"`
LocalDeps [][]string `json:"localDeps"` LocalDeps [][]string `json:"localDeps"`
ForeignDeps []string `json:"foreignDeps"` ForeignDeps []foreignDep `json:"foreignDeps"`
IsCommand bool `json:"isCommand"` IsCommand bool `json:"isCommand"`
}
type foreignDep struct {
Path string `json:"path"`
// filename, column and line number of the import, if known
Position string `json:"position"`
} }
// findGoDirs returns a filepath.WalkFunc that identifies all // findGoDirs returns a filepath.WalkFunc that identifies all
@ -88,7 +94,7 @@ func analysePackage(root, source, importpath string, stdlib map[string]bool) (pk
} }
local := [][]string{} local := [][]string{}
foreign := []string{} foreign := []foreignDep{}
for _, i := range p.Imports { for _, i := range p.Imports {
if stdlib[i] { if stdlib[i] {
@ -100,7 +106,12 @@ func analysePackage(root, source, importpath string, stdlib map[string]bool) (pk
} else if strings.HasPrefix(i, importpath+"/") { } else if strings.HasPrefix(i, importpath+"/") {
local = append(local, strings.Split(strings.TrimPrefix(i, importpath+"/"), "/")) local = append(local, strings.Split(strings.TrimPrefix(i, importpath+"/"), "/"))
} else { } else {
foreign = append(foreign, i) // The import positions is a map keyed on the import name.
// The value is a list, presumably because an import can appear
// multiple times in a package. Lets just take the first one,
// should be enough for a good error message.
firstPos := p.ImportPos[i][0].String()
foreign = append(foreign, foreignDep{Path: i, Position: firstPos})
} }
} }