From f4f6e8fbbe78d3a27f3a1011bff36fdcf0cffe79 Mon Sep 17 00:00:00 2001 From: Dominik Jain Date: Thu, 29 May 2025 14:31:38 +0200 Subject: [PATCH 1/3] Revert "Hotfix: fix equality check of SymbolLocation" This reverts commit ba1a613bc9c0178db06229686008c9fe809be17a. --- src/serena/symbol.py | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/src/serena/symbol.py b/src/serena/symbol.py index 14acc57..3178d55 100644 --- a/src/serena/symbol.py +++ b/src/serena/symbol.py @@ -17,7 +17,7 @@ if TYPE_CHECKING: log = logging.getLogger(__name__) -@dataclass(eq=False) +@dataclass class SymbolLocation: """ Represents the location of a symbol, including the line where the identifier @@ -59,17 +59,6 @@ class SymbolLocation: def has_position_in_file(self) -> bool: return self.relative_path is not None and self.line is not None and self.column is not None - def matches_identifier_location(self, other: Self) -> bool: - """ - Checks if this instance matches a symbol identifier location. - Since symbol identifiers are only concerned with the start position, - the end_line is not taken into account. - """ - if self.relative_path is None: - # not defined locations don't match anything - return False - return self.relative_path == other.relative_path and self.line == other.line and self.column == other.column - class Symbol(ToStringMixin): _NAME_PATH_SEP = "/" @@ -379,7 +368,7 @@ class SymbolManager: symbol_dicts, roots = self.lang_server.request_document_symbols(location.relative_path, include_body=False) for symbol_dict in symbol_dicts: symbol = Symbol(symbol_dict) - if symbol.location.matches_identifier_location(location): + if symbol.location == location: return symbol return None From ba7ec5f0c236849d139c46c2e26e638db46f7b74 Mon Sep 17 00:00:00 2001 From: Dominik Jain Date: Thu, 29 May 2025 14:35:51 +0200 Subject: [PATCH 2/3] Revert "Add end_line to serena's Symbol representation" This reverts commit 6c121836bc10ad4fbbb50a47241d65155b34be6f. --- src/serena/symbol.py | 27 +++++---------------------- 1 file changed, 5 insertions(+), 22 deletions(-) diff --git a/src/serena/symbol.py b/src/serena/symbol.py index 3178d55..c06d977 100644 --- a/src/serena/symbol.py +++ b/src/serena/symbol.py @@ -20,8 +20,7 @@ log = logging.getLogger(__name__) @dataclass class SymbolLocation: """ - Represents the location of a symbol, including the line where the identifier - is defined and the end line of the symbol's body + Represents the (start) location of a symbol identifier """ relative_path: str | None @@ -38,16 +37,6 @@ class SymbolLocation: the column number in which the symbol identifier is defined (if the symbol is a function, class, etc.); may be None for some types of symbols (e.g. SymbolKind.File) """ - end_line: int | None = None - """ - the line in which the symbol's body ends. For methods that search based on SymbolLocation, - the end line is not needed, as it is unused by the language server in the search. - However, the end_line will typically be included in the results of search methods, - and thus be provided to the user in the response to such requests. - This is useful for the LLMs, especially the less intelligent ones, as they often fail - to perform symbolic operations and when falling back to line-editing tools, will just make up - an end line. - """ def __post_init__(self) -> None: if self.relative_path is not None: @@ -129,7 +118,10 @@ class Symbol(ToStringMixin): @property def location(self) -> SymbolLocation: - return SymbolLocation(relative_path=self.relative_path, line=self.line, column=self.column, end_line=self.end_line) + """ + :return: the start location of the actual symbol identifier + """ + return SymbolLocation(relative_path=self.relative_path, line=self.line, column=self.column) @property def body_start_position(self) -> Position | None: @@ -155,21 +147,12 @@ class Symbol(ToStringMixin): @property def line(self) -> int | None: - """The line in which the symbol identifier is defined (start line).""" if "selectionRange" in self.symbol_root: return self.symbol_root["selectionRange"]["start"]["line"] else: # line is expected to be undefined for some types of symbols (e.g. SymbolKind.File) return None - @property - def end_line(self) -> int | None: - """The end line of the symbol body, also contained in the `body_end_position`.""" - body_end_position = self.body_end_position - if body_end_position is not None: - return body_end_position["line"] - return None - @property def column(self) -> int | None: if "selectionRange" in self.symbol_root: From 68c64e7e11a434f6e84121254dfe9ffa496dbd77 Mon Sep 17 00:00:00 2001 From: Dominik Jain Date: Thu, 29 May 2025 14:49:47 +0200 Subject: [PATCH 3/3] Add body location (start/end line) to Symbol dictionary representation (if location enabled) --- src/serena/symbol.py | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/serena/symbol.py b/src/serena/symbol.py index c06d977..66110f9 100644 --- a/src/serena/symbol.py +++ b/src/serena/symbol.py @@ -20,7 +20,7 @@ log = logging.getLogger(__name__) @dataclass class SymbolLocation: """ - Represents the (start) location of a symbol identifier + Represents the (start) location of a symbol identifier, which, within Serena, uniquely identifies the symbol. """ relative_path: str | None @@ -145,8 +145,18 @@ class Symbol(ToStringMixin): return end_pos return None + def get_body_line_numbers(self) -> tuple[int | None, int | None]: + start_pos = self.body_start_position + end_pos = self.body_end_position + start_line = start_pos["line"] if start_pos else None + end_line = end_pos["line"] if end_pos else None + return start_line, end_line + @property def line(self) -> int | None: + """ + :return: the line in which the symbol identifier is defined. + """ if "selectionRange" in self.symbol_root: return self.symbol_root["selectionRange"]["start"]["line"] else: @@ -265,7 +275,7 @@ class Symbol(ToStringMixin): self, kind: bool = False, location: bool = False, depth: int = 0, include_body: bool = False, include_children_body: bool = False ) -> dict[str, Any]: """ - Convert the symbol to a dictionary. + Converts the symbol to a dictionary. :param kind: whether to include the kind of the symbol :param location: whether to include the location of the symbol @@ -284,6 +294,8 @@ class Symbol(ToStringMixin): if location: result["location"] = self.location.to_dict() + body_start_line, body_end_line = self.get_body_line_numbers() + result["body_location"] = {"start_line": body_start_line, "end_line": body_end_line} if include_body: if self.body is None: