From c4b192b67b0491d303aa7863798d30b3f0b16a93 Mon Sep 17 00:00:00 2001 From: Clayton Coleman Date: Sun, 24 Apr 2016 19:11:54 -0400 Subject: [PATCH] Protobuf generation should strip empty-imports The imports are generated because the packages are in the search tree, but nothing in the generated code needs them. For now, strip them. --- .../go2idl/go-to-protobuf/protobuf/parser.go | 37 ++++++++++++++++++- 1 file changed, 35 insertions(+), 2 deletions(-) diff --git a/cmd/libs/go2idl/go-to-protobuf/protobuf/parser.go b/cmd/libs/go2idl/go-to-protobuf/protobuf/parser.go index 4da6e070730..4ac4b86a37d 100644 --- a/cmd/libs/go2idl/go-to-protobuf/protobuf/parser.go +++ b/cmd/libs/go2idl/go-to-protobuf/protobuf/parser.go @@ -81,9 +81,13 @@ func RewriteGeneratedGogoProtobufFile(name string, extractFn ExtractFunc, header // remove types that are already declared decls := []ast.Decl{} for _, d := range file.Decls { - if !dropExistingTypeDeclarations(d, extractFn) { - decls = append(decls, d) + if dropExistingTypeDeclarations(d, extractFn) { + continue } + if dropEmptyImportDeclarations(d) { + continue + } + decls = append(decls, d) } file.Decls = decls @@ -93,6 +97,8 @@ func RewriteGeneratedGogoProtobufFile(name string, extractFn ExtractFunc, header }) } +// dropExistingTypeDeclarations removes any type declaration for which extractFn returns true. The function +// returns true if the entire declaration should be dropped. func dropExistingTypeDeclarations(decl ast.Decl, extractFn ExtractFunc) bool { switch t := decl.(type) { case *ast.GenDecl: @@ -117,6 +123,33 @@ func dropExistingTypeDeclarations(decl ast.Decl, extractFn ExtractFunc) bool { return false } +// dropEmptyImportDeclarations strips any generated but no-op imports from the generated code +// to prevent generation from being able to define side-effects. The function returns true +// if the entire declaration should be dropped. +func dropEmptyImportDeclarations(decl ast.Decl) bool { + switch t := decl.(type) { + case *ast.GenDecl: + if t.Tok != token.IMPORT { + return false + } + specs := []ast.Spec{} + for _, s := range t.Specs { + switch spec := s.(type) { + case *ast.ImportSpec: + if spec.Name != nil && spec.Name.Name == "_" { + continue + } + specs = append(specs, spec) + } + } + if len(specs) == 0 { + return true + } + t.Specs = specs + } + return false +} + func RewriteTypesWithProtobufStructTags(name string, structTags map[string]map[string]string) error { return rewriteFile(name, []byte{}, func(fset *token.FileSet, file *ast.File) error { allErrs := []error{}