Skip to content

Commit 547ee7e

Browse files
authored
Add support to open the online message documentation as quick fix action (#298)
1 parent b52e0f9 commit 547ee7e

File tree

3 files changed

+54
-1
lines changed

3 files changed

+54
-1
lines changed

bundled/tool/lsp_server.py

+13-1
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ def update_sys_path(path_to_add: str, strategy: str) -> None:
5454
# **********************************************************
5555
TOOL_MODULE = "pylint"
5656
TOOL_DISPLAY = "Pylint"
57+
DOCUMENTATION_HOME = "https://pylint.readthedocs.io/en/latest/user_guide/messages"
5758

5859
# Default arguments always passed to pylint.
5960
TOOL_ARGS = ["--reports=n", "--output-format=json"]
@@ -136,6 +137,14 @@ def _get_severity(
136137
return lsp.DiagnosticSeverity.Error
137138

138139

140+
def _build_message_doc_url(code: str) -> str:
141+
"""Build the URL to the documentation for this diagnostic message."""
142+
msg_id, message = code.split(":")
143+
category = utils.get_message_category(msg_id)
144+
uri = f"{category}/{message}.html" if category else DOCUMENTATION_HOME
145+
return f"{DOCUMENTATION_HOME}/{uri}"
146+
147+
139148
def _parse_output(
140149
content: str,
141150
severity: Dict[str, str],
@@ -164,13 +173,17 @@ def _parse_output(
164173
# points to.
165174
end = start
166175

176+
code = f"{data.get('message-id')}:{data.get('symbol')}"
177+
documentation_url = _build_message_doc_url(code)
178+
167179
diagnostic = lsp.Diagnostic(
168180
range=lsp.Range(start=start, end=end),
169181
message=data.get("message"),
170182
severity=_get_severity(
171183
data.get("symbol"), data.get("message-id"), data.get("type"), severity
172184
),
173185
code=f"{data.get('message-id')}:{data.get('symbol')}",
186+
code_description=lsp.CodeDescription(href=documentation_url),
174187
source=TOOL_DISPLAY,
175188
)
176189

@@ -253,7 +266,6 @@ def code_action(params: lsp.CodeActionParams) -> List[lsp.CodeAction]:
253266
func = QUICK_FIXES.solutions(diagnostic.code)
254267
if func:
255268
code_actions.extend(func(document, [diagnostic]))
256-
257269
return code_actions
258270

259271

bundled/tool/lsp_utils.py

+13
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,14 @@
1717
# Save the working directory used when loading this module
1818
SERVER_CWD = os.getcwd()
1919
CWD_LOCK = threading.Lock()
20+
CATEGORIES = {
21+
"F": "fatal",
22+
"E": "error",
23+
"W": "warning",
24+
"C": "convention",
25+
"R": "refactor",
26+
"I": "information",
27+
}
2028

2129

2230
def as_list(content: Union[Any, List[Any], Tuple[Any]]) -> Union[List[Any], Tuple[Any]]:
@@ -26,6 +34,11 @@ def as_list(content: Union[Any, List[Any], Tuple[Any]]) -> Union[List[Any], Tupl
2634
return [content]
2735

2836

37+
def get_message_category(code: str) -> Optional[str]:
38+
"""Get the full name of the message category."""
39+
return CATEGORIES.get(code[0].upper())
40+
41+
2942
# pylint: disable-next=consider-using-generator
3043
_site_paths = tuple(
3144
[

src/test/python_tests/test_linting.py

+28
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
TEST_FILE_URI = utils.as_uri(str(TEST_FILE_PATH))
1717
LINTER = utils.get_server_info_defaults()
1818
TIMEOUT = 10 # 10 seconds
19+
DOCUMENTATION_HOME = "https://pylint.readthedocs.io/en/latest/user_guide/messages"
1920

2021

2122
def test_publish_diagnostics_on_open():
@@ -60,6 +61,9 @@ def _handler(params):
6061
"message": "Missing module docstring",
6162
"severity": 3,
6263
"code": "C0114:missing-module-docstring",
64+
"codeDescription": {
65+
"href": f"{DOCUMENTATION_HOME}/convention/missing-module-docstring.html"
66+
},
6367
"source": LINTER["name"],
6468
},
6569
{
@@ -73,6 +77,9 @@ def _handler(params):
7377
"message": "Undefined variable 'x'",
7478
"severity": 1,
7579
"code": "E0602:undefined-variable",
80+
"codeDescription": {
81+
"href": f"{DOCUMENTATION_HOME}/error/undefined-variable.html"
82+
},
7683
"source": LINTER["name"],
7784
},
7885
{
@@ -86,6 +93,9 @@ def _handler(params):
8693
"message": "Unused import sys",
8794
"severity": 2,
8895
"code": "W0611:unused-import",
96+
"codeDescription": {
97+
"href": f"{DOCUMENTATION_HOME}/warning/unused-import.html"
98+
},
8999
"source": LINTER["name"],
90100
},
91101
],
@@ -136,6 +146,9 @@ def _handler(params):
136146
"message": "Missing module docstring",
137147
"severity": 3,
138148
"code": "C0114:missing-module-docstring",
149+
"codeDescription": {
150+
"href": f"{DOCUMENTATION_HOME}/convention/missing-module-docstring.html"
151+
},
139152
"source": LINTER["name"],
140153
},
141154
{
@@ -149,6 +162,9 @@ def _handler(params):
149162
"message": "Undefined variable 'x'",
150163
"severity": 1,
151164
"code": "E0602:undefined-variable",
165+
"codeDescription": {
166+
"href": f"{DOCUMENTATION_HOME}/error/undefined-variable.html"
167+
},
152168
"source": LINTER["name"],
153169
},
154170
{
@@ -162,6 +178,9 @@ def _handler(params):
162178
"message": "Unused import sys",
163179
"severity": 2,
164180
"code": "W0611:unused-import",
181+
"codeDescription": {
182+
"href": f"{DOCUMENTATION_HOME}/warning/unused-import.html"
183+
},
165184
"source": LINTER["name"],
166185
},
167186
],
@@ -273,6 +292,9 @@ def _handler(params):
273292
"message": "Missing module docstring",
274293
"severity": 3,
275294
"code": "C0114:missing-module-docstring",
295+
"codeDescription": {
296+
"href": f"{DOCUMENTATION_HOME}/convention/missing-module-docstring.html"
297+
},
276298
"source": LINTER["name"],
277299
},
278300
{
@@ -286,6 +308,9 @@ def _handler(params):
286308
"message": "Undefined variable 'x'",
287309
"severity": 1,
288310
"code": "E0602:undefined-variable",
311+
"codeDescription": {
312+
"href": f"{DOCUMENTATION_HOME}/error/undefined-variable.html"
313+
},
289314
"source": LINTER["name"],
290315
},
291316
{
@@ -299,6 +324,9 @@ def _handler(params):
299324
"message": "Unused import sys",
300325
"severity": 1,
301326
"code": "W0611:unused-import",
327+
"codeDescription": {
328+
"href": f"{DOCUMENTATION_HOME}/warning/unused-import.html"
329+
},
302330
"source": LINTER["name"],
303331
},
304332
],

0 commit comments

Comments
 (0)