Jelajahi Sumber

protoc-gen-go: only disambiguate predefined idents for local package names (#724)

Permit creating a generated package named e.g., "string". Apply disambiguation
to prevent creating a local import name that conflicts with predefined
identifiers; importing package "string" will be done as:

    import string1 "string"
Damien Neil 7 tahun lalu
induk
melakukan
ddf22928ea

+ 5 - 5
protoc-gen-go/generator/generator.go

@@ -535,7 +535,7 @@ func (g *Generator) GoPackageName(importPath GoImportPath) GoPackageName {
 		return name
 	}
 	name := cleanPackageName(baseName(string(importPath)))
-	for i, orig := 1, name; g.usedPackageNames[name]; i++ {
+	for i, orig := 1, name; g.usedPackageNames[name] || isGoPredeclaredIdentifier[string(name)]; i++ {
 		name = orig + GoPackageName(strconv.Itoa(i))
 	}
 	g.packageNames[importPath] = name
@@ -567,8 +567,7 @@ func RegisterUniquePackageName(pkg string, f *FileDescriptor) string {
 	return string(name)
 }
 
-var isGoKeywordOrPredeclaredIdentifier = map[string]bool{
-	// Keywords
+var isGoKeyword = map[string]bool{
 	"break":       true,
 	"case":        true,
 	"chan":        true,
@@ -594,8 +593,9 @@ var isGoKeywordOrPredeclaredIdentifier = map[string]bool{
 	"switch":      true,
 	"type":        true,
 	"var":         true,
+}
 
-	// Predeclared Identifiers
+var isGoPredeclaredIdentifier = map[string]bool{
 	"append":     true,
 	"bool":       true,
 	"byte":       true,
@@ -640,7 +640,7 @@ var isGoKeywordOrPredeclaredIdentifier = map[string]bool{
 func cleanPackageName(name string) GoPackageName {
 	name = strings.Map(badToUnderscore, name)
 	// Identifier must not be keyword or predeclared identifier: insert _.
-	if isGoKeywordOrPredeclaredIdentifier[name] {
+	if isGoKeyword[name] {
 		name = "_" + name
 	}
 	// Identifier must not begin with digit: insert _.

+ 20 - 1
protoc-gen-go/generator/name_test.go

@@ -68,7 +68,7 @@ func TestGoPackageOption(t *testing.T) {
 		{"foo", "", "foo", true},
 		{"github.com/golang/bar", "github.com/golang/bar", "bar", true},
 		{"github.com/golang/bar;baz", "github.com/golang/bar", "baz", true},
-		{"github.com/golang/string", "github.com/golang/string", "_string", true},
+		{"github.com/golang/string", "github.com/golang/string", "string", true},
 	}
 	for _, tc := range tests {
 		d := &FileDescriptor{
@@ -86,6 +86,25 @@ func TestGoPackageOption(t *testing.T) {
 	}
 }
 
+func TestPackageNames(t *testing.T) {
+	g := New()
+	g.packageNames = make(map[GoImportPath]GoPackageName)
+	g.usedPackageNames = make(map[GoPackageName]bool)
+	for _, test := range []struct {
+		importPath GoImportPath
+		want       GoPackageName
+	}{
+		{"github.com/golang/foo", "foo"},
+		{"github.com/golang/second/package/named/foo", "foo1"},
+		{"github.com/golang/third/package/named/foo", "foo2"},
+		{"github.com/golang/conflicts/with/predeclared/ident/string", "string1"},
+	} {
+		if got := g.GoPackageName(test.importPath); got != test.want {
+			t.Errorf("GoPackageName(%v) = %v, want %v", test.importPath, got, test.want)
+		}
+	}
+}
+
 func TestUnescape(t *testing.T) {
 	tests := []struct {
 		in  string