Просмотр исходного кода

protoc-gen-go: handle package import names per-file (#543)

Rework the handling of imported packages.

Do not add imported protobuf packages to a global registry. Instead,
maintain a per-file list of packages and names. This avoids imports
in one file affecting the generated code in a second one.

Consistently deal with imports in terms of import path, rather than
source file. This avoids imports of two .proto files in the same
Go package producing redundant import statements.

Introduce ImportPath and PackageName types to prevent confusion about
which values contain import paths ("github.com/golang/protobuf/proto")
and which contain package names ("proto").

Convert many uses of FileDescriptorProto to FileDescriptor, for
consistency and general convenience.
Damien Neil 8 лет назад
Родитель
Сommit
9d4962b4dc

+ 66 - 66
_conformance/conformance.pb.go

@@ -6,12 +6,12 @@ package conformance
 import proto "github.com/golang/protobuf/proto"
 import proto "github.com/golang/protobuf/proto"
 import fmt "fmt"
 import fmt "fmt"
 import math "math"
 import math "math"
-import google_protobuf "github.com/golang/protobuf/ptypes/any"
-import google_protobuf1 "github.com/golang/protobuf/ptypes/duration"
-import google_protobuf2 "google.golang.org/genproto/protobuf"
-import google_protobuf3 "github.com/golang/protobuf/ptypes/struct"
-import google_protobuf4 "github.com/golang/protobuf/ptypes/timestamp"
-import google_protobuf5 "github.com/golang/protobuf/ptypes/wrappers"
+import any "github.com/golang/protobuf/ptypes/any"
+import duration "github.com/golang/protobuf/ptypes/duration"
+import _struct "github.com/golang/protobuf/ptypes/struct"
+import timestamp "github.com/golang/protobuf/ptypes/timestamp"
+import wrappers "github.com/golang/protobuf/ptypes/wrappers"
+import protobuf "google.golang.org/genproto/protobuf"
 
 
 // Reference imports to suppress errors if they are not otherwise used.
 // Reference imports to suppress errors if they are not otherwise used.
 var _ = proto.Marshal
 var _ = proto.Marshal
@@ -581,36 +581,36 @@ type TestAllTypes struct {
 	//	*TestAllTypes_OneofEnum
 	//	*TestAllTypes_OneofEnum
 	OneofField isTestAllTypes_OneofField `protobuf_oneof:"oneof_field"`
 	OneofField isTestAllTypes_OneofField `protobuf_oneof:"oneof_field"`
 	// Well-known types
 	// Well-known types
-	OptionalBoolWrapper   *google_protobuf5.BoolValue     `protobuf:"bytes,201,opt,name=optional_bool_wrapper,json=optionalBoolWrapper" json:"optional_bool_wrapper,omitempty"`
-	OptionalInt32Wrapper  *google_protobuf5.Int32Value    `protobuf:"bytes,202,opt,name=optional_int32_wrapper,json=optionalInt32Wrapper" json:"optional_int32_wrapper,omitempty"`
-	OptionalInt64Wrapper  *google_protobuf5.Int64Value    `protobuf:"bytes,203,opt,name=optional_int64_wrapper,json=optionalInt64Wrapper" json:"optional_int64_wrapper,omitempty"`
-	OptionalUint32Wrapper *google_protobuf5.UInt32Value   `protobuf:"bytes,204,opt,name=optional_uint32_wrapper,json=optionalUint32Wrapper" json:"optional_uint32_wrapper,omitempty"`
-	OptionalUint64Wrapper *google_protobuf5.UInt64Value   `protobuf:"bytes,205,opt,name=optional_uint64_wrapper,json=optionalUint64Wrapper" json:"optional_uint64_wrapper,omitempty"`
-	OptionalFloatWrapper  *google_protobuf5.FloatValue    `protobuf:"bytes,206,opt,name=optional_float_wrapper,json=optionalFloatWrapper" json:"optional_float_wrapper,omitempty"`
-	OptionalDoubleWrapper *google_protobuf5.DoubleValue   `protobuf:"bytes,207,opt,name=optional_double_wrapper,json=optionalDoubleWrapper" json:"optional_double_wrapper,omitempty"`
-	OptionalStringWrapper *google_protobuf5.StringValue   `protobuf:"bytes,208,opt,name=optional_string_wrapper,json=optionalStringWrapper" json:"optional_string_wrapper,omitempty"`
-	OptionalBytesWrapper  *google_protobuf5.BytesValue    `protobuf:"bytes,209,opt,name=optional_bytes_wrapper,json=optionalBytesWrapper" json:"optional_bytes_wrapper,omitempty"`
-	RepeatedBoolWrapper   []*google_protobuf5.BoolValue   `protobuf:"bytes,211,rep,name=repeated_bool_wrapper,json=repeatedBoolWrapper" json:"repeated_bool_wrapper,omitempty"`
-	RepeatedInt32Wrapper  []*google_protobuf5.Int32Value  `protobuf:"bytes,212,rep,name=repeated_int32_wrapper,json=repeatedInt32Wrapper" json:"repeated_int32_wrapper,omitempty"`
-	RepeatedInt64Wrapper  []*google_protobuf5.Int64Value  `protobuf:"bytes,213,rep,name=repeated_int64_wrapper,json=repeatedInt64Wrapper" json:"repeated_int64_wrapper,omitempty"`
-	RepeatedUint32Wrapper []*google_protobuf5.UInt32Value `protobuf:"bytes,214,rep,name=repeated_uint32_wrapper,json=repeatedUint32Wrapper" json:"repeated_uint32_wrapper,omitempty"`
-	RepeatedUint64Wrapper []*google_protobuf5.UInt64Value `protobuf:"bytes,215,rep,name=repeated_uint64_wrapper,json=repeatedUint64Wrapper" json:"repeated_uint64_wrapper,omitempty"`
-	RepeatedFloatWrapper  []*google_protobuf5.FloatValue  `protobuf:"bytes,216,rep,name=repeated_float_wrapper,json=repeatedFloatWrapper" json:"repeated_float_wrapper,omitempty"`
-	RepeatedDoubleWrapper []*google_protobuf5.DoubleValue `protobuf:"bytes,217,rep,name=repeated_double_wrapper,json=repeatedDoubleWrapper" json:"repeated_double_wrapper,omitempty"`
-	RepeatedStringWrapper []*google_protobuf5.StringValue `protobuf:"bytes,218,rep,name=repeated_string_wrapper,json=repeatedStringWrapper" json:"repeated_string_wrapper,omitempty"`
-	RepeatedBytesWrapper  []*google_protobuf5.BytesValue  `protobuf:"bytes,219,rep,name=repeated_bytes_wrapper,json=repeatedBytesWrapper" json:"repeated_bytes_wrapper,omitempty"`
-	OptionalDuration      *google_protobuf1.Duration      `protobuf:"bytes,301,opt,name=optional_duration,json=optionalDuration" json:"optional_duration,omitempty"`
-	OptionalTimestamp     *google_protobuf4.Timestamp     `protobuf:"bytes,302,opt,name=optional_timestamp,json=optionalTimestamp" json:"optional_timestamp,omitempty"`
-	OptionalFieldMask     *google_protobuf2.FieldMask     `protobuf:"bytes,303,opt,name=optional_field_mask,json=optionalFieldMask" json:"optional_field_mask,omitempty"`
-	OptionalStruct        *google_protobuf3.Struct        `protobuf:"bytes,304,opt,name=optional_struct,json=optionalStruct" json:"optional_struct,omitempty"`
-	OptionalAny           *google_protobuf.Any            `protobuf:"bytes,305,opt,name=optional_any,json=optionalAny" json:"optional_any,omitempty"`
-	OptionalValue         *google_protobuf3.Value         `protobuf:"bytes,306,opt,name=optional_value,json=optionalValue" json:"optional_value,omitempty"`
-	RepeatedDuration      []*google_protobuf1.Duration    `protobuf:"bytes,311,rep,name=repeated_duration,json=repeatedDuration" json:"repeated_duration,omitempty"`
-	RepeatedTimestamp     []*google_protobuf4.Timestamp   `protobuf:"bytes,312,rep,name=repeated_timestamp,json=repeatedTimestamp" json:"repeated_timestamp,omitempty"`
-	RepeatedFieldmask     []*google_protobuf2.FieldMask   `protobuf:"bytes,313,rep,name=repeated_fieldmask,json=repeatedFieldmask" json:"repeated_fieldmask,omitempty"`
-	RepeatedStruct        []*google_protobuf3.Struct      `protobuf:"bytes,324,rep,name=repeated_struct,json=repeatedStruct" json:"repeated_struct,omitempty"`
-	RepeatedAny           []*google_protobuf.Any          `protobuf:"bytes,315,rep,name=repeated_any,json=repeatedAny" json:"repeated_any,omitempty"`
-	RepeatedValue         []*google_protobuf3.Value       `protobuf:"bytes,316,rep,name=repeated_value,json=repeatedValue" json:"repeated_value,omitempty"`
+	OptionalBoolWrapper   *wrappers.BoolValue     `protobuf:"bytes,201,opt,name=optional_bool_wrapper,json=optionalBoolWrapper" json:"optional_bool_wrapper,omitempty"`
+	OptionalInt32Wrapper  *wrappers.Int32Value    `protobuf:"bytes,202,opt,name=optional_int32_wrapper,json=optionalInt32Wrapper" json:"optional_int32_wrapper,omitempty"`
+	OptionalInt64Wrapper  *wrappers.Int64Value    `protobuf:"bytes,203,opt,name=optional_int64_wrapper,json=optionalInt64Wrapper" json:"optional_int64_wrapper,omitempty"`
+	OptionalUint32Wrapper *wrappers.UInt32Value   `protobuf:"bytes,204,opt,name=optional_uint32_wrapper,json=optionalUint32Wrapper" json:"optional_uint32_wrapper,omitempty"`
+	OptionalUint64Wrapper *wrappers.UInt64Value   `protobuf:"bytes,205,opt,name=optional_uint64_wrapper,json=optionalUint64Wrapper" json:"optional_uint64_wrapper,omitempty"`
+	OptionalFloatWrapper  *wrappers.FloatValue    `protobuf:"bytes,206,opt,name=optional_float_wrapper,json=optionalFloatWrapper" json:"optional_float_wrapper,omitempty"`
+	OptionalDoubleWrapper *wrappers.DoubleValue   `protobuf:"bytes,207,opt,name=optional_double_wrapper,json=optionalDoubleWrapper" json:"optional_double_wrapper,omitempty"`
+	OptionalStringWrapper *wrappers.StringValue   `protobuf:"bytes,208,opt,name=optional_string_wrapper,json=optionalStringWrapper" json:"optional_string_wrapper,omitempty"`
+	OptionalBytesWrapper  *wrappers.BytesValue    `protobuf:"bytes,209,opt,name=optional_bytes_wrapper,json=optionalBytesWrapper" json:"optional_bytes_wrapper,omitempty"`
+	RepeatedBoolWrapper   []*wrappers.BoolValue   `protobuf:"bytes,211,rep,name=repeated_bool_wrapper,json=repeatedBoolWrapper" json:"repeated_bool_wrapper,omitempty"`
+	RepeatedInt32Wrapper  []*wrappers.Int32Value  `protobuf:"bytes,212,rep,name=repeated_int32_wrapper,json=repeatedInt32Wrapper" json:"repeated_int32_wrapper,omitempty"`
+	RepeatedInt64Wrapper  []*wrappers.Int64Value  `protobuf:"bytes,213,rep,name=repeated_int64_wrapper,json=repeatedInt64Wrapper" json:"repeated_int64_wrapper,omitempty"`
+	RepeatedUint32Wrapper []*wrappers.UInt32Value `protobuf:"bytes,214,rep,name=repeated_uint32_wrapper,json=repeatedUint32Wrapper" json:"repeated_uint32_wrapper,omitempty"`
+	RepeatedUint64Wrapper []*wrappers.UInt64Value `protobuf:"bytes,215,rep,name=repeated_uint64_wrapper,json=repeatedUint64Wrapper" json:"repeated_uint64_wrapper,omitempty"`
+	RepeatedFloatWrapper  []*wrappers.FloatValue  `protobuf:"bytes,216,rep,name=repeated_float_wrapper,json=repeatedFloatWrapper" json:"repeated_float_wrapper,omitempty"`
+	RepeatedDoubleWrapper []*wrappers.DoubleValue `protobuf:"bytes,217,rep,name=repeated_double_wrapper,json=repeatedDoubleWrapper" json:"repeated_double_wrapper,omitempty"`
+	RepeatedStringWrapper []*wrappers.StringValue `protobuf:"bytes,218,rep,name=repeated_string_wrapper,json=repeatedStringWrapper" json:"repeated_string_wrapper,omitempty"`
+	RepeatedBytesWrapper  []*wrappers.BytesValue  `protobuf:"bytes,219,rep,name=repeated_bytes_wrapper,json=repeatedBytesWrapper" json:"repeated_bytes_wrapper,omitempty"`
+	OptionalDuration      *duration.Duration      `protobuf:"bytes,301,opt,name=optional_duration,json=optionalDuration" json:"optional_duration,omitempty"`
+	OptionalTimestamp     *timestamp.Timestamp    `protobuf:"bytes,302,opt,name=optional_timestamp,json=optionalTimestamp" json:"optional_timestamp,omitempty"`
+	OptionalFieldMask     *protobuf.FieldMask     `protobuf:"bytes,303,opt,name=optional_field_mask,json=optionalFieldMask" json:"optional_field_mask,omitempty"`
+	OptionalStruct        *_struct.Struct         `protobuf:"bytes,304,opt,name=optional_struct,json=optionalStruct" json:"optional_struct,omitempty"`
+	OptionalAny           *any.Any                `protobuf:"bytes,305,opt,name=optional_any,json=optionalAny" json:"optional_any,omitempty"`
+	OptionalValue         *_struct.Value          `protobuf:"bytes,306,opt,name=optional_value,json=optionalValue" json:"optional_value,omitempty"`
+	RepeatedDuration      []*duration.Duration    `protobuf:"bytes,311,rep,name=repeated_duration,json=repeatedDuration" json:"repeated_duration,omitempty"`
+	RepeatedTimestamp     []*timestamp.Timestamp  `protobuf:"bytes,312,rep,name=repeated_timestamp,json=repeatedTimestamp" json:"repeated_timestamp,omitempty"`
+	RepeatedFieldmask     []*protobuf.FieldMask   `protobuf:"bytes,313,rep,name=repeated_fieldmask,json=repeatedFieldmask" json:"repeated_fieldmask,omitempty"`
+	RepeatedStruct        []*_struct.Struct       `protobuf:"bytes,324,rep,name=repeated_struct,json=repeatedStruct" json:"repeated_struct,omitempty"`
+	RepeatedAny           []*any.Any              `protobuf:"bytes,315,rep,name=repeated_any,json=repeatedAny" json:"repeated_any,omitempty"`
+	RepeatedValue         []*_struct.Value        `protobuf:"bytes,316,rep,name=repeated_value,json=repeatedValue" json:"repeated_value,omitempty"`
 	// Test field-name-to-JSON-name convention.
 	// Test field-name-to-JSON-name convention.
 	// (protobuf says names can be any valid C/C++ identifier.)
 	// (protobuf says names can be any valid C/C++ identifier.)
 	Fieldname1           int32    `protobuf:"varint,401,opt,name=fieldname1" json:"fieldname1,omitempty"`
 	Fieldname1           int32    `protobuf:"varint,401,opt,name=fieldname1" json:"fieldname1,omitempty"`
@@ -1206,210 +1206,210 @@ func (m *TestAllTypes) GetOneofEnum() TestAllTypes_NestedEnum {
 	return TestAllTypes_FOO
 	return TestAllTypes_FOO
 }
 }
 
 
-func (m *TestAllTypes) GetOptionalBoolWrapper() *google_protobuf5.BoolValue {
+func (m *TestAllTypes) GetOptionalBoolWrapper() *wrappers.BoolValue {
 	if m != nil {
 	if m != nil {
 		return m.OptionalBoolWrapper
 		return m.OptionalBoolWrapper
 	}
 	}
 	return nil
 	return nil
 }
 }
 
 
-func (m *TestAllTypes) GetOptionalInt32Wrapper() *google_protobuf5.Int32Value {
+func (m *TestAllTypes) GetOptionalInt32Wrapper() *wrappers.Int32Value {
 	if m != nil {
 	if m != nil {
 		return m.OptionalInt32Wrapper
 		return m.OptionalInt32Wrapper
 	}
 	}
 	return nil
 	return nil
 }
 }
 
 
-func (m *TestAllTypes) GetOptionalInt64Wrapper() *google_protobuf5.Int64Value {
+func (m *TestAllTypes) GetOptionalInt64Wrapper() *wrappers.Int64Value {
 	if m != nil {
 	if m != nil {
 		return m.OptionalInt64Wrapper
 		return m.OptionalInt64Wrapper
 	}
 	}
 	return nil
 	return nil
 }
 }
 
 
-func (m *TestAllTypes) GetOptionalUint32Wrapper() *google_protobuf5.UInt32Value {
+func (m *TestAllTypes) GetOptionalUint32Wrapper() *wrappers.UInt32Value {
 	if m != nil {
 	if m != nil {
 		return m.OptionalUint32Wrapper
 		return m.OptionalUint32Wrapper
 	}
 	}
 	return nil
 	return nil
 }
 }
 
 
-func (m *TestAllTypes) GetOptionalUint64Wrapper() *google_protobuf5.UInt64Value {
+func (m *TestAllTypes) GetOptionalUint64Wrapper() *wrappers.UInt64Value {
 	if m != nil {
 	if m != nil {
 		return m.OptionalUint64Wrapper
 		return m.OptionalUint64Wrapper
 	}
 	}
 	return nil
 	return nil
 }
 }
 
 
-func (m *TestAllTypes) GetOptionalFloatWrapper() *google_protobuf5.FloatValue {
+func (m *TestAllTypes) GetOptionalFloatWrapper() *wrappers.FloatValue {
 	if m != nil {
 	if m != nil {
 		return m.OptionalFloatWrapper
 		return m.OptionalFloatWrapper
 	}
 	}
 	return nil
 	return nil
 }
 }
 
 
-func (m *TestAllTypes) GetOptionalDoubleWrapper() *google_protobuf5.DoubleValue {
+func (m *TestAllTypes) GetOptionalDoubleWrapper() *wrappers.DoubleValue {
 	if m != nil {
 	if m != nil {
 		return m.OptionalDoubleWrapper
 		return m.OptionalDoubleWrapper
 	}
 	}
 	return nil
 	return nil
 }
 }
 
 
-func (m *TestAllTypes) GetOptionalStringWrapper() *google_protobuf5.StringValue {
+func (m *TestAllTypes) GetOptionalStringWrapper() *wrappers.StringValue {
 	if m != nil {
 	if m != nil {
 		return m.OptionalStringWrapper
 		return m.OptionalStringWrapper
 	}
 	}
 	return nil
 	return nil
 }
 }
 
 
-func (m *TestAllTypes) GetOptionalBytesWrapper() *google_protobuf5.BytesValue {
+func (m *TestAllTypes) GetOptionalBytesWrapper() *wrappers.BytesValue {
 	if m != nil {
 	if m != nil {
 		return m.OptionalBytesWrapper
 		return m.OptionalBytesWrapper
 	}
 	}
 	return nil
 	return nil
 }
 }
 
 
-func (m *TestAllTypes) GetRepeatedBoolWrapper() []*google_protobuf5.BoolValue {
+func (m *TestAllTypes) GetRepeatedBoolWrapper() []*wrappers.BoolValue {
 	if m != nil {
 	if m != nil {
 		return m.RepeatedBoolWrapper
 		return m.RepeatedBoolWrapper
 	}
 	}
 	return nil
 	return nil
 }
 }
 
 
-func (m *TestAllTypes) GetRepeatedInt32Wrapper() []*google_protobuf5.Int32Value {
+func (m *TestAllTypes) GetRepeatedInt32Wrapper() []*wrappers.Int32Value {
 	if m != nil {
 	if m != nil {
 		return m.RepeatedInt32Wrapper
 		return m.RepeatedInt32Wrapper
 	}
 	}
 	return nil
 	return nil
 }
 }
 
 
-func (m *TestAllTypes) GetRepeatedInt64Wrapper() []*google_protobuf5.Int64Value {
+func (m *TestAllTypes) GetRepeatedInt64Wrapper() []*wrappers.Int64Value {
 	if m != nil {
 	if m != nil {
 		return m.RepeatedInt64Wrapper
 		return m.RepeatedInt64Wrapper
 	}
 	}
 	return nil
 	return nil
 }
 }
 
 
-func (m *TestAllTypes) GetRepeatedUint32Wrapper() []*google_protobuf5.UInt32Value {
+func (m *TestAllTypes) GetRepeatedUint32Wrapper() []*wrappers.UInt32Value {
 	if m != nil {
 	if m != nil {
 		return m.RepeatedUint32Wrapper
 		return m.RepeatedUint32Wrapper
 	}
 	}
 	return nil
 	return nil
 }
 }
 
 
-func (m *TestAllTypes) GetRepeatedUint64Wrapper() []*google_protobuf5.UInt64Value {
+func (m *TestAllTypes) GetRepeatedUint64Wrapper() []*wrappers.UInt64Value {
 	if m != nil {
 	if m != nil {
 		return m.RepeatedUint64Wrapper
 		return m.RepeatedUint64Wrapper
 	}
 	}
 	return nil
 	return nil
 }
 }
 
 
-func (m *TestAllTypes) GetRepeatedFloatWrapper() []*google_protobuf5.FloatValue {
+func (m *TestAllTypes) GetRepeatedFloatWrapper() []*wrappers.FloatValue {
 	if m != nil {
 	if m != nil {
 		return m.RepeatedFloatWrapper
 		return m.RepeatedFloatWrapper
 	}
 	}
 	return nil
 	return nil
 }
 }
 
 
-func (m *TestAllTypes) GetRepeatedDoubleWrapper() []*google_protobuf5.DoubleValue {
+func (m *TestAllTypes) GetRepeatedDoubleWrapper() []*wrappers.DoubleValue {
 	if m != nil {
 	if m != nil {
 		return m.RepeatedDoubleWrapper
 		return m.RepeatedDoubleWrapper
 	}
 	}
 	return nil
 	return nil
 }
 }
 
 
-func (m *TestAllTypes) GetRepeatedStringWrapper() []*google_protobuf5.StringValue {
+func (m *TestAllTypes) GetRepeatedStringWrapper() []*wrappers.StringValue {
 	if m != nil {
 	if m != nil {
 		return m.RepeatedStringWrapper
 		return m.RepeatedStringWrapper
 	}
 	}
 	return nil
 	return nil
 }
 }
 
 
-func (m *TestAllTypes) GetRepeatedBytesWrapper() []*google_protobuf5.BytesValue {
+func (m *TestAllTypes) GetRepeatedBytesWrapper() []*wrappers.BytesValue {
 	if m != nil {
 	if m != nil {
 		return m.RepeatedBytesWrapper
 		return m.RepeatedBytesWrapper
 	}
 	}
 	return nil
 	return nil
 }
 }
 
 
-func (m *TestAllTypes) GetOptionalDuration() *google_protobuf1.Duration {
+func (m *TestAllTypes) GetOptionalDuration() *duration.Duration {
 	if m != nil {
 	if m != nil {
 		return m.OptionalDuration
 		return m.OptionalDuration
 	}
 	}
 	return nil
 	return nil
 }
 }
 
 
-func (m *TestAllTypes) GetOptionalTimestamp() *google_protobuf4.Timestamp {
+func (m *TestAllTypes) GetOptionalTimestamp() *timestamp.Timestamp {
 	if m != nil {
 	if m != nil {
 		return m.OptionalTimestamp
 		return m.OptionalTimestamp
 	}
 	}
 	return nil
 	return nil
 }
 }
 
 
-func (m *TestAllTypes) GetOptionalFieldMask() *google_protobuf2.FieldMask {
+func (m *TestAllTypes) GetOptionalFieldMask() *protobuf.FieldMask {
 	if m != nil {
 	if m != nil {
 		return m.OptionalFieldMask
 		return m.OptionalFieldMask
 	}
 	}
 	return nil
 	return nil
 }
 }
 
 
-func (m *TestAllTypes) GetOptionalStruct() *google_protobuf3.Struct {
+func (m *TestAllTypes) GetOptionalStruct() *_struct.Struct {
 	if m != nil {
 	if m != nil {
 		return m.OptionalStruct
 		return m.OptionalStruct
 	}
 	}
 	return nil
 	return nil
 }
 }
 
 
-func (m *TestAllTypes) GetOptionalAny() *google_protobuf.Any {
+func (m *TestAllTypes) GetOptionalAny() *any.Any {
 	if m != nil {
 	if m != nil {
 		return m.OptionalAny
 		return m.OptionalAny
 	}
 	}
 	return nil
 	return nil
 }
 }
 
 
-func (m *TestAllTypes) GetOptionalValue() *google_protobuf3.Value {
+func (m *TestAllTypes) GetOptionalValue() *_struct.Value {
 	if m != nil {
 	if m != nil {
 		return m.OptionalValue
 		return m.OptionalValue
 	}
 	}
 	return nil
 	return nil
 }
 }
 
 
-func (m *TestAllTypes) GetRepeatedDuration() []*google_protobuf1.Duration {
+func (m *TestAllTypes) GetRepeatedDuration() []*duration.Duration {
 	if m != nil {
 	if m != nil {
 		return m.RepeatedDuration
 		return m.RepeatedDuration
 	}
 	}
 	return nil
 	return nil
 }
 }
 
 
-func (m *TestAllTypes) GetRepeatedTimestamp() []*google_protobuf4.Timestamp {
+func (m *TestAllTypes) GetRepeatedTimestamp() []*timestamp.Timestamp {
 	if m != nil {
 	if m != nil {
 		return m.RepeatedTimestamp
 		return m.RepeatedTimestamp
 	}
 	}
 	return nil
 	return nil
 }
 }
 
 
-func (m *TestAllTypes) GetRepeatedFieldmask() []*google_protobuf2.FieldMask {
+func (m *TestAllTypes) GetRepeatedFieldmask() []*protobuf.FieldMask {
 	if m != nil {
 	if m != nil {
 		return m.RepeatedFieldmask
 		return m.RepeatedFieldmask
 	}
 	}
 	return nil
 	return nil
 }
 }
 
 
-func (m *TestAllTypes) GetRepeatedStruct() []*google_protobuf3.Struct {
+func (m *TestAllTypes) GetRepeatedStruct() []*_struct.Struct {
 	if m != nil {
 	if m != nil {
 		return m.RepeatedStruct
 		return m.RepeatedStruct
 	}
 	}
 	return nil
 	return nil
 }
 }
 
 
-func (m *TestAllTypes) GetRepeatedAny() []*google_protobuf.Any {
+func (m *TestAllTypes) GetRepeatedAny() []*any.Any {
 	if m != nil {
 	if m != nil {
 		return m.RepeatedAny
 		return m.RepeatedAny
 	}
 	}
 	return nil
 	return nil
 }
 }
 
 
-func (m *TestAllTypes) GetRepeatedValue() []*google_protobuf3.Value {
+func (m *TestAllTypes) GetRepeatedValue() []*_struct.Value {
 	if m != nil {
 	if m != nil {
 		return m.RepeatedValue
 		return m.RepeatedValue
 	}
 	}

+ 43 - 43
jsonpb/jsonpb_test_proto/test_objects.pb.go

@@ -6,11 +6,11 @@ package jsonpb
 import proto "github.com/golang/protobuf/proto"
 import proto "github.com/golang/protobuf/proto"
 import fmt "fmt"
 import fmt "fmt"
 import math "math"
 import math "math"
-import google_protobuf "github.com/golang/protobuf/ptypes/any"
-import google_protobuf1 "github.com/golang/protobuf/ptypes/duration"
-import google_protobuf2 "github.com/golang/protobuf/ptypes/struct"
-import google_protobuf3 "github.com/golang/protobuf/ptypes/timestamp"
-import google_protobuf4 "github.com/golang/protobuf/ptypes/wrappers"
+import any "github.com/golang/protobuf/ptypes/any"
+import duration "github.com/golang/protobuf/ptypes/duration"
+import _struct "github.com/golang/protobuf/ptypes/struct"
+import timestamp "github.com/golang/protobuf/ptypes/timestamp"
+import wrappers "github.com/golang/protobuf/ptypes/wrappers"
 
 
 // Reference imports to suppress errors if they are not otherwise used.
 // Reference imports to suppress errors if they are not otherwise used.
 var _ = proto.Marshal
 var _ = proto.Marshal
@@ -827,24 +827,24 @@ var E_Complex_RealExtension = &proto.ExtensionDesc{
 }
 }
 
 
 type KnownTypes struct {
 type KnownTypes struct {
-	An                   *google_protobuf.Any          `protobuf:"bytes,14,opt,name=an" json:"an,omitempty"`
-	Dur                  *google_protobuf1.Duration    `protobuf:"bytes,1,opt,name=dur" json:"dur,omitempty"`
-	St                   *google_protobuf2.Struct      `protobuf:"bytes,12,opt,name=st" json:"st,omitempty"`
-	Ts                   *google_protobuf3.Timestamp   `protobuf:"bytes,2,opt,name=ts" json:"ts,omitempty"`
-	Lv                   *google_protobuf2.ListValue   `protobuf:"bytes,15,opt,name=lv" json:"lv,omitempty"`
-	Val                  *google_protobuf2.Value       `protobuf:"bytes,16,opt,name=val" json:"val,omitempty"`
-	Dbl                  *google_protobuf4.DoubleValue `protobuf:"bytes,3,opt,name=dbl" json:"dbl,omitempty"`
-	Flt                  *google_protobuf4.FloatValue  `protobuf:"bytes,4,opt,name=flt" json:"flt,omitempty"`
-	I64                  *google_protobuf4.Int64Value  `protobuf:"bytes,5,opt,name=i64" json:"i64,omitempty"`
-	U64                  *google_protobuf4.UInt64Value `protobuf:"bytes,6,opt,name=u64" json:"u64,omitempty"`
-	I32                  *google_protobuf4.Int32Value  `protobuf:"bytes,7,opt,name=i32" json:"i32,omitempty"`
-	U32                  *google_protobuf4.UInt32Value `protobuf:"bytes,8,opt,name=u32" json:"u32,omitempty"`
-	Bool                 *google_protobuf4.BoolValue   `protobuf:"bytes,9,opt,name=bool" json:"bool,omitempty"`
-	Str                  *google_protobuf4.StringValue `protobuf:"bytes,10,opt,name=str" json:"str,omitempty"`
-	Bytes                *google_protobuf4.BytesValue  `protobuf:"bytes,11,opt,name=bytes" json:"bytes,omitempty"`
-	XXX_NoUnkeyedLiteral struct{}                      `json:"-"`
-	XXX_unrecognized     []byte                        `json:"-"`
-	XXX_sizecache        int32                         `json:"-"`
+	An                   *any.Any              `protobuf:"bytes,14,opt,name=an" json:"an,omitempty"`
+	Dur                  *duration.Duration    `protobuf:"bytes,1,opt,name=dur" json:"dur,omitempty"`
+	St                   *_struct.Struct       `protobuf:"bytes,12,opt,name=st" json:"st,omitempty"`
+	Ts                   *timestamp.Timestamp  `protobuf:"bytes,2,opt,name=ts" json:"ts,omitempty"`
+	Lv                   *_struct.ListValue    `protobuf:"bytes,15,opt,name=lv" json:"lv,omitempty"`
+	Val                  *_struct.Value        `protobuf:"bytes,16,opt,name=val" json:"val,omitempty"`
+	Dbl                  *wrappers.DoubleValue `protobuf:"bytes,3,opt,name=dbl" json:"dbl,omitempty"`
+	Flt                  *wrappers.FloatValue  `protobuf:"bytes,4,opt,name=flt" json:"flt,omitempty"`
+	I64                  *wrappers.Int64Value  `protobuf:"bytes,5,opt,name=i64" json:"i64,omitempty"`
+	U64                  *wrappers.UInt64Value `protobuf:"bytes,6,opt,name=u64" json:"u64,omitempty"`
+	I32                  *wrappers.Int32Value  `protobuf:"bytes,7,opt,name=i32" json:"i32,omitempty"`
+	U32                  *wrappers.UInt32Value `protobuf:"bytes,8,opt,name=u32" json:"u32,omitempty"`
+	Bool                 *wrappers.BoolValue   `protobuf:"bytes,9,opt,name=bool" json:"bool,omitempty"`
+	Str                  *wrappers.StringValue `protobuf:"bytes,10,opt,name=str" json:"str,omitempty"`
+	Bytes                *wrappers.BytesValue  `protobuf:"bytes,11,opt,name=bytes" json:"bytes,omitempty"`
+	XXX_NoUnkeyedLiteral struct{}              `json:"-"`
+	XXX_unrecognized     []byte                `json:"-"`
+	XXX_sizecache        int32                 `json:"-"`
 }
 }
 
 
 func (m *KnownTypes) Reset()         { *m = KnownTypes{} }
 func (m *KnownTypes) Reset()         { *m = KnownTypes{} }
@@ -871,105 +871,105 @@ func (m *KnownTypes) XXX_DiscardUnknown() {
 
 
 var xxx_messageInfo_KnownTypes proto.InternalMessageInfo
 var xxx_messageInfo_KnownTypes proto.InternalMessageInfo
 
 
-func (m *KnownTypes) GetAn() *google_protobuf.Any {
+func (m *KnownTypes) GetAn() *any.Any {
 	if m != nil {
 	if m != nil {
 		return m.An
 		return m.An
 	}
 	}
 	return nil
 	return nil
 }
 }
 
 
-func (m *KnownTypes) GetDur() *google_protobuf1.Duration {
+func (m *KnownTypes) GetDur() *duration.Duration {
 	if m != nil {
 	if m != nil {
 		return m.Dur
 		return m.Dur
 	}
 	}
 	return nil
 	return nil
 }
 }
 
 
-func (m *KnownTypes) GetSt() *google_protobuf2.Struct {
+func (m *KnownTypes) GetSt() *_struct.Struct {
 	if m != nil {
 	if m != nil {
 		return m.St
 		return m.St
 	}
 	}
 	return nil
 	return nil
 }
 }
 
 
-func (m *KnownTypes) GetTs() *google_protobuf3.Timestamp {
+func (m *KnownTypes) GetTs() *timestamp.Timestamp {
 	if m != nil {
 	if m != nil {
 		return m.Ts
 		return m.Ts
 	}
 	}
 	return nil
 	return nil
 }
 }
 
 
-func (m *KnownTypes) GetLv() *google_protobuf2.ListValue {
+func (m *KnownTypes) GetLv() *_struct.ListValue {
 	if m != nil {
 	if m != nil {
 		return m.Lv
 		return m.Lv
 	}
 	}
 	return nil
 	return nil
 }
 }
 
 
-func (m *KnownTypes) GetVal() *google_protobuf2.Value {
+func (m *KnownTypes) GetVal() *_struct.Value {
 	if m != nil {
 	if m != nil {
 		return m.Val
 		return m.Val
 	}
 	}
 	return nil
 	return nil
 }
 }
 
 
-func (m *KnownTypes) GetDbl() *google_protobuf4.DoubleValue {
+func (m *KnownTypes) GetDbl() *wrappers.DoubleValue {
 	if m != nil {
 	if m != nil {
 		return m.Dbl
 		return m.Dbl
 	}
 	}
 	return nil
 	return nil
 }
 }
 
 
-func (m *KnownTypes) GetFlt() *google_protobuf4.FloatValue {
+func (m *KnownTypes) GetFlt() *wrappers.FloatValue {
 	if m != nil {
 	if m != nil {
 		return m.Flt
 		return m.Flt
 	}
 	}
 	return nil
 	return nil
 }
 }
 
 
-func (m *KnownTypes) GetI64() *google_protobuf4.Int64Value {
+func (m *KnownTypes) GetI64() *wrappers.Int64Value {
 	if m != nil {
 	if m != nil {
 		return m.I64
 		return m.I64
 	}
 	}
 	return nil
 	return nil
 }
 }
 
 
-func (m *KnownTypes) GetU64() *google_protobuf4.UInt64Value {
+func (m *KnownTypes) GetU64() *wrappers.UInt64Value {
 	if m != nil {
 	if m != nil {
 		return m.U64
 		return m.U64
 	}
 	}
 	return nil
 	return nil
 }
 }
 
 
-func (m *KnownTypes) GetI32() *google_protobuf4.Int32Value {
+func (m *KnownTypes) GetI32() *wrappers.Int32Value {
 	if m != nil {
 	if m != nil {
 		return m.I32
 		return m.I32
 	}
 	}
 	return nil
 	return nil
 }
 }
 
 
-func (m *KnownTypes) GetU32() *google_protobuf4.UInt32Value {
+func (m *KnownTypes) GetU32() *wrappers.UInt32Value {
 	if m != nil {
 	if m != nil {
 		return m.U32
 		return m.U32
 	}
 	}
 	return nil
 	return nil
 }
 }
 
 
-func (m *KnownTypes) GetBool() *google_protobuf4.BoolValue {
+func (m *KnownTypes) GetBool() *wrappers.BoolValue {
 	if m != nil {
 	if m != nil {
 		return m.Bool
 		return m.Bool
 	}
 	}
 	return nil
 	return nil
 }
 }
 
 
-func (m *KnownTypes) GetStr() *google_protobuf4.StringValue {
+func (m *KnownTypes) GetStr() *wrappers.StringValue {
 	if m != nil {
 	if m != nil {
 		return m.Str
 		return m.Str
 	}
 	}
 	return nil
 	return nil
 }
 }
 
 
-func (m *KnownTypes) GetBytes() *google_protobuf4.BytesValue {
+func (m *KnownTypes) GetBytes() *wrappers.BytesValue {
 	if m != nil {
 	if m != nil {
 		return m.Bytes
 		return m.Bytes
 	}
 	}
@@ -1108,10 +1108,10 @@ func (m *MsgWithRequiredBytes) GetByts() []byte {
 }
 }
 
 
 type MsgWithRequiredWKT struct {
 type MsgWithRequiredWKT struct {
-	Str                  *google_protobuf4.StringValue `protobuf:"bytes,1,req,name=str" json:"str,omitempty"`
-	XXX_NoUnkeyedLiteral struct{}                      `json:"-"`
-	XXX_unrecognized     []byte                        `json:"-"`
-	XXX_sizecache        int32                         `json:"-"`
+	Str                  *wrappers.StringValue `protobuf:"bytes,1,req,name=str" json:"str,omitempty"`
+	XXX_NoUnkeyedLiteral struct{}              `json:"-"`
+	XXX_unrecognized     []byte                `json:"-"`
+	XXX_sizecache        int32                 `json:"-"`
 }
 }
 
 
 func (m *MsgWithRequiredWKT) Reset()         { *m = MsgWithRequiredWKT{} }
 func (m *MsgWithRequiredWKT) Reset()         { *m = MsgWithRequiredWKT{} }
@@ -1138,7 +1138,7 @@ func (m *MsgWithRequiredWKT) XXX_DiscardUnknown() {
 
 
 var xxx_messageInfo_MsgWithRequiredWKT proto.InternalMessageInfo
 var xxx_messageInfo_MsgWithRequiredWKT proto.InternalMessageInfo
 
 
-func (m *MsgWithRequiredWKT) GetStr() *google_protobuf4.StringValue {
+func (m *MsgWithRequiredWKT) GetStr() *wrappers.StringValue {
 	if m != nil {
 	if m != nil {
 		return m.Str
 		return m.Str
 	}
 	}

+ 171 - 184
protoc-gen-go/generator/generator.go

@@ -92,6 +92,12 @@ func RegisterPlugin(p Plugin) {
 	plugins = append(plugins, p)
 	plugins = append(plugins, p)
 }
 }
 
 
+// A GoImportPath is the import path of a Go package. e.g., "google.golang.org/genproto/protobuf".
+type GoImportPath string
+
+// A GoPackageName is the name of a Go package. e.g., "protobuf".
+type GoPackageName string
+
 // Each type we import as a protocol buffer (other than FileDescriptorProto) needs
 // Each type we import as a protocol buffer (other than FileDescriptorProto) needs
 // a pointer to the FileDescriptorProto that represents it.  These types achieve that
 // a pointer to the FileDescriptorProto that represents it.  These types achieve that
 // wrapping by placing each Proto inside a struct with the pointer to its File. The
 // wrapping by placing each Proto inside a struct with the pointer to its File. The
@@ -100,19 +106,21 @@ func RegisterPlugin(p Plugin) {
 
 
 // The file and package name method are common to messages and enums.
 // The file and package name method are common to messages and enums.
 type common struct {
 type common struct {
-	file *descriptor.FileDescriptorProto // File this object comes from.
+	file *FileDescriptor // File this object comes from.
 }
 }
 
 
-// PackageName is name in the package clause in the generated file.
-func (c *common) PackageName() string { return uniquePackageOf(c.file) }
+// GoImportPath is the import path of the Go package containing the type.
+func (c *common) GoImportPath() GoImportPath {
+	return c.file.importPath
+}
 
 
-func (c *common) File() *descriptor.FileDescriptorProto { return c.file }
+func (c *common) File() *FileDescriptor { return c.file }
 
 
 func fileIsProto3(file *descriptor.FileDescriptorProto) bool {
 func fileIsProto3(file *descriptor.FileDescriptorProto) bool {
 	return file.GetSyntax() == "proto3"
 	return file.GetSyntax() == "proto3"
 }
 }
 
 
-func (c *common) proto3() bool { return fileIsProto3(c.file) }
+func (c *common) proto3() bool { return fileIsProto3(c.file.FileDescriptorProto) }
 
 
 // Descriptor represents a protocol buffer message.
 // Descriptor represents a protocol buffer message.
 type Descriptor struct {
 type Descriptor struct {
@@ -260,14 +268,12 @@ type FileDescriptor struct {
 	// This is used for supporting public imports.
 	// This is used for supporting public imports.
 	exported map[Object][]symbol
 	exported map[Object][]symbol
 
 
-	fingerprint string // Fingerprint of this file's contents.
+	fingerprint string       // Fingerprint of this file's contents.
+	importPath  GoImportPath // Import path of this file's package.
 
 
 	proto3 bool // whether to generate proto3 code for this file
 	proto3 bool // whether to generate proto3 code for this file
 }
 }
 
 
-// PackageName is the package name we'll use in the generated code to refer to this file.
-func (d *FileDescriptor) PackageName() string { return uniquePackageOf(d.FileDescriptorProto) }
-
 // VarName is the variable name we'll use in the generated code to refer
 // VarName is the variable name we'll use in the generated code to refer
 // to the compressed bytes of this descriptor. It is not exported, so
 // to the compressed bytes of this descriptor. It is not exported, so
 // it is only valid inside the generated package.
 // it is only valid inside the generated package.
@@ -280,25 +286,22 @@ func (d *FileDescriptor) VarName() string {
 // If there is no go_package, it returns ("", "", false).
 // If there is no go_package, it returns ("", "", false).
 // If there's a simple name, it returns ("", pkg, true).
 // If there's a simple name, it returns ("", pkg, true).
 // If the option implies an import path, it returns (impPath, pkg, true).
 // If the option implies an import path, it returns (impPath, pkg, true).
-func (d *FileDescriptor) goPackageOption() (impPath, pkg string, ok bool) {
-	pkg = d.GetOptions().GetGoPackage()
-	if pkg == "" {
-		return
+func (d *FileDescriptor) goPackageOption() (impPath GoImportPath, pkg GoPackageName, ok bool) {
+	opt := d.GetOptions().GetGoPackage()
+	if opt == "" {
+		return "", "", false
 	}
 	}
-	ok = true
 	// The presence of a slash implies there's an import path.
 	// The presence of a slash implies there's an import path.
-	slash := strings.LastIndex(pkg, "/")
+	slash := strings.LastIndex(opt, "/")
 	if slash < 0 {
 	if slash < 0 {
-		return
+		return "", GoPackageName(opt), true
 	}
 	}
-	impPath, pkg = pkg, pkg[slash+1:]
 	// A semicolon-delimited suffix overrides the package name.
 	// A semicolon-delimited suffix overrides the package name.
-	sc := strings.IndexByte(impPath, ';')
+	sc := strings.Index(opt, ";")
 	if sc < 0 {
 	if sc < 0 {
-		return
+		return GoImportPath(opt), cleanPackageName(opt[slash+1:]), true
 	}
 	}
-	impPath, pkg = impPath[:sc], impPath[sc+1:]
-	return
+	return GoImportPath(opt[:sc]), cleanPackageName(opt[sc+1:]), true
 }
 }
 
 
 // goPackageName returns the Go package name to use in the
 // goPackageName returns the Go package name to use in the
@@ -306,18 +309,18 @@ func (d *FileDescriptor) goPackageOption() (impPath, pkg string, ok bool) {
 // came from an option go_package statement.  If explicit is false,
 // came from an option go_package statement.  If explicit is false,
 // the name was derived from the protocol buffer's package statement
 // the name was derived from the protocol buffer's package statement
 // or the input file name.
 // or the input file name.
-func (d *FileDescriptor) goPackageName() (name string, explicit bool) {
+func (d *FileDescriptor) goPackageName() (name GoPackageName, explicit bool) {
 	// Does the file have a "go_package" option?
 	// Does the file have a "go_package" option?
 	if _, pkg, ok := d.goPackageOption(); ok {
 	if _, pkg, ok := d.goPackageOption(); ok {
 		return pkg, true
 		return pkg, true
 	}
 	}
 
 
 	// Does the file have a package clause?
 	// Does the file have a package clause?
-	if pkg := d.GetPackage(); pkg != "" {
-		return pkg, false
+	if p := d.GetPackage(); p != "" {
+		return cleanPackageName(p), false
 	}
 	}
 	// Use the file base name.
 	// Use the file base name.
-	return baseName(d.GetName()), false
+	return cleanPackageName(baseName(d.GetName())), false
 }
 }
 
 
 // goFileName returns the output name for the generated Go file.
 // goFileName returns the output name for the generated Go file.
@@ -333,7 +336,7 @@ func (d *FileDescriptor) goFileName() string {
 	if impPath, _, ok := d.goPackageOption(); ok && impPath != "" {
 	if impPath, _, ok := d.goPackageOption(); ok && impPath != "" {
 		// Replace the existing dirname with the declared import path.
 		// Replace the existing dirname with the declared import path.
 		_, name = path.Split(name)
 		_, name = path.Split(name)
-		name = path.Join(impPath, name)
+		name = path.Join(string(impPath), name)
 		return name
 		return name
 	}
 	}
 
 
@@ -348,7 +351,7 @@ func (d *FileDescriptor) addExport(obj Object, sym symbol) {
 type symbol interface {
 type symbol interface {
 	// GenerateAlias should generate an appropriate alias
 	// GenerateAlias should generate an appropriate alias
 	// for the symbol from the named package.
 	// for the symbol from the named package.
-	GenerateAlias(g *Generator, pkg string)
+	GenerateAlias(g *Generator, pkg GoPackageName)
 }
 }
 
 
 type messageSymbol struct {
 type messageSymbol struct {
@@ -365,8 +368,8 @@ type getterSymbol struct {
 	genType  bool   // whether typ contains a generated type (message/group/enum)
 	genType  bool   // whether typ contains a generated type (message/group/enum)
 }
 }
 
 
-func (ms *messageSymbol) GenerateAlias(g *Generator, pkg string) {
-	remoteSym := pkg + "." + ms.sym
+func (ms *messageSymbol) GenerateAlias(g *Generator, pkg GoPackageName) {
+	remoteSym := string(pkg) + "." + ms.sym
 
 
 	g.P("type ", ms.sym, " ", remoteSym)
 	g.P("type ", ms.sym, " ", remoteSym)
 	g.P("func (m *", ms.sym, ") Reset() { (*", remoteSym, ")(m).Reset() }")
 	g.P("func (m *", ms.sym, ") Reset() { (*", remoteSym, ")(m).Reset() }")
@@ -513,7 +516,7 @@ type enumSymbol struct {
 	proto3 bool // Whether this came from a proto3 file.
 	proto3 bool // Whether this came from a proto3 file.
 }
 }
 
 
-func (es enumSymbol) GenerateAlias(g *Generator, pkg string) {
+func (es enumSymbol) GenerateAlias(g *Generator, pkg GoPackageName) {
 	s := es.name
 	s := es.name
 	g.P("type ", s, " ", pkg, ".", s)
 	g.P("type ", s, " ", pkg, ".", s)
 	g.P("var ", s, "_name = ", pkg, ".", s, "_name")
 	g.P("var ", s, "_name = ", pkg, ".", s, "_name")
@@ -531,8 +534,8 @@ type constOrVarSymbol struct {
 	cast string // if non-empty, a type cast is required (used for enums)
 	cast string // if non-empty, a type cast is required (used for enums)
 }
 }
 
 
-func (cs constOrVarSymbol) GenerateAlias(g *Generator, pkg string) {
-	v := pkg + "." + cs.sym
+func (cs constOrVarSymbol) GenerateAlias(g *Generator, pkg GoPackageName) {
+	v := string(pkg) + "." + cs.sym
 	if cs.cast != "" {
 	if cs.cast != "" {
 		v = cs.cast + "(" + v + ")"
 		v = cs.cast + "(" + v + ")"
 	}
 	}
@@ -541,21 +544,9 @@ func (cs constOrVarSymbol) GenerateAlias(g *Generator, pkg string) {
 
 
 // Object is an interface abstracting the abilities shared by enums, messages, extensions and imported objects.
 // Object is an interface abstracting the abilities shared by enums, messages, extensions and imported objects.
 type Object interface {
 type Object interface {
-	PackageName() string // The name we use in our output (a_b_c), possibly renamed for uniqueness.
+	GoImportPath() GoImportPath
 	TypeName() []string
 	TypeName() []string
-	File() *descriptor.FileDescriptorProto
-}
-
-// Each package name we generate must be unique. The package we're generating
-// gets its own name but every other package must have a unique name that does
-// not conflict in the code we generate.  These names are chosen globally (although
-// they don't have to be, it simplifies things to do them globally).
-func uniquePackageOf(fd *descriptor.FileDescriptorProto) string {
-	s, ok := uniquePackageName[fd]
-	if !ok {
-		log.Fatal("internal error: no package name defined for " + fd.GetName())
-	}
-	return s
+	File() *FileDescriptor
 }
 }
 
 
 // Generator is the type whose methods generate the output, stored in the associated response structure.
 // Generator is the type whose methods generate the output, stored in the associated response structure.
@@ -565,21 +556,23 @@ type Generator struct {
 	Request  *plugin.CodeGeneratorRequest  // The input.
 	Request  *plugin.CodeGeneratorRequest  // The input.
 	Response *plugin.CodeGeneratorResponse // The output.
 	Response *plugin.CodeGeneratorResponse // The output.
 
 
-	Param             map[string]string // Command-line parameters.
-	PackageImportPath string            // Go import path of the package we're generating code for
-	ImportPrefix      string            // String to prefix to imported package file names.
-	ImportMap         map[string]string // Mapping from .proto file name to import path
+	Param             map[string]string       // Command-line parameters.
+	PackageImportPath string                  // Go import path of the package we're generating code for
+	ImportPrefix      GoImportPath            // String to prefix to imported package file names.
+	ImportMap         map[string]GoImportPath // Mapping from .proto file name to import path
 
 
 	Pkg map[string]string // The names under which we import support packages
 	Pkg map[string]string // The names under which we import support packages
 
 
-	packageName      string                     // What we're calling ourselves.
-	allFiles         []*FileDescriptor          // All files in the tree
-	allFilesByName   map[string]*FileDescriptor // All files by filename.
-	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.
-	init             []string                   // Lines to emit in the init function.
+	packageName      GoPackageName                  // What we're calling ourselves.
+	allFiles         []*FileDescriptor              // All files in the tree
+	allFilesByName   map[string]*FileDescriptor     // All files by filename.
+	genFiles         []*FileDescriptor              // Those files we will generate output for.
+	file             *FileDescriptor                // The file we are compiling now.
+	packageNames     map[GoImportPath]GoPackageName // Imported package names in the current file.
+	usedPackages     map[GoImportPath]bool          // Packages used in current file.
+	usedPackageNames map[GoPackageName]bool         // Package names used in the current file.
+	typeNameToObject map[string]Object              // Key is a fully-qualified name in input syntax.
+	init             []string                       // Lines to emit in the init function.
 	indent           string
 	indent           string
 	writeOutput      bool
 	writeOutput      bool
 	annotateCode     bool                                       // whether to store annotations
 	annotateCode     bool                                       // whether to store annotations
@@ -622,12 +615,12 @@ func (g *Generator) CommandLineParameters(parameter string) {
 		}
 		}
 	}
 	}
 
 
-	g.ImportMap = make(map[string]string)
+	g.ImportMap = make(map[string]GoImportPath)
 	pluginList := "none" // Default list of plugin names to enable (empty means all).
 	pluginList := "none" // Default list of plugin names to enable (empty means all).
 	for k, v := range g.Param {
 	for k, v := range g.Param {
 		switch k {
 		switch k {
 		case "import_prefix":
 		case "import_prefix":
-			g.ImportPrefix = v
+			g.ImportPrefix = GoImportPath(v)
 		case "import_path":
 		case "import_path":
 			g.PackageImportPath = v
 			g.PackageImportPath = v
 		case "plugins":
 		case "plugins":
@@ -638,7 +631,7 @@ func (g *Generator) CommandLineParameters(parameter string) {
 			}
 			}
 		default:
 		default:
 			if len(k) > 0 && k[0] == 'M' {
 			if len(k) > 0 && k[0] == 'M' {
-				g.ImportMap[k[1:]] = v
+				g.ImportMap[k[1:]] = GoImportPath(v)
 			}
 			}
 		}
 		}
 	}
 	}
@@ -662,37 +655,42 @@ func (g *Generator) CommandLineParameters(parameter string) {
 // If its file is in a different package, it returns the package name we're using for this file, plus ".".
 // If its file is in a different package, it returns the package name we're using for this file, plus ".".
 // Otherwise it returns the empty string.
 // Otherwise it returns the empty string.
 func (g *Generator) DefaultPackageName(obj Object) string {
 func (g *Generator) DefaultPackageName(obj Object) string {
-	pkg := obj.PackageName()
-	if pkg == g.packageName {
+	importPath := obj.GoImportPath()
+	if importPath == g.file.importPath {
 		return ""
 		return ""
 	}
 	}
-	return pkg + "."
+	return string(g.GoPackageName(importPath)) + "."
 }
 }
 
 
-// For each input file, the unique package name to use, underscored.
-var uniquePackageName = make(map[*descriptor.FileDescriptorProto]string)
+// GoPackageName returns the name used for a package.
+func (g *Generator) GoPackageName(importPath GoImportPath) GoPackageName {
+	if name, ok := g.packageNames[importPath]; ok {
+		return name
+	}
+	name := cleanPackageName(baseName(string(importPath)))
+	for i, orig := 1, name; g.usedPackageNames[name]; i++ {
+		name = orig + GoPackageName(strconv.Itoa(i))
+	}
+	g.packageNames[importPath] = name
+	g.usedPackageNames[name] = true
+	return name
+}
 
 
-// Package names already registered.  Key is the name from the .proto file;
-// value is the name that appears in the generated code.
-var pkgNamesInUse = make(map[string]bool)
+var globalPackageNames = map[GoPackageName]bool{
+	"fmt":   true,
+	"math":  true,
+	"proto": true,
+}
 
 
-// Create and remember a guaranteed unique package name for this file descriptor.
-// Pkg is the candidate name.  If f is nil, it's a builtin package like "proto" and
-// has no file descriptor.
+// Create and remember a guaranteed unique package name. Pkg is the candidate name.
+// The FileDescriptor parameter is unused.
 func RegisterUniquePackageName(pkg string, f *FileDescriptor) string {
 func RegisterUniquePackageName(pkg string, f *FileDescriptor) string {
-	// Convert dots to underscores before finding a unique alias.
-	pkg = strings.Map(badToUnderscore, pkg)
-
-	for i, orig := 1, pkg; pkgNamesInUse[pkg]; i++ {
-		// It's a duplicate; must rename.
-		pkg = orig + strconv.Itoa(i)
-	}
-	// Install it.
-	pkgNamesInUse[pkg] = true
-	if f != nil {
-		uniquePackageName[f.FileDescriptorProto] = pkg
+	name := cleanPackageName(pkg)
+	for i, orig := 1, name; globalPackageNames[name]; i++ {
+		name = orig + GoPackageName(strconv.Itoa(i))
 	}
 	}
-	return pkg
+	globalPackageNames[name] = true
+	return string(name)
 }
 }
 
 
 var isGoKeyword = map[string]bool{
 var isGoKeyword = map[string]bool{
@@ -723,27 +721,27 @@ var isGoKeyword = map[string]bool{
 	"var":         true,
 	"var":         true,
 }
 }
 
 
+func cleanPackageName(name string) GoPackageName {
+	name = strings.Map(badToUnderscore, name)
+	// Identifier must not be keyword: insert _.
+	if isGoKeyword[name] {
+		name = "_" + name
+	}
+	// Identifier must not begin with digit: insert _.
+	if r, _ := utf8.DecodeRuneInString(name); unicode.IsDigit(r) {
+		name = "_" + name
+	}
+	return GoPackageName(name)
+}
+
 // defaultGoPackage returns the package name to use,
 // defaultGoPackage returns the package name to use,
 // derived from the import path of the package we're building code for.
 // derived from the import path of the package we're building code for.
-func (g *Generator) defaultGoPackage() string {
+func (g *Generator) defaultGoPackage() GoPackageName {
 	p := g.PackageImportPath
 	p := g.PackageImportPath
 	if i := strings.LastIndex(p, "/"); i >= 0 {
 	if i := strings.LastIndex(p, "/"); i >= 0 {
 		p = p[i+1:]
 		p = p[i+1:]
 	}
 	}
-	if p == "" {
-		return ""
-	}
-
-	p = strings.Map(badToUnderscore, p)
-	// Identifier must not be keyword: insert _.
-	if isGoKeyword[p] {
-		p = "_" + p
-	}
-	// Identifier must not begin with digit: insert _.
-	if r, _ := utf8.DecodeRuneInString(p); unicode.IsDigit(r) {
-		p = "_" + p
-	}
-	return p
+	return cleanPackageName(p)
 }
 }
 
 
 // SetPackageNames sets the package name for this run.
 // SetPackageNames sets the package name for this run.
@@ -762,7 +760,7 @@ func (g *Generator) SetPackageNames() {
 				// Let this file's go_package option serve for all input files.
 				// Let this file's go_package option serve for all input files.
 				pkg, explicit = thisPkg, true
 				pkg, explicit = thisPkg, true
 			} else if thisPkg != pkg {
 			} else if thisPkg != pkg {
-				g.Fail("inconsistent package names:", thisPkg, pkg)
+				g.Fail("inconsistent package names:", string(thisPkg), string(pkg))
 			}
 			}
 		}
 		}
 	}
 	}
@@ -783,37 +781,19 @@ func (g *Generator) SetPackageNames() {
 		for _, f := range g.genFiles {
 		for _, f := range g.genFiles {
 			thisPkg, _ := f.goPackageName()
 			thisPkg, _ := f.goPackageName()
 			if thisPkg != pkg {
 			if thisPkg != pkg {
-				g.Fail("inconsistent package names:", thisPkg, pkg)
+				g.Fail("inconsistent package names:", string(thisPkg), string(pkg))
 			}
 			}
 		}
 		}
 	}
 	}
 
 
-	g.packageName = RegisterUniquePackageName(pkg, g.genFiles[0])
+	g.packageName = pkg
 
 
-	// Register the support package names. They might collide with the
-	// name of a package we import.
+	// Names of support packages. These never vary (if there are conflicts,
+	// we rename the conflicting package), so this could be removed someday.
 	g.Pkg = map[string]string{
 	g.Pkg = map[string]string{
-		"fmt":   RegisterUniquePackageName("fmt", nil),
-		"math":  RegisterUniquePackageName("math", nil),
-		"proto": RegisterUniquePackageName("proto", nil),
-	}
-
-AllFiles:
-	for _, f := range g.allFiles {
-		for _, genf := range g.genFiles {
-			if f == genf {
-				// In this package already.
-				uniquePackageName[f.FileDescriptorProto] = g.packageName
-				continue AllFiles
-			}
-		}
-		// The file is a dependency, so we want to ignore its go_package option
-		// because that is only relevant for its specific generated output.
-		pkg := f.GetPackage()
-		if pkg == "" {
-			pkg = baseName(*f.Name)
-		}
-		RegisterUniquePackageName(pkg, f)
+		"fmt":   "fmt",
+		"math":  "math",
+		"proto": "proto",
 	}
 	}
 }
 }
 
 
@@ -824,26 +804,30 @@ func (g *Generator) WrapTypes() {
 	g.allFiles = make([]*FileDescriptor, 0, len(g.Request.ProtoFile))
 	g.allFiles = make([]*FileDescriptor, 0, len(g.Request.ProtoFile))
 	g.allFilesByName = make(map[string]*FileDescriptor, len(g.allFiles))
 	g.allFilesByName = make(map[string]*FileDescriptor, len(g.allFiles))
 	for _, f := range g.Request.ProtoFile {
 	for _, f := range g.Request.ProtoFile {
-		// We must wrap the descriptors before we wrap the enums
-		descs := wrapDescriptors(f)
-		g.buildNestedDescriptors(descs)
-		enums := wrapEnumDescriptors(f, descs)
-		g.buildNestedEnums(descs, enums)
-		exts := wrapExtensions(f)
 		fd := &FileDescriptor{
 		fd := &FileDescriptor{
 			FileDescriptorProto: f,
 			FileDescriptorProto: f,
-			desc:                descs,
-			enum:                enums,
-			ext:                 exts,
 			exported:            make(map[Object][]symbol),
 			exported:            make(map[Object][]symbol),
 			proto3:              fileIsProto3(f),
 			proto3:              fileIsProto3(f),
 		}
 		}
+		if substitution, ok := g.ImportMap[f.GetName()]; ok {
+			fd.importPath = substitution
+		} else if p, _, _ := fd.goPackageOption(); p != "" {
+			fd.importPath = p
+		} else {
+			fd.importPath = GoImportPath(path.Dir(f.GetName()))
+		}
+		// We must wrap the descriptors before we wrap the enums
+		fd.desc = wrapDescriptors(fd)
+		g.buildNestedDescriptors(fd.desc)
+		fd.enum = wrapEnumDescriptors(fd, fd.desc)
+		g.buildNestedEnums(fd.desc, fd.enum)
+		fd.ext = wrapExtensions(fd)
 		extractComments(fd)
 		extractComments(fd)
 		g.allFiles = append(g.allFiles, fd)
 		g.allFiles = append(g.allFiles, fd)
 		g.allFilesByName[f.GetName()] = fd
 		g.allFilesByName[f.GetName()] = fd
 	}
 	}
 	for _, fd := range g.allFiles {
 	for _, fd := range g.allFiles {
-		fd.imp = wrapImported(fd.FileDescriptorProto, g)
+		fd.imp = wrapImported(fd, g)
 	}
 	}
 
 
 	g.genFiles = make([]*FileDescriptor, 0, len(g.Request.FileToGenerate))
 	g.genFiles = make([]*FileDescriptor, 0, len(g.Request.FileToGenerate))
@@ -905,7 +889,7 @@ func (g *Generator) buildNestedEnums(descs []*Descriptor, enums []*EnumDescripto
 }
 }
 
 
 // Construct the Descriptor
 // Construct the Descriptor
-func newDescriptor(desc *descriptor.DescriptorProto, parent *Descriptor, file *descriptor.FileDescriptorProto, index int) *Descriptor {
+func newDescriptor(desc *descriptor.DescriptorProto, parent *Descriptor, file *FileDescriptor, index int) *Descriptor {
 	d := &Descriptor{
 	d := &Descriptor{
 		common:          common{file},
 		common:          common{file},
 		DescriptorProto: desc,
 		DescriptorProto: desc,
@@ -942,7 +926,7 @@ func newDescriptor(desc *descriptor.DescriptorProto, parent *Descriptor, file *d
 }
 }
 
 
 // Return a slice of all the Descriptors defined within this file
 // Return a slice of all the Descriptors defined within this file
-func wrapDescriptors(file *descriptor.FileDescriptorProto) []*Descriptor {
+func wrapDescriptors(file *FileDescriptor) []*Descriptor {
 	sl := make([]*Descriptor, 0, len(file.MessageType)+10)
 	sl := make([]*Descriptor, 0, len(file.MessageType)+10)
 	for i, desc := range file.MessageType {
 	for i, desc := range file.MessageType {
 		sl = wrapThisDescriptor(sl, desc, nil, file, i)
 		sl = wrapThisDescriptor(sl, desc, nil, file, i)
@@ -951,7 +935,7 @@ func wrapDescriptors(file *descriptor.FileDescriptorProto) []*Descriptor {
 }
 }
 
 
 // Wrap this Descriptor, recursively
 // Wrap this Descriptor, recursively
-func wrapThisDescriptor(sl []*Descriptor, desc *descriptor.DescriptorProto, parent *Descriptor, file *descriptor.FileDescriptorProto, index int) []*Descriptor {
+func wrapThisDescriptor(sl []*Descriptor, desc *descriptor.DescriptorProto, parent *Descriptor, file *FileDescriptor, index int) []*Descriptor {
 	sl = append(sl, newDescriptor(desc, parent, file, index))
 	sl = append(sl, newDescriptor(desc, parent, file, index))
 	me := sl[len(sl)-1]
 	me := sl[len(sl)-1]
 	for i, nested := range desc.NestedType {
 	for i, nested := range desc.NestedType {
@@ -961,7 +945,7 @@ func wrapThisDescriptor(sl []*Descriptor, desc *descriptor.DescriptorProto, pare
 }
 }
 
 
 // Construct the EnumDescriptor
 // Construct the EnumDescriptor
-func newEnumDescriptor(desc *descriptor.EnumDescriptorProto, parent *Descriptor, file *descriptor.FileDescriptorProto, index int) *EnumDescriptor {
+func newEnumDescriptor(desc *descriptor.EnumDescriptorProto, parent *Descriptor, file *FileDescriptor, index int) *EnumDescriptor {
 	ed := &EnumDescriptor{
 	ed := &EnumDescriptor{
 		common:              common{file},
 		common:              common{file},
 		EnumDescriptorProto: desc,
 		EnumDescriptorProto: desc,
@@ -977,7 +961,7 @@ func newEnumDescriptor(desc *descriptor.EnumDescriptorProto, parent *Descriptor,
 }
 }
 
 
 // Return a slice of all the EnumDescriptors defined within this file
 // Return a slice of all the EnumDescriptors defined within this file
-func wrapEnumDescriptors(file *descriptor.FileDescriptorProto, descs []*Descriptor) []*EnumDescriptor {
+func wrapEnumDescriptors(file *FileDescriptor, descs []*Descriptor) []*EnumDescriptor {
 	sl := make([]*EnumDescriptor, 0, len(file.EnumType)+10)
 	sl := make([]*EnumDescriptor, 0, len(file.EnumType)+10)
 	// Top-level enums.
 	// Top-level enums.
 	for i, enum := range file.EnumType {
 	for i, enum := range file.EnumType {
@@ -993,7 +977,7 @@ func wrapEnumDescriptors(file *descriptor.FileDescriptorProto, descs []*Descript
 }
 }
 
 
 // Return a slice of all the top-level ExtensionDescriptors defined within this file.
 // Return a slice of all the top-level ExtensionDescriptors defined within this file.
-func wrapExtensions(file *descriptor.FileDescriptorProto) []*ExtensionDescriptor {
+func wrapExtensions(file *FileDescriptor) []*ExtensionDescriptor {
 	var sl []*ExtensionDescriptor
 	var sl []*ExtensionDescriptor
 	for _, field := range file.Extension {
 	for _, field := range file.Extension {
 		sl = append(sl, &ExtensionDescriptor{common{file}, field, nil})
 		sl = append(sl, &ExtensionDescriptor{common{file}, field, nil})
@@ -1002,7 +986,7 @@ func wrapExtensions(file *descriptor.FileDescriptorProto) []*ExtensionDescriptor
 }
 }
 
 
 // Return a slice of all the types that are publicly imported into this file.
 // Return a slice of all the types that are publicly imported into this file.
-func wrapImported(file *descriptor.FileDescriptorProto, g *Generator) (sl []*ImportedDescriptor) {
+func wrapImported(file *FileDescriptor, g *Generator) (sl []*ImportedDescriptor) {
 	for _, index := range file.PublicDependency {
 	for _, index := range file.PublicDependency {
 		df := g.fileByName(file.Dependency[index])
 		df := g.fileByName(file.Dependency[index])
 		for _, d := range df.desc {
 		for _, d := range df.desc {
@@ -1111,7 +1095,7 @@ type AnnotatedAtoms struct {
 
 
 // Annotate records the file name and proto AST path of a list of atoms
 // Annotate records the file name and proto AST path of a list of atoms
 // so that a later call to P can emit a link from each atom to its origin.
 // so that a later call to P can emit a link from each atom to its origin.
-func Annotate(file *descriptor.FileDescriptorProto, path string, atoms ...interface{}) *AnnotatedAtoms {
+func Annotate(file *FileDescriptor, path string, atoms ...interface{}) *AnnotatedAtoms {
 	return &AnnotatedAtoms{source: *file.Name, path: path, atoms: atoms}
 	return &AnnotatedAtoms{source: *file.Name, path: path, atoms: atoms}
 }
 }
 
 
@@ -1136,6 +1120,10 @@ func (g *Generator) printAtom(v interface{}) {
 		fmt.Fprint(g, v)
 		fmt.Fprint(g, v)
 	case *float64:
 	case *float64:
 		fmt.Fprint(g, *v)
 		fmt.Fprint(g, *v)
+	case GoPackageName:
+		g.WriteString(string(v))
+	case GoImportPath:
+		g.WriteString(strconv.Quote(string(v)))
 	default:
 	default:
 		g.Fail(fmt.Sprintf("unknown type in printer: %T", v))
 		g.Fail(fmt.Sprintf("unknown type in printer: %T", v))
 	}
 	}
@@ -1241,22 +1229,16 @@ func (g *Generator) runPlugins(file *FileDescriptor) {
 	}
 	}
 }
 }
 
 
-// FileOf return the FileDescriptor for this FileDescriptorProto.
-func (g *Generator) FileOf(fd *descriptor.FileDescriptorProto) *FileDescriptor {
-	for _, file := range g.allFiles {
-		if file.FileDescriptorProto == fd {
-			return file
-		}
-	}
-	g.Fail("could not find file in table:", fd.GetName())
-	return nil
-}
-
 // Fill the response protocol buffer with the generated output for all the files we're
 // Fill the response protocol buffer with the generated output for all the files we're
 // supposed to generate.
 // supposed to generate.
 func (g *Generator) generate(file *FileDescriptor) {
 func (g *Generator) generate(file *FileDescriptor) {
-	g.file = g.FileOf(file.FileDescriptorProto)
-	g.usedPackages = make(map[string]bool)
+	g.file = file
+	g.usedPackages = make(map[GoImportPath]bool)
+	g.packageNames = make(map[GoImportPath]GoPackageName)
+	g.usedPackageNames = make(map[GoPackageName]bool)
+	for name := range globalPackageNames {
+		g.usedPackageNames[name] = true
+	}
 
 
 	g.P("// This is a compile-time assertion to ensure that this generated file")
 	g.P("// This is a compile-time assertion to ensure that this generated file")
 	g.P("// is compatible with the proto package it is being compiled against.")
 	g.P("// is compatible with the proto package it is being compiled against.")
@@ -1356,12 +1338,12 @@ func (g *Generator) generateHeader() {
 	}
 	}
 	g.P()
 	g.P()
 
 
-	name := g.file.PackageName()
+	name, _ := g.file.goPackageName()
 	importPath, _, haveImportPath := g.file.goPackageOption()
 	importPath, _, haveImportPath := g.file.goPackageOption()
 	if !haveImportPath {
 	if !haveImportPath {
 		g.P("package ", name)
 		g.P("package ", name)
 	} else {
 	} else {
-		g.P("package ", name, " // import ", strconv.Quote(g.ImportPrefix+importPath))
+		g.P("package ", name, " // import ", g.ImportPrefix+importPath)
 	}
 	}
 	g.P()
 	g.P()
 
 
@@ -1421,35 +1403,46 @@ func (g *Generator) generateImports() {
 	// We almost always need a proto import.  Rather than computing when we
 	// We almost always need a proto import.  Rather than computing when we
 	// do, which is tricky when there's a plugin, just import it and
 	// do, which is tricky when there's a plugin, just import it and
 	// reference it later. The same argument applies to the fmt and math packages.
 	// reference it later. The same argument applies to the fmt and math packages.
-	g.P("import " + g.Pkg["proto"] + " " + strconv.Quote(g.ImportPrefix+"github.com/golang/protobuf/proto"))
+	g.P("import "+g.Pkg["proto"]+" ", g.ImportPrefix+"github.com/golang/protobuf/proto")
 	g.P("import " + g.Pkg["fmt"] + ` "fmt"`)
 	g.P("import " + g.Pkg["fmt"] + ` "fmt"`)
 	g.P("import " + g.Pkg["math"] + ` "math"`)
 	g.P("import " + g.Pkg["math"] + ` "math"`)
+	var (
+		imports       = make(map[GoImportPath]bool)
+		strongImports = make(map[GoImportPath]bool)
+		importPaths   []string
+	)
 	for i, s := range g.file.Dependency {
 	for i, s := range g.file.Dependency {
 		fd := g.fileByName(s)
 		fd := g.fileByName(s)
+		importPath := fd.importPath
 		// Do not import our own package.
 		// Do not import our own package.
-		if fd.PackageName() == g.packageName {
+		if importPath == g.file.importPath {
 			continue
 			continue
 		}
 		}
-		filename := fd.goFileName()
-		// By default, import path is the dirname of the Go filename.
-		importPath := path.Dir(filename)
-		if substitution, ok := g.ImportMap[s]; ok {
-			importPath = substitution
+		if !imports[importPath] {
+			importPaths = append(importPaths, string(importPath))
+		}
+		imports[importPath] = true
+		if !g.weak(int32(i)) {
+			strongImports[importPath] = true
 		}
 		}
-		importPath = g.ImportPrefix + importPath
+	}
+	sort.Strings(importPaths)
+	for i := range importPaths {
+		importPath := GoImportPath(importPaths[i])
+		packageName := g.GoPackageName(importPath)
+		fullPath := g.ImportPrefix + importPath
 		// Skip weak imports.
 		// Skip weak imports.
-		if g.weak(int32(i)) {
-			g.P("// skipping weak import ", fd.PackageName(), " ", strconv.Quote(importPath))
+		if !strongImports[importPath] {
+			g.P("// skipping weak import ", packageName, " ", fullPath)
 			continue
 			continue
 		}
 		}
 		// We need to import all the dependencies, even if we don't reference them,
 		// We need to import all the dependencies, even if we don't reference them,
 		// because other code and tools depend on having the full transitive closure
 		// because other code and tools depend on having the full transitive closure
 		// of protocol buffer types in the binary.
 		// of protocol buffer types in the binary.
-		pname := fd.PackageName()
-		if _, ok := g.usedPackages[pname]; !ok {
-			pname = "_"
+		if _, ok := g.usedPackages[importPath]; !ok {
+			packageName = "_"
 		}
 		}
-		g.P("import ", pname, " ", strconv.Quote(importPath))
+		g.P("import ", packageName, " ", fullPath)
 	}
 	}
 	g.P()
 	g.P()
 	// TODO: may need to worry about uniqueness across plugins
 	// TODO: may need to worry about uniqueness across plugins
@@ -1471,7 +1464,7 @@ func (g *Generator) generateImported(id *ImportedDescriptor) {
 	// because g.genFiles isn't populated at that stage.
 	// because g.genFiles isn't populated at that stage.
 	tn := id.TypeName()
 	tn := id.TypeName()
 	sn := tn[len(tn)-1]
 	sn := tn[len(tn)-1]
-	df := g.FileOf(id.o.File())
+	df := id.o.File()
 	filename := *df.Name
 	filename := *df.Name
 	for _, fd := range g.genFiles {
 	for _, fd := range g.genFiles {
 		if *fd.Name == filename {
 		if *fd.Name == filename {
@@ -1481,10 +1474,10 @@ func (g *Generator) generateImported(id *ImportedDescriptor) {
 		}
 		}
 	}
 	}
 	g.P("// ", sn, " from public import ", filename)
 	g.P("// ", sn, " from public import ", filename)
-	g.usedPackages[df.PackageName()] = true
+	g.usedPackages[df.importPath] = true
 
 
 	for _, sym := range df.exported[id.o] {
 	for _, sym := range df.exported[id.o] {
-		sym.GenerateAlias(g, df.PackageName())
+		sym.GenerateAlias(g, g.GoPackageName(df.importPath))
 	}
 	}
 
 
 	g.P()
 	g.P()
@@ -1651,7 +1644,7 @@ func (g *Generator) goTag(message *Descriptor, field *descriptor.FieldDescriptor
 	}
 	}
 	enum := ""
 	enum := ""
 	if *field.Type == descriptor.FieldDescriptorProto_TYPE_ENUM {
 	if *field.Type == descriptor.FieldDescriptorProto_TYPE_ENUM {
-		// We avoid using obj.PackageName(), because we want to use the
+		// We avoid using obj.GoPackageName(), because we want to use the
 		// original (proto-world) package name.
 		// original (proto-world) package name.
 		obj := g.ObjectNamed(field.GetTypeName())
 		obj := g.ObjectNamed(field.GetTypeName())
 		if id, ok := obj.(*ImportedDescriptor); ok {
 		if id, ok := obj.(*ImportedDescriptor); ok {
@@ -1733,12 +1726,6 @@ func (g *Generator) TypeName(obj Object) string {
 	return g.DefaultPackageName(obj) + CamelCaseSlice(obj.TypeName())
 	return g.DefaultPackageName(obj) + CamelCaseSlice(obj.TypeName())
 }
 }
 
 
-// TypeNameWithPackage is like TypeName, but always includes the package
-// name even if the object is in our own package.
-func (g *Generator) TypeNameWithPackage(obj Object) string {
-	return obj.PackageName() + CamelCaseSlice(obj.TypeName())
-}
-
 // GoType returns a string representing the type name, and the wire type
 // GoType returns a string representing the type name, and the wire type
 func (g *Generator) GoType(message *Descriptor, field *descriptor.FieldDescriptorProto) (typ string, wire string) {
 func (g *Generator) GoType(message *Descriptor, field *descriptor.FieldDescriptorProto) (typ string, wire string) {
 	// TODO: Options.
 	// TODO: Options.
@@ -1801,7 +1788,7 @@ func (g *Generator) RecordTypeUse(t string) {
 	if _, ok := g.typeNameToObject[t]; ok {
 	if _, ok := g.typeNameToObject[t]; ok {
 		// Call ObjectNamed to get the true object to record the use.
 		// Call ObjectNamed to get the true object to record the use.
 		obj := g.ObjectNamed(t)
 		obj := g.ObjectNamed(t)
-		g.usedPackages[obj.PackageName()] = true
+		g.usedPackages[obj.GoImportPath()] = true
 	}
 	}
 }
 }
 
 
@@ -2279,7 +2266,7 @@ func (g *Generator) generateMessage(message *Descriptor) {
 			getter = false
 			getter = false
 		case descriptor.FieldDescriptorProto_TYPE_MESSAGE, descriptor.FieldDescriptorProto_TYPE_ENUM:
 		case descriptor.FieldDescriptorProto_TYPE_MESSAGE, descriptor.FieldDescriptorProto_TYPE_ENUM:
 			// Only export getter if its return type is in this package.
 			// Only export getter if its return type is in this package.
-			getter = g.ObjectNamed(field.GetTypeName()).PackageName() == message.PackageName()
+			getter = g.ObjectNamed(field.GetTypeName()).GoImportPath() == message.GoImportPath()
 			genType = true
 			genType = true
 		default:
 		default:
 			getter = true
 			getter = true

+ 2 - 2
protoc-gen-go/grpc/grpc.go

@@ -130,8 +130,8 @@ func (g *grpc) GenerateImports(file *generator.FileDescriptor) {
 		return
 		return
 	}
 	}
 	g.P("import (")
 	g.P("import (")
-	g.P(contextPkg, " ", strconv.Quote(path.Join(g.gen.ImportPrefix, contextPkgPath)))
-	g.P(grpcPkg, " ", strconv.Quote(path.Join(g.gen.ImportPrefix, grpcPkgPath)))
+	g.P(contextPkg, " ", generator.GoImportPath(path.Join(string(g.gen.ImportPrefix), contextPkgPath)))
+	g.P(grpcPkg, " ", generator.GoImportPath(path.Join(string(g.gen.ImportPrefix), grpcPkgPath)))
 	g.P(")")
 	g.P(")")
 	g.P()
 	g.P()
 }
 }

+ 2 - 2
protoc-gen-go/testdata/imports/fmt/m.pb.go

@@ -4,12 +4,12 @@
 package fmt // import "github.com/golang/protobuf/protoc-gen-go/testdata/imports/fmt"
 package fmt // import "github.com/golang/protobuf/protoc-gen-go/testdata/imports/fmt"
 
 
 import proto "github.com/golang/protobuf/proto"
 import proto "github.com/golang/protobuf/proto"
-import fmt1 "fmt"
+import fmt "fmt"
 import math "math"
 import math "math"
 
 
 // Reference imports to suppress errors if they are not otherwise used.
 // Reference imports to suppress errors if they are not otherwise used.
 var _ = proto.Marshal
 var _ = proto.Marshal
-var _ = fmt1.Errorf
+var _ = fmt.Errorf
 var _ = math.Inf
 var _ = math.Inf
 
 
 // This is a compile-time assertion to ensure that this generated file
 // This is a compile-time assertion to ensure that this generated file

+ 6 - 6
protoc-gen-go/testdata/imports/test_import_a1m1.pb.go

@@ -6,7 +6,7 @@ package imports // import "github.com/golang/protobuf/protoc-gen-go/testdata/imp
 import proto "github.com/golang/protobuf/proto"
 import proto "github.com/golang/protobuf/proto"
 import fmt "fmt"
 import fmt "fmt"
 import math "math"
 import math "math"
-import test_a "github.com/golang/protobuf/protoc-gen-go/testdata/imports/test_a_1"
+import test_a_1 "github.com/golang/protobuf/protoc-gen-go/testdata/imports/test_a_1"
 
 
 // Reference imports to suppress errors if they are not otherwise used.
 // Reference imports to suppress errors if they are not otherwise used.
 var _ = proto.Marshal
 var _ = proto.Marshal
@@ -20,10 +20,10 @@ var _ = math.Inf
 const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
 const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
 
 
 type A1M1 struct {
 type A1M1 struct {
-	F                    *test_a.M1 `protobuf:"bytes,1,opt,name=f" json:"f,omitempty"`
-	XXX_NoUnkeyedLiteral struct{}   `json:"-"`
-	XXX_unrecognized     []byte     `json:"-"`
-	XXX_sizecache        int32      `json:"-"`
+	F                    *test_a_1.M1 `protobuf:"bytes,1,opt,name=f" json:"f,omitempty"`
+	XXX_NoUnkeyedLiteral struct{}     `json:"-"`
+	XXX_unrecognized     []byte       `json:"-"`
+	XXX_sizecache        int32        `json:"-"`
 }
 }
 
 
 func (m *A1M1) Reset()         { *m = A1M1{} }
 func (m *A1M1) Reset()         { *m = A1M1{} }
@@ -50,7 +50,7 @@ func (m *A1M1) XXX_DiscardUnknown() {
 
 
 var xxx_messageInfo_A1M1 proto.InternalMessageInfo
 var xxx_messageInfo_A1M1 proto.InternalMessageInfo
 
 
-func (m *A1M1) GetF() *test_a.M1 {
+func (m *A1M1) GetF() *test_a_1.M1 {
 	if m != nil {
 	if m != nil {
 		return m.F
 		return m.F
 	}
 	}

+ 6 - 6
protoc-gen-go/testdata/imports/test_import_a1m2.pb.go

@@ -6,7 +6,7 @@ package imports // import "github.com/golang/protobuf/protoc-gen-go/testdata/imp
 import proto "github.com/golang/protobuf/proto"
 import proto "github.com/golang/protobuf/proto"
 import fmt "fmt"
 import fmt "fmt"
 import math "math"
 import math "math"
-import test_a1 "github.com/golang/protobuf/protoc-gen-go/testdata/imports/test_a_1"
+import test_a_1 "github.com/golang/protobuf/protoc-gen-go/testdata/imports/test_a_1"
 
 
 // Reference imports to suppress errors if they are not otherwise used.
 // Reference imports to suppress errors if they are not otherwise used.
 var _ = proto.Marshal
 var _ = proto.Marshal
@@ -20,10 +20,10 @@ var _ = math.Inf
 const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
 const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
 
 
 type A1M2 struct {
 type A1M2 struct {
-	F                    *test_a1.M2 `protobuf:"bytes,1,opt,name=f" json:"f,omitempty"`
-	XXX_NoUnkeyedLiteral struct{}    `json:"-"`
-	XXX_unrecognized     []byte      `json:"-"`
-	XXX_sizecache        int32       `json:"-"`
+	F                    *test_a_1.M2 `protobuf:"bytes,1,opt,name=f" json:"f,omitempty"`
+	XXX_NoUnkeyedLiteral struct{}     `json:"-"`
+	XXX_unrecognized     []byte       `json:"-"`
+	XXX_sizecache        int32        `json:"-"`
 }
 }
 
 
 func (m *A1M2) Reset()         { *m = A1M2{} }
 func (m *A1M2) Reset()         { *m = A1M2{} }
@@ -50,7 +50,7 @@ func (m *A1M2) XXX_DiscardUnknown() {
 
 
 var xxx_messageInfo_A1M2 proto.InternalMessageInfo
 var xxx_messageInfo_A1M2 proto.InternalMessageInfo
 
 
-func (m *A1M2) GetF() *test_a1.M2 {
+func (m *A1M2) GetF() *test_a_1.M2 {
 	if m != nil {
 	if m != nil {
 		return m.F
 		return m.F
 	}
 	}

+ 19 - 22
protoc-gen-go/testdata/imports/test_import_all.pb.go

@@ -6,13 +6,10 @@ package imports // import "github.com/golang/protobuf/protoc-gen-go/testdata/imp
 import proto "github.com/golang/protobuf/proto"
 import proto "github.com/golang/protobuf/proto"
 import fmt "fmt"
 import fmt "fmt"
 import math "math"
 import math "math"
-import test_a "github.com/golang/protobuf/protoc-gen-go/testdata/imports/test_a_1"
-import test_a1 "github.com/golang/protobuf/protoc-gen-go/testdata/imports/test_a_1"
-import test_a2 "github.com/golang/protobuf/protoc-gen-go/testdata/imports/test_a_2"
-import test_a3 "github.com/golang/protobuf/protoc-gen-go/testdata/imports/test_a_2"
-import test_b_part1 "github.com/golang/protobuf/protoc-gen-go/testdata/imports/test_b_1"
-import test_b_part2 "github.com/golang/protobuf/protoc-gen-go/testdata/imports/test_b_1"
 import fmt1 "github.com/golang/protobuf/protoc-gen-go/testdata/imports/fmt"
 import fmt1 "github.com/golang/protobuf/protoc-gen-go/testdata/imports/fmt"
+import test_a_1 "github.com/golang/protobuf/protoc-gen-go/testdata/imports/test_a_1"
+import test_a_2 "github.com/golang/protobuf/protoc-gen-go/testdata/imports/test_a_2"
+import test_b_1 "github.com/golang/protobuf/protoc-gen-go/testdata/imports/test_b_1"
 
 
 // Reference imports to suppress errors if they are not otherwise used.
 // Reference imports to suppress errors if they are not otherwise used.
 var _ = proto.Marshal
 var _ = proto.Marshal
@@ -26,16 +23,16 @@ var _ = math.Inf
 const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
 const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
 
 
 type All struct {
 type All struct {
-	Am1                  *test_a.M1       `protobuf:"bytes,1,opt,name=am1" json:"am1,omitempty"`
-	Am2                  *test_a1.M2      `protobuf:"bytes,2,opt,name=am2" json:"am2,omitempty"`
-	Am3                  *test_a2.M3      `protobuf:"bytes,3,opt,name=am3" json:"am3,omitempty"`
-	Am4                  *test_a3.M4      `protobuf:"bytes,4,opt,name=am4" json:"am4,omitempty"`
-	Bm1                  *test_b_part1.M1 `protobuf:"bytes,5,opt,name=bm1" json:"bm1,omitempty"`
-	Bm2                  *test_b_part2.M2 `protobuf:"bytes,6,opt,name=bm2" json:"bm2,omitempty"`
-	Fmt                  *fmt1.M          `protobuf:"bytes,7,opt,name=fmt" json:"fmt,omitempty"`
-	XXX_NoUnkeyedLiteral struct{}         `json:"-"`
-	XXX_unrecognized     []byte           `json:"-"`
-	XXX_sizecache        int32            `json:"-"`
+	Am1                  *test_a_1.M1 `protobuf:"bytes,1,opt,name=am1" json:"am1,omitempty"`
+	Am2                  *test_a_1.M2 `protobuf:"bytes,2,opt,name=am2" json:"am2,omitempty"`
+	Am3                  *test_a_2.M3 `protobuf:"bytes,3,opt,name=am3" json:"am3,omitempty"`
+	Am4                  *test_a_2.M4 `protobuf:"bytes,4,opt,name=am4" json:"am4,omitempty"`
+	Bm1                  *test_b_1.M1 `protobuf:"bytes,5,opt,name=bm1" json:"bm1,omitempty"`
+	Bm2                  *test_b_1.M2 `protobuf:"bytes,6,opt,name=bm2" json:"bm2,omitempty"`
+	Fmt                  *fmt1.M      `protobuf:"bytes,7,opt,name=fmt" json:"fmt,omitempty"`
+	XXX_NoUnkeyedLiteral struct{}     `json:"-"`
+	XXX_unrecognized     []byte       `json:"-"`
+	XXX_sizecache        int32        `json:"-"`
 }
 }
 
 
 func (m *All) Reset()         { *m = All{} }
 func (m *All) Reset()         { *m = All{} }
@@ -62,42 +59,42 @@ func (m *All) XXX_DiscardUnknown() {
 
 
 var xxx_messageInfo_All proto.InternalMessageInfo
 var xxx_messageInfo_All proto.InternalMessageInfo
 
 
-func (m *All) GetAm1() *test_a.M1 {
+func (m *All) GetAm1() *test_a_1.M1 {
 	if m != nil {
 	if m != nil {
 		return m.Am1
 		return m.Am1
 	}
 	}
 	return nil
 	return nil
 }
 }
 
 
-func (m *All) GetAm2() *test_a1.M2 {
+func (m *All) GetAm2() *test_a_1.M2 {
 	if m != nil {
 	if m != nil {
 		return m.Am2
 		return m.Am2
 	}
 	}
 	return nil
 	return nil
 }
 }
 
 
-func (m *All) GetAm3() *test_a2.M3 {
+func (m *All) GetAm3() *test_a_2.M3 {
 	if m != nil {
 	if m != nil {
 		return m.Am3
 		return m.Am3
 	}
 	}
 	return nil
 	return nil
 }
 }
 
 
-func (m *All) GetAm4() *test_a3.M4 {
+func (m *All) GetAm4() *test_a_2.M4 {
 	if m != nil {
 	if m != nil {
 		return m.Am4
 		return m.Am4
 	}
 	}
 	return nil
 	return nil
 }
 }
 
 
-func (m *All) GetBm1() *test_b_part1.M1 {
+func (m *All) GetBm1() *test_b_1.M1 {
 	if m != nil {
 	if m != nil {
 		return m.Bm1
 		return m.Bm1
 	}
 	}
 	return nil
 	return nil
 }
 }
 
 
-func (m *All) GetBm2() *test_b_part2.M2 {
+func (m *All) GetBm2() *test_b_1.M2 {
 	if m != nil {
 	if m != nil {
 		return m.Bm2
 		return m.Bm2
 	}
 	}

+ 13 - 13
protoc-gen-go/testdata/imports/test_import_public.pb.go

@@ -6,7 +6,7 @@ package imports // import "github.com/golang/protobuf/protoc-gen-go/testdata/imp
 import proto "github.com/golang/protobuf/proto"
 import proto "github.com/golang/protobuf/proto"
 import fmt "fmt"
 import fmt "fmt"
 import math "math"
 import math "math"
-import test_a "github.com/golang/protobuf/protoc-gen-go/testdata/imports/test_a_1"
+import test_a_1 "github.com/golang/protobuf/protoc-gen-go/testdata/imports/test_a_1"
 
 
 // Reference imports to suppress errors if they are not otherwise used.
 // Reference imports to suppress errors if they are not otherwise used.
 var _ = proto.Marshal
 var _ = proto.Marshal
@@ -20,23 +20,23 @@ var _ = math.Inf
 const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
 const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
 
 
 // M1 from public import imports/test_a_1/m1.proto
 // M1 from public import imports/test_a_1/m1.proto
-type M1 test_a.M1
+type M1 test_a_1.M1
 
 
-func (m *M1) Reset()                         { (*test_a.M1)(m).Reset() }
-func (m *M1) String() string                 { return (*test_a.M1)(m).String() }
+func (m *M1) Reset()                         { (*test_a_1.M1)(m).Reset() }
+func (m *M1) String() string                 { return (*test_a_1.M1)(m).String() }
 func (*M1) ProtoMessage()                    {}
 func (*M1) ProtoMessage()                    {}
-func (m *M1) XXX_Unmarshal(buf []byte) error { return (*test_a.M1)(m).XXX_Unmarshal(buf) }
+func (m *M1) XXX_Unmarshal(buf []byte) error { return (*test_a_1.M1)(m).XXX_Unmarshal(buf) }
 func (m *M1) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
 func (m *M1) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
-	return (*test_a.M1)(m).XXX_Marshal(b, deterministic)
+	return (*test_a_1.M1)(m).XXX_Marshal(b, deterministic)
 }
 }
-func (m *M1) XXX_Size() int       { return (*test_a.M1)(m).XXX_Size() }
-func (m *M1) XXX_DiscardUnknown() { (*test_a.M1)(m).XXX_DiscardUnknown() }
+func (m *M1) XXX_Size() int       { return (*test_a_1.M1)(m).XXX_Size() }
+func (m *M1) XXX_DiscardUnknown() { (*test_a_1.M1)(m).XXX_DiscardUnknown() }
 
 
 type Public struct {
 type Public struct {
-	F                    *test_a.M1 `protobuf:"bytes,1,opt,name=f" json:"f,omitempty"`
-	XXX_NoUnkeyedLiteral struct{}   `json:"-"`
-	XXX_unrecognized     []byte     `json:"-"`
-	XXX_sizecache        int32      `json:"-"`
+	F                    *test_a_1.M1 `protobuf:"bytes,1,opt,name=f" json:"f,omitempty"`
+	XXX_NoUnkeyedLiteral struct{}     `json:"-"`
+	XXX_unrecognized     []byte       `json:"-"`
+	XXX_sizecache        int32        `json:"-"`
 }
 }
 
 
 func (m *Public) Reset()         { *m = Public{} }
 func (m *Public) Reset()         { *m = Public{} }
@@ -63,7 +63,7 @@ func (m *Public) XXX_DiscardUnknown() {
 
 
 var xxx_messageInfo_Public proto.InternalMessageInfo
 var xxx_messageInfo_Public proto.InternalMessageInfo
 
 
-func (m *Public) GetF() *test_a.M1 {
+func (m *Public) GetF() *test_a_1.M1 {
 	if m != nil {
 	if m != nil {
 		return m.F
 		return m.F
 	}
 	}