in tools/go-agent/instrument/plugins/rewrite/context.go [162:340]
func (c *Context) enhanceTypeNameWhenRewrite(fieldType dst.Expr, parent dst.Node, argIndex int) (string, string) {
switch t := fieldType.(type) {
case *dst.Ident:
name := t.Name
if c.typeIsBasicTypeValueOrEnhanceName(name) {
return "", ""
}
if c.callIsBasicNamesOrEnhanceName(name) {
return "", ""
}
if mappingName := c.rewriteMapping.findVarMappingName(name); mappingName != "" {
t.Name = mappingName
return "", ""
}
if mappingName := c.rewriteMapping.findTypeMappingName(name); mappingName != "" {
t.Name = mappingName
return "", ""
}
if native := c.rewriteMapping.findNativeTypeMapping(name); native != nil {
// change to the selector expr(package.type) and enhance
pkgBase := filepath.Base(native.packageName)
// check the package have been import or not
c.AddingImportToCurrentFile(pkgBase, native.packageName)
c.enhanceTypeNameWhenRewrite(&dst.SelectorExpr{
X: dst.NewIdent(pkgBase),
Sel: dst.NewIdent(native.typeName),
}, parent, argIndex)
return "", ""
}
// if parent is function call, then the name should be method name
if _, ok := parent.(*dst.CallExpr); ok {
t.Name = fmt.Sprintf("%s%s%s", StaticMethodPrefix, c.currentPackageTitle, name)
} else {
t.Name = fmt.Sprintf("%s%s%s", TypePrefix, c.currentPackageTitle, name)
}
return name, t.Name
case *dst.SelectorExpr:
pkgRefName, ok := t.X.(*dst.Ident)
if !ok {
return c.enhanceTypeNameWhenRewrite(t.X, parent, -1)
}
// reference by package name
var foundPackage *rewriteImportInfo
for refImportName, pkgInfo := range c.packageImport {
if pkgRefName.Name == refImportName {
foundPackage = pkgInfo
break
}
}
// if the method call
if v := c.rewriteMapping.findVarMappingName(pkgRefName.Name); v != "" {
t.X = dst.NewIdent(v)
return "", ""
}
// is the other package reference
if strings.HasPrefix(pkgRefName.Name, tools.OtherPackageRefPrefix) {
t.X = dst.NewIdent(pkgRefName.Name[len(tools.OtherPackageRefPrefix):])
return "", ""
}
var generateExpr func() dst.Expr
var generateCallExpr func(parent *dst.CallExpr)
if foundPackage != nil {
generateCallExpr = func(parent *dst.CallExpr) {
if c.rewriteVarIfExistingMapping(t.Sel, parent) {
if argIndex >= 0 {
parent.Args[argIndex] = t.Sel
} else {
parent.Fun = dst.NewIdent(t.Sel.Name)
}
} else {
parent.Fun = foundPackage.generateStaticMethod(t.Sel.Name)
}
}
generateExpr = func() dst.Expr {
return foundPackage.generateType(t.Sel.Name)
}
} else {
// if it cannot found the package, then it just keep the data
generateCallExpr = func(parent *dst.CallExpr) {
if argIndex >= 0 {
parent.Args[argIndex] = fieldType
} else {
parent.Fun = fieldType
}
}
generateExpr = func() dst.Expr {
return fieldType
}
}
switch p := parent.(type) {
case *dst.CallExpr:
generateCallExpr(p)
case *dst.Field:
p.Type = generateExpr()
case *dst.Ellipsis:
p.Elt = generateExpr()
case *dst.StarExpr:
p.X = generateExpr()
case *dst.TypeAssertExpr:
p.Type = generateExpr()
case *dst.CompositeLit:
p.Type = generateExpr()
case *dst.ArrayType:
p.Elt = generateExpr()
case *dst.ValueSpec:
p.Type = generateExpr()
case *dst.BinaryExpr:
if argIndex == 0 {
p.X = generateExpr()
} else if argIndex == 1 {
p.Y = generateExpr()
} else {
panic("binary expr arg index error")
}
case *dst.CaseClause:
if argIndex < 0 {
panic("case clause arg index error")
}
p.List[argIndex] = generateExpr()
}
case *dst.StarExpr:
return c.enhanceTypeNameWhenRewrite(t.X, t, -1)
case *dst.ArrayType:
return c.enhanceTypeNameWhenRewrite(t.Elt, t, -1)
case *dst.Ellipsis:
return c.enhanceTypeNameWhenRewrite(t.Elt, t, -1)
case *dst.CompositeLit:
for _, elt := range t.Elts {
// for struct data, ex: "&xxx{k: v}"
if kv, ok := elt.(*dst.KeyValueExpr); ok {
c.rewriteVarIfExistingMapping(kv.Value, elt)
} else if call, ok := elt.(*dst.CallExpr); ok {
c.enhanceTypeNameWhenRewrite(call, t, -1)
}
}
return c.enhanceTypeNameWhenRewrite(t.Type, t, -1)
case *dst.UnaryExpr:
return c.enhanceTypeNameWhenRewrite(t.X, t, -1)
case *dst.CallExpr:
for inx, arg := range t.Args {
c.enhanceTypeNameWhenRewrite(arg, t, inx)
}
if id, ok := t.Fun.(*dst.Ident); ok {
if c.callIsBasicNamesOrEnhanceName(id.Name) {
return "", ""
}
return c.enhanceTypeNameWhenRewrite(t.Fun, t, -1)
}
c.enhanceTypeNameWhenRewrite(t.Fun, t, -1)
case *dst.FuncType:
c.enhanceFuncParameter(t.TypeParams)
c.enhanceFuncParameter(t.Params)
c.enhanceFuncParameter(t.Results)
case *dst.IndexExpr:
c.rewriteVarIfExistingMapping(t.Index, t)
return c.enhanceTypeNameWhenRewrite(t.X, t, -1)
case *dst.TypeAssertExpr:
c.enhanceTypeNameWhenRewrite(t.Type, t, -1)
return c.enhanceTypeNameWhenRewrite(t.X, t, -1)
case *dst.FuncLit:
c.enhanceTypeNameWhenRewrite(t.Type, t, -1)
for _, stmt := range t.Body.List {
c.enhanceFuncStmt(stmt)
}
case *dst.BinaryExpr:
c.enhanceTypeNameWhenRewrite(t.X, t, 0)
c.enhanceTypeNameWhenRewrite(t.Y, t, 1)
case *dst.ParenExpr:
c.rewriteVarIfExistingMapping(t.X, t)
case *dst.MapType:
c.enhanceTypeNameWhenRewrite(t.Key, t, -1)
c.enhanceTypeNameWhenRewrite(t.Value, t, -1)
}
return "", ""
}