mirror of
https://github.com/tiennm99/serena.git
synced 2026-10-15 08:17:15 +00:00
fix(csharp): fold newly created files into the loaded Roslyn project (#1981)
* fix(csharp): fold newly created files into the loaded Roslyn project Roslyn only learns which files belong to a project from the solution/open and project/open notifications _open_solution_and_projects sends once at startup. The generic didChangeWatchedFiles/open-close cycle that poll_and_notify sends for every backend on file creation does not make it re-evaluate the project, so a .cs file created after the project was already indexed stayed a standalone Miscellaneous Files document, producing phantom diagnostics (e.g. an incorrect "using directive is unnecessary") instead of the real ones. Add an overridable SolidLanguageServer.notify_files_created hook, called by LanguageServerFileChangeNotifier.poll_and_notify before it opens newly created files. CSharpLanguageServer overrides it to resend the same solution/project notifications and wait for Roslyn's own reload-complete log line before the file is opened; every other backend keeps its current behavior via the no-op default. Fixes #1961 * fix(test): use get_language_server_manager_or_raise in csharp fold test project.language_server_manager is typed LanguageServerManager | None, so calling .iter_language_servers() on it directly failed ty's unresolved-attribute check. Agent already exposes a non-Optional accessor for the same value.
This commit is contained in:
1 parent
cf54869af8
commit
714c260e1f
5 files changed
+93
-5
No files matched your search
@@ -3,6 +3,7 @@ End-to-end test for language server file synchronisation as a result of external
|
||||
|
||||
Exercises all three ``FileChangeType`` branches against a real pyright backend:
|
||||
Created (new caller file), Changed (append a second caller), Deleted (remove the caller file).
|
||||
Also covers a Roslyn-specific Created regression (test_new_csharp_file_is_folded_into_compilation).
|
||||
"""
|
||||
|
||||
import json
|
||||
@@ -192,3 +193,46 @@ def test_find_symbol_tool_reflects_external_change_to_open_buffer(tmp_path):
|
||||
of Serena's own edit tools.
|
||||
"""
|
||||
SymbolPositionStaleAfterExternalEditTestCase().run(tmp_path)
|
||||
|
||||
|
||||
@pytest.mark.csharp
|
||||
def test_new_csharp_file_is_folded_into_compilation(tmp_path):
|
||||
"""
|
||||
Regression test for oraios/serena#1961: a .cs file created after the project has already
|
||||
been indexed used to stay a standalone Miscellaneous Files document to Roslyn, since the
|
||||
generic didChangeWatchedFiles/open-close cycle that poll_and_notify sends for every backend
|
||||
is not enough to make Roslyn's project system re-evaluate which files belong to the already-
|
||||
loaded .csproj. The tell is a phantom 'Using directive is unnecessary' (IDE0005) on a using
|
||||
the new file genuinely needs, since Roslyn cannot resolve the type it imports.
|
||||
"""
|
||||
repo_root = tmp_path / "repo"
|
||||
shutil.copytree(get_repo_path(LanguageServerId.CSHARP), repo_root)
|
||||
new_file_rel = "UsesPerson.cs"
|
||||
new_file_abs = repo_root / new_file_rel
|
||||
|
||||
with agent_for_project_context(LanguageServerId.CSHARP, str(repo_root)) as agent:
|
||||
project = agent.get_active_project_or_raise()
|
||||
ls = next(iter(agent.get_language_server_manager_or_raise().iter_language_servers()))
|
||||
|
||||
new_file_abs.write_text(
|
||||
"using TestProject.Models;\n\n"
|
||||
"namespace TestProject;\n\n"
|
||||
"public class UsesPerson\n"
|
||||
"{\n"
|
||||
" public Person Get() => new Person();\n"
|
||||
"}\n",
|
||||
encoding="utf-8",
|
||||
)
|
||||
assert project.ls_sync_file_system_changes() == 1, "expected exactly one Created event"
|
||||
|
||||
diagnostics = ls.request_text_document_diagnostics(new_file_rel, min_severity=4)
|
||||
messages = [d["message"] for d in diagnostics]
|
||||
|
||||
assert not any("unnecessary" in m.lower() for m in messages), (
|
||||
f"new file was analyzed as a standalone document instead of being folded into the "
|
||||
f"already-loaded project (phantom 'using directive is unnecessary'): {messages}"
|
||||
)
|
||||
assert any("Person" in m and "name" in m for m in messages), (
|
||||
f"expected the real compiler diagnostic for the missing Person(name, age, email) "
|
||||
f"argument, which only fires once the file is actually part of the compilation: {messages}"
|
||||
)
|
||||
Reference in new issue
Block a user