Skip to content

Commit 1009587

Browse files
flw-cnzmb3
authored andcommitted
Feat: Add local package support (#34)
The current version of gogetdoc can't work for a local package, This means if your code is not put in GOPATH, then you can't get any help with gogetdoc. This commit changes the current behavior and adds a function named `importLocalPackage` which can import local packages, when `buildutil.ContainingPackage(...)` failed, `importLocalPackage` will be called instead of return an error. It also adds two test cases for test `Run` from outside of GOPATH.
1 parent a74a92c commit 1009587

File tree

3 files changed

+98
-2
lines changed

3 files changed

+98
-2
lines changed

main.go

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,10 @@ func Run(ctx *build.Context, filename string, offset int64) (*Doc, error) {
9999
}
100100
bp, err := buildutil.ContainingPackage(ctx, wd, filename)
101101
if err != nil {
102-
return nil, fmt.Errorf("gogetdoc: couldn't get package for %s: %s", filename, err.Error())
102+
bp, err = importLocalPackage(wd, filename)
103+
if err != nil {
104+
return nil, fmt.Errorf("gogetdoc: couldn't get package for %s: %s", filename, err.Error())
105+
}
103106
}
104107
var parseError error
105108
conf := &loader.Config{
@@ -226,3 +229,20 @@ func sameFile(a, b string) bool {
226229
}
227230
return false
228231
}
232+
233+
func importLocalPackage(wd string, filename string) (*build.Package, error) {
234+
if !filepath.IsAbs(filename) {
235+
filename = filepath.Clean(filepath.Join(wd, filename))
236+
}
237+
238+
filename, err := filepath.Rel(wd, filename)
239+
if err != nil {
240+
return build.Import(".", wd, build.FindOnly)
241+
}
242+
243+
path := filepath.Dir(filename)
244+
if path != "." {
245+
path = "./" + path
246+
}
247+
return build.Import(path, wd, build.FindOnly)
248+
}

main_test.go

Lines changed: 70 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,13 @@
11
package main
22

3-
import "testing"
3+
import (
4+
"go/build"
5+
"io/ioutil"
6+
"os"
7+
"path/filepath"
8+
"strings"
9+
"testing"
10+
)
411

512
func TestParseValidPos(t *testing.T) {
613
fname, offset, err := parsePos("foo.go:#123")
@@ -37,3 +44,65 @@ func TestParseInvalidPos(t *testing.T) {
3744
}
3845
}
3946
}
47+
48+
func TestRunOutsideGopath(t *testing.T) {
49+
cleanup, err := makeTempWorkspace("hello.go")
50+
if err != nil {
51+
t.Fatal(err)
52+
}
53+
54+
if cleanup != nil {
55+
defer cleanup()
56+
}
57+
58+
tests := []struct {
59+
Pos int64
60+
Doc string
61+
}{
62+
{Pos: 23, Doc: "\tPackage fmt implements formatted I/O"}, // import "fmt"
63+
{Pos: 48, Doc: "Println formats using the default formats"}, // call fmt.Println()
64+
}
65+
66+
for _, test := range tests {
67+
ctx := build.Default
68+
doc, err := Run(&ctx, "hello.go", test.Pos)
69+
if err != nil {
70+
t.Fatal(err)
71+
}
72+
if !strings.HasPrefix(doc.Doc, test.Doc) {
73+
t.Errorf("want '%s', got '%s'", test.Doc, doc.Doc)
74+
}
75+
}
76+
}
77+
78+
func makeTempWorkspace(fileList ...string) (cleanup func(), err error) {
79+
cwd, err := os.Getwd()
80+
if err != nil {
81+
return nil, err
82+
}
83+
84+
tmpDir, err := ioutil.TempDir("", "gogetdoc-tmp")
85+
if err != nil {
86+
return nil, err
87+
}
88+
89+
for _, file := range fileList {
90+
err = copyFile(filepath.Join(tmpDir, file), filepath.FromSlash("./testdata/"+file))
91+
if err != nil {
92+
os.RemoveAll(tmpDir)
93+
return nil, err
94+
}
95+
}
96+
97+
err = os.Chdir(tmpDir)
98+
if err != nil {
99+
os.RemoveAll(tmpDir)
100+
return nil, err
101+
}
102+
103+
cleanup = func() {
104+
os.RemoveAll(tmpDir)
105+
os.Chdir(cwd)
106+
}
107+
return cleanup, nil
108+
}

testdata/hello.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package main
2+
3+
import "fmt"
4+
5+
func main() {
6+
fmt.Println("Hello, world!")
7+
}

0 commit comments

Comments
 (0)