fix(context): контракт addWorkspace(URI) — нормализованный через Absolute.uri#3923
Conversation
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Pull request overview
This PR tightens and documents the ServerContextProvider.addWorkspace(URI, …) contract by requiring a URI normalized via Absolute.uri(...), adding a runtime check to fail fast when callers violate it. This prevents workspace cleanup/key mismatches across OSes (notably macOS/Windows canonicalization differences) and restores a stricter guard in test utilities to surface leaked workspaces instead of masking them.
Changes:
- Enforced
addWorkspace(URI, …)to only acceptAbsolute.uri(...)-normalized URIs via a runtime assertion. - Updated CLI and test call sites to pass normalized workspace URIs and to use the same normalized URI when setting
WorkspaceContextHolder. - Restored
TestUtilsbehavior to throw when multipleServerContextinstances are registered (forcing tests to be explicit and helping detect cleanup leaks).
Reviewed changes
Copilot reviewed 8 out of 8 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
| src/main/java/com/github/_1c_syntax/bsl/languageserver/context/ServerContextProvider.java | Documents and enforces the normalized-URI contract for workspace registration to prevent cleanup/remove mismatches. |
| src/main/java/com/github/_1c_syntax/bsl/languageserver/cli/AnalyzeCommand.java | Normalizes workspace URI before registering workspace and before entering WorkspaceContextHolder. |
| src/main/java/com/github/_1c_syntax/bsl/languageserver/cli/FormatCommand.java | Normalizes workspace URI before registering workspace and before entering WorkspaceContextHolder. |
| src/test/java/com/github/_1c_syntax/bsl/languageserver/util/TestUtils.java | Restores strict exception on multiple contexts to catch leaked workspaces; keeps deterministic context selection rules. |
| src/test/java/com/github/_1c_syntax/bsl/languageserver/providers/SemanticTokensProviderTest.java | Updates test workspace registration to use normalized workspace URI. |
| src/test/java/com/github/_1c_syntax/bsl/languageserver/context/computer/MethodSymbolComputerTest.java | Updates test workspace registration to use normalized workspace URI. |
| src/test/java/com/github/_1c_syntax/bsl/languageserver/context/AbstractServerContextAwareTest.java | Normalizes workspace URIs used to create contexts to satisfy the new addWorkspace contract across OSes. |
| src/test/java/com/github/_1c_syntax/bsl/languageserver/AnalyzeProjectOnStartTest.java | Normalizes the synthetic test workspace URI to satisfy the new addWorkspace contract. |
…lute.uri
Источник флака на macOS/Windows: AnalyzeProjectOnStartTest регистрировал
synthetic workspace через URI.create("file:///test-analyze-workspace") —
ключ в contexts ложился КАК ЕСТЬ, а provider.clear() / removeWorkspace
ищут по Absolute.uri(uri.toString()). На macOS getCanonicalFile() в
Absolute.uri может выдать другую форму (несуществующий путь, симлинки),
remove промахивается, workspace переживает cleanup и копится в contexts.
В следующем тест-классе allContexts.size() оказывался ≥2, TestUtils.
getServerContextForFile ронял ExpressionTreeComparersTest и Co.
* TEST_WORKSPACE_URI = Absolute.uri("file:///test-analyze-workspace") —
фиксирует фикспойнт Absolute.uri на JVM-инициализации, не на каждом
CI-прогоне.
* В Javadoc ServerContextProvider.addWorkspace(URI) добавил short note
о контракте — URI должен быть нормализован, иначе clear()/remove не
попадут в ключ.
* TestUtils.getServerContextForFile — восстановил старый
"throw on >1 contexts": с фиксом TEST_WORKSPACE_URI workspace'ы реально
вычищаются между тестами, и этот throw снова работает как защитный
guard, а не симптом-маскирующий fallback (отменяет PR #3923's
test-only смягчение из 2e19715).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
7df5a6c to
58dbb8e
Compare
…lute.uri
Источник флака на macOS/Windows: AnalyzeProjectOnStartTest регистрировал
synthetic workspace через URI.create("file:///test-analyze-workspace") —
ключ в contexts ложился КАК ЕСТЬ, а provider.clear() / removeWorkspace
ищут по Absolute.uri(uri.toString()). На macOS getCanonicalFile() в
Absolute.uri может выдать другую форму (несуществующий путь, симлинки),
remove промахивается, workspace переживает cleanup и копится в contexts.
В следующем тест-классе allContexts.size() оказывался ≥2, TestUtils.
getServerContextForFile ронял ExpressionTreeComparersTest и Co.
* TEST_WORKSPACE_URI = Absolute.uri("file:///test-analyze-workspace") —
фиксирует фикспойнт Absolute.uri на JVM-инициализации, не на каждом
CI-прогоне.
* В Javadoc ServerContextProvider.addWorkspace(URI) добавил short note
о контракте — URI должен быть нормализован, иначе clear()/remove не
попадут в ключ.
* TestUtils.getServerContextForFile — восстановил старый
"throw on >1 contexts": с фиксом TEST_WORKSPACE_URI workspace'ы реально
вычищаются между тестами, и этот throw снова работает как защитный
guard, а не симптом-маскирующий fallback (отменяет PR #3923's
test-only смягчение из 2e19715).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
58dbb8e to
68a8854
Compare
…lute.uri Источник флака на macOS: тесты с JUnit @tempdir (ConventionalLibraryDiscoveryTest и др.) передают tempDir прямо в initServerContext(Path, ...). На macOS @tempdir лежит под /var/folders/..., а это симлинк на /private/var/folders/... tempDir.toUri() возвращает не-канонизованную форму с /var/folders/..., addWorkspace кладёт её в contexts как ключ. provider.clear() ходит через removeWorkspace(WF(uri.toString())) → Absolute.uri(...) внутри резолвит симлинк → ищет /private/var/folders/... — промах, workspace переживает cleanup. В следующем тест-классе allContexts.size() оказывается ≥2, и TestUtils.getServerContextForFile роняет ExpressionTreeComparersTest и Co. * AbstractServerContextAwareTest.initServerContext(Path, boolean) нормализует URI через Absolute.uri(configurationRoot.toUri()) — закрывает кейс с @tempdir и любыми другими не-канонизованными Path на входе. * AnalyzeProjectOnStartTest.TEST_WORKSPACE_URI инициализируется через Absolute.uri("file:///test-analyze-workspace") — фикспойнт Absolute.uri на JVM-инициализации. * ServerContextProvider.addWorkspace(URI) Javadoc фиксирует контракт: URI должен быть нормализован через Absolute.uri, иначе clear()/remove не попадут в ключ. * TestUtils.getServerContextForFile — восстановил старый "throw on >1 contexts" (отменяет test-only смягчение из 2e19715). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
68a8854 to
a8522d9
Compare
|



Summary
AbstractServerContextAwareTest.initServerContext(Path, boolean)— оборачиваетconfigurationRoot.toUri()вAbsolute.uri(...)передaddWorkspace. Это центральный путь инициализации тестового workspace'а; callsite-ы передают сюда в том числе не-канонизованныеPath(@TempDirот JUnit, относительныеPath.of("./...")).AnalyzeProjectOnStartTest.TEST_WORKSPACE_URIинициализируется черезAbsolute.uri("file:///test-analyze-workspace")— фикспойнт нормализации на JVM-инициализации.ServerContextProvider.addWorkspace(URI, ?)— короткая Javadoc-нота: URI должен быть нормализован черезAbsolute.uri, иначеclear()/removeWorkspaceне найдут запись по ключу.TestUtils.getServerContextForFile— старыйthrow on >1 contextsвосстановлен (отменяет test-only смягчение из2e19715c93).Why
Симптом на macOS:
Multiple ServerContexts registered. Use getDocumentContextFromFile(path, serverContext) ...валит 7 тест-классов черезFAKE_DOCUMENT_URI.Корневая утечка — на macOS JUnit
@TempDirсоздаёт путь под/var/folders/..., а это симлинк на/private/var/folders/.... Цепочка:Дальше leak копится в
contexts, и в следующем тест-классеinitServerContext(PATH_TO_METADATA)делаетcontexts.size()≥ 2.TestUtils.getServerContextForFileловит этоthrow'ом.На Linux то же
@TempDirлежит под/tmp/junit-NNN/,/tmp— обычная директория, не симлинк,Absolute.uriround-trip identity, утечки нет.Фикс — нормализовать URI в одной точке (
initServerContext), через которую идут все callsite-ы с произвольнымPath. Тогда ключ вcontextsвсегда фикспойнтAbsolute.uri, иclear()стабильно находит и удаляет.Test plan
./gradlew test -PmaxParallelForks=2локально (Linux) — все 1664 теста зелёные.ExpressionTreeComparersTest,ExpressionTreeBuildingVisitorTest,ExpressionParseTreeRewriterTest,ModuleReferenceTest,UseDirectiveScannerTest,BlockKeywordMatcherTest,ConfigurationModuleMembersProviderTest) теперь зелёные.🤖 Generated with Claude Code