avrae-ls 0.6.4__py3-none-any.whl → 0.7.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- avrae_ls/__main__.py +42 -5
- avrae_ls/alias_preview.py +38 -6
- avrae_ls/alias_tests.py +2 -0
- avrae_ls/ast_utils.py +14 -0
- avrae_ls/code_actions.py +6 -2
- avrae_ls/completions.py +191 -1156
- avrae_ls/config.py +1 -0
- avrae_ls/context.py +62 -32
- avrae_ls/diagnostics.py +33 -60
- avrae_ls/lsp_utils.py +41 -0
- avrae_ls/parser.py +30 -3
- avrae_ls/server.py +85 -47
- avrae_ls/source_context.py +30 -0
- avrae_ls/symbols.py +27 -60
- avrae_ls/type_inference.py +470 -0
- avrae_ls/type_system.py +729 -0
- {avrae_ls-0.6.4.dist-info → avrae_ls-0.7.0.dist-info}/METADATA +6 -1
- avrae_ls-0.7.0.dist-info/RECORD +39 -0
- avrae_ls-0.6.4.dist-info/RECORD +0 -34
- {avrae_ls-0.6.4.dist-info → avrae_ls-0.7.0.dist-info}/WHEEL +0 -0
- {avrae_ls-0.6.4.dist-info → avrae_ls-0.7.0.dist-info}/entry_points.txt +0 -0
- {avrae_ls-0.6.4.dist-info → avrae_ls-0.7.0.dist-info}/licenses/LICENSE +0 -0
avrae_ls/server.py
CHANGED
|
@@ -17,12 +17,12 @@ from .context import ContextBuilder
|
|
|
17
17
|
from .diagnostics import DiagnosticProvider
|
|
18
18
|
from .runtime import MockExecutor
|
|
19
19
|
from .alias_preview import render_alias_command, simulate_command
|
|
20
|
-
from .parser import
|
|
20
|
+
from .parser import is_alias_module_path
|
|
21
|
+
from .source_context import build_source_context, block_for_line
|
|
21
22
|
from .signature_help import load_signatures, signature_help_for_code
|
|
22
23
|
from .completions import gather_suggestions, completion_items_for_position, hover_for_position
|
|
23
24
|
from .code_actions import code_actions_for_document
|
|
24
25
|
from .symbols import build_symbol_table, document_symbols, find_definition_range, find_references, range_for_word
|
|
25
|
-
from .argument_parsing import apply_argument_parsing
|
|
26
26
|
|
|
27
27
|
# Prefer package metadata so the server version matches the installed wheel.
|
|
28
28
|
try:
|
|
@@ -134,14 +134,14 @@ async def did_change_config(server: AvraeLanguageServer, params: types.DidChange
|
|
|
134
134
|
@ls.feature(types.TEXT_DOCUMENT_DOCUMENT_SYMBOL)
|
|
135
135
|
def on_document_symbol(server: AvraeLanguageServer, params: types.DocumentSymbolParams):
|
|
136
136
|
doc = server.workspace.get_text_document(params.text_document.uri)
|
|
137
|
-
symbols = document_symbols(doc.source)
|
|
137
|
+
symbols = document_symbols(doc.source, treat_as_module=_is_alias_module_document(doc))
|
|
138
138
|
return symbols
|
|
139
139
|
|
|
140
140
|
|
|
141
141
|
@ls.feature(types.TEXT_DOCUMENT_DEFINITION)
|
|
142
142
|
def on_definition(server: AvraeLanguageServer, params: types.DefinitionParams):
|
|
143
143
|
doc = server.workspace.get_text_document(params.text_document.uri)
|
|
144
|
-
table = build_symbol_table(doc.source)
|
|
144
|
+
table = build_symbol_table(doc.source, treat_as_module=_is_alias_module_document(doc))
|
|
145
145
|
word = doc.word_at_position(params.position)
|
|
146
146
|
rng = find_definition_range(table, word)
|
|
147
147
|
if rng is None:
|
|
@@ -152,19 +152,26 @@ def on_definition(server: AvraeLanguageServer, params: types.DefinitionParams):
|
|
|
152
152
|
@ls.feature(types.TEXT_DOCUMENT_REFERENCES)
|
|
153
153
|
def on_references(server: AvraeLanguageServer, params: types.ReferenceParams):
|
|
154
154
|
doc = server.workspace.get_text_document(params.text_document.uri)
|
|
155
|
-
|
|
155
|
+
is_module = _is_alias_module_document(doc)
|
|
156
|
+
table = build_symbol_table(doc.source, treat_as_module=is_module)
|
|
156
157
|
word = doc.word_at_position(params.position)
|
|
157
158
|
if not word or not table.lookup(word):
|
|
158
159
|
return []
|
|
159
160
|
|
|
160
|
-
ranges = find_references(
|
|
161
|
+
ranges = find_references(
|
|
162
|
+
table,
|
|
163
|
+
doc.source,
|
|
164
|
+
word,
|
|
165
|
+
include_declaration=params.context.include_declaration,
|
|
166
|
+
treat_as_module=is_module,
|
|
167
|
+
)
|
|
161
168
|
return [types.Location(uri=params.text_document.uri, range=rng) for rng in ranges]
|
|
162
169
|
|
|
163
170
|
|
|
164
171
|
@ls.feature(types.TEXT_DOCUMENT_PREPARE_RENAME)
|
|
165
172
|
def on_prepare_rename(server: AvraeLanguageServer, params: types.PrepareRenameParams):
|
|
166
173
|
doc = server.workspace.get_text_document(params.text_document.uri)
|
|
167
|
-
table = build_symbol_table(doc.source)
|
|
174
|
+
table = build_symbol_table(doc.source, treat_as_module=_is_alias_module_document(doc))
|
|
168
175
|
word = doc.word_at_position(params.position)
|
|
169
176
|
if not word or not table.lookup(word):
|
|
170
177
|
return None
|
|
@@ -174,12 +181,13 @@ def on_prepare_rename(server: AvraeLanguageServer, params: types.PrepareRenamePa
|
|
|
174
181
|
@ls.feature(types.TEXT_DOCUMENT_RENAME)
|
|
175
182
|
def on_rename(server: AvraeLanguageServer, params: types.RenameParams):
|
|
176
183
|
doc = server.workspace.get_text_document(params.text_document.uri)
|
|
177
|
-
|
|
184
|
+
is_module = _is_alias_module_document(doc)
|
|
185
|
+
table = build_symbol_table(doc.source, treat_as_module=is_module)
|
|
178
186
|
word = doc.word_at_position(params.position)
|
|
179
187
|
if not word or not table.lookup(word) or not params.new_name:
|
|
180
188
|
return None
|
|
181
189
|
|
|
182
|
-
ranges = find_references(table, doc.source, word, include_declaration=True)
|
|
190
|
+
ranges = find_references(table, doc.source, word, include_declaration=True, treat_as_module=is_module)
|
|
183
191
|
if not ranges:
|
|
184
192
|
return None
|
|
185
193
|
edits = [types.TextEdit(range=rng, new_text=params.new_name) for rng in ranges]
|
|
@@ -191,7 +199,7 @@ def on_workspace_symbol(server: AvraeLanguageServer, params: types.WorkspaceSymb
|
|
|
191
199
|
symbols: list[types.SymbolInformation] = []
|
|
192
200
|
query = (params.query or "").lower()
|
|
193
201
|
for uri, doc in server.workspace.text_documents.items():
|
|
194
|
-
table = build_symbol_table(doc.source)
|
|
202
|
+
table = build_symbol_table(doc.source, treat_as_module=_is_alias_module_document(doc))
|
|
195
203
|
for entry in table.entries:
|
|
196
204
|
if query and query not in entry.name.lower():
|
|
197
205
|
continue
|
|
@@ -208,20 +216,18 @@ def on_workspace_symbol(server: AvraeLanguageServer, params: types.WorkspaceSymb
|
|
|
208
216
|
@ls.feature(types.TEXT_DOCUMENT_SIGNATURE_HELP)
|
|
209
217
|
def on_signature_help(server: AvraeLanguageServer, params: types.SignatureHelpParams):
|
|
210
218
|
doc = server.workspace.get_text_document(params.text_document.uri)
|
|
211
|
-
|
|
212
|
-
|
|
219
|
+
is_module = _is_alias_module_document(doc)
|
|
220
|
+
source_ctx = build_source_context(doc.source, is_module)
|
|
213
221
|
pos = params.position
|
|
214
|
-
if not blocks:
|
|
215
|
-
return signature_help_for_code(
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
help_
|
|
223
|
-
if help_:
|
|
224
|
-
return help_
|
|
222
|
+
if not source_ctx.blocks:
|
|
223
|
+
return signature_help_for_code(source_ctx.prepared, pos.line, pos.character, server._signatures)
|
|
224
|
+
|
|
225
|
+
block = block_for_line(source_ctx.blocks, pos.line)
|
|
226
|
+
if block:
|
|
227
|
+
rel_line = pos.line - block.line_offset
|
|
228
|
+
help_ = signature_help_for_code(block.code, rel_line, pos.character, server._signatures)
|
|
229
|
+
if help_:
|
|
230
|
+
return help_
|
|
225
231
|
return None
|
|
226
232
|
|
|
227
233
|
|
|
@@ -233,18 +239,16 @@ def on_completion(server: AvraeLanguageServer, params: types.CompletionParams):
|
|
|
233
239
|
doc = server.workspace.get_text_document(params.text_document.uri)
|
|
234
240
|
ctx_data = server.state.context_builder.build()
|
|
235
241
|
suggestions = gather_suggestions(ctx_data, server.state.context_builder.gvar_resolver, server._signatures)
|
|
236
|
-
|
|
237
|
-
|
|
242
|
+
is_module = _is_alias_module_document(doc)
|
|
243
|
+
source_ctx = build_source_context(doc.source, is_module)
|
|
238
244
|
pos = params.position
|
|
239
|
-
if not blocks:
|
|
240
|
-
return completion_items_for_position(
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
rel_line = pos.line - start
|
|
247
|
-
return completion_items_for_position(block.code, rel_line, pos.character, suggestions)
|
|
245
|
+
if not source_ctx.blocks:
|
|
246
|
+
return completion_items_for_position(source_ctx.prepared, pos.line, pos.character, suggestions)
|
|
247
|
+
|
|
248
|
+
block = block_for_line(source_ctx.blocks, pos.line)
|
|
249
|
+
if block:
|
|
250
|
+
rel_line = pos.line - block.line_offset
|
|
251
|
+
return completion_items_for_position(block.code, rel_line, pos.character, suggestions)
|
|
248
252
|
return []
|
|
249
253
|
|
|
250
254
|
|
|
@@ -253,24 +257,41 @@ def on_hover(server: AvraeLanguageServer, params: types.HoverParams):
|
|
|
253
257
|
doc = server.workspace.get_text_document(params.text_document.uri)
|
|
254
258
|
ctx_data = server.state.context_builder.build()
|
|
255
259
|
pos = params.position
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
if not blocks:
|
|
259
|
-
return hover_for_position(
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
260
|
+
is_module = _is_alias_module_document(doc)
|
|
261
|
+
source_ctx = build_source_context(doc.source, is_module)
|
|
262
|
+
if not source_ctx.blocks:
|
|
263
|
+
return hover_for_position(
|
|
264
|
+
source_ctx.prepared,
|
|
265
|
+
pos.line,
|
|
266
|
+
pos.character,
|
|
267
|
+
server._signatures,
|
|
268
|
+
ctx_data,
|
|
269
|
+
server.state.context_builder.gvar_resolver,
|
|
270
|
+
)
|
|
271
|
+
|
|
272
|
+
block = block_for_line(source_ctx.blocks, pos.line)
|
|
273
|
+
if block:
|
|
274
|
+
rel_line = pos.line - block.line_offset
|
|
275
|
+
return hover_for_position(
|
|
276
|
+
block.code,
|
|
277
|
+
rel_line,
|
|
278
|
+
pos.character,
|
|
279
|
+
server._signatures,
|
|
280
|
+
ctx_data,
|
|
281
|
+
server.state.context_builder.gvar_resolver,
|
|
282
|
+
)
|
|
267
283
|
return None
|
|
268
284
|
|
|
269
285
|
|
|
270
286
|
@ls.feature(types.TEXT_DOCUMENT_CODE_ACTION)
|
|
271
287
|
def on_code_action(server: AvraeLanguageServer, params: types.CodeActionParams):
|
|
272
288
|
doc = server.workspace.get_text_document(params.text_document.uri)
|
|
273
|
-
return code_actions_for_document(
|
|
289
|
+
return code_actions_for_document(
|
|
290
|
+
doc.source,
|
|
291
|
+
params,
|
|
292
|
+
server.workspace_root,
|
|
293
|
+
treat_as_module=_is_alias_module_document(doc),
|
|
294
|
+
)
|
|
274
295
|
|
|
275
296
|
|
|
276
297
|
@ls.command(RUN_ALIAS_COMMAND)
|
|
@@ -372,7 +393,10 @@ async def _publish_diagnostics(
|
|
|
372
393
|
doc = server.workspace.get_text_document(uri)
|
|
373
394
|
ctx_data = server.state.context_builder.build(profile)
|
|
374
395
|
diags = await server.state.diagnostics.analyze(
|
|
375
|
-
doc.source,
|
|
396
|
+
doc.source,
|
|
397
|
+
ctx_data,
|
|
398
|
+
server.state.context_builder.gvar_resolver,
|
|
399
|
+
treat_as_module=_is_alias_module_document(doc),
|
|
376
400
|
)
|
|
377
401
|
if extra:
|
|
378
402
|
diags.extend(extra)
|
|
@@ -443,5 +467,19 @@ def _find_using_range(source: str, module: str | None) -> types.Range | None:
|
|
|
443
467
|
return None
|
|
444
468
|
|
|
445
469
|
|
|
470
|
+
def _is_alias_module_document(doc: Any) -> bool:
|
|
471
|
+
language_id = getattr(doc, "language_id", None)
|
|
472
|
+
if language_id == "avrae-module":
|
|
473
|
+
return True
|
|
474
|
+
uri = getattr(doc, "uri", None)
|
|
475
|
+
if not isinstance(uri, str):
|
|
476
|
+
return False
|
|
477
|
+
try:
|
|
478
|
+
path = Path(uris.to_fs_path(uri))
|
|
479
|
+
except Exception:
|
|
480
|
+
return uri.endswith(".alias-module")
|
|
481
|
+
return is_alias_module_path(path)
|
|
482
|
+
|
|
483
|
+
|
|
446
484
|
def create_server() -> AvraeLanguageServer:
|
|
447
485
|
return ls
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from dataclasses import dataclass
|
|
4
|
+
from typing import Sequence
|
|
5
|
+
|
|
6
|
+
from .argument_parsing import apply_argument_parsing
|
|
7
|
+
from .parser import DraconicBlock, find_draconic_blocks
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
@dataclass(frozen=True)
|
|
11
|
+
class SourceContext:
|
|
12
|
+
source: str
|
|
13
|
+
prepared: str
|
|
14
|
+
blocks: list[DraconicBlock]
|
|
15
|
+
treat_as_module: bool
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def build_source_context(source: str, treat_as_module: bool, *, apply_args: bool = True) -> SourceContext:
|
|
19
|
+
prepared = apply_argument_parsing(source) if apply_args and not treat_as_module else source
|
|
20
|
+
blocks = find_draconic_blocks(prepared, treat_as_module=treat_as_module)
|
|
21
|
+
return SourceContext(source=source, prepared=prepared, blocks=blocks, treat_as_module=treat_as_module)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def block_for_line(blocks: Sequence[DraconicBlock], line: int) -> DraconicBlock | None:
|
|
25
|
+
for block in blocks:
|
|
26
|
+
start = block.line_offset
|
|
27
|
+
end = block.line_offset + block.line_count
|
|
28
|
+
if start <= line <= end:
|
|
29
|
+
return block
|
|
30
|
+
return None
|
avrae_ls/symbols.py
CHANGED
|
@@ -8,8 +8,9 @@ from typing import Dict, Iterable, List, Optional
|
|
|
8
8
|
import draconic
|
|
9
9
|
from lsprotocol import types
|
|
10
10
|
|
|
11
|
-
from .
|
|
12
|
-
from .parser import
|
|
11
|
+
from .source_context import build_source_context
|
|
12
|
+
from .parser import wrap_draconic
|
|
13
|
+
from .lsp_utils import range_from_positions, shift_range
|
|
13
14
|
|
|
14
15
|
log = logging.getLogger(__name__)
|
|
15
16
|
|
|
@@ -35,20 +36,19 @@ class SymbolTable:
|
|
|
35
36
|
return self._index.get(name)
|
|
36
37
|
|
|
37
38
|
|
|
38
|
-
def build_symbol_table(source: str) -> SymbolTable:
|
|
39
|
+
def build_symbol_table(source: str, *, treat_as_module: bool = False) -> SymbolTable:
|
|
39
40
|
entries: list[SymbolEntry] = []
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
entries.extend(_symbols_from_code(parsed_source, 0, 0))
|
|
41
|
+
source_ctx = build_source_context(source, treat_as_module)
|
|
42
|
+
if not source_ctx.blocks:
|
|
43
|
+
entries.extend(_symbols_from_code(source_ctx.prepared, 0, 0))
|
|
44
44
|
else:
|
|
45
|
-
for block in blocks:
|
|
45
|
+
for block in source_ctx.blocks:
|
|
46
46
|
entries.extend(_symbols_from_code(block.code, block.line_offset, block.char_offset))
|
|
47
47
|
return SymbolTable(entries)
|
|
48
48
|
|
|
49
49
|
|
|
50
|
-
def document_symbols(source: str) -> List[types.DocumentSymbol]:
|
|
51
|
-
table = build_symbol_table(source)
|
|
50
|
+
def document_symbols(source: str, *, treat_as_module: bool = False) -> List[types.DocumentSymbol]:
|
|
51
|
+
table = build_symbol_table(source, treat_as_module=treat_as_module)
|
|
52
52
|
return [
|
|
53
53
|
types.DocumentSymbol(
|
|
54
54
|
name=entry.name,
|
|
@@ -68,9 +68,13 @@ def find_definition_range(table: SymbolTable, name: str) -> types.Range | None:
|
|
|
68
68
|
|
|
69
69
|
|
|
70
70
|
def find_references(
|
|
71
|
-
table: SymbolTable,
|
|
71
|
+
table: SymbolTable,
|
|
72
|
+
source: str,
|
|
73
|
+
name: str,
|
|
74
|
+
include_declaration: bool = True,
|
|
75
|
+
*,
|
|
76
|
+
treat_as_module: bool = False,
|
|
72
77
|
) -> List[types.Range]:
|
|
73
|
-
parsed_source = apply_argument_parsing(source)
|
|
74
78
|
ranges: list[types.Range] = []
|
|
75
79
|
entry = table.lookup(name)
|
|
76
80
|
include_stores = include_declaration and entry is None
|
|
@@ -78,11 +82,11 @@ def find_references(
|
|
|
78
82
|
if entry:
|
|
79
83
|
ranges.append(entry.selection_range)
|
|
80
84
|
|
|
81
|
-
|
|
82
|
-
if not blocks:
|
|
83
|
-
ranges.extend(_references_from_code(
|
|
85
|
+
source_ctx = build_source_context(source, treat_as_module)
|
|
86
|
+
if not source_ctx.blocks:
|
|
87
|
+
ranges.extend(_references_from_code(source_ctx.prepared, name, 0, 0, include_stores))
|
|
84
88
|
else:
|
|
85
|
-
for block in blocks:
|
|
89
|
+
for block in source_ctx.blocks:
|
|
86
90
|
ranges.extend(
|
|
87
91
|
_references_from_code(block.code, name, block.line_offset, block.char_offset, include_stores)
|
|
88
92
|
)
|
|
@@ -158,13 +162,14 @@ def _entry_from_node(node: ast.AST, line_offset: int = 0, char_offset: int = 0)
|
|
|
158
162
|
else:
|
|
159
163
|
return None
|
|
160
164
|
|
|
161
|
-
rng =
|
|
165
|
+
rng = range_from_positions(
|
|
162
166
|
getattr(node, "lineno", 1),
|
|
163
167
|
getattr(node, "col_offset", 0),
|
|
164
168
|
getattr(node, "end_lineno", None),
|
|
165
169
|
getattr(node, "end_col_offset", None),
|
|
170
|
+
ensure_nonempty=True,
|
|
166
171
|
)
|
|
167
|
-
rng =
|
|
172
|
+
rng = shift_range(rng, line_offset, char_offset)
|
|
168
173
|
return SymbolEntry(name=name, kind=kind, range=rng, selection_range=rng)
|
|
169
174
|
|
|
170
175
|
|
|
@@ -179,11 +184,12 @@ class _ReferenceCollector(ast.NodeVisitor):
|
|
|
179
184
|
if node.id == self._target:
|
|
180
185
|
if isinstance(node.ctx, ast.Store) and not self._include_stores:
|
|
181
186
|
return
|
|
182
|
-
rng =
|
|
187
|
+
rng = range_from_positions(
|
|
183
188
|
getattr(node, "lineno", 1),
|
|
184
189
|
getattr(node, "col_offset", 0),
|
|
185
190
|
getattr(node, "end_lineno", None),
|
|
186
191
|
getattr(node, "end_col_offset", None),
|
|
192
|
+
ensure_nonempty=True,
|
|
187
193
|
)
|
|
188
194
|
self.ranges.append(rng)
|
|
189
195
|
self.generic_visit(node)
|
|
@@ -205,7 +211,7 @@ def _references_from_code(
|
|
|
205
211
|
collector.visit(node)
|
|
206
212
|
|
|
207
213
|
local_offset = line_offset + offset_adjust
|
|
208
|
-
return [
|
|
214
|
+
return [shift_range(rng, local_offset, char_offset) for rng in collector.ranges]
|
|
209
215
|
|
|
210
216
|
|
|
211
217
|
def _parse_draconic(code: str) -> tuple[list[ast.AST], int]:
|
|
@@ -213,7 +219,7 @@ def _parse_draconic(code: str) -> tuple[list[ast.AST], int]:
|
|
|
213
219
|
try:
|
|
214
220
|
return parser.parse(code), 0
|
|
215
221
|
except draconic.DraconicSyntaxError:
|
|
216
|
-
wrapped, added =
|
|
222
|
+
wrapped, added = wrap_draconic(code)
|
|
217
223
|
try:
|
|
218
224
|
return parser.parse(wrapped), -added
|
|
219
225
|
except draconic.DraconicSyntaxError:
|
|
@@ -223,45 +229,6 @@ def _parse_draconic(code: str) -> tuple[list[ast.AST], int]:
|
|
|
223
229
|
return [], 0
|
|
224
230
|
|
|
225
231
|
|
|
226
|
-
def _range_from_positions(
|
|
227
|
-
lineno: int | None,
|
|
228
|
-
col_offset: int | None,
|
|
229
|
-
end_lineno: int | None,
|
|
230
|
-
end_col_offset: int | None,
|
|
231
|
-
) -> types.Range:
|
|
232
|
-
start_line = max((lineno or 1) - 1, 0)
|
|
233
|
-
start_char = max(col_offset or 0, 0)
|
|
234
|
-
end_line = max(((end_lineno or lineno or 1) - 1), 0)
|
|
235
|
-
raw_end_char = end_col_offset if end_col_offset is not None else col_offset
|
|
236
|
-
end_char = max(raw_end_char or start_char, start_char)
|
|
237
|
-
if end_char <= start_char:
|
|
238
|
-
end_char = start_char + 1
|
|
239
|
-
return types.Range(
|
|
240
|
-
start=types.Position(line=start_line, character=start_char),
|
|
241
|
-
end=types.Position(line=end_line, character=end_char),
|
|
242
|
-
)
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
def _shift_range(rng: types.Range, line_offset: int, char_offset: int = 0) -> types.Range:
|
|
246
|
-
start_char = rng.start.character + (char_offset if rng.start.line == 0 else 0)
|
|
247
|
-
end_char = rng.end.character + (char_offset if rng.end.line == 0 else 0)
|
|
248
|
-
if line_offset == 0:
|
|
249
|
-
return types.Range(
|
|
250
|
-
start=types.Position(line=rng.start.line, character=start_char),
|
|
251
|
-
end=types.Position(line=rng.end.line, character=end_char),
|
|
252
|
-
)
|
|
253
|
-
return types.Range(
|
|
254
|
-
start=types.Position(line=max(rng.start.line + line_offset, 0), character=max(start_char, 0)),
|
|
255
|
-
end=types.Position(line=max(rng.end.line + line_offset, 0), character=max(end_char, 0)),
|
|
256
|
-
)
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
def _wrap_draconic(code: str) -> tuple[str, int]:
|
|
260
|
-
indented = "\n".join(f" {line}" for line in code.splitlines())
|
|
261
|
-
wrapped = f"def __alias_main__():\n{indented}\n__alias_main__()"
|
|
262
|
-
return wrapped, 1
|
|
263
|
-
|
|
264
|
-
|
|
265
232
|
def _dedupe_ranges(ranges: Iterable[types.Range]) -> List[types.Range]:
|
|
266
233
|
seen = set()
|
|
267
234
|
unique: list[types.Range] = []
|