Implement deferred core utility parity APIs/tests and refresh tracking artifacts

This commit is contained in:
Joseph Doherty
2026-02-27 10:27:05 -05:00
parent c0aaae9236
commit b94a67be6e
17 changed files with 842 additions and 9 deletions

View File

@@ -256,6 +256,10 @@ func (a *Analyzer) parseTestFile(filePath string) ([]TestFunc, []ImportInfo, int
}
test.FeatureName = a.inferFeatureName(name)
test.BestFeatureIdx = -1
if fn.Body != nil {
test.Calls = a.extractCalls(fn.Body)
}
tests = append(tests, test)
}
@@ -331,6 +335,210 @@ func (a *Analyzer) inferFeatureName(testName string) string {
return name
}
// extractCalls walks an AST block statement and extracts all function/method calls.
func (a *Analyzer) extractCalls(body *ast.BlockStmt) []CallInfo {
seen := make(map[string]bool)
var calls []CallInfo
ast.Inspect(body, func(n ast.Node) bool {
callExpr, ok := n.(*ast.CallExpr)
if !ok {
return true
}
var ci CallInfo
switch fun := callExpr.Fun.(type) {
case *ast.Ident:
ci = CallInfo{FuncName: fun.Name}
case *ast.SelectorExpr:
ci = CallInfo{
RecvOrPkg: extractIdent(fun.X),
MethodName: fun.Sel.Name,
IsSelector: true,
}
default:
return true
}
key := ci.callKey()
if !seen[key] && !isFilteredCall(ci) {
seen[key] = true
calls = append(calls, ci)
}
return true
})
return calls
}
// extractIdent extracts an identifier name from an expression (handles X in X.Y).
func extractIdent(expr ast.Expr) string {
switch e := expr.(type) {
case *ast.Ident:
return e.Name
case *ast.SelectorExpr:
return extractIdent(e.X) + "." + e.Sel.Name
default:
return ""
}
}
// isFilteredCall returns true if a call should be excluded from feature matching.
func isFilteredCall(c CallInfo) bool {
if c.IsSelector {
recv := c.RecvOrPkg
// testing.T/B methods
if recv == "t" || recv == "b" || recv == "tb" {
return true
}
// stdlib packages
if stdlibPkgs[recv] {
return true
}
// NATS client libs
if recv == "nats" || recv == "nuid" || recv == "nkeys" || recv == "jwt" {
return true
}
return false
}
// Go builtins
name := c.FuncName
if builtinFuncs[name] {
return true
}
// Test assertion helpers
lower := strings.ToLower(name)
if strings.HasPrefix(name, "require_") {
return true
}
for _, prefix := range []string{"check", "verify", "assert", "expect"} {
if strings.HasPrefix(lower, prefix) {
return true
}
}
return false
}
// featureRef identifies a feature within the analysis result.
type featureRef struct {
moduleIdx int
featureIdx int
goFile string
goClass string
}
// resolveCallGraph matches test calls against known features across all modules.
func resolveCallGraph(result *AnalysisResult) {
// Build method index: go_method name → list of feature refs
methodIndex := make(map[string][]featureRef)
for mi, mod := range result.Modules {
for fi, feat := range mod.Features {
ref := featureRef{
moduleIdx: mi,
featureIdx: fi,
goFile: feat.GoFile,
goClass: feat.GoClass,
}
methodIndex[feat.GoMethod] = append(methodIndex[feat.GoMethod], ref)
}
}
// For each test, resolve calls to features
for mi := range result.Modules {
mod := &result.Modules[mi]
for ti := range mod.Tests {
test := &mod.Tests[ti]
seen := make(map[int]bool) // feature indices already linked
var linked []int
testFileBase := sourceFileBase(test.GoFile)
for _, call := range test.Calls {
// Look up the method name
name := call.MethodName
if !call.IsSelector {
name = call.FuncName
}
candidates := methodIndex[name]
if len(candidates) == 0 {
continue
}
// Ambiguity threshold: skip very common method names
if len(candidates) > 10 {
continue
}
// Filter to same module
var sameModule []featureRef
for _, ref := range candidates {
if ref.moduleIdx == mi {
sameModule = append(sameModule, ref)
}
}
if len(sameModule) == 0 {
continue
}
for _, ref := range sameModule {
if !seen[ref.featureIdx] {
seen[ref.featureIdx] = true
linked = append(linked, ref.featureIdx)
}
}
}
test.LinkedFeatures = linked
// Set BestFeatureIdx using priority:
// (a) existing inferFeatureName match
// (b) same-file-base match
// (c) first remaining candidate
if test.BestFeatureIdx < 0 && len(linked) > 0 {
// Try same-file-base match first
for _, fi := range linked {
featFileBase := sourceFileBase(mod.Features[fi].GoFile)
if featFileBase == testFileBase {
test.BestFeatureIdx = fi
break
}
}
// Fall back to first candidate
if test.BestFeatureIdx < 0 {
test.BestFeatureIdx = linked[0]
}
}
}
}
}
// sourceFileBase strips _test.go suffix and path to get the base file name.
func sourceFileBase(goFile string) string {
base := filepath.Base(goFile)
base = strings.TrimSuffix(base, "_test.go")
base = strings.TrimSuffix(base, ".go")
return base
}
var stdlibPkgs = map[string]bool{
"fmt": true, "time": true, "strings": true, "bytes": true, "errors": true,
"os": true, "math": true, "sort": true, "reflect": true, "sync": true,
"context": true, "io": true, "filepath": true, "strconv": true,
"encoding": true, "json": true, "binary": true, "hex": true, "rand": true,
"runtime": true, "atomic": true, "slices": true, "testing": true,
"net": true, "bufio": true, "crypto": true, "log": true, "regexp": true,
"unicode": true, "http": true, "url": true,
}
var builtinFuncs = map[string]bool{
"make": true, "append": true, "len": true, "cap": true, "close": true,
"delete": true, "panic": true, "recover": true, "print": true,
"println": true, "copy": true, "new": true,
}
// isStdlib checks if an import path is a Go standard library package.
func isStdlib(importPath string) bool {
firstSlash := strings.Index(importPath, "/")