mirror of
https://github.com/colbymchenry/codegraph.git
synced 2026-11-05 08:53:34 +08:00
fix(rust): a bare name is in scope only through its module or a use (#2214)
The Rust scope rule (#2124) only checked prelude names; every other bare name could mean any same-named project item, and a name after any path (`io::Result`) could mean any at all. The Rust framework resolver's PascalCase / handler / service patterns bound names with no scope check at 0.7-0.8. tokio's 1,221 `io::Result<...>` went to a private `runtime::task::Result` alias, 642 `Context<'_>` (from `use std::task::{Context, Poll}`) to `runtime::context::Context`. - A type or function from another file is in scope only through a `use` that binds it (its leaf, `as` alias, or `{self}`) or a glob over its module; methods and fields (reached through a value), import refs and module / file targets are unaffected. - A name a file imports from outside the project - `std` / `core` / `alloc`, or a crate its Cargo manifests declare as a dependency - is that outside item. (An inline `mod support { pub mod panic; }` is the project's.) - A path names its module: `seg::Name` reaches an item of module `seg`; a path rooted at std (`std::io::Error`) or at an outside import (`io::` under `use std::io`) reaches none; `crate::` / `self::` / `super::` and a project crate's name (`clap::Command`, re-exported) look it up as before. The path is read anywhere on the line, not only at the reference's column. - The framework resolver's patterns apply the same check. tokio -3008 +610, serde -792 +650, ripgrep -602 +247, axum -453 +186, clap -342 +32, bat -38 +9. Sampled losses: std / core / futures / syn / http / anyhow imports and paths, associated types (`S::Ok`, `S::Error`, `V::Value`, `Fut::Output`); gains are same-module items the old first match hid. Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
5f1a635714
commit
fa8d7284c5
@@ -8,6 +8,17 @@ import { Node } from '../../types';
|
||||
import { FrameworkResolver, UnresolvedRef, ResolvedRef, ResolutionContext } from '../types';
|
||||
import { stripCommentsForRegex } from '../strip-comments';
|
||||
import { getCargoWorkspaceCrateMap } from './cargo-workspace';
|
||||
import { isRustNameInScope } from '../name-matcher';
|
||||
|
||||
/**
|
||||
* Whether the item a name heuristic found is one the reference can name:
|
||||
* `Context<'_>` under `use std::task::{Context, Poll}` is std's, not tokio's
|
||||
* `runtime::context::Context` (642 of them).
|
||||
*/
|
||||
function inRustScope(id: string, ref: UnresolvedRef, context: ResolutionContext): boolean {
|
||||
const node = context.getNodeById?.(id);
|
||||
return !node || isRustNameInScope(node, ref, context);
|
||||
}
|
||||
|
||||
const cargoWorkspaceMapCache = new WeakMap<ResolutionContext, Map<string, string>>();
|
||||
|
||||
@@ -32,7 +43,7 @@ export const rustResolver: FrameworkResolver = {
|
||||
// Pattern 1: Handler references
|
||||
if (ref.referenceName.endsWith('_handler') || ref.referenceName.startsWith('handle_')) {
|
||||
const result = resolveByNameAndKind(ref.referenceName, FUNCTION_KINDS, HANDLER_DIRS, context);
|
||||
if (result) {
|
||||
if (result && inRustScope(result, ref, context)) {
|
||||
return {
|
||||
original: ref,
|
||||
targetNodeId: result,
|
||||
@@ -45,7 +56,7 @@ export const rustResolver: FrameworkResolver = {
|
||||
// Pattern 2: Service/Repository trait implementations
|
||||
if (ref.referenceName.endsWith('Service') || ref.referenceName.endsWith('Repository')) {
|
||||
const result = resolveByNameAndKind(ref.referenceName, SERVICE_KINDS, SERVICE_DIRS, context);
|
||||
if (result) {
|
||||
if (result && inRustScope(result, ref, context)) {
|
||||
return {
|
||||
original: ref,
|
||||
targetNodeId: result,
|
||||
@@ -58,7 +69,7 @@ export const rustResolver: FrameworkResolver = {
|
||||
// Pattern 3: Struct references (PascalCase)
|
||||
if (/^[A-Z][a-zA-Z]+$/.test(ref.referenceName)) {
|
||||
const result = resolveByNameAndKind(ref.referenceName, STRUCT_KINDS, MODEL_DIRS, context);
|
||||
if (result) {
|
||||
if (result && inRustScope(result, ref, context)) {
|
||||
return {
|
||||
original: ref,
|
||||
targetNodeId: result,
|
||||
|
||||
Reference in New Issue
Block a user