Repository navigation
Fix crash in path completions for URLs with a query or fragment - #65342
Open
Ryan Cavanaugh (RyanCavanaugh) wants to merge 1 commit into
Open
Ryan Cavanaugh (RyanCavanaugh) wants to merge 1 commit into
Ryan Cavanaugh (RyanCavanaugh) wants to merge 1 commit into
Conversation
Completions inside a module specifier such as
`require("https://example.com/a?b/c")` treat the URL-like specifier as a
relative path and resolve its directory portion against the script
directory. When that directory portion is a URL containing `?` or `#`,
ResolveDirectory panics because rooted paths never carry a URL query or
fragment.
Add RootedDirectoryPath.TryResolveDirectory and use it in
getCompletionEntriesForDirectoryFragment so that such fragments produce
no path completions, matching Strada (where the resolved directory simply
does not exist).
Part of microsoft#65068
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: dec07792-6b96-4d6d-b2c8-c8a49abd0ce6
Contributor
There was a problem hiding this comment.
🟢 Approval recommended
No active review issues block the URL path-completion changes.
No open issues 🎉
What changed in this PR
Prevents language-server path completions from panicking when a directory resolves to a URL containing a query or fragment, partially addressing #65068 while preserving rooted-path assertions.
Changes:
- Adds
TryResolveDirectoryto reject unsupported URL paths without panicking. - Returns no directory completions when resolution is rejected.
- Adds unit and fourslash regression tests, including coverage that preserves valid disk paths containing
?.
| File | Description |
|---|---|
tsc/internal/tspath/typed_paths_test.go |
Tests rejected URL paths and successful directory resolution. |
tsc/internal/tspath/rooted_path.go |
Adds the non-panicking directory resolution helper. |
tsc/internal/ls/string_completions.go |
Uses the helper to safely skip unsupported directory paths. |
tsc/internal/fourslash/tests/completionForStringLiteralUrlQueryOrFragmentNoCrash_test.go |
Covers three URL-related completion crash scenarios. |
Review effort: Balanced
This branch has not been deployed
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.
Part of #65068 (partially: the
textDocument/completionpanic "path must not contain a URL query or fragment" viagetCompletionEntriesForRelativeModules->getCompletionEntriesForDirectoryFragment, comment 1)Analysis
String-literal path completions in a module specifier treat the specifier as "relative" when it starts with
.//../, or (with nopaths) when it is a rooted disk path or a URL (tspath.IsUrl, i.e. anything containing://).getCompletionEntriesForDirectoryFragmentthen strips the basename and resolves the remaining directory portion against the script directory withRootedDirectoryPath.ResolveDirectory.If that directory portion is URL-rooted and contains a
?or#,ResolveDirectory->ToRootedPathhits the (intentional) assertion that rooted paths never carry a URL query or fragment:(
import/import()with such specifiers hit a separate module-resolution panic first, which is handled elsewhere;requirein a.tsfile isn't resolved, so it isolates the completion crash.) The same assertion is reachable when the script directory itself is URL-rooted and a relative fragment contains?/#.Before paths were strongly typed, this code used
tspath.ResolvePath+DirectoryExists, which simply found no such directory. Strada (src/services/stringCompletions.ts) does the same:resolvePath(scriptDirectory, fragment)followed bytryDirectoryExists, which yields no completions for these inputs.Fix
Add
RootedDirectoryPath.TryResolveDirectory, which mirrorsResolveDirectorybut returnsfalse(instead of panicking) exactly when the path would resolve to a URL with a query or fragment.getCompletionEntriesForDirectoryFragmentuses it and returns no path completions in that case, matching Strada. The tspath assertions are unchanged.Because the fix is inside
getCompletionEntriesForDirectoryFragment, it should also cover the sibling crash in #65068 wheregetCompletionEntriesForNonRelativeModulescallsgetCompletionEntriesForDirectoryFragment(comment 3), though that path isn't separately tested here.Alternatives considered:
strings.ContainsAny(fragment, "?#")in the language service: this would also wrongly drop completions for legitimate on-disk directories whose names contain?/#on non-URL paths, and would need to duplicate tspath's URL-root detection.Tests: new fourslash test
completionForStringLiteralUrlQueryOrFragmentNoCrash(panicked before the fix with the exact message from the issue), plus a small unit test forTryResolveDirectory.Copilot Checklist
I successfully ran the applicable command at the end of my session, and it completed without error: