diff --git a/internal/wire/testdata/ReservedKeywords/foo/foo.go b/internal/wire/testdata/ReservedKeywords/foo/foo.go new file mode 100644 index 0000000..2b7d816 --- /dev/null +++ b/internal/wire/testdata/ReservedKeywords/foo/foo.go @@ -0,0 +1,35 @@ +// Copyright 2018 The Go Cloud Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package main + +import ( + "fmt" +) + +func main() { + i := injectInterface() + fmt.Println(i) +} + +type Interface int +type Select int + +func provideInterface(s Select) Interface { + return Interface(int(s) + 1) +} + +func provideSelect() Select { + return Select(41) +} diff --git a/internal/wire/testdata/ReservedKeywords/foo/wire.go b/internal/wire/testdata/ReservedKeywords/foo/wire.go new file mode 100644 index 0000000..0d78098 --- /dev/null +++ b/internal/wire/testdata/ReservedKeywords/foo/wire.go @@ -0,0 +1,32 @@ +// Copyright 2018 The Go Cloud Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//+build wireinject + +package main + +import ( + "github.com/google/go-cloud/wire" +) + +// Wire tries to disambiguate the variable "select" by prepending +// the package name; this package-scoped variable conflicts with that +// and forces a different name. +var mainSelect = 0 + +func injectInterface() Interface { + // interface and select are Go reserved words, so + // Wire should avoid using them as variable names. + panic(wire.Build(provideInterface, provideSelect)) +} diff --git a/internal/wire/testdata/ReservedKeywords/pkg b/internal/wire/testdata/ReservedKeywords/pkg new file mode 100644 index 0000000..f7a5c8c --- /dev/null +++ b/internal/wire/testdata/ReservedKeywords/pkg @@ -0,0 +1 @@ +example.com/foo diff --git a/internal/wire/testdata/ReservedKeywords/want/program_out.txt b/internal/wire/testdata/ReservedKeywords/want/program_out.txt new file mode 100644 index 0000000..d81cc07 --- /dev/null +++ b/internal/wire/testdata/ReservedKeywords/want/program_out.txt @@ -0,0 +1 @@ +42 diff --git a/internal/wire/testdata/ReservedKeywords/want/wire_gen.go b/internal/wire/testdata/ReservedKeywords/want/wire_gen.go new file mode 100644 index 0000000..646e34e --- /dev/null +++ b/internal/wire/testdata/ReservedKeywords/want/wire_gen.go @@ -0,0 +1,18 @@ +// Code generated by Wire. DO NOT EDIT. + +//go:generate wire +//+build !wireinject + +package main + +// Injectors from wire.go: + +func injectInterface() Interface { + select2 := provideSelect() + mainInterface := provideInterface(select2) + return mainInterface +} + +// wire.go: + +var mainSelect = 0 diff --git a/internal/wire/wire.go b/internal/wire/wire.go index 0204fde..f064aac 100644 --- a/internal/wire/wire.go +++ b/internal/wire/wire.go @@ -709,7 +709,7 @@ func typeVariableName(t types.Type, defaultName string, transform func(string) s // See if there's an unambiguous name; if so, use it. for _, name := range names { - if !collides(name) { + if !reservedKeyword[name] && !collides(name) { return name } } @@ -767,9 +767,40 @@ func export(name string) string { return sbuf.String() } +// reservedKeyword is a set of Go's reserved keywords: +// https://golang.org/ref/spec#Keywords +var reservedKeyword = map[string]bool{ + "break": true, + "case": true, + "chan": true, + "const": true, + "continue": true, + "default": true, + "defer": true, + "else": true, + "fallthrough": true, + "for": true, + "func": true, + "go": true, + "goto": true, + "if": true, + "import": true, + "interface": true, + "map": true, + "package": true, + "range": true, + "return": true, + "select": true, + "struct": true, + "switch": true, + "type": true, + "var": true, +} + // disambiguate picks a unique name, preferring name if it is already unique. +// It also disambiguates against Go's reserved keywords. func disambiguate(name string, collides func(string) bool) string { - if !collides(name) { + if !reservedKeyword[name] && !collides(name) { return name } buf := []byte(name) @@ -780,7 +811,7 @@ func disambiguate(name string, collides func(string) bool) string { for n := 2; ; n++ { buf = strconv.AppendInt(buf[:base], int64(n), 10) sbuf := string(buf) - if !collides(sbuf) { + if !reservedKeyword[sbuf] && !collides(sbuf) { return sbuf } } diff --git a/internal/wire/wire_test.go b/internal/wire/wire_test.go index 78f333d..f6571fa 100644 --- a/internal/wire/wire_test.go +++ b/internal/wire/wire_test.go @@ -303,6 +303,8 @@ func TestDisambiguate(t *testing.T) { {"foo1", "foo1_2", map[string]bool{"foo": true, "foo1": true, "foo2": true}}, {"foo\u0661", "foo\u0661", map[string]bool{"foo": true, "foo1": true, "foo2": true}}, {"foo\u0661", "foo\u06612", map[string]bool{"foo": true, "foo1": true, "foo2": true, "foo\u0661": true}}, + {"select", "select2", nil}, + {"var", "var2", nil}, } for _, test := range tests { t.Run(fmt.Sprintf("disambiguate(%q, %v)", test.name, test.collides), func(t *testing.T) {