diff --git a/src/serena/resources/config/contexts/chatgpt.yml b/src/serena/resources/config/contexts/chatgpt.yml index c758b2c3..b3780f4c 100644 --- a/src/serena/resources/config/contexts/chatgpt.yml +++ b/src/serena/resources/config/contexts/chatgpt.yml @@ -16,8 +16,8 @@ included_optional_tools: tool_description_overrides: find_symbol: | - Retrieves symbols matching `name_path` in a file. - Use `depth > 0` to include children. `name_path` can be: "foo": any symbol named "foo"; "foo/bar": "bar" within "foo"; "/foo/bar": only top-level "foo/bar" + Retrieves symbols matching `name_path_pattern` in a file. + Use `depth > 0` to include children. `name_path_pattern` can be: "foo": any symbol named "foo"; "foo/bar": "bar" within "foo"; "/foo/bar": only top-level "foo/bar" replace_regex: | Replaces text using regular expressions. Preferred for smaller edits where symbol-level tools aren't appropriate. Use wildcards (.*?) to match large sections efficiently: "beginning.*?end" instead of specifying exact content. diff --git a/src/serena/tools/jetbrains_tools.py b/src/serena/tools/jetbrains_tools.py index db3a97c7..97cfd19f 100644 --- a/src/serena/tools/jetbrains_tools.py +++ b/src/serena/tools/jetbrains_tools.py @@ -6,51 +6,39 @@ from serena.tools.jetbrains_plugin_client import JetBrainsPluginClient class JetBrainsFindSymbolTool(Tool, ToolMarkerSymbolicRead, ToolMarkerOptional): """ - Performs a global (or local) search for symbols with/containing a given name/substring (optionally filtered by type). + Performs a global (or local) search for symbols using the JetBrains backend """ def apply( self, - name_path: str, + name_path_pattern: str, depth: int = 0, relative_path: str | None = None, include_body: bool = False, max_answer_chars: int = -1, ) -> str: """ - Retrieves information on all symbols/code entities (classes, methods, etc.) based on the given `name_path`, - which represents a pattern for the symbol's path within the symbol tree of a single file. - The returned symbol location can be used for edits or further queries. + Retrieves information on all symbols/code entities (classes, methods, etc.) based on the given name path pattern. + The returned symbol information can be used for edits or further queries. Specify `depth > 0` to retrieve children (e.g., methods of a class). - The matching behavior is determined by the structure of `name_path`, which can - either be a simple name (e.g. "method") or a name path like "class/method" (relative name path) - or "/class/method" (absolute name path). - Note that the name path is not a path in the file system but rather a path in the symbol tree - **within a single file**. Thus, file or directory names should never be included in the `name_path`. - For restricting the search to a single file or directory, pass the `relative_path` parameter. - The retrieved symbols' `name_path` attribute will always be composed of symbol names, never file - or directory names. + A name path is a path in the symbol tree *within a source file*. + For example, the method `my_method` defined in class `MyClass` would have the name path `MyClass/my_method`. + If a symbol is overloaded (e.g., in Java), a 0-based index is appended (e.g. "MyClass/my_method[0]") to + uniquely identify it. - Key aspects of the name path matching behavior: - - The name of the retrieved symbols will match the last segment of `name_path`, while preceding segments - will restrict the search to symbols that have a desired sequence of ancestors. - - If there is no `/` in `name_path`, there is no restriction on the ancestor symbols. - For example, passing `method` will match against all symbols with name paths like `method`, - `class/method`, `class/nested_class/method`, etc. - - If `name_path` contains at least one `/`, the matching is restricted to symbols - with the respective ancestors. For example, passing `class/method` will match against - `class/method` as well as `nested_class/class/method` but not `other_class/method`. - - If `name_path` starts with a `/`, it will be treated as an absolute name path pattern, i.e. - all ancestors are provided and must match. - For example, passing `/class` will match only against top-level symbols named `class` but - will not match `nested_class/class`. Passing `/class/method` will match `class/method` but - not `outer_class/class/method`. + To search for a symbol, you provide a name path pattern that is used to match against name paths. + It can be + * a simple name (e.g. "method"), which will match any symbol with that name + * a relative path like "class/method", which will match any symbol with that name path suffix + * an absolute name path "/class/method" (absolute name path), which requires an exact match of the full name path within the source file. + Append an index `[i]` to match a specific overload only, e.g. "MyClass/my_method[1]". - :param name_path: The name path pattern to search for, see above for details. - :param depth: Depth to retrieve descendants (e.g., 1 for class methods/attributes). - :param relative_path: Optional. Restrict search to this file or directory. - If None, searches entire codebase. + :param name_path_pattern: the name path matching pattern (see above) + :param depth: depth up to which descendants shall be retrieved (e.g. use 1 to also retrieve immediate children; + for the case where the symbol is a class, this will return its methods). + Default 0. + :param relative_path: Optional. Restrict search to this file or directory. If None, searches entire codebase. If a directory is passed, the search will be restricted to the files in that directory. If a file is passed, the search will be restricted to that file. If you have some knowledge about the codebase, you should use this parameter, as it will significantly @@ -62,7 +50,7 @@ class JetBrainsFindSymbolTool(Tool, ToolMarkerSymbolicRead, ToolMarkerOptional): """ with JetBrainsPluginClient.from_project(self.project) as client: response_dict = client.find_symbol( - name_path=name_path, + name_path=name_path_pattern, relative_path=relative_path, depth=depth, include_body=include_body, @@ -73,7 +61,7 @@ class JetBrainsFindSymbolTool(Tool, ToolMarkerSymbolicRead, ToolMarkerOptional): class JetBrainsFindReferencingSymbolsTool(Tool, ToolMarkerSymbolicRead, ToolMarkerOptional): """ - Finds symbols that reference the given symbol + Finds symbols that reference the given symbol using the JetBrains backend """ def apply( @@ -104,7 +92,7 @@ class JetBrainsFindReferencingSymbolsTool(Tool, ToolMarkerSymbolicRead, ToolMark class JetBrainsGetSymbolsOverviewTool(Tool, ToolMarkerSymbolicRead, ToolMarkerOptional): """ - Retrieves an overview of the top-level symbols within a specified file + Retrieves an overview of the top-level symbols within a specified file using the JetBrains backend """ def apply( diff --git a/src/serena/tools/symbol_tools.py b/src/serena/tools/symbol_tools.py index 01c0dfaa..62a4fd9e 100644 --- a/src/serena/tools/symbol_tools.py +++ b/src/serena/tools/symbol_tools.py @@ -79,13 +79,13 @@ class GetSymbolsOverviewTool(Tool, ToolMarkerSymbolicRead): class FindSymbolTool(Tool, ToolMarkerSymbolicRead): """ - Performs a global (or local) search for symbols with/containing a given name/substring (optionally filtered by type). + Performs a global (or local) search using the language server backend. """ # noinspection PyDefaultArgument def apply( self, - name_path: str, + name_path_pattern: str, depth: int = 0, relative_path: str = "", include_body: bool = False, @@ -95,38 +95,26 @@ class FindSymbolTool(Tool, ToolMarkerSymbolicRead): max_answer_chars: int = -1, ) -> str: """ - Retrieves information on all symbols/code entities (classes, methods, etc.) based on the given `name_path`, - which represents a pattern for the symbol's path within the symbol tree of a single file. - The returned symbol location can be used for edits or further queries. - Specify `depth > 0` to retrieve children (e.g., methods of a class). + Retrieves information on all symbols/code entities (classes, methods, etc.) based on the given name path pattern. + The returned symbol information can be used for edits or further queries. + Specify `depth > 0` to also retrieve children/descendants (e.g., methods of a class). - The matching behavior is determined by the structure of `name_path`, which can - either be a simple name (e.g. "method") or a name path like "class/method" (relative name path) - or "/class/method" (absolute name path). Note that the name path is not a path in the file system - but rather a path in the symbol tree **within a single file**. Thus, file or directory names should never - be included in the `name_path`. For restricting the search to a single file or directory, - the `within_relative_path` parameter should be used instead. The retrieved symbols' `name_path` attribute - will always be composed of symbol names, never file or directory names. + A name path is a path in the symbol tree *within a source file*. + For example, the method `my_method` defined in class `MyClass` would have the name path `MyClass/my_method`. + If a symbol is overloaded (e.g., in Java), a 0-based index is appended (e.g. "MyClass/my_method[0]") to + uniquely identify it. - Key aspects of the name path matching behavior: - - Trailing slashes in `name_path` play no role and are ignored. - - The name of the retrieved symbols will match (either exactly or as a substring) - the last segment of `name_path`, while other segments will restrict the search to symbols that - have a desired sequence of ancestors. - - If there is no starting or intermediate slash in `name_path`, there is no - restriction on the ancestor symbols. For example, passing `method` will match - against symbols with name paths like `method`, `class/method`, `class/nested_class/method`, etc. - - If `name_path` contains a `/` but doesn't start with a `/`, the matching is restricted to symbols - with the same ancestors as the last segment of `name_path`. For example, passing `class/method` will match against - `class/method` as well as `nested_class/class/method` but not `method`. - - If `name_path` starts with a `/`, it will be treated as an absolute name path pattern, meaning - that the first segment of it must match the first segment of the symbol's name path. - For example, passing `/class` will match only against top-level symbols like `class` but not against `nested_class/class`. - Passing `/class/method` will match against `class/method` but not `nested_class/class/method` or `method`. + To search for a symbol, you provide a name path pattern that is used to match against name paths. + It can be + * a simple name (e.g. "method"), which will match any symbol with that name + * a relative path like "class/method", which will match any symbol with that name path suffix + * an absolute name path "/class/method" (absolute name path), which requires an exact match of the full name path within the source file. + Append an index `[i]` to match a specific overload only, e.g. "MyClass/my_method[1]". - - :param name_path: The name path pattern to search for, see above for details. - :param depth: Depth to retrieve descendants (e.g., 1 for class methods/attributes). + :param name_path_pattern: the name path matching pattern (see above) + :param depth: depth up to which descendants shall be retrieved (e.g. use 1 to also retrieve immediate children; + for the case where the symbol is a class, this will return its methods). + Default 0. :param relative_path: Optional. Restrict search to this file or directory. If None, searches entire codebase. If a directory is passed, the search will be restricted to the files in that directory. If a file is passed, the search will be restricted to that file. @@ -140,7 +128,8 @@ class FindSymbolTool(Tool, ToolMarkerSymbolicRead): If not provided, all kinds are included. :param exclude_kinds: Optional. List of LSP symbol kind integers to exclude. Takes precedence over `include_kinds`. If not provided, no kinds are excluded. - :param substring_matching: If True, use substring matching for the last segment of `name`. + :param substring_matching: If True, use substring matching for the last element of the pattern, such that + "Foo/get" would match "Foo/getValue" and "Foo/getData". :param max_answer_chars: Max characters for the JSON result. If exceeded, no content is returned. -1 means the default value from the config will be used. :return: a list of symbols (with locations) matching the name. @@ -149,7 +138,7 @@ class FindSymbolTool(Tool, ToolMarkerSymbolicRead): parsed_exclude_kinds: Sequence[SymbolKind] | None = [SymbolKind(k) for k in exclude_kinds] if exclude_kinds else None symbol_retriever = self.create_language_server_symbol_retriever() symbols = symbol_retriever.find_by_name( - name_path, + name_path_pattern, include_kinds=parsed_include_kinds, exclude_kinds=parsed_exclude_kinds, substring_matching=substring_matching, @@ -162,7 +151,7 @@ class FindSymbolTool(Tool, ToolMarkerSymbolicRead): class FindReferencingSymbolsTool(Tool, ToolMarkerSymbolicRead): """ - Finds symbols that reference the symbol at the given location (optionally filtered by type). + Finds symbols that reference the given symbol using the language server backend """ # noinspection PyDefaultArgument @@ -215,7 +204,7 @@ class FindReferencingSymbolsTool(Tool, ToolMarkerSymbolicRead): class ReplaceSymbolBodyTool(Tool, ToolMarkerSymbolicEdit): """ - Replaces the full definition of a symbol. + Replaces the full definition of a symbol using the language server backend. """ def apply( diff --git a/test/serena/test_serena_agent.py b/test/serena/test_serena_agent.py index 882b45be..e2ac4c62 100644 --- a/test/serena/test_serena_agent.py +++ b/test/serena/test_serena_agent.py @@ -86,7 +86,7 @@ class TestSerenaAgent: def test_find_symbol(self, serena_agent, symbol_name: str, expected_kind: str, expected_file: str): agent = serena_agent find_symbol_tool = agent.get_tool(FindSymbolTool) - result = find_symbol_tool.apply_ex(name_path=symbol_name) + result = find_symbol_tool.apply_ex(name_path_pattern=symbol_name) symbols = json.loads(result) assert any( @@ -138,7 +138,7 @@ class TestSerenaAgent: # Find the symbol location first find_symbol_tool = agent.get_tool(FindSymbolTool) - result = find_symbol_tool.apply_ex(name_path=symbol_name, relative_path=def_file) + result = find_symbol_tool.apply_ex(name_path_pattern=symbol_name, relative_path=def_file) time.sleep(1) symbols = json.loads(result) @@ -233,7 +233,7 @@ class TestSerenaAgent: find_symbol_tool = agent.get_tool(FindSymbolTool) result = find_symbol_tool.apply_ex( - name_path=name_path, + name_path_pattern=name_path, depth=0, relative_path=None, include_body=False, @@ -277,7 +277,7 @@ class TestSerenaAgent: find_symbol_tool = agent.get_tool(FindSymbolTool) result = find_symbol_tool.apply_ex( - name_path=name_path, + name_path_pattern=name_path, depth=0, substring_matching=True, )