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:
Amir Fathi authored and GitHub committed 2026-09-21 12:14:38 +02:00
1 parent fba5258294
commit 941f4ded18
3 files changed
+35 -4

No files matched your search

@@ -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: