diff --git a/gnovm/cmd/gno/doc_test.go b/gnovm/cmd/gno/doc_test.go index 513862ad2dc..e0140c131d7 100644 --- a/gnovm/cmd/gno/doc_test.go +++ b/gnovm/cmd/gno/doc_test.go @@ -1,29 +1,11 @@ package main -import "testing" +import ( + "testing" -func TestGnoDoc(t *testing.T) { - tc := []testMainCase{ - { - args: []string{"doc", "io.Writer"}, - stdoutShouldContain: "Writer is the interface that wraps", - }, - { - args: []string{"doc", "avl"}, - stdoutShouldContain: "func NewTree", - }, - { - args: []string{"doc", "-u", "avl.Node"}, - stdoutShouldContain: "node *Node", - }, - { - args: []string{"doc", "dkfdkfkdfjkdfj"}, - errShouldContain: "package not found", - }, - { - args: []string{"doc", "There.Are.Too.Many.Dots"}, - errShouldContain: "invalid arguments", - }, - } - testMainCaseRun(t, tc) + "github.com/rogpeppe/go-internal/testscript" +) + +func TestDoc(t *testing.T) { + testscript.Run(t, setupTestScript(t, "testdata/gno_doc")) } diff --git a/gnovm/cmd/gno/testdata/gno_doc/invalid_args.txtar b/gnovm/cmd/gno/testdata/gno_doc/invalid_args.txtar new file mode 100644 index 00000000000..02814b36ff5 --- /dev/null +++ b/gnovm/cmd/gno/testdata/gno_doc/invalid_args.txtar @@ -0,0 +1,6 @@ +# Test with an invalid syntax for gno doc + +! gno doc There.Are.Too.Many.Dots + +! stdout .+ +stderr 'invalid arguments' diff --git a/gnovm/cmd/gno/testdata/gno_doc/mod_order.txtar b/gnovm/cmd/gno/testdata/gno_doc/mod_order.txtar new file mode 100644 index 00000000000..12e2d61d4b4 --- /dev/null +++ b/gnovm/cmd/gno/testdata/gno_doc/mod_order.txtar @@ -0,0 +1,53 @@ +# Ensure that imported gno.mods are processed after a first run through modDirs +# Underlying cause of https://github.com/gnolang/gno/pull/1301 + +env GNOROOT=${WORK} +env GNO_HOME=${WORK}/home + +gno doc pkg1 + +stdout Pkg1\(\) +! stderr .+ + +gno doc pkg2 + +stdout Pkg2\(\) +! stderr .+ + +gno doc pkg3 + +stdout Pkg3\(\) +! stderr .+ + +-- gnovm/stdlibs/pkg1/hello.gno -- +package pkg1 + +func Pkg1() {} + +-- examples/pkg2/gno.mod -- +module pkg2 + +require ( + pkg3 v0.0.0-latest +) + +-- examples/pkg2/pkg2.gno -- +package pkg2 + +func Pkg2() {} + +-- examples/pkg3/gno.mod -- +module pkg3 + +-- examples/pkg3/pkg3.gno -- +package pkg3 + +func Pkg3() {} + +-- home/pkg/mod/pkg3/gno.mod -- +module pkg3 + +-- home/pkg/mod/pkg3/pkg3.gno -- +package pkg3 + +func Pkg3Mod() {} diff --git a/gnovm/cmd/gno/testdata/gno_doc/ok_avl.txtar b/gnovm/cmd/gno/testdata/gno_doc/ok_avl.txtar new file mode 100644 index 00000000000..4bc0a814a2f --- /dev/null +++ b/gnovm/cmd/gno/testdata/gno_doc/ok_avl.txtar @@ -0,0 +1,6 @@ +# Test getting documentation for package avl + +gno doc avl + +stdout 'func NewTree' +! stderr .+ diff --git a/gnovm/cmd/gno/testdata/gno_doc/ok_avl_unexp.txtar b/gnovm/cmd/gno/testdata/gno_doc/ok_avl_unexp.txtar new file mode 100644 index 00000000000..567f39cd84b --- /dev/null +++ b/gnovm/cmd/gno/testdata/gno_doc/ok_avl_unexp.txtar @@ -0,0 +1,6 @@ +# Test getting an unexported struct field from avl + +gno doc -u avl.Tree + +stdout 'node \*Node' +! stderr .+ diff --git a/gnovm/cmd/gno/testdata/gno_doc/ok_io_writer.txtar b/gnovm/cmd/gno/testdata/gno_doc/ok_io_writer.txtar new file mode 100644 index 00000000000..75d6a7a385a --- /dev/null +++ b/gnovm/cmd/gno/testdata/gno_doc/ok_io_writer.txtar @@ -0,0 +1,6 @@ +# Gno doc on a standard library function + +gno doc io.Writer + +stdout 'Writer is the interface that wraps' +! stderr .+ diff --git a/gnovm/cmd/gno/testdata/gno_doc/package_not_found.txtar b/gnovm/cmd/gno/testdata/gno_doc/package_not_found.txtar new file mode 100644 index 00000000000..72f584dff32 --- /dev/null +++ b/gnovm/cmd/gno/testdata/gno_doc/package_not_found.txtar @@ -0,0 +1,6 @@ +# query an invalid package + +! gno doc ajfdhalksdsadkj + +! stdout .+ +stderr 'package not found' diff --git a/gnovm/pkg/doc/dirs.go b/gnovm/pkg/doc/dirs.go index 21216828ce4..02fd2ca8136 100644 --- a/gnovm/pkg/doc/dirs.go +++ b/gnovm/pkg/doc/dirs.go @@ -43,28 +43,48 @@ func newDirs(dirs []string, modDirs []string) *bfsDirs { scan: make(chan bfsDir), } + // to perform de-duplication. + added := make(map[bfsDir]struct{}, 256) + roots := make([]bfsDir, 0, len(dirs)+len(modDirs)) for _, dir := range dirs { - roots = append(roots, bfsDir{ + d := bfsDir{ dir: dir, importPath: "", - }) + } + if _, ok := added[d]; !ok { + roots = append(roots, d) + added[d] = struct{}{} + } } + // enforce putting first "explicit" dirs, then dirs imported through gno.mod. + var modDirRoots []bfsDir + for _, mdir := range modDirs { gm, err := parseGnoMod(filepath.Join(mdir, "gno.mod")) if err != nil { log.Printf("%v", err) continue } - roots = append(roots, bfsDir{ + d := bfsDir{ dir: mdir, importPath: gm.Module.Mod.Path, - }) - roots = append(roots, getGnoModDirs(gm)...) + } + if _, ok := added[d]; ok { + continue + } + roots = append(roots, d) + added[d] = struct{}{} + for _, rt := range getGnoModDirs(gm) { + if _, ok := added[rt]; !ok { + modDirRoots = append(modDirRoots, rt) + added[rt] = struct{}{} + } + } } - go d.walk(roots) + go d.walk(append(roots, modDirRoots...)) return d }