diff --git a/analyzer/analyzer.go b/analyzer/analyzer.go index 543b4bd..c2d3537 100644 --- a/analyzer/analyzer.go +++ b/analyzer/analyzer.go @@ -171,11 +171,10 @@ func (n *perfSprint) run(pass *analysis.Pass) (interface{}, error) { removedFmtUsages[fname]++ if fn == "fmt.Errorf" { neededPackages[fname]["errors"] = true - d = &analysis.Diagnostic{ - Pos: call.Pos(), - End: call.End(), - Message: fn + " can be replaced with errors.New", - SuggestedFixes: []analysis.SuggestedFix{ + d = newAnalysisDiagnostic( + call, + fn+" can be replaced with errors.New", + []analysis.SuggestedFix{ { Message: "Use errors.New", TextEdits: []analysis.TextEdit{{ @@ -185,13 +184,12 @@ func (n *perfSprint) run(pass *analysis.Pass) (interface{}, error) { }}, }, }, - } + ) } else { - d = &analysis.Diagnostic{ - Pos: call.Pos(), - End: call.End(), - Message: fn + " can be replaced with just using the string", - SuggestedFixes: []analysis.SuggestedFix{ + d = newAnalysisDiagnostic( + call, + fn+" can be replaced with just using the string", + []analysis.SuggestedFix{ { Message: "Just use string value", TextEdits: []analysis.TextEdit{{ @@ -201,7 +199,7 @@ func (n *perfSprint) run(pass *analysis.Pass) (interface{}, error) { }}, }, }, - } + ) } case types.Implements(valueType, errIface) && oneOf(verb, "%v", "%s") && n.errError: // known false positive if this error is nil @@ -209,11 +207,10 @@ func (n *perfSprint) run(pass *analysis.Pass) (interface{}, error) { errMethodCall := formatNode(pass.Fset, value) + ".Error()" fname := pass.Fset.File(call.Pos()).Name() removedFmtUsages[fname]++ - d = &analysis.Diagnostic{ - Pos: call.Pos(), - End: call.End(), - Message: fn + " can be replaced with " + errMethodCall, - SuggestedFixes: []analysis.SuggestedFix{ + d = newAnalysisDiagnostic( + call, + fn+" can be replaced with "+errMethodCall, + []analysis.SuggestedFix{ { Message: "Use " + errMethodCall, TextEdits: []analysis.TextEdit{{ @@ -223,7 +220,7 @@ func (n *perfSprint) run(pass *analysis.Pass) (interface{}, error) { }}, }, }, - } + ) case isBasicType(valueType, types.Bool) && oneOf(verb, "%v", "%t"): fname := pass.Fset.File(call.Pos()).Name() @@ -233,11 +230,10 @@ func (n *perfSprint) run(pass *analysis.Pass) (interface{}, error) { neededPackages[fname] = make(map[string]bool) } neededPackages[fname]["strconv"] = true - d = &analysis.Diagnostic{ - Pos: call.Pos(), - End: call.End(), - Message: fn + " can be replaced with faster strconv.FormatBool", - SuggestedFixes: []analysis.SuggestedFix{ + d = newAnalysisDiagnostic( + call, + fn+" can be replaced with faster strconv.FormatBool", + []analysis.SuggestedFix{ { Message: "Use strconv.FormatBool", TextEdits: []analysis.TextEdit{{ @@ -247,7 +243,7 @@ func (n *perfSprint) run(pass *analysis.Pass) (interface{}, error) { }}, }, }, - } + ) case isArray && isBasicType(a.Elem(), types.Uint8) && oneOf(verb, "%x"): if _, ok := value.(*ast.Ident); !ok { @@ -262,11 +258,10 @@ func (n *perfSprint) run(pass *analysis.Pass) (interface{}, error) { neededPackages[fname] = make(map[string]bool) } neededPackages[fname]["encoding/hex"] = true - d = &analysis.Diagnostic{ - Pos: call.Pos(), - End: call.End(), - Message: fn + " can be replaced with faster hex.EncodeToString", - SuggestedFixes: []analysis.SuggestedFix{ + d = newAnalysisDiagnostic( + call, + fn+" can be replaced with faster hex.EncodeToString", + []analysis.SuggestedFix{ { Message: "Use hex.EncodeToString", TextEdits: []analysis.TextEdit{ @@ -283,7 +278,7 @@ func (n *perfSprint) run(pass *analysis.Pass) (interface{}, error) { }, }, }, - } + ) case isSlice && isBasicType(s.Elem(), types.Uint8) && oneOf(verb, "%x"): fname := pass.Fset.File(call.Pos()).Name() removedFmtUsages[fname]++ @@ -292,11 +287,10 @@ func (n *perfSprint) run(pass *analysis.Pass) (interface{}, error) { neededPackages[fname] = make(map[string]bool) } neededPackages[fname]["encoding/hex"] = true - d = &analysis.Diagnostic{ - Pos: call.Pos(), - End: call.End(), - Message: fn + " can be replaced with faster hex.EncodeToString", - SuggestedFixes: []analysis.SuggestedFix{ + d = newAnalysisDiagnostic( + call, + fn+" can be replaced with faster hex.EncodeToString", + []analysis.SuggestedFix{ { Message: "Use hex.EncodeToString", TextEdits: []analysis.TextEdit{{ @@ -306,7 +300,7 @@ func (n *perfSprint) run(pass *analysis.Pass) (interface{}, error) { }}, }, }, - } + ) case isBasicType(valueType, types.Int8, types.Int16, types.Int32) && oneOf(verb, "%v", "%d") && n.intConv: fname := pass.Fset.File(call.Pos()).Name() @@ -316,11 +310,10 @@ func (n *perfSprint) run(pass *analysis.Pass) (interface{}, error) { neededPackages[fname] = make(map[string]bool) } neededPackages[fname]["strconv"] = true - d = &analysis.Diagnostic{ - Pos: call.Pos(), - End: call.End(), - Message: fn + " can be replaced with faster strconv.Itoa", - SuggestedFixes: []analysis.SuggestedFix{ + d = newAnalysisDiagnostic( + call, + fn+" can be replaced with faster strconv.Itoa", + []analysis.SuggestedFix{ { Message: "Use strconv.Itoa", TextEdits: []analysis.TextEdit{ @@ -337,7 +330,7 @@ func (n *perfSprint) run(pass *analysis.Pass) (interface{}, error) { }, }, }, - } + ) case isBasicType(valueType, types.Int) && oneOf(verb, "%v", "%d"): fname := pass.Fset.File(call.Pos()).Name() removedFmtUsages[fname]++ @@ -346,11 +339,10 @@ func (n *perfSprint) run(pass *analysis.Pass) (interface{}, error) { neededPackages[fname] = make(map[string]bool) } neededPackages[fname]["strconv"] = true - d = &analysis.Diagnostic{ - Pos: call.Pos(), - End: call.End(), - Message: fn + " can be replaced with faster strconv.Itoa", - SuggestedFixes: []analysis.SuggestedFix{ + d = newAnalysisDiagnostic( + call, + fn+" can be replaced with faster strconv.Itoa", + []analysis.SuggestedFix{ { Message: "Use strconv.Itoa", TextEdits: []analysis.TextEdit{{ @@ -360,7 +352,7 @@ func (n *perfSprint) run(pass *analysis.Pass) (interface{}, error) { }}, }, }, - } + ) case isBasicType(valueType, types.Int64) && oneOf(verb, "%v", "%d"): fname := pass.Fset.File(call.Pos()).Name() removedFmtUsages[fname]++ @@ -369,11 +361,10 @@ func (n *perfSprint) run(pass *analysis.Pass) (interface{}, error) { neededPackages[fname] = make(map[string]bool) } neededPackages[fname]["strconv"] = true - d = &analysis.Diagnostic{ - Pos: call.Pos(), - End: call.End(), - Message: fn + " can be replaced with faster strconv.FormatInt", - SuggestedFixes: []analysis.SuggestedFix{ + d = newAnalysisDiagnostic( + call, + fn+" can be replaced with faster strconv.FormatInt", + []analysis.SuggestedFix{ { Message: "Use strconv.FormatInt", TextEdits: []analysis.TextEdit{ @@ -390,7 +381,7 @@ func (n *perfSprint) run(pass *analysis.Pass) (interface{}, error) { }, }, }, - } + ) case isBasicType(valueType, types.Uint8, types.Uint16, types.Uint32, types.Uint) && oneOf(verb, "%v", "%d", "%x") && n.intConv: base := []byte("), 10") @@ -438,11 +429,10 @@ func (n *perfSprint) run(pass *analysis.Pass) (interface{}, error) { neededPackages[fname] = make(map[string]bool) } neededPackages[fname]["strconv"] = true - d = &analysis.Diagnostic{ - Pos: call.Pos(), - End: call.End(), - Message: fn + " can be replaced with faster strconv.FormatUint", - SuggestedFixes: []analysis.SuggestedFix{ + d = newAnalysisDiagnostic( + call, + fn+" can be replaced with faster strconv.FormatUint", + []analysis.SuggestedFix{ { Message: "Use strconv.FormatUint", TextEdits: []analysis.TextEdit{ @@ -459,7 +449,7 @@ func (n *perfSprint) run(pass *analysis.Pass) (interface{}, error) { }, }, }, - } + ) case isBasicType(valueType, types.String) && fn == "fmt.Sprintf" && isConcatable(verb): var fix string if strings.HasSuffix(verb, "%s") { @@ -473,11 +463,10 @@ func (n *perfSprint) run(pass *analysis.Pass) (interface{}, error) { } fname := pass.Fset.File(call.Pos()).Name() removedFmtUsages[fname]++ - d = &analysis.Diagnostic{ - Pos: call.Pos(), - End: call.End(), - Message: fn + " can be replaced with string concatenation", - SuggestedFixes: []analysis.SuggestedFix{ + d = newAnalysisDiagnostic( + call, + fn+" can be replaced with string concatenation", + []analysis.SuggestedFix{ { Message: "Use string concatenation", TextEdits: []analysis.TextEdit{{ @@ -487,7 +476,7 @@ func (n *perfSprint) run(pass *analysis.Pass) (interface{}, error) { }}, }, }, - } + ) } if d != nil { @@ -553,11 +542,10 @@ func (n *perfSprint) run(pass *analysis.Pass) (interface{}, error) { for _, k := range keys { fix = fix + "\n\t\"" + k + `"` } - pass.Report(analysis.Diagnostic{ - Pos: gd.Pos(), - End: gd.End(), - Message: "Fix imports", - SuggestedFixes: []analysis.SuggestedFix{ + pass.Report(*newAnalysisDiagnostic( + gd, + "Fix imports", + []analysis.SuggestedFix{ { Message: "Fix imports", TextEdits: []analysis.TextEdit{{ @@ -566,7 +554,7 @@ func (n *perfSprint) run(pass *analysis.Pass) (interface{}, error) { NewText: []byte(fix), }}, }, - }}) + })) } }) } diff --git a/analyzer/diagnostics.go b/analyzer/diagnostics.go new file mode 100644 index 0000000..180887b --- /dev/null +++ b/analyzer/diagnostics.go @@ -0,0 +1,18 @@ +package analyzer + +import ( + "golang.org/x/tools/go/analysis" +) + +func newAnalysisDiagnostic( + analysisRange analysis.Range, + message string, + suggestedFixes []analysis.SuggestedFix, +) *analysis.Diagnostic { + return &analysis.Diagnostic{ + Pos: analysisRange.Pos(), + End: analysisRange.End(), + Message: message, + SuggestedFixes: suggestedFixes, + } +}