in dev/tools/controllerbuilder/pkg/io/compare.go [62:151]
func CompareStruct(code, otherCode string, factors ...string) (*Results, error) {
aFset := token.NewFileSet()
aFile, err := parser.ParseFile(aFset, "", code, parser.ParseComments)
if err != nil {
return nil, fmt.Errorf("parsing first go code snippet: %w", err)
}
bFset := token.NewFileSet()
// Make sure src package exists otherwise the parser will fail
_, _, found := strings.Cut(otherCode, "package")
if !found {
otherCode = "package main" + "\n" + otherCode
}
bFile, err := parser.ParseFile(bFset, "", otherCode, parser.ParseComments)
if err != nil {
return nil, fmt.Errorf("parsing second go code snippet: %w", err)
}
compareAll := false
if factors == nil {
compareAll = true
}
pairMap := make(map[string]*structPair)
for _, c := range factors {
pairMap[c] = &structPair{}
}
ast.Inspect(aFile, func(n ast.Node) bool {
x, ok := n.(*ast.GenDecl)
if !ok || x.Tok != token.TYPE {
return true
}
for _, spec := range x.Specs {
typeSpec, ok := spec.(*ast.TypeSpec)
if !ok {
continue
}
// record A for comparison
if pair, ok := pairMap[typeSpec.Name.Name]; compareAll || ok {
structType, typeOk := typeSpec.Type.(*ast.StructType)
if !typeOk {
continue
}
if pair == nil {
pair = &structPair{}
}
pair.A = structType
pairMap[typeSpec.Name.Name] = pair
}
}
return true
})
ast.Inspect(bFile, func(n ast.Node) bool {
x, ok := n.(*ast.GenDecl)
if !ok || x.Tok != token.TYPE {
return true
}
for _, spec := range x.Specs {
typeSpec, ok := spec.(*ast.TypeSpec)
if !ok {
continue
}
// record B for comparison
if pair, ok := pairMap[typeSpec.Name.Name]; compareAll || ok {
structType, typeOk := typeSpec.Type.(*ast.StructType)
if !typeOk {
continue
}
if pair == nil {
pair = &structPair{}
}
pair.B = structType
pairMap[typeSpec.Name.Name] = pair
}
}
return true
})
results := &Results{}
for name, pair := range pairMap {
r := compareFields(pair)
fmt.Println("Compare: ", name, "Result: ", r)
*results = append(*results, *r)
}
return results, nil
}