From 244b9c62ef62a46dafb3a7d6156fb68a72119727 Mon Sep 17 00:00:00 2001 From: Aerex Date: Tue, 11 Oct 2022 17:44:57 -0500 Subject: [PATCH] refactor(checkup): Split parsing go syntax tree into separate methods --- cmds/checkup.go | 161 ++++++++++++++++++++++++++++-------------------- 1 file changed, 93 insertions(+), 68 deletions(-) diff --git a/cmds/checkup.go b/cmds/checkup.go index 4ecb9a0..f636f63 100644 --- a/cmds/checkup.go +++ b/cmds/checkup.go @@ -117,6 +117,89 @@ func getGoFiles(dir string) (files []string) { return } +func (cu *Checkup) inspectAssignStmt(stmtMap map[string][]ast.AssignStmt, node *ast.AssignStmt) { + // use a hashmap for defined variables to a list of reassigned variables sharing the same var name + if assignStmt, okIdent := node.Lhs[0].(*ast.Ident); okIdent { + varName := assignStmt.Name + if node.Tok == token.DEFINE { + stmtMap[varName] = []ast.AssignStmt{} + } else if node.Tok == token.ASSIGN { + if _, exists := stmtMap[varName]; exists { + stmtMap[varName] = append(stmtMap[varName], *node) + } + } + } +} + +func (cu *Checkup) inspectStmt(translatedStrings []string, stmtMap map[string][]ast.AssignStmt, node ast.AssignStmt) []string { + if strStmtArg, ok := node.Rhs[0].(*ast.BasicLit); ok { + varName := node.Lhs[0].(*ast.Ident).Name + translatedString, err := strconv.Unquote(strStmtArg.Value) + if err != nil { + panic(err.Error()) + } + translatedStrings = append(translatedStrings, translatedString) + // apply all translation ids from reassigned variables + if _, exists := stmtMap[varName]; exists { + for _, assignStmt := range stmtMap[varName] { + strVarVal := assignStmt.Rhs[0].(*ast.BasicLit).Value + translatedString, err := strconv.Unquote(strVarVal) + if err != nil { + panic(err.Error()) + } + translatedStrings = append(translatedStrings, translatedString) + + } + } + } + + return translatedStrings +} + +func (cu *Checkup) inspectTFunc(translatedStrings []string, stmtMap map[string][]ast.AssignStmt, node ast.CallExpr) []string { + if stringArg, ok := node.Args[0].(*ast.BasicLit); ok { + translatedString, err := strconv.Unquote(stringArg.Value) + if err != nil { + panic(err.Error()) + } + translatedStrings = append(translatedStrings, translatedString) + } + if idt, okIdt := node.Args[0].(*ast.Ident); okIdt { + if obj := idt.Obj; obj != nil { + if stmtArg, okStmt := obj.Decl.(*ast.AssignStmt); okStmt { + translatedStrings = cu.inspectStmt(translatedStrings, stmtMap, *stmtArg) + } + } + } + + return translatedStrings +} + +func (cu *Checkup) inspectCallExpr(translatedStrings []string, stmtMap map[string][]ast.AssignStmt, node *ast.CallExpr) []string { + switch node.Fun.(type) { + case *ast.Ident: + funName := node.Fun.(*ast.Ident).Name + // inspect any T() or t() method calls + if funName == "T" || funName == "t" { + translatedStrings = cu.inspectTFunc(translatedStrings, stmtMap, *node) + } + + case *ast.SelectorExpr: + expr := node.Fun.(*ast.SelectorExpr) + if ident, ok := expr.X.(*ast.Ident); ok { + funName := expr.Sel.Name + // inspect any .T() or .t() method calls (eg. i18n.T()) + if ident.Name == cu.options.QualifierFlag && (funName == "T" || funName == "t") { + translatedStrings = cu.inspectTFunc(translatedStrings, stmtMap, *node) + } + } + default: + //Skip! + } + + return translatedStrings +} + func (cu *Checkup) inspectFile(file string) (translatedStrings []string, err error) { defineAssignStmtMap := make(map[string][]ast.AssignStmt) fset := token.NewFileSet() @@ -129,75 +212,17 @@ func (cu *Checkup) inspectFile(file string) (translatedStrings []string, err err ast.Inspect(astFile, func(n ast.Node) bool { switch x := n.(type) { case *ast.AssignStmt: - // use a hashmap for defined variables to a list of reassigned variables sharing the same var name - if assignStmt, okIdent := x.Lhs[0].(*ast.Ident); okIdent { - varName := assignStmt.Name - if x.Tok == token.DEFINE { - defineAssignStmtMap[varName] = []ast.AssignStmt{} - } else if x.Tok == token.ASSIGN { - if _, exists := defineAssignStmtMap[varName]; exists { - defineAssignStmtMap[varName] = append(defineAssignStmtMap[varName], *x) - } - } - } + // inspect any potential translation string in defined / assigned statement nodes + // add node to map if variable contains a translation string + // eg: translation := "Hello {{.FirstName}}" + // T(translation) + // translation = "Hello {{.LastName}}" + // T(translation) + cu.inspectAssignStmt(defineAssignStmtMap, x) case *ast.CallExpr: - switch x.Fun.(type) { - case *ast.Ident: - funName := x.Fun.(*ast.Ident).Name - - if funName == "T" || funName == "t" { - if stringArg, okStr := x.Args[0].(*ast.BasicLit); okStr { - translatedString, err := strconv.Unquote(stringArg.Value) - if err != nil { - panic(err.Error()) - } - translatedStrings = append(translatedStrings, translatedString) - } - if idt, okIdt := x.Args[0].(*ast.Ident); okIdt { - if obj := idt.Obj; obj != nil { - if stmtArg, okStmt := obj.Decl.(*ast.AssignStmt); okStmt { - if strStmtArg, okStrStmt := stmtArg.Rhs[0].(*ast.BasicLit); okStrStmt { - varName := stmtArg.Lhs[0].(*ast.Ident).Name - translatedString, err := strconv.Unquote(strStmtArg.Value) - if err != nil { - panic(err.Error()) - } - translatedStrings = append(translatedStrings, translatedString) - // apply all translation ids from reassigned variables - if _, exists := defineAssignStmtMap[varName]; exists { - for _, assignStmt := range defineAssignStmtMap[varName] { - strVarVal := assignStmt.Rhs[0].(*ast.BasicLit).Value - translatedString, err := strconv.Unquote(strVarVal) - if err != nil { - panic(err.Error()) - } - translatedStrings = append(translatedStrings, translatedString) - - } - } - } - } - } - } - - } - case *ast.SelectorExpr: - expr := x.Fun.(*ast.SelectorExpr) - if ident, ok := expr.X.(*ast.Ident); ok { - funName := expr.Sel.Name - if ident.Name == cu.options.QualifierFlag && (funName == "T" || funName == "t") { - if stringArg, ok := x.Args[0].(*ast.BasicLit); ok { - translatedString, err := strconv.Unquote(stringArg.Value) - if err != nil { - panic(err.Error()) - } - translatedStrings = append(translatedStrings, translatedString) - } - } - } - default: - //Skip! - } + // inspect any T()/t() or .T()/.t() (eg. i18n.T()) method calls using map + /// then retrieve a list of translation strings that were passed into method + translatedStrings = cu.inspectCallExpr(translatedStrings, defineAssignStmtMap, x) } return true })