Files
zzet--gortex/internal/parser/languages/rust_traitmethod_test.go
T
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

104 lines
3.2 KiB
Go

package languages
import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/zzet/gortex/internal/graph"
)
// Trait-declaration methods (both signatures and default methods) get their
// own <file>::<Trait>.<method> KindMethod node so dyn-dispatch call sites that
// bind to the declaration are answerable and find_implementations can pair the
// concrete impls against them.
func TestRsExtractor_TraitMethodNodes(t *testing.T) {
src := []byte(`pub trait SinkError: Sized {
fn error_message<T>(message: T) -> Self;
fn default_impl(&self) -> bool {
true
}
}
`)
e := NewRustExtractor()
result, err := e.Extract("sink.rs", src)
require.NoError(t, err)
em := nodeByID(result.Nodes, "sink.rs::SinkError.error_message")
require.NotNil(t, em, "signature method node")
assert.Equal(t, graph.KindMethod, em.Kind)
assert.Equal(t, "SinkError", em.Meta["receiver"])
assert.Equal(t, "true", em.Meta["trait_decl"])
di := nodeByID(result.Nodes, "sink.rs::SinkError.default_impl")
require.NotNil(t, di, "default method node")
assert.Equal(t, graph.KindMethod, di.Kind)
assert.Equal(t, "true", di.Meta["trait_decl"])
// The default method must NOT leak as a bare free function.
assert.Nil(t, nodeByID(result.Nodes, "sink.rs::default_impl"))
// Each trait method is a member of the trait interface node.
members := 0
for _, ed := range result.Edges {
if ed.Kind == graph.EdgeMemberOf && ed.To == "sink.rs::SinkError" &&
(ed.From == "sink.rs::SinkError.error_message" || ed.From == "sink.rs::SinkError.default_impl") {
members++
}
}
assert.Equal(t, 2, members)
// Backward compat: the interface node still lists method names in Meta.
iface := nodeByID(result.Nodes, "sink.rs::SinkError")
require.NotNil(t, iface)
names, _ := iface.Meta["methods"].([]string)
assert.Contains(t, names, "error_message")
}
// `impl Trait for Type` methods emit a method-level EdgeOverrides at the impl
// method, even when the implemented-for type is external (io::Error) and thus
// has no local type node — the case inferOverrides cannot cover.
func TestRsExtractor_TraitImplOverrides(t *testing.T) {
src := []byte(`pub trait SinkError: Sized {
fn error_message<T>(message: T) -> Self;
}
impl SinkError for io::Error {
fn error_message<T>(message: T) -> io::Error {
io::Error::new(io::ErrorKind::Other, message.to_string())
}
}
`)
e := NewRustExtractor()
result, err := e.Extract("sink.rs", src)
require.NoError(t, err)
require.NotNil(t, nodeByID(result.Nodes, "sink.rs::io::Error.error_message"))
var ov *graph.Edge
for _, ed := range result.Edges {
if ed.Kind == graph.EdgeOverrides && ed.From == "sink.rs::io::Error.error_message" {
ov = ed
break
}
}
require.NotNil(t, ov, "impl method should emit an EdgeOverrides")
assert.Equal(t, "unresolved::SinkError.error_message", ov.To)
}
// An inherent impl (no trait) must not emit any override edge.
func TestRsExtractor_InherentImplNoOverride(t *testing.T) {
src := []byte(`struct Foo {}
impl Foo {
fn bar(&self) {}
}
`)
e := NewRustExtractor()
result, err := e.Extract("foo.rs", src)
require.NoError(t, err)
for _, ed := range result.Edges {
assert.NotEqual(t, graph.EdgeOverrides, ed.Kind, "inherent impl should not override")
}
}