Files
codegraph/__tests__/rust-framework-name-scope.test.ts
Colby Mchenry 7365427d4f fix(rust): framework name heuristics never reach a function-local item (#2224)
The Rust resolver's handler/service/struct heuristics took the first
same-named item and then checked scope; they now drop items declared inside
a function body and out-of-scope names before choosing, and take the file's
own item first.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-01 00:34:57 +00:00

84 lines
2.8 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* The Rust resolver's struct/handler/service name heuristics never reach an
* item declared inside a function body — axum's examples' `Uri` (imported
* from `http`) went to a `struct Uri` a routing test declares inside itself —
* and a file's own item comes first: ripgrep's `Ok(Glob { … })` in
* globset's glob.rs is its own `Glob`, not the CLI flags' `Glob`.
*/
import { describe, it, expect, afterAll, beforeAll } from 'vitest';
import * as fs from 'fs';
import * as os from 'os';
import * as path from 'path';
import { CodeGraph } from '../src';
let root = '';
let cg: CodeGraph;
beforeAll(async () => {
root = fs.mkdtempSync(path.join(os.tmpdir(), 'cg-rust-fw-'));
const files: Record<string, string> = {
'Cargo.toml': '[workspace]\nmembers = ["crates/core", "crates/globset", "crates/web", "examples/tls"]\n',
'crates/core/Cargo.toml': '[package]\nname = "rg-core"\n',
'crates/web/Cargo.toml': '[package]\nname = "web"\n',
'crates/web/src/lib.rs': 'pub mod http;\n',
'crates/web/src/http.rs': 'pub use ::http::Uri;\n',
'crates/web/src/routing/tests.rs': `fn outer_middleware_still_see_whole_url() {
struct Uri;
let _ = Uri;
}
`,
'examples/tls/Cargo.toml': '[package]\nname = "example-tls"\n\n[dependencies]\nweb = { path = "../../crates/web" }\n',
'examples/tls/src/main.rs': `use web::http::Uri;
fn make_https(uri: Uri, port: u16) -> Uri {
uri
}
`,
'crates/core/src/flags/defs.rs': `pub struct Glob;
pub fn glob_flag() -> Glob {
Glob
}
`,
'crates/globset/Cargo.toml': '[package]\nname = "globset"\n',
'crates/globset/src/glob.rs': `pub struct Glob {
glob: String,
}
impl Glob {
pub fn new(glob: &str) -> Result<Glob, ()> {
Ok(Glob { glob: glob.to_string() })
}
}
`,
};
for (const [rel, content] of Object.entries(files)) {
fs.mkdirSync(path.dirname(path.join(root, rel)), { recursive: true });
fs.writeFileSync(path.join(root, rel), content);
}
cg = await CodeGraph.init(root, { index: true });
});
afterAll(() => {
cg?.close();
if (root) fs.rmSync(root, { recursive: true, force: true });
});
const targetsFrom = (file: string) => {
const ids = cg.getNodesInFile(file).map((n) => n.id);
return cg.getOutgoingEdgesFrom(ids).filter((e) => e.kind !== 'contains')
.map((e) => cg.getNode(e.target)!).map((t) => `${t.filePath}:${t.qualifiedName}`);
};
describe('Rust framework name heuristics', () => {
it('never reach an item declared inside a function body', () => {
expect(targetsFrom('examples/tls/src/main.rs').filter((t) => t.includes('outer_middleware'))).toEqual([]);
});
it('take the file’s own item first', () => {
const globs = targetsFrom('crates/globset/src/glob.rs').filter((t) => t.endsWith(':Glob'));
expect(globs.length).toBeGreaterThan(0);
expect(new Set(globs)).toEqual(new Set(['crates/globset/src/glob.rs:Glob']));
});
});