Skip to content

Commit

Permalink
Always ensure unique name even when ImportName or ImportAlias have be…
Browse files Browse the repository at this point in the history
…en used. Added more docs.
  • Loading branch information
dave committed Mar 10, 2018
1 parent 8156595 commit 9be9266
Show file tree
Hide file tree
Showing 5 changed files with 114 additions and 22 deletions.
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,13 @@ fmt.Printf("%#v", f)
// }
```

Note that
it is not possible to reliably determine the package name given an arbitrary
package path, so a sensible name is guessed from the path and added as an
alias. The names of all standard library packages are known so these do not
need to be aliased. If more control is needed of the aliases, see
[File.ImportName](#importname) or [File.ImportAlias](#importalias).

### List
List renders a comma separated list. Use for multiple return functions.

Expand Down
4 changes: 3 additions & 1 deletion README.md.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -65,10 +65,12 @@ preferred.

{{ "ExampleQual" | example }}

{{ "Qual[1:]" | doc }}
{{ "Qual[1:4]" | doc }}

{{ "ExampleQual_file" | example }}

{{ "Qual[4:]" | doc }}

### List
{{ "List" | doc }}

Expand Down
54 changes: 54 additions & 0 deletions jen/examples_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,60 @@ import (
. "github.com/dave/jennifer/jen"
)

func ExampleFile_ImportName_conflict() {
f := NewFile("main")

// We provide a hint that package foo/a should use name "a", but because package bar/a already
// registers the required name, foo/a is aliased.
f.ImportName("github.com/foo/a", "a")

f.Func().Id("main").Params().Block(
Qual("github.com/bar/a", "Bar").Call(),
Qual("github.com/foo/a", "Foo").Call(),
)
fmt.Printf("%#v", f)

// Output:
// package main
//
// import (
// a "github.com/bar/a"
// a1 "github.com/foo/a"
// )
//
// func main() {
// a.Bar()
// a1.Foo()
// }
}

func ExampleFile_ImportAlias_conflict() {
f := NewFile("main")

// We provide a hint that package foo/a should use alias "b", but because package bar/b already
// registers the required name, foo/a is aliased using the requested alias as a base.
f.ImportName("github.com/foo/a", "b")

f.Func().Id("main").Params().Block(
Qual("github.com/bar/b", "Bar").Call(),
Qual("github.com/foo/a", "Foo").Call(),
)
fmt.Printf("%#v", f)

// Output:
// package main
//
// import (
// b "github.com/bar/b"
// b1 "github.com/foo/a"
// )
//
// func main() {
// b.Bar()
// b1.Foo()
// }
}

func ExampleFile_ImportName() {
f := NewFile("main")

Expand Down
50 changes: 32 additions & 18 deletions jen/file.go
Original file line number Diff line number Diff line change
Expand Up @@ -165,30 +165,44 @@ func (f *File) register(path string) string {
return "C"
}

// look up the path in the list of provided package names and aliases by ImportName / ImportAlias
hint := f.hints[path]
if hint.name != "" {
f.imports[path] = importdef{name: hint.name, alias: hint.alias}
return hint.name
}

// look up the path in the list of standard library packages, if found add and return the name
if Hints[path] != "" {
f.imports[path] = importdef{name: Hints[path], alias: false}
return Hints[path]
}

alias := guessAlias(path)
unique := alias
var name string
var alias bool

if hint := f.hints[path]; hint.name != "" {
// look up the path in the list of provided package names and aliases by ImportName / ImportAlias
name = hint.name
alias = hint.alias
} else if Hints[path] != "" {
// look up the path in the list of standard library packages, if found add and return the name
name = Hints[path]
alias = false
} else {
// if a hint is not found for the package, guess the alias from the package path
name = guessAlias(path)
alias = true
}

// If the name is invalid or has been registered already, make it unique by appending a number
unique := name
i := 0
for !f.isValidAlias(unique) {
i++
unique = fmt.Sprintf("%s%d", alias, i)
unique = fmt.Sprintf("%s%d", name, i)
}
if f.PackagePrefix != "" {

// If we've changed the name to make it unique, it should definitely be an alias
if unique != name {
alias = true
}

// Only add a prefix if the name is an alias
if f.PackagePrefix != "" && alias {
unique = f.PackagePrefix + "_" + unique
}
f.imports[path] = importdef{name: unique, alias: true}

// Register the eventual name
f.imports[path] = importdef{name: unique, alias: alias}

return unique
}

Expand Down
21 changes: 18 additions & 3 deletions jen/tokens.go
Original file line number Diff line number Diff line change
Expand Up @@ -224,14 +224,24 @@ func (s *Statement) Id(name string) *Statement {

// Qual renders a qualified identifier. Imports are automatically added when
// used with a File. If the path matches the local path, the package name is
// omitted. If package names conflict they are automatically renamed.
// omitted. If package names conflict they are automatically renamed. Note that
// it is not possible to reliably determine the package name given an arbitrary
// package path, so a sensible name is guessed from the path and added as an
// alias. The names of all standard library packages are known so these do not
// need to be aliased. If more control is needed of the aliases, see
// [File.ImportName](#importname) or [File.ImportAlias](#importalias).
func Qual(path, name string) *Statement {
return newStatement().Qual(path, name)
}

// Qual renders a qualified identifier. Imports are automatically added when
// used with a File. If the path matches the local path, the package name is
// omitted. If package names conflict they are automatically renamed.
// omitted. If package names conflict they are automatically renamed. Note that
// it is not possible to reliably determine the package name given an arbitrary
// package path, so a sensible name is guessed from the path and added as an
// alias. The names of all standard library packages are known so these do not
// need to be aliased. If more control is needed of the aliases, see
// [File.ImportName](#importname) or [File.ImportAlias](#importalias).
func (g *Group) Qual(path, name string) *Statement {
s := Qual(path, name)
g.items = append(g.items, s)
Expand All @@ -240,7 +250,12 @@ func (g *Group) Qual(path, name string) *Statement {

// Qual renders a qualified identifier. Imports are automatically added when
// used with a File. If the path matches the local path, the package name is
// omitted. If package names conflict they are automatically renamed.
// omitted. If package names conflict they are automatically renamed. Note that
// it is not possible to reliably determine the package name given an arbitrary
// package path, so a sensible name is guessed from the path and added as an
// alias. The names of all standard library packages are known so these do not
// need to be aliased. If more control is needed of the aliases, see
// [File.ImportName](#importname) or [File.ImportAlias](#importalias).
func (s *Statement) Qual(path, name string) *Statement {
g := &Group{
close: "",
Expand Down

0 comments on commit 9be9266

Please sign in to comment.