func()

in tools/go-agent/instrument/plugins/rewrite/context.go [163:343]


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 {
			if !strings.Contains(name, BeforeInterStart) {
				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 "", ""
}