70 lines
1.9 KiB
Go
70 lines
1.9 KiB
Go
|
|
package main
|
||
|
|
|
||
|
|
import (
|
||
|
|
"go/ast"
|
||
|
|
"go/token"
|
||
|
|
"strings"
|
||
|
|
)
|
||
|
|
|
||
|
|
// Context usage types
|
||
|
|
type ContextInfo struct {
|
||
|
|
File string `json:"file"`
|
||
|
|
MissingContext []ContextUsage `json:"missing_context,omitempty"`
|
||
|
|
ProperUsage []ContextUsage `json:"proper_usage,omitempty"`
|
||
|
|
ImproperUsage []ContextUsage `json:"improper_usage,omitempty"`
|
||
|
|
}
|
||
|
|
|
||
|
|
type ContextUsage struct {
|
||
|
|
Function string `json:"function"`
|
||
|
|
Type string `json:"type"`
|
||
|
|
Description string `json:"description"`
|
||
|
|
Position Position `json:"position"`
|
||
|
|
}
|
||
|
|
|
||
|
|
func findContextUsage(dir string) ([]ContextInfo, error) {
|
||
|
|
var contextInfo []ContextInfo
|
||
|
|
|
||
|
|
err := walkGoFiles(dir, func(path string, src []byte, file *ast.File, fset *token.FileSet) error {
|
||
|
|
info := ContextInfo{
|
||
|
|
File: path,
|
||
|
|
}
|
||
|
|
|
||
|
|
ast.Inspect(file, func(n ast.Node) bool {
|
||
|
|
if fn, ok := n.(*ast.FuncDecl); ok && fn.Type.Params != nil {
|
||
|
|
hasContext := false
|
||
|
|
for _, param := range fn.Type.Params.List {
|
||
|
|
if exprToString(param.Type) == "context.Context" {
|
||
|
|
hasContext = true
|
||
|
|
break
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// Check if function should have context
|
||
|
|
if !hasContext && shouldHaveContext(fn) {
|
||
|
|
pos := fset.Position(fn.Pos())
|
||
|
|
info.MissingContext = append(info.MissingContext, ContextUsage{
|
||
|
|
Function: fn.Name.Name,
|
||
|
|
Type: "missing",
|
||
|
|
Description: "Function should accept context.Context",
|
||
|
|
Position: newPosition(pos),
|
||
|
|
})
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return true
|
||
|
|
})
|
||
|
|
|
||
|
|
if len(info.MissingContext) > 0 || len(info.ProperUsage) > 0 || len(info.ImproperUsage) > 0 {
|
||
|
|
contextInfo = append(contextInfo, info)
|
||
|
|
}
|
||
|
|
return nil
|
||
|
|
})
|
||
|
|
|
||
|
|
return contextInfo, err
|
||
|
|
}
|
||
|
|
|
||
|
|
func shouldHaveContext(fn *ast.FuncDecl) bool {
|
||
|
|
// Simple heuristic: functions that might do I/O
|
||
|
|
name := strings.ToLower(fn.Name.Name)
|
||
|
|
return strings.Contains(name, "get") || strings.Contains(name, "fetch") ||
|
||
|
|
strings.Contains(name, "load") || strings.Contains(name, "save")
|
||
|
|
}
|