1a4debd8508a3334e3db296dd3cc77d9347fa718 — Drew DeVault 4 months ago 453e8b0
Add getopt options
3 files changed, 79 insertions(+), 10 deletions(-)

M go.mod
M go.sum
M main.go
M go.mod => go.mod +4 -1
@@ 2,4 2,7 @@
 
 go 1.12
 
-require golang.org/x/tools v0.0.0-20190706070813-72ffa07ba3db
+require (
+	git.sr.ht/~sircmpwn/getopt v0.0.0-20190621174457-292febf82fd0
+	golang.org/x/tools v0.0.0-20190706070813-72ffa07ba3db
+)

M go.sum => go.sum +6 -0
@@ 1,3 1,9 @@
+git.sr.ht/~sircmpwn/getopt v0.0.0-20190621174457-292febf82fd0 h1:gUeOEsT0mhoCKxKYJk8HeYtUZME686xs70eG2l80W5U=
+git.sr.ht/~sircmpwn/getopt v0.0.0-20190621174457-292febf82fd0/go.mod h1:wMEGFFFNuPos7vHmWXfszqImLppbc0wEhh6JBfJIUgw=
+github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
+github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
 golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
 golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=

M main.go => main.go +69 -9
@@ 12,6 12,8 @@
 	"os"
 	"os/exec"
 	"strings"
+
+	"git.sr.ht/~sircmpwn/getopt"
 )
 
 var cwd string


@@ 27,6 29,7 @@
 	Len    int     `json:"len"`
 	To     string  `json:"to"`
 	Title  *string `json:"title,omitempty"`
+	Color  *string `json:"color,omitempty"`
 }
 
 type MarkdownAnnotation struct {


@@ 82,11 85,48 @@
 	return m
 }
 
+func godocUrl(object types.Object) string {
+	var receiver string
+	pkg := object.Pkg()
+	if sig, ok := object.Type().(*types.Signature); ok {
+		if recv := sig.Recv(); recv != nil {
+			if ptr, ok := recv.Type().(*types.Pointer); ok {
+				if n, ok := ptr.Elem().(*types.Named); ok {
+					receiver = n.Obj().Name()
+				}
+			} else if n, ok := recv.Type().(*types.Named); ok {
+				receiver = n.Obj().Name()
+			}
+		}
+	}
+	if receiver != "" {
+		return fmt.Sprintf("https://godoc.org/%s#%s.%s",
+			pkg.Path(), receiver, object.Name())
+	}
+	return fmt.Sprintf("https://godoc.org/%s#%s", pkg.Path(), object.Name())
+}
+
 func main() {
+	var (
+		disableGodoc bool
+		enableTests  bool
+		enableVars   bool
+	)
+	getopt.BoolVar(&enableVars, "-v", false,
+		"Enables linking of variables to their declarations")
+	getopt.BoolVar(&disableGodoc, "-d", false,
+		"Disables linking to external symbols via Godoc")
+	getopt.BoolVar(&enableTests, "-T", false,
+		"Enables scanning of test files as well as normal code")
+	err := getopt.Parse()
+	if err != nil {
+		log.Fatalf("getopt: ", err)
+	}
+
 	log.SetFlags(0)
 	fset := token.NewFileSet()
 	conf := packages.Config{
-		// TODO: Configure other opts through command line
+		Tests: enableTests,
 		Fset: fset,
 		Mode: (packages.NeedName |
 			packages.NeedSyntax |


@@ 96,9 136,9 @@
 			packages.NeedDeps |
 			packages.NeedImports),
 	}
-	pkgs, err := packages.Load(&conf, os.Args[1:]...)
+	pkgs, err := packages.Load(&conf, getopt.Args()...)
 	if err != nil {
-		panic(err)
+		log.Fatal(err)
 	}
 	tree := crawlGitTree()
 	annotations := make(map[string][]interface{})


@@ 113,15 153,14 @@
 			}
 			length := ident.End() - ident.Pos()
 			filename = normalizePath(filename)
-			if tree != nil {
-				var ok bool
-				if filename, ok = tree[filename]; !ok {
-					continue
-				}
+			var ok bool
+			if filename, ok = tree[filename]; !ok {
+				continue
 			}
 			var (
-				to    string
+				color string
 				title string
+				to    string
 			)
 			switch object := object.(type) {
 			case *types.Func:


@@ 136,7 175,25 @@
 					path := normalizePath(fpos.Filename)
 					to = fmt.Sprintf("%s#L%d", path, fpos.Line)
 					title = object.FullName()
+				} else if object.Pkg() != nil && !disableGodoc {
+					to = godocUrl(object)
+					title = object.FullName() + " on Godoc"
+				}
+			case *types.Var:
+				if !enableVars {
+					break
 				}
+				tpos := fset.Position(object.Pos())
+				if tpos.IsValid() && strings.HasPrefix(tpos.Filename, cwd) {
+					/* Internal reference */
+					path := normalizePath(tpos.Filename)
+					to = fmt.Sprintf("%s#L%d", path, tpos.Line)
+					title = object.Name()
+				} else if object.Pkg() != nil && !disableGodoc {
+					to = godocUrl(object)
+					title = object.Name() + " on Godoc"
+				}
+				color = "transparent"
 			}
 			if to != "" {
 				if _, ok := annotations[filename]; !ok {


@@ 152,6 209,9 @@
 				if title != "" {
 					anno.Title = &title
 				}
+				if color != "" {
+					anno.Color = &color
+				}
 				annotations[filename] = append(annotations[filename], anno)
 			}
 		}