//
// Copyright (c) 2026, Novant LLC
// Licensed under the MIT License
//
// History:
// 26 Oct 2026 Andy Frank Creation
//
*************************************************************************
** Resolver
*************************************************************************
** Resolver expands command line targets into the qualified test
** method names fant will run, using the same rules as 'TestRunner'.
const class Resolver
{
** Resolve targets to test method qnames, or throw ArgErr if
** any target does not exist.
static Str[] resolve(Str[] targets)
{
acc := Str[,]
targets.each |t| { acc.addAll(resolveTarget(t)) }
return acc
}
** Resolve a single '<pod>', '<pod>::<Type>', or '<pod>::<Type>.<method>'.
static Str[] resolveTarget(Str target)
{
// pod
colons := target.index("::")
if (colons == null) return podTests(findPod(target))
// pod::Type
pod := findPod(target[0..<colons])
rest := target[colons+2..-1]
dot := rest.index(".")
if (dot == null) return typeTests(findType(pod, rest))
// pod::Type.method
type := findType(pod, rest[0..<dot])
name := rest[dot+1..-1]
if (type.method(name, false) == null) throw ArgErr("Unknown method: ${type.qname}.${name}")
return ["${type.qname}.${name}"]
}
** All test methods on all concrete Test types in pod.
static Str[] podTests(Pod pod)
{
acc := Str[,]
pod.types.each |t|
{
if (t.fits(Test#) && !t.isAbstract) acc.addAll(typeTests(t))
}
return acc
}
** All 'test*' methods on given type.
static Str[] typeTests(Type type)
{
type.methods
.findAll |m| { m.name.startsWith("test") && !m.isAbstract }
.map |m->Str| { "${type.qname}.${m.name}" }
}
private static Pod findPod(Str name)
{
Pod.find(name, false) ?: throw ArgErr("Unknown pod: $name")
}
private static Type findType(Pod pod, Str name)
{
type := pod.type(name, false) ?: throw ArgErr("Unknown type: ${pod.name}::${name}")
if (!type.fits(Test#)) throw ArgErr("Not a Test type: $type.qname")
return type
}
}