renpy-language-server 0.2.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.
Potentially problematic release.
This version of renpy-language-server might be problematic. Click here for more details.
- renpy_language_server/__init__.py +6 -0
- renpy_language_server/__main__.py +5 -0
- renpy_language_server/analysis.py +230 -0
- renpy_language_server/assets.py +104 -0
- renpy_language_server/builtins.py +54 -0
- renpy_language_server/cli.py +190 -0
- renpy_language_server/code_actions.py +130 -0
- renpy_language_server/completion.py +1191 -0
- renpy_language_server/completion_data.py +74 -0
- renpy_language_server/dap.py +824 -0
- renpy_language_server/data/__init__.py +1 -0
- renpy_language_server/data/completion.json +756 -0
- renpy_language_server/data/renpy_api.json +8073 -0
- renpy_language_server/definition.py +77 -0
- renpy_language_server/diagnostics.py +895 -0
- renpy_language_server/docs.py +21 -0
- renpy_language_server/edits.py +70 -0
- renpy_language_server/folding.py +107 -0
- renpy_language_server/formatter.py +288 -0
- renpy_language_server/hover.py +238 -0
- renpy_language_server/index.py +1002 -0
- renpy_language_server/positions.py +28 -0
- renpy_language_server/py.typed +0 -0
- renpy_language_server/python_format.py +141 -0
- renpy_language_server/python_index.py +371 -0
- renpy_language_server/quotes.py +143 -0
- renpy_language_server/references.py +40 -0
- renpy_language_server/rename.py +293 -0
- renpy_language_server/resolve.py +807 -0
- renpy_language_server/scanner.py +86 -0
- renpy_language_server/semantic.py +488 -0
- renpy_language_server/server.py +770 -0
- renpy_language_server/settings.py +187 -0
- renpy_language_server/signature.py +371 -0
- renpy_language_server/spacing.py +261 -0
- renpy_language_server/strings.py +86 -0
- renpy_language_server/symbols.py +163 -0
- renpy_language_server/targets.py +51 -0
- renpy_language_server-0.2.0.dist-info/METADATA +434 -0
- renpy_language_server-0.2.0.dist-info/RECORD +44 -0
- renpy_language_server-0.2.0.dist-info/WHEEL +4 -0
- renpy_language_server-0.2.0.dist-info/entry_points.txt +3 -0
- renpy_language_server-0.2.0.dist-info/licenses/LICENSE +21 -0
- renpy_language_server-0.2.0.dist-info/licenses/NOTICE.md +41 -0
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
"""Quick fixes for diagnostics that can be repaired without guessing."""
|
|
2
|
+
|
|
3
|
+
import re
|
|
4
|
+
from collections.abc import Sequence
|
|
5
|
+
|
|
6
|
+
from lsprotocol import types
|
|
7
|
+
|
|
8
|
+
from .diagnostics import COMPARISON, STRAY_DOLLAR, TABS, UNKNOWN_LABEL
|
|
9
|
+
from .index import utf16_length
|
|
10
|
+
|
|
11
|
+
_UNKNOWN_LABEL = re.compile(r"Unknown label '(.+)'\.")
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def code_actions_for(
|
|
15
|
+
uri: str,
|
|
16
|
+
source: str,
|
|
17
|
+
requested: types.Range,
|
|
18
|
+
diagnostics: Sequence[types.Diagnostic],
|
|
19
|
+
indent: int = 4,
|
|
20
|
+
) -> list[types.CodeAction]:
|
|
21
|
+
"""Return quick fixes for diagnostics overlapping ``requested``."""
|
|
22
|
+
actions: list[types.CodeAction] = []
|
|
23
|
+
for diagnostic in diagnostics:
|
|
24
|
+
if not _overlaps(diagnostic.range, requested):
|
|
25
|
+
continue
|
|
26
|
+
action = _action(uri, source, diagnostic, indent)
|
|
27
|
+
if action is not None:
|
|
28
|
+
actions.append(action)
|
|
29
|
+
return actions
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def _action(
|
|
33
|
+
uri: str,
|
|
34
|
+
source: str,
|
|
35
|
+
diagnostic: types.Diagnostic,
|
|
36
|
+
indent: int,
|
|
37
|
+
) -> types.CodeAction | None:
|
|
38
|
+
code = diagnostic.code
|
|
39
|
+
if code == COMPARISON:
|
|
40
|
+
return _edit_action(
|
|
41
|
+
uri,
|
|
42
|
+
'Replace "=" with "=="',
|
|
43
|
+
diagnostic,
|
|
44
|
+
diagnostic.range,
|
|
45
|
+
"==",
|
|
46
|
+
)
|
|
47
|
+
if code == STRAY_DOLLAR:
|
|
48
|
+
return _edit_action(
|
|
49
|
+
uri,
|
|
50
|
+
'Remove stray "$"',
|
|
51
|
+
diagnostic,
|
|
52
|
+
diagnostic.range,
|
|
53
|
+
"",
|
|
54
|
+
)
|
|
55
|
+
if code == TABS:
|
|
56
|
+
tabs = _text_at(source, diagnostic.range)
|
|
57
|
+
if "\t" not in tabs:
|
|
58
|
+
return None
|
|
59
|
+
return _edit_action(
|
|
60
|
+
uri,
|
|
61
|
+
"Replace tabs with spaces",
|
|
62
|
+
diagnostic,
|
|
63
|
+
diagnostic.range,
|
|
64
|
+
" " * (indent * tabs.count("\t")),
|
|
65
|
+
)
|
|
66
|
+
if code == UNKNOWN_LABEL:
|
|
67
|
+
match = _UNKNOWN_LABEL.fullmatch(diagnostic.message)
|
|
68
|
+
if match is None:
|
|
69
|
+
return None
|
|
70
|
+
name = match.group(1)
|
|
71
|
+
if not name or name.startswith("."):
|
|
72
|
+
return None
|
|
73
|
+
return _edit_action(
|
|
74
|
+
uri,
|
|
75
|
+
f"Create label '{name}'",
|
|
76
|
+
diagnostic,
|
|
77
|
+
_end_of_document(source),
|
|
78
|
+
_new_label(source, name, indent),
|
|
79
|
+
)
|
|
80
|
+
return None
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def _edit_action(
|
|
84
|
+
uri: str,
|
|
85
|
+
title: str,
|
|
86
|
+
diagnostic: types.Diagnostic,
|
|
87
|
+
range_: types.Range,
|
|
88
|
+
new_text: str,
|
|
89
|
+
) -> types.CodeAction:
|
|
90
|
+
return types.CodeAction(
|
|
91
|
+
title=title,
|
|
92
|
+
kind=types.CodeActionKind.QuickFix,
|
|
93
|
+
diagnostics=[diagnostic],
|
|
94
|
+
edit=types.WorkspaceEdit(
|
|
95
|
+
changes={uri: [types.TextEdit(range=range_, new_text=new_text)]}
|
|
96
|
+
),
|
|
97
|
+
)
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
def _new_label(source: str, name: str, indent: int) -> str:
|
|
101
|
+
separator = "" if not source or source.endswith("\n") else "\n"
|
|
102
|
+
return f"{separator}\nlabel {name}:\n{' ' * indent}return\n"
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
def _end_of_document(source: str) -> types.Range:
|
|
106
|
+
normalized = source.replace("\r\n", "\n").replace("\r", "\n")
|
|
107
|
+
lines = normalized.split("\n")
|
|
108
|
+
return types.Range(
|
|
109
|
+
start=types.Position(line=len(lines) - 1, character=utf16_length(lines[-1])),
|
|
110
|
+
end=types.Position(line=len(lines) - 1, character=utf16_length(lines[-1])),
|
|
111
|
+
)
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
def _text_at(source: str, range_: types.Range) -> str:
|
|
115
|
+
lines = source.replace("\r\n", "\n").replace("\r", "\n").split("\n")
|
|
116
|
+
if range_.start.line != range_.end.line:
|
|
117
|
+
return ""
|
|
118
|
+
if range_.start.line >= len(lines):
|
|
119
|
+
return ""
|
|
120
|
+
return lines[range_.start.line][range_.start.character : range_.end.character]
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
def _overlaps(left: types.Range, right: types.Range) -> bool:
|
|
124
|
+
return _position(left.start) <= _position(right.end) and _position(
|
|
125
|
+
right.start
|
|
126
|
+
) <= _position(left.end)
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
def _position(position: types.Position) -> tuple[int, int]:
|
|
130
|
+
return position.line, position.character
|