Files
wehub-resource-sync a06f331eb8
CI / benchmark (push) Has been skipped
install-script / posix-syntax (push) Successful in 6m1s
CI / build-onnx (push) Failing after 6m43s
init-smoke / dry-run (push) Failing after 15m57s
security / govulncheck (push) Has been cancelled
security / trivy-fs (push) Has been cancelled
CI / test (1.26, ubuntu-latest) (push) Has been cancelled
Scorecard supply-chain security / Scorecard analysis (push) Has been cancelled
CI / test (1.26, macos-latest) (push) Has been cancelled
CI / build-windows (push) Has been cancelled
CI / lint (push) Has been cancelled
install-script / powershell-syntax (push) Has been cancelled
install-script / install (macos-14) (push) Has been cancelled
install-script / install (ubuntu-latest) (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:33:42 +08:00

339 lines
12 KiB
Go

package languages
import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/zzet/gortex/internal/graph"
)
// dartRefEdge reports whether edges contains an edge of kind to
// "unresolved::"+typeName whose Meta["ref_context"] equals refContext (pass
// "" to require no ref_context, e.g. for EdgeInstantiates).
func dartRefEdge(edges []*graph.Edge, kind graph.EdgeKind, typeName, refContext string) bool {
want := "unresolved::" + typeName
for _, e := range edges {
if e.Kind != kind || e.To != want {
continue
}
got := ""
if e.Meta != nil {
if v, ok := e.Meta["ref_context"].(string); ok {
got = v
}
}
if got == refContext {
return true
}
}
return false
}
// countRefEdge counts edges of kind to "unresolved::"+typeName.
func countRefEdge(edges []*graph.Edge, kind graph.EdgeKind, typeName string) int {
want := "unresolved::" + typeName
n := 0
for _, e := range edges {
if e.Kind == kind && e.To == want {
n++
}
}
return n
}
// TestDartRefForm_Instantiation covers `Foo()` (unadorned), `new Foo()`, and
// `const Foo.named()`. For a local type, extractCalls owns the bare-call
// instantiation; new / const forms are owned by this pass.
func TestDartRefForm_Instantiation(t *testing.T) {
src := []byte(`class Widget {
Widget.named();
}
void run() {
var a = Widget();
var b = new Widget();
var c = const Widget.named();
foo();
}
void foo() {}
`)
res, err := NewDartExtractor().Extract("w.dart", src)
require.NoError(t, err)
// `Widget()`, `new Widget()`, `const Widget.named()` all construct Widget.
assert.True(t, dartRefEdge(res.Edges, graph.EdgeInstantiates, "Widget", ""),
"Widget construction should emit EdgeInstantiates; edges=%v", res.Edges)
// Origin is OriginASTResolved (guard-survival + consistency).
for _, e := range res.Edges {
if e.Kind == graph.EdgeInstantiates && e.To == "unresolved::Widget" {
assert.Equal(t, graph.OriginASTResolved, e.Origin)
}
}
// A lowercase free-function call `foo()` is NOT a construction.
assert.False(t, dartRefEdge(res.Edges, graph.EdgeInstantiates, "foo", ""),
"lowercase call foo() must not be an instantiation")
// `const Widget.named()` references Widget once as instantiation; the bare
// `Widget()` is emitted by extractCalls (local type). This pass must not
// double-emit the bare local construction.
assert.GreaterOrEqual(t, countRefEdge(res.Edges, graph.EdgeInstantiates, "Widget"), 1)
}
// TestDartRefForm_InstantiationExternalType verifies an unadorned `Client()`
// for a type NOT defined in the file (imported) surfaces as an instantiation,
// while a lowercase callee does not.
func TestDartRefForm_InstantiationExternalType(t *testing.T) {
src := []byte(`void run() {
var c = Client();
var r = Response();
helper();
}
`)
res, err := NewDartExtractor().Extract("api.dart", src)
require.NoError(t, err)
assert.True(t, dartRefEdge(res.Edges, graph.EdgeInstantiates, "Client", ""),
"imported Client() should emit EdgeInstantiates; edges=%v", res.Edges)
assert.True(t, dartRefEdge(res.Edges, graph.EdgeInstantiates, "Response", ""),
"imported Response() should emit EdgeInstantiates")
assert.False(t, dartRefEdge(res.Edges, graph.EdgeInstantiates, "helper", ""),
"lowercase call helper() must not be an instantiation")
}
// TestDartRefForm_Inheritance covers extends / with / implements.
func TestDartRefForm_Inheritance(t *testing.T) {
src := []byte(`class Base {}
mixin M {}
abstract class I {}
class X extends Base with M implements I {}
`)
res, err := NewDartExtractor().Extract("x.dart", src)
require.NoError(t, err)
assert.True(t, dartRefEdge(res.Edges, graph.EdgeReferences, "Base", graph.RefContextInherit),
"extends Base should emit inherit reference; edges=%v", res.Edges)
assert.True(t, dartRefEdge(res.Edges, graph.EdgeReferences, "M", graph.RefContextInherit),
"with M should emit inherit reference")
assert.True(t, dartRefEdge(res.Edges, graph.EdgeReferences, "I", graph.RefContextInherit),
"implements I should emit inherit reference")
// Inherit references attribute to the file node (the class line is not
// inside a function range) and ride OriginASTResolved.
for _, e := range res.Edges {
if e.Kind == graph.EdgeReferences && e.Meta != nil &&
e.Meta["ref_context"] == graph.RefContextInherit {
assert.Equal(t, graph.OriginASTResolved, e.Origin)
assert.Equal(t, "x.dart", e.From)
}
}
}
// TestDartRefForm_CastAndTypeTest covers `x as Foo`, `x is Foo`, `x is! Foo`.
func TestDartRefForm_CastAndTypeTest(t *testing.T) {
src := []byte(`void run(Object o) {
var a = o as Account;
if (o is User) {}
if (o is! Token) {}
}
`)
res, err := NewDartExtractor().Extract("c.dart", src)
require.NoError(t, err)
assert.True(t, dartRefEdge(res.Edges, graph.EdgeReferences, "Account", graph.RefContextCast),
"`o as Account` should emit cast reference; edges=%v", res.Edges)
assert.True(t, dartRefEdge(res.Edges, graph.EdgeReferences, "User", graph.RefContextCast),
"`o is User` should emit cast reference")
assert.True(t, dartRefEdge(res.Edges, graph.EdgeReferences, "Token", graph.RefContextCast),
"`o is! Token` should emit cast reference")
// Casts inside run() attribute to the enclosing method.
for _, e := range res.Edges {
if e.Kind == graph.EdgeReferences && e.Meta != nil &&
e.Meta["ref_context"] == graph.RefContextCast {
assert.Equal(t, "c.dart::run", e.From)
}
}
}
// TestDartRefForm_StaticAccess covers `Foo.constant`, `Foo.empty()`,
// `Foo.staticMethod()`.
func TestDartRefForm_StaticAccess(t *testing.T) {
src := []byte(`void run() {
var a = Colors.red;
var b = Logger.empty();
var c = Math.max(1, 2);
}
`)
res, err := NewDartExtractor().Extract("s.dart", src)
require.NoError(t, err)
assert.True(t, dartRefEdge(res.Edges, graph.EdgeReferences, "Colors", graph.RefContextStaticAccess),
"`Colors.red` should emit static_access reference; edges=%v", res.Edges)
assert.True(t, dartRefEdge(res.Edges, graph.EdgeReferences, "Logger", graph.RefContextStaticAccess),
"`Logger.empty()` should emit static_access reference")
assert.True(t, dartRefEdge(res.Edges, graph.EdgeReferences, "Math", graph.RefContextStaticAccess),
"`Math.max(...)` should emit static_access reference")
}
// TestDartRefForm_Negatives verifies the false-positive guards: a lowercase
// free call, a lowercase instance call, `this.x`, a chained access, and a
// primitive emit nothing on the reference surface.
func TestDartRefForm_Negatives(t *testing.T) {
src := []byte(`class C {
var x = 0;
void run() {
foo();
obj.method();
this.x = 1;
one.Two.three;
int n = 5;
}
}
`)
res, err := NewDartExtractor().Extract("n.dart", src)
require.NoError(t, err)
// Lowercase free call → not an instantiation.
assert.False(t, dartRefEdge(res.Edges, graph.EdgeInstantiates, "foo", ""),
"foo() must not be an instantiation")
// Lowercase instance call → not a static access (head is lowercase `obj`).
assert.False(t, dartRefEdge(res.Edges, graph.EdgeReferences, "obj", graph.RefContextStaticAccess),
"obj.method() must not be a static access")
assert.False(t, dartRefEdge(res.Edges, graph.EdgeReferences, "method", graph.RefContextStaticAccess),
"method must not be referenced as a static access")
// `this.x` → no reference (`this` is filtered by capitalization gate).
assert.False(t, dartRefEdge(res.Edges, graph.EdgeReferences, "this", graph.RefContextStaticAccess),
"this.x must not emit a static access")
// Chained `one.Two.three`: the head is lowercase `one`, so even though
// `Two` is capitalized it is NOT a static-access head (it lives inside a
// selector). Two must not be referenced as a static access.
assert.False(t, dartRefEdge(res.Edges, graph.EdgeReferences, "Two", graph.RefContextStaticAccess),
"chained one.Two.three must not treat Two as a static-access head")
// Primitive `int` emits nothing on any reference surface.
for _, e := range res.Edges {
assert.NotEqual(t, "unresolved::int", e.To, "primitive int must not appear on a reference edge")
}
}
// TestDartRefForm_GenericArgs verifies that the element type(s) of a
// parameterised type surface as generic_arg references in every position:
// a class field annotation, a parameter, a return type, a typed local, a
// supertype clause (extends / with / implements), and nested generics. Each
// rides EdgeReferences with Meta["ref_context"]="generic_arg" and
// OriginASTResolved. Primitive element types (String) are filtered, and the
// generic *parameter* declaration `<T>` (a type_parameters node, not a use) is
// never read as a reference.
func TestDartRefForm_GenericArgs(t *testing.T) {
src := []byte(`class Box<T> extends Base<Sup> with Mix<MixArg> implements Iface<IfArg> {
List<Field> field = [];
Map<String, List<Nested>> nested = {};
Future<Ret> fetch(Set<Param> accts, [List<Opt>? logs]) async {
List<Local> users = [];
return get();
}
}
`)
res, err := NewDartExtractor().Extract("box.dart", src)
require.NoError(t, err)
gen := func(typeName string) bool {
return dartRefEdge(res.Edges, graph.EdgeReferences, typeName, graph.RefContextGenericArg)
}
// Every element type, in every position, surfaces as a generic_arg.
assert.True(t, gen("Field"), "field List<Field> element; edges=%v", res.Edges)
assert.True(t, gen("Nested"), "nested Map<String, List<Nested>> element")
assert.True(t, gen("Ret"), "return Future<Ret> element")
assert.True(t, gen("Param"), "parameter Set<Param> element")
assert.True(t, gen("Opt"), "optional parameter List<Opt>? element")
assert.True(t, gen("Local"), "typed local List<Local> element")
assert.True(t, gen("Sup"), "supertype extends Base<Sup> element")
assert.True(t, gen("MixArg"), "mixin with Mix<MixArg> element")
assert.True(t, gen("IfArg"), "interface implements Iface<IfArg> element")
// Primitive element type String must never surface.
assert.False(t, gen("String"), "primitive generic arg String must not surface")
// The generic *parameter* declaration `<T>` is a type_parameters node, not a
// use — T must not be read as a generic_arg reference.
assert.False(t, gen("T"), "generic parameter declaration <T> must not be a use")
// Generic-arg references ride OriginASTResolved.
for _, e := range res.Edges {
if e.Kind == graph.EdgeReferences && e.Meta != nil &&
e.Meta["ref_context"] == graph.RefContextGenericArg {
assert.Equal(t, graph.OriginASTResolved, e.Origin,
"generic_arg reference Origin must be OriginASTResolved")
}
}
// Generic args inside fetch() attribute to the enclosing method; the
// supertype / field args (outside any function) fall back to the file node.
for _, e := range res.Edges {
if e.Kind != graph.EdgeReferences || e.Meta == nil ||
e.Meta["ref_context"] != graph.RefContextGenericArg {
continue
}
switch e.To {
case "unresolved::Ret", "unresolved::Param", "unresolved::Opt", "unresolved::Local":
assert.Equal(t, "box.dart::Box.fetch", e.From,
"generic arg %s should attribute to the enclosing method", e.To)
case "unresolved::Sup", "unresolved::MixArg", "unresolved::IfArg", "unresolved::Field", "unresolved::Nested":
assert.Equal(t, "box.dart", e.From,
"generic arg %s outside any function should attribute to the file node", e.To)
}
}
}
// TestDartRefForm_GenericArgsNoDuplicate guards the per-(owner,type,line,
// ref_context) dedup: the same generic element type repeated on one line emits
// a single generic_arg edge.
func TestDartRefForm_GenericArgsNoDuplicate(t *testing.T) {
src := []byte(`void run() {
Map<Key, Key> m = {};
}
`)
res, err := NewDartExtractor().Extract("d.dart", src)
require.NoError(t, err)
n := 0
for _, e := range res.Edges {
if e.Kind == graph.EdgeReferences && e.To == "unresolved::Key" &&
e.Meta != nil && e.Meta["ref_context"] == graph.RefContextGenericArg {
n++
}
}
assert.Equal(t, 1, n, "Map<Key, Key> must dedup to one generic_arg edge for Key")
}
// TestDartRefForm_NoDuplicateEdges guards the per-(owner,type,line,ref_context)
// dedup: the same static access twice on one line emits a single edge.
func TestDartRefForm_NoDuplicateEdges(t *testing.T) {
src := []byte(`void run() {
var a = Config.a + Config.b;
}
`)
res, err := NewDartExtractor().Extract("d.dart", src)
require.NoError(t, err)
// Two `Config.` accesses on the same line dedup to one static_access edge.
n := 0
for _, e := range res.Edges {
if e.Kind == graph.EdgeReferences && e.To == "unresolved::Config" &&
e.Meta != nil && e.Meta["ref_context"] == graph.RefContextStaticAccess {
n++
}
}
assert.Equal(t, 1, n, "two Config. accesses on one line must dedup to one static_access edge")
}