-
Notifications
You must be signed in to change notification settings - Fork 114
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Refactor import-loading to simplify the type-generation code #101
Merged
Merged
Changes from 1 commit
Commits
Show all changes
2 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
package {{.Config.Package}} | ||
|
||
// Code generated by github.com/Khan/genqlient, DO NOT EDIT. | ||
|
||
{{.Imports}} | ||
|
||
{{if and (ne .Config.ContextType "-") (ne .Config.ContextType "context.Context") }} | ||
// Check that context_type from genqlient.yaml implements context.Context. | ||
var _ {{ref "context.Context"}} = ({{ref .Config.ContextType}})(nil) | ||
{{end}} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -9,60 +9,46 @@ import ( | |
) | ||
|
||
func (g *generator) addImportFor(pkgPath string) (alias string) { | ||
if existingAlias, ok := g.imports[pkgPath]; ok { | ||
return existingAlias | ||
} | ||
|
||
pkgName := pkgPath[strings.LastIndex(pkgPath, "/")+1:] | ||
alias = pkgName | ||
suffix := 2 | ||
for g.usedAliases[alias] { | ||
alias = pkgName + strconv.Itoa(suffix) | ||
suffix++ | ||
} | ||
|
||
g.imports[pkgPath] = alias | ||
g.usedAliases[alias] = true | ||
return alias | ||
} | ||
|
||
// addRef adds any imports necessary to refer to the given name, and returns a | ||
// reference alias.Name for it. | ||
func (g *generator) addRef(fullyQualifiedName string) (qualifiedName string, err error) { | ||
return g.getRef(fullyQualifiedName, true) | ||
} | ||
|
||
// ref returns a reference alias.Name for the given import, if its package was | ||
// already added (e.g. via addRef), and an error if not. | ||
func (g *generator) ref(fullyQualifiedName string) (qualifiedName string, err error) { | ||
return g.getRef(fullyQualifiedName, false) | ||
} | ||
|
||
var _sliceOrMapPrefixRegexp = regexp.MustCompile(`^(\*|\[\d*\]|map\[string\])*`) | ||
|
||
func (g *generator) getRef(fullyQualifiedName string, addImport bool) (qualifiedName string, err error) { | ||
// Ideally, we want to allow a reference to basically an arbitrary symbol. | ||
// But that's very hard, because it might be quite complicated, like | ||
// struct{ F []map[mypkg.K]otherpkg.V } | ||
// Now in practice, using an unnamed struct is not a great idea, but we do | ||
// want to allow as much as we can that encoding/json knows how to work | ||
// with, since you would reasonably expect us to accept, say, | ||
// map[string][]interface{}. So we allow: | ||
// - any named type (mypkg.T) | ||
// - any predeclared basic type (string, int, etc.) | ||
// - interface{} | ||
// - for any allowed type T, *T, []T, [N]T, and map[string]T | ||
// which effectively excludes: | ||
// - unnamed struct types | ||
// - map[K]V where K is a named type wrapping string | ||
// - any nonstandard spelling of those (interface {/* hi */}, | ||
// map[ string ]T) | ||
// TODO: document that somewhere visible | ||
|
||
// ref takes a Go fully-qualified name, ensures that any necessary symbols are | ||
// imported, and returns an appropriate reference. | ||
// | ||
// Ideally, we want to allow a reference to basically an arbitrary symbol. | ||
// But that's very hard, because it might be quite complicated, like | ||
// struct{ F []map[mypkg.K]otherpkg.V } | ||
// Now in practice, using an unnamed struct is not a great idea, but we do | ||
// want to allow as much as we can that encoding/json knows how to work | ||
// with, since you would reasonably expect us to accept, say, | ||
// map[string][]interface{}. So we allow: | ||
// - any named type (mypkg.T) | ||
// - any predeclared basic type (string, int, etc.) | ||
// - interface{} | ||
// - for any allowed type T, *T, []T, [N]T, and map[string]T | ||
// which effectively excludes: | ||
// - unnamed struct types | ||
// - map[K]V where K is a named type wrapping string | ||
// - any nonstandard spelling of those (interface {/* hi */}, | ||
// map[ string ]T) | ||
// (This is documented in docs/genqlient.yaml) | ||
func (g *generator) ref(fullyQualifiedName string) (qualifiedName string, err error) { | ||
errorMsg := `invalid type-name "%v" (%v); expected a builtin, ` + | ||
`path/to/package.Name, interface{}, or a slice, map, or pointer of those` | ||
|
||
if strings.Contains(fullyQualifiedName, " ") { | ||
// TODO: pass in pos here and below | ||
return "", errorf(nil, errorMsg, fullyQualifiedName, "contains spaces") | ||
} | ||
|
||
|
@@ -80,22 +66,20 @@ func (g *generator) getRef(fullyQualifiedName string, addImport bool) (qualified | |
|
||
pkgPath := nameToImport[:i] | ||
localName := nameToImport[i+1:] | ||
var alias string | ||
if addImport { | ||
alias = g.addImportFor(pkgPath) | ||
} else { | ||
var ok bool | ||
alias, ok = g.imports[pkgPath] | ||
if !ok { | ||
// This is an internal error, not a user error. | ||
return "", errorf(nil, `no alias defined for package "%v"`, pkgPath) | ||
alias, ok := g.imports[pkgPath] | ||
if !ok { | ||
if g.importsLocked { | ||
return "", errorf(nil, | ||
`genqlient internal error: imports locked but no alias defined for package "%v"`, pkgPath) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. perhaps: "imports locked but package "%v" has not been imported"? |
||
} | ||
alias = g.addImportFor(pkgPath) | ||
} | ||
return prefix + alias + "." + localName, nil | ||
} | ||
|
||
// Returns the import-clause to use in the generated code. | ||
func (g *generator) Imports() string { | ||
g.importsLocked = true | ||
if len(g.imports) == 0 { | ||
return "" | ||
} | ||
|
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I know "execute" is based on text/template terminology, but that isn't super clear in the context of the generator, IMO. Perhaps this function could be named
renderTemplate
or something similar.