mirror of
https://github.com/colbymchenry/codegraph.git
synced 2026-10-28 14:08:56 +08:00
fix(rust): a same-file path's inline module is read from its braces, not its indentation (#2713)
PR #2711 and PR #2702 landed a way each to tell which inline `mod` a
place in a Rust file is in. #2711's isInRustInlineModule scanned lines
upward for `mod <name> {` and trusted rustfmt's indentation to find where
the block closes. #2702's rustModBlocks scans the braces, skipping
strings, raw strings, char literals and comments, and keeps the result in
rustUsesOf. isInRustInlineModule now asks rustBlockAt for the innermost
block around the candidate, as rustDeclaredItems does, so there is one
answer to that question.
What changes:
- An item written without indentation inside `mod flat { … }` is found
through `flat::Flat`. The indentation rule rejected it.
- `outer::Shell` is only `outer`'s own `Shell`, not one declared in a
`mod deep` inside it. The upward scan accepted any item below the
`mod outer {` line.
- A file whose braces don't all close says nothing, as it does for the
`use` walk of PR #2702.
The A/B (main 818e7803 vs this change; axum, tokio, clap, serde,
ripgrep, gleam, dioxus, and the gin, serilog, flask and express
controls) is byte-identical. rust-path-same-file.test.ts gains the two
cases. The `flat::Flat` one fails on main.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
818e780336
commit
e2aa5d205d
@@ -9132,26 +9132,17 @@ function matchRustSelfPath(name: string, ref: UnresolvedRef, context: Resolution
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether `candidate` sits in an inline `mod <name> { … }` of its own file —
|
||||
* the only way a path through `name` reaches it, since an inline module adds
|
||||
* nothing to its items' qualified names. rustfmt closes the block at the
|
||||
* indentation it opens at.
|
||||
* Whether `candidate` is declared directly in an inline `mod <name> { … }` of
|
||||
* its own file — the only way a path through `name` reaches it, since an
|
||||
* inline module adds nothing to its items' qualified names. The module is the
|
||||
* innermost block rustModBlocks finds around it; a file whose braces don't
|
||||
* all close says nothing.
|
||||
*/
|
||||
function isInRustInlineModule(candidate: Node, name: string, context: ResolutionContext): boolean {
|
||||
const lines = context.getFileLines?.(candidate.filePath) ?? context.readFile(candidate.filePath)?.split(/\r?\n/) ?? [];
|
||||
const head = new RegExp(`^(\\s*)(?:pub(?:\\([^)]*\\))?\\s+)?mod\\s+${name}\\s*\\{`);
|
||||
for (let i = candidate.startLine - 2; i >= 0; i--) {
|
||||
const open = head.exec(lines[i] ?? '');
|
||||
if (!open) continue;
|
||||
const indent = open[1]!.length;
|
||||
if (candidate.startColumn <= indent) return false;
|
||||
for (let j = i + 1; j < candidate.startLine - 1; j++) {
|
||||
const closer = /^(\s*)\}/.exec(lines[j] ?? '');
|
||||
if (closer && closer[1]!.length <= indent) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
const layout = rustUsesOf(candidate.filePath, context);
|
||||
if (!layout.balanced) return false;
|
||||
const at = (layout.lineStarts[candidate.startLine - 1] ?? 0) + Math.max(0, candidate.startColumn ?? 0);
|
||||
return rustBlockAt(layout.blocks, at)?.name === name;
|
||||
}
|
||||
|
||||
/** Whether `candidate` is declared in the same `impl` / `trait` block as `ref`, above it. */
|
||||
|
||||
Reference in New Issue
Block a user