From d0d47bb94fcc018d03f47faa51f981b8902fc7cd Mon Sep 17 00:00:00 2001
From: Michael Fraenkel <michael.fraenkel@gmail.com>
Date: Wed, 23 May 2018 17:23:35 -0400
Subject: [PATCH] cmd/doc: continue to search when package import fails

Keep searching for a package that is both findable and importable. The
current code would always guarantee that a package was findable but
exited if it was not importable.

Fixes #25478

Change-Id: I237b7dfafb930cae02538c4a2e4d5ce0c1058478
Reviewed-on: https://go-review.googlesource.com/114295
Reviewed-by: Bryan C. Mills <bcmills@google.com>
Reviewed-by: Rob Pike <r@golang.org>
Run-TryBot: Bryan C. Mills <bcmills@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
---
 src/cmd/doc/doc_test.go                    | 20 ++++++++++++++-
 src/cmd/doc/main.go                        | 29 +++++++++++++++-------
 src/cmd/doc/testdata/nested/ignore.go      |  4 +++
 src/cmd/doc/testdata/nested/nested/real.go |  4 +++
 4 files changed, 47 insertions(+), 10 deletions(-)
 create mode 100644 src/cmd/doc/testdata/nested/ignore.go
 create mode 100644 src/cmd/doc/testdata/nested/nested/real.go

diff --git a/src/cmd/doc/doc_test.go b/src/cmd/doc/doc_test.go
index f1072b5e41..e68e95f3fb 100644
--- a/src/cmd/doc/doc_test.go
+++ b/src/cmd/doc/doc_test.go
@@ -26,7 +26,7 @@ func TestMain(m *testing.M) {
 	if err != nil {
 		panic(err)
 	}
-	dirsInit(testdataDir)
+	dirsInit(testdataDir, filepath.Join(testdataDir, "nested"), filepath.Join(testdataDir, "nested", "nested"))
 
 	os.Exit(m.Run())
 }
@@ -510,6 +510,24 @@ var tests = []test{
 			"\\)\n+const", // This will appear if the const decl appears twice.
 		},
 	},
+	{
+		"non-imported: pkg.sym",
+		[]string{"nested.Foo"},
+		[]string{"Foo struct"},
+		nil,
+	},
+	{
+		"non-imported: pkg only",
+		[]string{"nested"},
+		[]string{"Foo struct"},
+		nil,
+	},
+	{
+		"non-imported: pkg sym",
+		[]string{"nested", "Foo"},
+		[]string{"Foo struct"},
+		nil,
+	},
 }
 
 func TestDoc(t *testing.T) {
diff --git a/src/cmd/doc/main.go b/src/cmd/doc/main.go
index 9f947146a4..bf0c7723f8 100644
--- a/src/cmd/doc/main.go
+++ b/src/cmd/doc/main.go
@@ -189,11 +189,16 @@ func parseArgs(args []string) (pkg *build.Package, path, symbol string, more boo
 		// Done below.
 	case 2:
 		// Package must be findable and importable.
-		packagePath, ok := findPackage(arg)
-		if !ok {
-			return nil, args[0], args[1], false
+		for {
+			packagePath, ok := findNextPackage(arg)
+			if !ok {
+				break
+			}
+			if pkg, err := build.ImportDir(packagePath, build.ImportComment); err == nil {
+				return pkg, arg, args[1], true
+			}
 		}
-		return importDir(packagePath), arg, args[1], true
+		return nil, args[0], args[1], false
 	}
 	// Usual case: one argument.
 	// If it contains slashes, it begins with a package path.
@@ -241,9 +246,15 @@ func parseArgs(args []string) (pkg *build.Package, path, symbol string, more boo
 		}
 		// See if we have the basename or tail of a package, as in json for encoding/json
 		// or ivy/value for robpike.io/ivy/value.
-		path, ok := findPackage(arg[0:period])
-		if ok {
-			return importDir(path), arg[0:period], symbol, true
+		pkgName := arg[:period]
+		for {
+			path, ok := findNextPackage(pkgName)
+			if !ok {
+				break
+			}
+			if pkg, err = build.ImportDir(path, build.ImportComment); err == nil {
+				return pkg, arg[0:period], symbol, true
+			}
 		}
 		dirs.Reset() // Next iteration of for loop must scan all the directories again.
 	}
@@ -338,9 +349,9 @@ func isUpper(name string) bool {
 	return unicode.IsUpper(ch)
 }
 
-// findPackage returns the full file name path that first matches the
+// findNextPackage returns the next full file name path that matches the
 // (perhaps partial) package path pkg. The boolean reports if any match was found.
-func findPackage(pkg string) (string, bool) {
+func findNextPackage(pkg string) (string, bool) {
 	if pkg == "" || isUpper(pkg) { // Upper case symbol cannot be a package name.
 		return "", false
 	}
diff --git a/src/cmd/doc/testdata/nested/ignore.go b/src/cmd/doc/testdata/nested/ignore.go
new file mode 100644
index 0000000000..c497f1b5bc
--- /dev/null
+++ b/src/cmd/doc/testdata/nested/ignore.go
@@ -0,0 +1,4 @@
+// +build ignore
+
+// Ignored package
+package nested
diff --git a/src/cmd/doc/testdata/nested/nested/real.go b/src/cmd/doc/testdata/nested/nested/real.go
new file mode 100644
index 0000000000..1e5546081c
--- /dev/null
+++ b/src/cmd/doc/testdata/nested/nested/real.go
@@ -0,0 +1,4 @@
+package nested
+
+type Foo struct {
+}
-- 
2.30.9