Don't generate import statements for unused imports.
R=r
http://codereview.appspot.com/979046
diff --git a/compiler/generator/generator.go b/compiler/generator/generator.go
index 5cef6f5..cbef5ed 100644
--- a/compiler/generator/generator.go
+++ b/compiler/generator/generator.go
@@ -251,7 +251,7 @@
// Generator is the type whose methods generate the output, stored in the associated response structure.
type Generator struct {
- bytes.Buffer
+ *bytes.Buffer
Request *plugin.CodeGeneratorRequest // The input.
Response *plugin.CodeGeneratorResponse // The output.
@@ -260,6 +260,7 @@
allFiles []*FileDescriptor // All files in the tree
genFiles []*FileDescriptor // Those files we will generate output for.
file *FileDescriptor // The file we are compiling now.
+ usedPackages map[string]bool // Names of packages used in current file.
typeNameToObject map[string]Object // Key is a fully-qualified name in input syntax.
indent string
}
@@ -267,6 +268,7 @@
// New creates a new generator and allocates the request and response protobufs.
func New() *Generator {
g := new(Generator)
+ g.Buffer = new(bytes.Buffer)
g.Request = plugin.NewCodeGeneratorRequest()
g.Response = plugin.NewCodeGeneratorResponse()
return g
@@ -573,8 +575,8 @@
// supposed to generate.
func (g *Generator) generate(file *FileDescriptor) {
g.file = g.FileOf(file.FileDescriptorProto)
- g.generateHeader()
- g.generateImports()
+ g.usedPackages = make(map[string]bool)
+
for _, enum := range g.file.enum {
g.generateEnum(enum)
}
@@ -585,6 +587,13 @@
g.generateExtension(ext)
}
g.generateInitFunction()
+
+ // Generate header and imports last, though they appear first in the output.
+ rem := g.Buffer
+ g.Buffer = new(bytes.Buffer)
+ g.generateHeader()
+ g.generateImports()
+ g.Write(rem.Bytes())
}
// Generate the header, including package definition and imports
@@ -609,7 +618,11 @@
if strings.HasSuffix(filename, ".go") {
filename = filename[0:len(filename)-3]
}
- g.P("import ", fd.PackageName(), " ", Quote(filename))
+ if _, ok := g.usedPackages[fd.PackageName()]; ok {
+ g.P("import ", fd.PackageName(), " ", Quote(filename))
+ } else {
+ log.Stderr("protoc-gen-go: discarding unused import: ", filename)
+ }
break
}
}
@@ -814,6 +827,12 @@
return
}
+func (g *Generator) RecordTypeUse(t string) {
+ if obj, ok := g.typeNameToObject[t]; ok {
+ g.usedPackages[obj.PackageName()] = true
+ }
+}
+
// Generate the type and default constant definitions for this Descriptor.
func (g *Generator) generateMessage(message *Descriptor) {
// The full type name
@@ -828,6 +847,7 @@
typename, wiretype := g.GoType(message, field)
tag := g.goTag(field, wiretype)
g.P(fieldname, "\t", typename, "\t", tag)
+ g.RecordTypeUse(proto.GetString(field.TypeName))
}
if len(message.ExtensionRange) > 0 {
g.P("XXX_extensions\t\tmap[int32][]byte")
@@ -927,6 +947,7 @@
field := ext.FieldDescriptorProto
fieldType, wireType := g.GoType(ext.parent, field)
tag := g.goTag(field, wireType)
+ g.RecordTypeUse(*ext.Extendee)
g.P("var ", ccTypeName, " = &proto.ExtensionDesc{")
g.In()