Skip to content

Commit 001b53a

Browse files
committed
update
1 parent 3820b11 commit 001b53a

8 files changed

Lines changed: 1175 additions & 176 deletions

File tree

python/src/lsap/locate.py

Lines changed: 44 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import re
22
from pathlib import Path
3-
from typing import Protocol
3+
from typing import NamedTuple, Protocol
44

55
from attrs import define
66
from lsap_schema.locate import (
@@ -43,51 +43,54 @@ def _to_regex(text: str) -> str:
4343
if not tokens:
4444
return ""
4545

46-
result: list[str] = []
47-
for i, token in enumerate(tokens):
48-
if token[0].isspace():
49-
result.append(r"\s+")
50-
else:
51-
result.append(re.escape(token))
52-
if i < len(tokens) - 1 and not tokens[i + 1][0].isspace():
53-
result.append(r"\s*")
54-
return "".join(result)
46+
def parts():
47+
for i, token in enumerate(tokens):
48+
if token[0].isspace():
49+
yield r"\s+"
50+
else:
51+
yield re.escape(token)
52+
if i < len(tokens) - 1 and not tokens[i + 1][0].isspace():
53+
yield r"\s*"
54+
55+
return "".join(parts())
56+
57+
58+
class ScopeInfo(NamedTuple):
59+
range: LSPRange
60+
selection_start: LSPPosition | None
5561

5662

5763
async def _get_scope_info(
5864
client: LocateClient,
5965
file_path: Path,
6066
scope: LineScope | SymbolScope | None,
6167
reader: DocumentReader,
62-
) -> tuple[LSPRange, LSPPosition | None]:
68+
) -> ScopeInfo:
6369
match scope:
6470
case None:
65-
return reader.full_range, None
71+
return ScopeInfo(reader.full_range, None)
6672

6773
case LineScope(line=line):
68-
if isinstance(line, int):
69-
start, end = line - 1, line - 1
70-
else:
71-
start, end = line[0] - 1, line[1] - 1
74+
match line:
75+
case int():
76+
start, end = line - 1, line - 1
77+
case (s, e):
78+
start, end = s - 1, e - 1
7279

73-
return (
80+
return ScopeInfo(
7481
LSPRange(
7582
start=LSPPosition(line=start, character=0),
7683
end=LSPPosition(line=end + 1, character=0),
7784
),
7885
None,
7986
)
80-
8187
case SymbolScope(symbol_path=path):
8288
symbols = await client.request_document_symbol_list(file_path)
8389
for s_path, symbol in iter_symbols(symbols or []):
8490
if s_path == path:
85-
return symbol.range, symbol.selection_range.start
91+
return ScopeInfo(symbol.range, symbol.selection_range.start)
8692
raise NotFoundError(f"Symbol {path} not found in {file_path}")
8793

88-
case _:
89-
return reader.full_range, None
90-
9194

9295
@define
9396
class LocateCapability(Capability[LocateClient, LocateRequest, LocateResponse]):
@@ -96,21 +99,18 @@ async def __call__(self, req: LocateRequest) -> LocateResponse | None:
9699
document = await self.client.read_file(locate.file_path)
97100
reader = DocumentReader(document)
98101

99-
scope_range, selection_start = await _get_scope_info(
102+
info = await _get_scope_info(
100103
self.client, locate.file_path, locate.scope, reader
101104
)
102105

103-
snippet = reader.read(scope_range)
106+
snippet = reader.read(info.range)
104107
if not snippet:
105108
return None
106109

107110
pos: LSPPosition | None = None
108111

109112
if locate.find:
110-
# Auto-detect marker in the find text
111-
marker_info = detect_marker(locate.find)
112-
113-
if marker_info:
113+
if marker_info := detect_marker(locate.find):
114114
marker, _, _ = marker_info
115115
before, _, after = locate.find.partition(marker)
116116
re_before, re_after = _to_regex(before), _to_regex(after)
@@ -129,11 +129,17 @@ async def __call__(self, req: LocateRequest) -> LocateResponse | None:
129129
return None
130130

131131
pos = reader.offset_to_position(snippet.range.start, offset)
132-
elif isinstance(locate.scope, SymbolScope):
133-
pos = selection_start
134-
elif isinstance(locate.scope, LineScope):
135-
m = re.search(r"\S", snippet.exact_content)
136-
pos = reader.offset_to_position(snippet.range.start, m.start() if m else 0)
132+
else:
133+
match locate.scope:
134+
case SymbolScope():
135+
pos = info.selection_start
136+
case LineScope():
137+
m = re.search(r"\S", snippet.exact_content)
138+
pos = reader.offset_to_position(
139+
snippet.range.start, m.start() if m else 0
140+
)
141+
case _:
142+
pos = info.range.start
137143

138144
if pos:
139145
return LocateResponse(
@@ -152,20 +158,20 @@ async def __call__(self, req: LocateRangeRequest) -> LocateRangeResponse | None:
152158
document = await self.client.read_file(locate.file_path)
153159
reader = DocumentReader(document)
154160

155-
scope_range, _ = await _get_scope_info(
161+
info = await _get_scope_info(
156162
self.client, locate.file_path, locate.scope, reader
157163
)
158164

159165
final_range: LSPRange | None = None
160166

161167
if locate.find:
162-
snippet = reader.read(scope_range)
168+
snippet = reader.read(info.range)
163169
if not snippet:
164170
return None
165171

166172
re_find = _to_regex(locate.find)
167173
if not re_find:
168-
final_range = scope_range
174+
final_range = info.range
169175
elif m := re.search(re_find, snippet.exact_content):
170176
final_range = LSPRange(
171177
start=reader.offset_to_position(snippet.range.start, m.start()),
@@ -174,7 +180,7 @@ async def __call__(self, req: LocateRangeRequest) -> LocateRangeResponse | None:
174180
else:
175181
return None
176182
else:
177-
final_range = scope_range
183+
final_range = info.range
178184

179185
if final_range:
180186
return LocateRangeResponse(
@@ -184,3 +190,4 @@ async def __call__(self, req: LocateRangeRequest) -> LocateRangeResponse | None:
184190
end=Position.from_lsp(final_range.end),
185191
),
186192
)
193+
return None

0 commit comments

Comments
 (0)