protogen: automatic handling of imports

The GoIdent type is now a tuple of import path and name. Generated files
have an associated import path. Writing a GoIdent to a generated file
qualifies the name if the identifier is from a different package.
All necessary imports are automatically added to generated Go files.

Change-Id: I839e0b7aa8ec967ce178aea4ffb960b62779cf74
Reviewed-on: https://go-review.googlesource.com/133635
Reviewed-by: Joe Tsai <thebrokentoaster@gmail.com>
diff --git a/protogen/protogen_test.go b/protogen/protogen_test.go
index 1d23cc0..4da5b3c 100644
--- a/protogen/protogen_test.go
+++ b/protogen/protogen_test.go
@@ -45,6 +45,57 @@
 	}
 }
 
+func TestImports(t *testing.T) {
+	gen, err := New(&pluginpb.CodeGeneratorRequest{})
+	if err != nil {
+		t.Fatal(err)
+	}
+	g := gen.NewGeneratedFile("foo.go", "golang.org/x/foo")
+	g.P("package foo")
+	g.P()
+	for _, importPath := range []GoImportPath{
+		"golang.org/x/foo",
+		// Multiple references to the same package.
+		"golang.org/x/bar",
+		"golang.org/x/bar",
+		// Reference to a different package with the same basename.
+		"golang.org/y/bar",
+		"golang.org/x/baz",
+	} {
+		g.P("var _ = ", GoIdent{GoName: "X", GoImportPath: importPath}, " // ", importPath)
+	}
+	want := `package foo
+
+import (
+	bar "golang.org/x/bar"
+	bar1 "golang.org/y/bar"
+	baz "golang.org/x/baz"
+)
+
+var _ = X      // "golang.org/x/foo"
+var _ = bar.X  // "golang.org/x/bar"
+var _ = bar.X  // "golang.org/x/bar"
+var _ = bar1.X // "golang.org/y/bar"
+var _ = baz.X  // "golang.org/x/baz"
+`
+	got, err := g.Content()
+	if err != nil {
+		t.Fatalf("g.Content() = %v", err)
+	}
+	if want != string(got) {
+		t.Fatalf(`want:
+==========
+%v
+==========
+
+got:
+==========
+%v
+==========`,
+			want, string(got))
+	}
+}
+
 // makeRequest returns a CodeGeneratorRequest for the given protoc inputs.
 //
 // It does this by running protoc with the current binary as the protoc-gen-go
@@ -86,7 +137,7 @@
 func init() {
 	if os.Getenv("RUN_AS_PROTOC_PLUGIN") != "" {
 		Run(func(p *Plugin) error {
-			g := p.NewGeneratedFile("request")
+			g := p.NewGeneratedFile("request", "")
 			return proto.MarshalText(g, p.Request)
 		})
 		os.Exit(0)