mirror of
https://github.com/tiennm99/serena.git
synced 2026-10-13 12:15:10 +00:00
fix(csharp): stop tuple-typed properties losing their name to the method branch (#1967)
* fix(csharp): stop tuple-typed properties losing their name to the method branch
_extract_base_name_and_type split Roslyn's "Name : Type" property names by
checking for a literal '(' anywhere in the raw string. A C# tuple type is
written with parentheses ("(int X, string Y)"), so a tuple-typed property
tripped that guard and fell into the method branch instead, which kept the
trailing " :" as part of the reported name (e.g. "Position :"). Since
find_symbol defaults to exact name-path matching, such a property becomes
unfindable by its real name.
The guard now only checks for '(' in the identifier segment before the
first " : ", not the whole string, so a parenthesis inside the type
annotation no longer affects branch selection.
* fix(csharp): bump the high-level symbol cache fingerprint
_normalize_symbol_name's output changed in this PR, and
_document_symbols_cache_fingerprint gates the cache that stores its
result; leaving the version at 1 would keep serving the old, corrupted
names to anyone with an existing on-disk cache.
This commit is contained in:
1 parent
fba5258294
commit
941f4ded18
3 files changed
+35
-4
No files matched your search
@@ -111,6 +111,10 @@ Status of the `main` branch. Changes prior to the next official version change w
|
||||
its global state under ``~/Library``; Serena now gives the child process an isolated home-directory view
|
||||
via ``solidity_state_dir`` without changing the parent process's ``HOME`` (#1817)
|
||||
- Add Fatou support as an alternative Julia language server (`julia_fatou`)
|
||||
- Fix: C# properties/fields whose type contains a literal `(`, e.g. a tuple type like
|
||||
`(int X, string Y)`, had their name corrupted to include a trailing `:` because the
|
||||
parenthesis in the type was mistaken for a method's parameter list; `find_symbol` on
|
||||
the real name then returned nothing
|
||||
- Fix: Nextflow's `_flush_deferred_workspace_scan` marked the workspace scan flushed even when both
|
||||
of its `completion` probes failed, permanently skipping the flush (and silencing retries) for the
|
||||
rest of the session (#1871)
|
||||
|
||||
@@ -257,7 +257,7 @@ class CSharpLanguageServer(SolidLanguageServer):
|
||||
return hover
|
||||
|
||||
def _document_symbols_cache_fingerprint(self) -> Hashable | None:
|
||||
normalize_symbol_name_version = 1
|
||||
normalize_symbol_name_version = 2
|
||||
return normalize_symbol_name_version
|
||||
|
||||
def _normalize_symbol_name(self, symbol: RawDocumentSymbol, relative_file_path: str) -> str:
|
||||
@@ -301,15 +301,19 @@ class CSharpLanguageServer(SolidLanguageServer):
|
||||
"Add(int, int) : int" -> ("Add", "(int, int) : int")
|
||||
"ToString()" -> ("ToString", "()")
|
||||
"SimpleMethod" -> ("SimpleMethod", "")
|
||||
"Position : (int X, string Y)" -> ("Position", ": (int X, string Y)")
|
||||
|
||||
Returns:
|
||||
Tuple of (base_name, type_info)
|
||||
|
||||
"""
|
||||
# Check for property pattern: "Name : Type"
|
||||
if " : " in roslyn_name and "(" not in roslyn_name:
|
||||
# Check for property pattern: "Name : Type". The '(' guard must look only at the
|
||||
# name segment before the first " : ", not the whole string, since a tuple type
|
||||
# ("(int X, string Y)") legitimately contains parentheses.
|
||||
if " : " in roslyn_name:
|
||||
base_name, type_part = roslyn_name.split(" : ", 1)
|
||||
return base_name.strip(), f": {type_part.strip()}"
|
||||
if "(" not in base_name:
|
||||
return base_name.strip(), f": {type_part.strip()}"
|
||||
|
||||
# Check for method pattern: "MethodName(params) : ReturnType"
|
||||
if "(" in roslyn_name:
|
||||
|
||||
@@ -7,6 +7,7 @@ import pytest
|
||||
|
||||
from solidlsp import SolidLanguageServer
|
||||
from solidlsp.language_servers.csharp_language_server import (
|
||||
CSharpLanguageServer,
|
||||
breadth_first_file_scan,
|
||||
find_solution_or_project_file,
|
||||
)
|
||||
@@ -200,6 +201,28 @@ class TestCSharpLanguageServer:
|
||||
), f"Expected ConsoleGreeter.FormatGreeting symbol, got: {implementing_symbols}"
|
||||
|
||||
|
||||
class TestCSharpExtractBaseNameAndType:
|
||||
"""Regression tests for _extract_base_name_and_type, no running language server needed."""
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("roslyn_name", "expected"),
|
||||
[
|
||||
# Property whose type is a tuple: the literal '(' in the type must not be
|
||||
# mistaken for a method's parameter list.
|
||||
("Position : (int X, string Y)", ("Position", ": (int X, string Y)")),
|
||||
("Name : string", ("Name", ": string")),
|
||||
("Add(int, int) : int", ("Add", "(int, int) : int")),
|
||||
("ToString()", ("ToString", "()")),
|
||||
("SimpleMethod", ("SimpleMethod", "")),
|
||||
# Both still have a '(' before the first " : ", so they keep the method branch.
|
||||
("GetPair() : (int, int)", ("GetPair", "() : (int, int)")),
|
||||
("Merge((int, int) a, (int, int) b) : void", ("Merge", "((int, int) a, (int, int) b) : void")),
|
||||
],
|
||||
)
|
||||
def test_extract_base_name_and_type(self, roslyn_name: str, expected: tuple[str, str]) -> None:
|
||||
assert CSharpLanguageServer._extract_base_name_and_type(roslyn_name) == expected
|
||||
|
||||
|
||||
@pytest.mark.csharp
|
||||
class TestCSharpSolutionProjectOpening:
|
||||
"""Test C# language server solution and project opening functionality."""
|
||||
|
||||
Reference in new issue
Block a user