mirror of
https://github.com/tiennm99/serena.git
synced 2026-10-13 22:16:23 +00:00
Remove obsolete glob pattern support in search_text, removing duplicate glob translation
This commit is contained in:
1 parent
52cf8552a0
commit
33125287dc
2 files changed
+1
-118
No files matched your search
@@ -117,34 +117,12 @@ class MatchedConsecutiveLines:
|
||||
return cls(lines=text_lines, source_file_path=source_file_path)
|
||||
|
||||
|
||||
def glob_to_regex(glob_pat: str) -> str:
|
||||
regex_parts: list[str] = []
|
||||
i = 0
|
||||
while i < len(glob_pat):
|
||||
ch = glob_pat[i]
|
||||
if ch == "*":
|
||||
regex_parts.append(".*")
|
||||
elif ch == "?":
|
||||
regex_parts.append(".")
|
||||
elif ch == "\\":
|
||||
i += 1
|
||||
if i < len(glob_pat):
|
||||
regex_parts.append(re.escape(glob_pat[i]))
|
||||
else:
|
||||
regex_parts.append("\\")
|
||||
else:
|
||||
regex_parts.append(re.escape(ch))
|
||||
i += 1
|
||||
return "".join(regex_parts)
|
||||
|
||||
|
||||
def search_text(
|
||||
pattern: str,
|
||||
content: str | None = None,
|
||||
source_file_path: str | None = None,
|
||||
context_lines_before: int = 0,
|
||||
context_lines_after: int = 0,
|
||||
is_glob: bool = False,
|
||||
multiline: bool = True,
|
||||
) -> list[MatchedConsecutiveLines]:
|
||||
"""
|
||||
@@ -156,8 +134,6 @@ def search_text(
|
||||
this has to be passed and the file will be read.
|
||||
:param context_lines_before: Number of context lines to include before matches
|
||||
:param context_lines_after: Number of context lines to include after matches
|
||||
:param is_glob: If True, pattern is treated as a glob-like pattern (e.g., "*.py", "test_??.py")
|
||||
and will be converted to regex internally
|
||||
:param multiline: whether to apply multi-line matching, enabling the flags re.DOTALL and re.MULTILINE
|
||||
:return: List of `TextSearchMatch` objects
|
||||
:raises: ValueError if the pattern is not valid
|
||||
@@ -173,10 +149,6 @@ def search_text(
|
||||
lines = TextUtils.split_lines(content)
|
||||
total_lines = len(lines)
|
||||
|
||||
# Convert pattern to a compiled regex if it's a string
|
||||
if is_glob:
|
||||
pattern = glob_to_regex(pattern)
|
||||
|
||||
# For multiline matches, optionally use DOTALL so '.' matches newlines
|
||||
flags = (re.MULTILINE | re.DOTALL) if multiline else 0
|
||||
compiled_pattern = re.compile(pattern, flags)
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
import re
|
||||
from collections.abc import Callable
|
||||
|
||||
import pytest
|
||||
|
||||
from serena.util.file_proxy import FileCollection, FileProxy
|
||||
from serena.util.text_utils import LineType, MultiFileContentReplacer, glob_to_regex, search_files, search_text
|
||||
from serena.util.text_utils import LineType, MultiFileContentReplacer, search_files, search_text
|
||||
|
||||
|
||||
class TestSearchText:
|
||||
@@ -177,94 +176,6 @@ class TestSearchText:
|
||||
match_lines = [line for line in multiline_match.lines if line.match_type == LineType.MATCH]
|
||||
assert len(match_lines) >= 3
|
||||
|
||||
def test_search_text_with_glob_pattern(self):
|
||||
"""Test searching with glob-like patterns."""
|
||||
content = """
|
||||
class UserService:
|
||||
def get_user(self, user_id):
|
||||
return {"id": user_id, "name": "Test User"}
|
||||
|
||||
def create_user(self, user_data):
|
||||
print(f"Creating user: {user_data}")
|
||||
return {"id": 123, **user_data}
|
||||
|
||||
def update_user(self, user_id, user_data):
|
||||
print(f"Updating user {user_id} with {user_data}")
|
||||
return True
|
||||
"""
|
||||
|
||||
# Search with a glob pattern for all user methods
|
||||
matches = search_text("*_user*", content=content, is_glob=True, multiline=False)
|
||||
|
||||
assert len(matches) == 3
|
||||
assert "get_user" in matches[0].lines[0].line_content
|
||||
assert "create_user" in matches[1].lines[0].line_content
|
||||
assert "update_user" in matches[2].lines[0].line_content
|
||||
|
||||
def test_search_text_with_complex_glob_pattern(self):
|
||||
"""Test searching with more complex glob patterns."""
|
||||
content = """
|
||||
def process_data(data):
|
||||
return [transform(item) for item in data]
|
||||
|
||||
def transform(item):
|
||||
if isinstance(item, dict):
|
||||
return {k: v.upper() if isinstance(v, str) else v for k, v in item.items()}
|
||||
elif isinstance(item, list):
|
||||
return [x * 2 for x in item if isinstance(x, (int, float))]
|
||||
elif isinstance(item, str):
|
||||
return item.upper()
|
||||
else:
|
||||
return item
|
||||
"""
|
||||
|
||||
# Search with a simplified glob pattern to find all isinstance occurrences
|
||||
matches = search_text("*isinstance*", content=content, is_glob=True, multiline=False)
|
||||
|
||||
# Should match lines with isinstance(item, dict) and isinstance(item, list)
|
||||
assert len(matches) >= 2
|
||||
instance_matches = [
|
||||
line.line_content
|
||||
for match in matches
|
||||
for line in match.lines
|
||||
if line.match_type == LineType.MATCH and "isinstance(item," in line.line_content
|
||||
]
|
||||
assert len(instance_matches) >= 2
|
||||
assert any("isinstance(item, dict)" in line for line in instance_matches)
|
||||
assert any("isinstance(item, list)" in line for line in instance_matches)
|
||||
|
||||
def test_search_text_glob_with_special_chars(self):
|
||||
"""Glob patterns containing regex special characters should match literally."""
|
||||
content = """
|
||||
def func_square():
|
||||
print("value[42]")
|
||||
|
||||
def func_curly():
|
||||
print("value{bar}")
|
||||
"""
|
||||
|
||||
matches_square = search_text(r"*\[42\]*", content=content, is_glob=True, multiline=False)
|
||||
assert len(matches_square) == 1
|
||||
assert "[42]" in matches_square[0].lines[0].line_content
|
||||
|
||||
matches_curly = search_text("*{bar}*", content=content, is_glob=True, multiline=False)
|
||||
assert len(matches_curly) == 1
|
||||
assert "{bar}" in matches_curly[0].lines[0].line_content
|
||||
|
||||
def test_glob_to_regex_question_matches_single_char(self):
|
||||
"""A glob '?' matches exactly one character, matching glob_match's documented semantics."""
|
||||
rx = glob_to_regex("a?c")
|
||||
assert re.fullmatch(rx, "abc") is not None
|
||||
assert re.fullmatch(rx, "ac") is None
|
||||
assert re.fullmatch(rx, "abbc") is None
|
||||
|
||||
def test_search_text_glob_question_single_char(self):
|
||||
"""search_text('c?t', is_glob=True) must match 'cat' (one char), not 'coat' (two chars)."""
|
||||
content = "value_cat_end\nvalue_coat_end"
|
||||
matches = search_text("c?t", content=content, is_glob=True, multiline=False)
|
||||
assert len(matches) == 1
|
||||
assert "value_cat_end" in matches[0].lines[0].line_content
|
||||
|
||||
def test_search_text_no_matches(self):
|
||||
"""Test searching with a pattern that doesn't match anything."""
|
||||
content = """
|
||||
|
||||
Reference in new issue
Block a user