Skip to content

Commit 24a7a1c

Browse files
committed
Make a separate module for text_edit
1 parent 26e977e commit 24a7a1c

File tree

5 files changed

+415
-413
lines changed

5 files changed

+415
-413
lines changed

Diff for: pylsp/text_edit.py

+77
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
def get_well_formatted_range(range):
2+
start = range['start']
3+
end = range['end']
4+
5+
if start['line'] > end['line'] or (start['line'] == end['line'] and start['character'] > end['character']):
6+
return { 'start': end, 'end': start }
7+
8+
return range
9+
10+
def get_well_formatted_edit(text_edit):
11+
range = get_well_formatted_range(text_edit['range'])
12+
if range != text_edit['range']:
13+
return { 'newText': text_edit['newText'], 'range': range }
14+
15+
return text_edit
16+
17+
def compare_text_edits(a, b):
18+
diff = a['range']['start']['line'] - b['range']['start']['line']
19+
if diff == 0:
20+
return a['range']['start']['character'] - b['range']['start']['character']
21+
22+
return diff
23+
24+
def merge_sort_text_edits(text_edits):
25+
if len(text_edits) <= 1:
26+
return text_edits
27+
28+
p = len(text_edits) // 2
29+
left = text_edits[:p]
30+
right = text_edits[p:]
31+
32+
merge_sort_text_edits(left)
33+
merge_sort_text_edits(right)
34+
35+
left_idx = 0
36+
right_idx = 0
37+
i = 0
38+
while left_idx < len(left) and right_idx < len(right):
39+
ret = compare_text_edits(left[left_idx], right[right_idx])
40+
if ret <= 0:
41+
# smaller_equal -> take left to preserve order
42+
text_edits[i] = left[left_idx]
43+
i += 1
44+
left_idx += 1
45+
else:
46+
# greater -> take right
47+
text_edits[i] = right[right_idx]
48+
i+=1
49+
right_idx +=1
50+
while left_idx < len(left):
51+
text_edits[i] = left[left_idx]
52+
i += 1
53+
left_idx += 1
54+
while right_idx < len(right):
55+
text_edits[i] = right[right_idx]
56+
i += 1
57+
right_idx += 1
58+
return text_edits
59+
60+
def apply_text_edits(doc, text_edits):
61+
text = doc.source
62+
sorted_edits = merge_sort_text_edits(list(map(get_well_formatted_edit,text_edits)))
63+
last_modified_offset = 0
64+
spans = []
65+
for e in sorted_edits:
66+
start_offset = doc.offset_at_position(e['range']['start'])
67+
if start_offset < last_modified_offset:
68+
raise Exception('overlapping edit')
69+
elif start_offset > last_modified_offset:
70+
spans.append(text[last_modified_offset:start_offset])
71+
72+
if len(e['newText']):
73+
spans.append(e['newText'])
74+
last_modified_offset = doc.offset_at_position(e['range']['end'])
75+
76+
spans.append(text[last_modified_offset:])
77+
return ''.join(spans)

Diff for: pylsp/workspace.py

-78
Original file line numberDiff line numberDiff line change
@@ -129,84 +129,6 @@ def _create_document(self, doc_uri, source=None, version=None):
129129
)
130130

131131

132-
def get_well_formatted_range(range):
133-
start = range['start']
134-
end = range['end']
135-
136-
if start['line'] > end['line'] or (start['line'] == end['line'] and start['character'] > end['character']):
137-
return { 'start': end, 'end': start }
138-
139-
return range
140-
141-
def get_well_formatted_edit(text_edit):
142-
range = get_well_formatted_range(text_edit['range'])
143-
if range != text_edit['range']:
144-
return { 'newText': text_edit['newText'], 'range': range }
145-
146-
return text_edit
147-
148-
def compare_text_edits(a, b):
149-
diff = a['range']['start']['line'] - b['range']['start']['line']
150-
if diff == 0:
151-
return a['range']['start']['character'] - b['range']['start']['character']
152-
153-
return diff
154-
155-
def merge_sort_text_edits(text_edits):
156-
if len(text_edits) <= 1:
157-
return text_edits
158-
159-
p = len(text_edits) // 2
160-
left = text_edits[:p]
161-
right = text_edits[p:]
162-
163-
merge_sort_text_edits(left)
164-
merge_sort_text_edits(right)
165-
166-
left_idx = 0
167-
right_idx = 0
168-
i = 0
169-
while left_idx < len(left) and right_idx < len(right):
170-
ret = compare_text_edits(left[left_idx], right[right_idx])
171-
if ret <= 0:
172-
# smaller_equal -> take left to preserve order
173-
text_edits[i] = left[left_idx]
174-
i += 1
175-
left_idx += 1
176-
else:
177-
# greater -> take right
178-
text_edits[i] = right[right_idx]
179-
i+=1
180-
right_idx +=1
181-
while left_idx < len(left):
182-
text_edits[i] = left[left_idx]
183-
i += 1
184-
left_idx += 1
185-
while right_idx < len(right):
186-
text_edits[i] = right[right_idx]
187-
i += 1
188-
right_idx += 1
189-
return text_edits
190-
191-
def apply_text_edits(doc, text_edits):
192-
text = doc.source
193-
sorted_edits = merge_sort_text_edits(list(map(get_well_formatted_edit,text_edits)))
194-
last_modified_offset = 0
195-
spans = []
196-
for e in sorted_edits:
197-
start_offset = doc.offset_at_position(e['range']['start'])
198-
if start_offset < last_modified_offset:
199-
raise Exception('overlapping edit')
200-
elif start_offset > last_modified_offset:
201-
spans.append(text[last_modified_offset:start_offset])
202-
203-
if len(e['newText']):
204-
spans.append(e['newText'])
205-
last_modified_offset = doc.offset_at_position(e['range']['end'])
206-
207-
spans.append(text[last_modified_offset:])
208-
return ''.join(spans)
209-
210132
class Document:
211133

212134
def __init__(self, uri, workspace, source=None, version=None, local=True, extra_sys_path=None,

Diff for: test/plugins/test_yapf_format.py

+1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
from pylsp import uris
77
from pylsp.plugins.yapf_format import pylsp_format_document, pylsp_format_range
88
from pylsp.workspace import Document, apply_text_edits
9+
from pylsp.text_edit import apply_text_edits
910

1011
DOC_URI = uris.from_fs_path(__file__)
1112
DOC = """A = [

0 commit comments

Comments
 (0)