| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768 |
- import { afterEach, beforeEach, expect, it } from 'vitest';
- import * as fs from 'node:fs';
- import * as os from 'node:os';
- import * as path from 'node:path';
- import { CodeGraph } from '../src';
- let root: string;
- let cg: CodeGraph | undefined;
- beforeEach(() => { root = fs.mkdtempSync(path.join(os.tmpdir(), 'cg-rust-self-owner-')); });
- afterEach(() => { cg?.close(); cg = undefined; fs.rmSync(root, { recursive: true, force: true }); });
- async function index(files: Record<string, string>) {
- fs.mkdirSync(path.join(root, 'src'));
- fs.writeFileSync(path.join(root, 'Cargo.toml'), '[package]\nname="owners"\nversion="0.1.0"\nedition="2021"\n');
- for (const [file, text] of Object.entries(files)) fs.writeFileSync(path.join(root, 'src', file), text);
- cg = await CodeGraph.init(root, { index: true });
- }
- function targets(file: string) {
- const caller = cg!.getNodesByKind('method').find(n => n.filePath === `src/${file}` && n.qualifiedName === 'Target::run');
- expect(caller).toBeDefined();
- return cg!.getOutgoingEdges(caller!.id).filter(e => e.kind === 'calls').map(e => {
- const target = cg!.getNode(e.target)!;
- return `${target.filePath}:${target.qualifiedName}`;
- });
- }
- it('does not borrow a missing method from a same-named type in another module (#1861)', async () => {
- await index({
- 'lib.rs': 'pub mod caller; pub mod decoy;',
- 'caller.rs': 'pub struct Target;\nimpl Target { pub fn run(&self) { self.reset(); } }',
- 'decoy.rs': 'pub struct Target;\nimpl Target { pub fn reset(&self) {} }',
- });
- expect(targets('caller.rs')).toEqual([]);
- });
- it('keeps a proven local owner despite a same-named type and method in another module (#1861)', async () => {
- await index({
- 'lib.rs': 'pub mod caller; pub mod decoy;',
- 'caller.rs': 'pub struct Target;\nimpl Target { pub fn reset(&self) {} }\nimpl Target { pub fn run(&self) { self.reset(); } }',
- 'decoy.rs': 'pub struct Target;\nimpl Target { pub fn reset(&self) {} }',
- });
- expect(targets('caller.rs')).toEqual(['src/caller.rs:Target::reset']);
- fs.writeFileSync(path.join(root, 'src/caller.rs'), 'pub struct Target;\nimpl Target { pub fn run(&self) { self.reset(); } }');
- await cg!.sync();
- expect(targets('caller.rs')).toEqual([]);
- fs.writeFileSync(path.join(root, 'src/caller.rs'), 'pub struct Target;\nimpl Target { pub fn reset(&self) {} }\nimpl Target { pub fn run(&self) { self.reset(); } }');
- await cg!.sync();
- expect(targets('caller.rs')).toEqual(['src/caller.rs:Target::reset']);
- });
- it('keeps a unique owner whose impl is split across files (#1861)', async () => {
- await index({
- 'lib.rs': 'pub mod caller;\npub struct Target;\nimpl Target { pub fn reset(&self) {} }',
- 'caller.rs': 'use crate::Target;\nimpl Target { pub fn run(&self) { self.reset(); } }',
- });
- expect(targets('caller.rs')).toEqual(['src/lib.rs:Target::reset']);
- });
- it('declines indistinguishable inline-module owners instead of claiming one (#1861)', async () => {
- await index({ 'lib.rs': `mod a {
- pub struct Target;
- impl Target { pub fn reset(&self) {} }
- }
- mod b {
- pub struct Target;
- impl Target { pub fn run(&self) { self.reset(); } }
- }` });
- expect(targets('lib.rs')).toEqual([]);
- });
|