Fix imports whose spelling does not match the file on disk - #188
Open
shellygr wants to merge 2 commits into
Open
Fix imports whose spelling does not match the file on disk#188shellygr wants to merge 2 commits into
shellygr wants to merge 2 commits into
Conversation
A project written on a case-insensitive filesystem can import a path that differs from the real filename, usually only in letter case. It compiles for its authors and fails on Linux. Compilation analysis now checks each component of an import path against the actual directory entries and rewrites the quoted literal to the spelling the filesystem holds. This runs before the existing import patcher. That patcher resolves relative imports against a map of real files and skips the ones that miss, so a misspelled import is precisely what it cannot canonicalize. As with the patcher, a rewrite survives if the retry compiles and is reverted if it does not. Nothing is resolved by guessing. Two candidates, a name that matches only by edit distance, or an import that goes through a package prefix all leave the file alone and log the reason. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The import scan accumulates lines until the next semicolon, so a commented-out import without one ran on to whatever semicolon came next and could land the rewrite on an ordinary string constant further down the file. Scanning now runs over a copy of the source with comment bytes replaced by spaces. Each byte is replaced one for one, so columns still address the real file and the rewrite is applied to it unchanged. Comment starts are found by scanning characters in context rather than by matching // or /* directly. A block comment spans lines, so recognising it at all needs state carried between them, and the same pass keeps string literals out of it for free. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What this fixes
A Solidity project written on macOS or Windows can import a file by a path that does not match
the real filename, usually differing only in letter case. Those filesystems are case-insensitive,
so the project compiles for its authors and cannot compile anywhere case-sensitive. Compilation
analysis used to stop there, with a source-not-found error and nothing to try next.
Approach
New module
certora_autosetup/setup/import_spelling_fix.py. It checks each component of an importpath against the real directory entries with
os.scandirinstead of asking whether the pathexists. An existence check on a case-insensitive filesystem resolves the misspelled path happily,
which would make the defect invisible on the machine where the code is written and leave the fixer
firing only in production.
Handled: letter case in the basename, in any directory component, and in the extension; Windows
separators and doubled slashes; and the right basename in the wrong directory, but only when
exactly one file on disk carries that basename.
Not handled, each one an explicit bail rather than a silent miss:
import at it gives you a project that compiles while verifying code nobody asked about.
workaround.
filesystem, so an ambiguous match rewrites nothing.
Integration
Runs in
run_compilation_analysisahead of the existing import patcher. The order matters: thatpatcher resolves each relative import against its map of real files and skips the ones that miss,
so an import with a wrong spelling is exactly the case it cannot help with. Either fix applying is
reason enough to compile again. If the retry still fails, both revert in reverse order of
application; if it succeeds, the fix stays.
Rewrites are scoped to the quoted path literal, checked against the recorded bytes before anything
is written, kept single-line so the patcher's line-indexed revert stays correct, never applied
inside a dependency tree, and logged at WARNING with the old and new spelling.
Also adds a small
package_prefixes()helper toutils/import_diagnostics.pyso the fixer canleave remapped prefixes alone.
Testing
24 unit tests. They assert on planned and applied rewrites built from one real file plus a
wrong-cased import string, rather than creating two files that differ only in case. The latter is
impossible on a case-insensitive filesystem and would make the suite behave differently per
developer machine.
Full suite: 1142 passed, 10 skipped, 11 deselected. pyright: 0 errors.
Known limitation
extract_imports_multilineaccumulates lines until the next;, so a commented-outimportwithno semicolon can make the scan land on an ordinary string constant further down the file and
rewrite it. Closing this properly wants comment-aware scanning or a real parser; the typed solc
AST is not an option at this point because it only exists after a successful build, and here the
build has failed. Left open deliberately rather than papered over with more string handling.
🤖 Generated with Claude Code