rlp/rlpgen: implement package renaming support
This commit adds support for package renaming in the RLP code generator to handle import name conflicts. Key changes include: - Added automatic package alias generation for conflicting imports - Implemented package loading to get correct package names - Modified import handling to support aliased imports - Updated importsList to generate proper import statements with aliases - Added helper functions for alias management The changes allow the code generator to handle cases where multiple imported packages have the same base name by automatically generating unique aliases, improving the robustness of the generated code.
This commit is contained in:
parent
4cda8f06ea
commit
96ff33133a
|
@ -22,8 +22,10 @@ import (
|
|||
"go/format"
|
||||
"go/types"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/ethereum/go-ethereum/rlp/internal/rlpstruct"
|
||||
"golang.org/x/tools/go/packages"
|
||||
)
|
||||
|
||||
// buildContext keeps the data needed for make*Op.
|
||||
|
@ -96,14 +98,15 @@ func (bctx *buildContext) typeToStructType(typ types.Type) *rlpstruct.Type {
|
|||
// file and assigns unique names of temporary variables.
|
||||
type genContext struct {
|
||||
inPackage *types.Package
|
||||
imports map[string]struct{}
|
||||
imports map[string]string // Changed from map[string]struct{} to map[string]string to store package aliases
|
||||
tempCounter int
|
||||
}
|
||||
|
||||
func newGenContext(inPackage *types.Package) *genContext {
|
||||
return &genContext{
|
||||
inPackage: inPackage,
|
||||
imports: make(map[string]struct{}),
|
||||
inPackage: inPackage,
|
||||
imports: make(map[string]string),
|
||||
tempCounter: 0,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -117,32 +120,83 @@ func (ctx *genContext) resetTemp() {
|
|||
ctx.tempCounter = 0
|
||||
}
|
||||
|
||||
func (ctx *genContext) addImport(path string) {
|
||||
func (ctx *genContext) addImport(path string) string {
|
||||
if path == ctx.inPackage.Path() {
|
||||
return // avoid importing the package that we're generating in.
|
||||
return "" // avoid importing the package that we're generating in
|
||||
}
|
||||
// TODO: renaming?
|
||||
ctx.imports[path] = struct{}{}
|
||||
|
||||
// Check if we already have an alias for this package
|
||||
if alias, exists := ctx.imports[path]; exists {
|
||||
return alias
|
||||
}
|
||||
|
||||
// Get the package name and check for conflicts
|
||||
pkg, err := ctx.loadPackage(path)
|
||||
if err != nil {
|
||||
// If we can't load the package, use the last component of the path
|
||||
parts := strings.Split(path, "/")
|
||||
pkg = types.NewPackage(path, parts[len(parts)-1])
|
||||
}
|
||||
|
||||
baseName := pkg.Name()
|
||||
alias := baseName
|
||||
counter := 1
|
||||
|
||||
// If the base name conflicts with any existing import, add a numeric suffix
|
||||
for ctx.hasAlias(alias) {
|
||||
alias = fmt.Sprintf("%s%d", baseName, counter)
|
||||
counter++
|
||||
}
|
||||
|
||||
ctx.imports[path] = alias
|
||||
return alias
|
||||
}
|
||||
|
||||
// importsList returns all packages that need to be imported.
|
||||
func (ctx *genContext) importsList() []string {
|
||||
imp := make([]string, 0, len(ctx.imports))
|
||||
for k := range ctx.imports {
|
||||
imp = append(imp, k)
|
||||
// hasAlias checks if an alias is already in use
|
||||
func (ctx *genContext) hasAlias(alias string) bool {
|
||||
for _, existingAlias := range ctx.imports {
|
||||
if existingAlias == alias {
|
||||
return true
|
||||
}
|
||||
}
|
||||
sort.Strings(imp)
|
||||
return imp
|
||||
return false
|
||||
}
|
||||
|
||||
// qualify is the types.Qualifier used for printing types.
|
||||
// loadPackage attempts to load package information
|
||||
func (ctx *genContext) loadPackage(path string) (*types.Package, error) {
|
||||
cfg := &packages.Config{Mode: packages.NeedName}
|
||||
pkgs, err := packages.Load(cfg, path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(pkgs) == 0 {
|
||||
return nil, fmt.Errorf("no package found for path %s", path)
|
||||
}
|
||||
return types.NewPackage(path, pkgs[0].Name), nil
|
||||
}
|
||||
|
||||
// qualify is the types.Qualifier used for printing types
|
||||
func (ctx *genContext) qualify(pkg *types.Package) string {
|
||||
if pkg.Path() == ctx.inPackage.Path() {
|
||||
return ""
|
||||
}
|
||||
ctx.addImport(pkg.Path())
|
||||
// TODO: renaming?
|
||||
return pkg.Name()
|
||||
return ctx.addImport(pkg.Path())
|
||||
}
|
||||
|
||||
// importsList returns all packages that need to be imported
|
||||
func (ctx *genContext) importsList() []string {
|
||||
imp := make([]string, 0, len(ctx.imports))
|
||||
for path, alias := range ctx.imports {
|
||||
if alias == pkg.Name() {
|
||||
// If the alias matches the package name, use standard import
|
||||
imp = append(imp, fmt.Sprintf("%q", path))
|
||||
} else {
|
||||
// If we have a custom alias, use aliased import
|
||||
imp = append(imp, fmt.Sprintf("%s %q", alias, path))
|
||||
}
|
||||
}
|
||||
sort.Strings(imp)
|
||||
return imp
|
||||
}
|
||||
|
||||
type op interface {
|
||||
|
|
Loading…
Reference in New Issue