feat: Add Rust trait inheritance and impl block extraction with method receiver type support

Addresses Rust's impl block syntax where trait implementations (`impl Trait for Type`) and trait supertraits (`trait Sub: Super`) create inheritance relationships. Adds getReceiverType to extract method receiver types from impl blocks, enabling proper method-to-struct relationships and qualified name resolution. Verified against Deno codebase and moved from "Needs Verification" to completed language support.
This commit is contained in:
Colby McHenry
2026-04-06 21:50:03 -05:00
parent ce7b7684db
commit 2d14503258
4 changed files with 243 additions and 7 deletions
+72
View File
@@ -650,6 +650,78 @@ pub trait Repository {
expect(traitNode).toBeDefined();
expect(traitNode?.name).toBe('Repository');
});
it('should extract impl Trait for Type as implements edges', () => {
const code = `
pub struct MyCache {}
pub trait Cache {
fn get(&self, key: &str) -> Option<String>;
}
impl Cache for MyCache {
fn get(&self, key: &str) -> Option<String> {
None
}
}
`;
const result = extractFromSource('cache.rs', code);
// Should have an unresolved reference for implements
const implRef = result.unresolvedReferences.find(
(r) => r.referenceKind === 'implements' && r.referenceName === 'Cache'
);
expect(implRef).toBeDefined();
// The struct MyCache should be the source
const myCacheNode = result.nodes.find((n) => n.name === 'MyCache' && n.kind === 'struct');
expect(myCacheNode).toBeDefined();
expect(implRef?.fromNodeId).toBe(myCacheNode?.id);
});
it('should extract trait supertraits as extends references', () => {
const code = `
pub trait Display {}
pub trait Error: Display {
fn description(&self) -> &str;
}
`;
const result = extractFromSource('error.rs', code);
const extendsRef = result.unresolvedReferences.find(
(r) => r.referenceKind === 'extends' && r.referenceName === 'Display'
);
expect(extendsRef).toBeDefined();
const errorTrait = result.nodes.find((n) => n.name === 'Error' && n.kind === 'trait');
expect(errorTrait).toBeDefined();
expect(extendsRef?.fromNodeId).toBe(errorTrait?.id);
});
it('should not create implements edges for plain impl blocks', () => {
const code = `
pub struct Counter {
count: u32,
}
impl Counter {
pub fn new() -> Counter {
Counter { count: 0 }
}
pub fn increment(&mut self) {
self.count += 1;
}
}
`;
const result = extractFromSource('counter.rs', code);
// Should have no implements references (no trait involved)
const implRefs = result.unresolvedReferences.filter(
(r) => r.referenceKind === 'implements'
);
expect(implRefs).toHaveLength(0);
});
});
describe('Java Extraction', () => {