protogen: annotate interface methods

Record annotations on methods in interface types (e.g., gRPC
server/client methods).

Generate annotations in golden tests, even when not checking the
content, to catch annotations without a corresponding symbol.

Change-Id: I44ae6caf66f709dc7f4686e931be04b8b6fa843d
Reviewed-on: https://go-review.googlesource.com/c/153877
Reviewed-by: Joe Tsai <thebrokentoaster@gmail.com>
diff --git a/internal/protogen/goldentest/goldentest.go b/internal/protogen/goldentest/goldentest.go
index 0902ad7..f8abc31 100644
--- a/internal/protogen/goldentest/goldentest.go
+++ b/internal/protogen/goldentest/goldentest.go
@@ -53,7 +53,7 @@
 
 	// Compile each package, using this binary as protoc-gen-go.
 	for _, sources := range packages {
-		args := []string{"-Itestdata", "--go_out=paths=source_relative:" + workdir}
+		args := []string{"-Itestdata", "--go_out=paths=source_relative,annotate_code:" + workdir}
 		args = append(args, sources...)
 		Protoc(t, args)
 	}
@@ -63,6 +63,9 @@
 		if info.IsDir() {
 			return nil
 		}
+		if strings.HasSuffix(genPath, ".meta") {
+			return nil
+		}
 
 		// For each generated file, figure out the path to the corresponding
 		// golden file in the testdata directory.
diff --git a/protogen/protogen.go b/protogen/protogen.go
index cdfccce..a2de5ac 100644
--- a/protogen/protogen.go
+++ b/protogen/protogen.go
@@ -1015,12 +1015,19 @@
 				switch spec := spec.(type) {
 				case *ast.TypeSpec:
 					annotate(spec.Name.Name, spec.Name)
-					if st, ok := spec.Type.(*ast.StructType); ok {
+					switch st := spec.Type.(type) {
+					case *ast.StructType:
 						for _, field := range st.Fields.List {
 							for _, name := range field.Names {
 								annotate(spec.Name.Name+"."+name.Name, name)
 							}
 						}
+					case *ast.InterfaceType:
+						for _, field := range st.Methods.List {
+							for _, name := range field.Names {
+								annotate(spec.Name.Name+"."+name.Name, name)
+							}
+						}
 					}
 				case *ast.ValueSpec:
 					for _, name := range spec.Names {