Skip to content

Commit 4e02dac

Browse files
committed
alternative approach: explicit, optional progress reporting for each plugin
1 parent 2adaf8f commit 4e02dac

File tree

6 files changed

+143
-115
lines changed

6 files changed

+143
-115
lines changed

Diff for: pylsp/plugins/definition.py

+17-16
Original file line numberDiff line numberDiff line change
@@ -8,24 +8,25 @@
88

99

1010
@hookimpl
11-
def pylsp_definitions(config, document, position):
12-
settings = config.plugin_settings('jedi_definition')
13-
code_position = _utils.position_to_jedi_linecolumn(document, position)
14-
definitions = document.jedi_script(use_document_path=True).goto(
15-
follow_imports=settings.get('follow_imports', True),
16-
follow_builtin_imports=settings.get('follow_builtin_imports', True),
17-
**code_position)
11+
def pylsp_definitions(config, workspace, document, position):
12+
with workspace.report_progress("definitions"):
13+
settings = config.plugin_settings('jedi_definition')
14+
code_position = _utils.position_to_jedi_linecolumn(document, position)
15+
definitions = document.jedi_script(use_document_path=True).goto(
16+
follow_imports=settings.get('follow_imports', True),
17+
follow_builtin_imports=settings.get('follow_builtin_imports', True),
18+
**code_position)
1819

19-
return [
20-
{
21-
'uri': uris.uri_with(document.uri, path=str(d.module_path)),
22-
'range': {
23-
'start': {'line': d.line - 1, 'character': d.column},
24-
'end': {'line': d.line - 1, 'character': d.column + len(d.name)},
20+
return [
21+
{
22+
'uri': uris.uri_with(document.uri, path=str(d.module_path)),
23+
'range': {
24+
'start': {'line': d.line - 1, 'character': d.column},
25+
'end': {'line': d.line - 1, 'character': d.column + len(d.name)},
26+
}
2527
}
26-
}
27-
for d in definitions if d.is_definition() and _not_internal_definition(d)
28-
]
28+
for d in definitions if d.is_definition() and _not_internal_definition(d)
29+
]
2930

3031

3132
def _not_internal_definition(definition):

Diff for: pylsp/plugins/flake8_lint.py

+51-50
Original file line numberDiff line numberDiff line change
@@ -23,56 +23,57 @@ def pylsp_settings():
2323

2424
@hookimpl
2525
def pylsp_lint(workspace, document):
26-
config = workspace._config
27-
settings = config.plugin_settings('flake8', document_path=document.path)
28-
log.debug("Got flake8 settings: %s", settings)
29-
30-
ignores = settings.get("ignore", [])
31-
per_file_ignores = settings.get("perFileIgnores")
32-
33-
if per_file_ignores:
34-
prev_file_pat = None
35-
for path in per_file_ignores:
36-
try:
37-
file_pat, errors = path.split(":")
38-
prev_file_pat = file_pat
39-
except ValueError:
40-
# It's legal to just specify another error type for the same
41-
# file pattern:
42-
if prev_file_pat is None:
43-
log.warning(
44-
"skipping a Per-file-ignore with no file pattern")
45-
continue
46-
file_pat = prev_file_pat
47-
errors = path
48-
if PurePath(document.path).match(file_pat):
49-
ignores.extend(errors.split(","))
50-
51-
opts = {
52-
'config': settings.get('config'),
53-
'exclude': settings.get('exclude'),
54-
'filename': settings.get('filename'),
55-
'hang-closing': settings.get('hangClosing'),
56-
'ignore': ignores or None,
57-
'max-line-length': settings.get('maxLineLength'),
58-
'indent-size': settings.get('indentSize'),
59-
'select': settings.get('select'),
60-
}
61-
62-
# flake takes only absolute path to the config. So we should check and
63-
# convert if necessary
64-
if opts.get('config') and not os.path.isabs(opts.get('config')):
65-
opts['config'] = os.path.abspath(os.path.expanduser(os.path.expandvars(
66-
opts.get('config')
67-
)))
68-
log.debug("using flake8 with config: %s", opts['config'])
69-
70-
# Call the flake8 utility then parse diagnostics from stdout
71-
flake8_executable = settings.get('executable', 'flake8')
72-
73-
args = build_args(opts)
74-
output = run_flake8(flake8_executable, args, document)
75-
return parse_stdout(document, output)
26+
with workspace.report_progress("flake8"):
27+
config = workspace._config
28+
settings = config.plugin_settings('flake8', document_path=document.path)
29+
log.debug("Got flake8 settings: %s", settings)
30+
31+
ignores = settings.get("ignore", [])
32+
per_file_ignores = settings.get("perFileIgnores")
33+
34+
if per_file_ignores:
35+
prev_file_pat = None
36+
for path in per_file_ignores:
37+
try:
38+
file_pat, errors = path.split(":")
39+
prev_file_pat = file_pat
40+
except ValueError:
41+
# It's legal to just specify another error type for the same
42+
# file pattern:
43+
if prev_file_pat is None:
44+
log.warning(
45+
"skipping a Per-file-ignore with no file pattern")
46+
continue
47+
file_pat = prev_file_pat
48+
errors = path
49+
if PurePath(document.path).match(file_pat):
50+
ignores.extend(errors.split(","))
51+
52+
opts = {
53+
'config': settings.get('config'),
54+
'exclude': settings.get('exclude'),
55+
'filename': settings.get('filename'),
56+
'hang-closing': settings.get('hangClosing'),
57+
'ignore': ignores or None,
58+
'max-line-length': settings.get('maxLineLength'),
59+
'indent-size': settings.get('indentSize'),
60+
'select': settings.get('select'),
61+
}
62+
63+
# flake takes only absolute path to the config. So we should check and
64+
# convert if necessary
65+
if opts.get('config') and not os.path.isabs(opts.get('config')):
66+
opts['config'] = os.path.abspath(os.path.expanduser(os.path.expandvars(
67+
opts.get('config')
68+
)))
69+
log.debug("using flake8 with config: %s", opts['config'])
70+
71+
# Call the flake8 utility then parse diagnostics from stdout
72+
flake8_executable = settings.get('executable', 'flake8')
73+
74+
args = build_args(opts)
75+
output = run_flake8(flake8_executable, args, document)
76+
return parse_stdout(document, output)
7677

7778

7879
def run_flake8(flake8_executable, args, document):

Diff for: pylsp/plugins/jedi_rename.py

+36-31
Original file line numberDiff line numberDiff line change
@@ -10,38 +10,43 @@
1010

1111
@hookimpl
1212
def pylsp_rename(config, workspace, document, position, new_name): # pylint: disable=unused-argument
13-
log.debug('Executing rename of %s to %s', document.word_at_position(position), new_name)
14-
kwargs = _utils.position_to_jedi_linecolumn(document, position)
15-
kwargs['new_name'] = new_name
16-
try:
17-
refactoring = document.jedi_script().rename(**kwargs)
18-
except NotImplementedError as exc:
19-
raise Exception('No support for renaming in Python 2/3.5 with Jedi. '
20-
'Consider using the rope_rename plugin instead') from exc
21-
log.debug('Finished rename: %s', refactoring.get_diff())
22-
changes = []
23-
for file_path, changed_file in refactoring.get_changed_files().items():
24-
uri = uris.from_fs_path(str(file_path))
25-
doc = workspace.get_maybe_document(uri)
26-
changes.append({
27-
'textDocument': {
28-
'uri': uri,
29-
'version': doc.version if doc else None
30-
},
31-
'edits': [
32-
{
33-
'range': {
34-
'start': {'line': 0, 'character': 0},
35-
'end': {
36-
'line': _num_lines(changed_file.get_new_code()),
37-
'character': 0,
13+
with workspace.report_progress("rename") as report_progress:
14+
log.debug('Executing rename of %s to %s', document.word_at_position(position), new_name)
15+
kwargs = _utils.position_to_jedi_linecolumn(document, position)
16+
kwargs['new_name'] = new_name
17+
report_progress("refactoring")
18+
try:
19+
refactoring = document.jedi_script().rename(**kwargs)
20+
except NotImplementedError as exc:
21+
raise Exception('No support for renaming in Python 2/3.5 with Jedi. '
22+
'Consider using the rope_rename plugin instead') from exc
23+
log.debug('Finished rename: %s', refactoring.get_diff())
24+
changes = []
25+
26+
changed_files = refactoring.get_changed_files()
27+
for n, (file_path, changed_file) in enumerate(changed_files.items()):
28+
report_progress(changed_file, percentage=n/len(changed_files)*100)
29+
uri = uris.from_fs_path(str(file_path))
30+
doc = workspace.get_maybe_document(uri)
31+
changes.append({
32+
'textDocument': {
33+
'uri': uri,
34+
'version': doc.version if doc else None
35+
},
36+
'edits': [
37+
{
38+
'range': {
39+
'start': {'line': 0, 'character': 0},
40+
'end': {
41+
'line': _num_lines(changed_file.get_new_code()),
42+
'character': 0,
43+
},
3844
},
39-
},
40-
'newText': changed_file.get_new_code(),
41-
}
42-
],
43-
})
44-
return {'documentChanges': changes}
45+
'newText': changed_file.get_new_code(),
46+
}
47+
],
48+
})
49+
return {'documentChanges': changes}
4550

4651

4752
def _num_lines(file_contents):

Diff for: pylsp/plugins/references.py

+15-14
Original file line numberDiff line numberDiff line change
@@ -8,19 +8,20 @@
88

99

1010
@hookimpl
11-
def pylsp_references(document, position, exclude_declaration=False):
12-
code_position = _utils.position_to_jedi_linecolumn(document, position)
13-
usages = document.jedi_script().get_references(**code_position)
11+
def pylsp_references(document, workspace, position, exclude_declaration=False):
12+
with workspace.report_progress("references"):
13+
code_position = _utils.position_to_jedi_linecolumn(document, position)
14+
usages = document.jedi_script().get_references(**code_position)
1415

15-
if exclude_declaration:
16-
# Filter out if the usage is the actual declaration of the thing
17-
usages = [d for d in usages if not d.is_definition()]
16+
if exclude_declaration:
17+
# Filter out if the usage is the actual declaration of the thing
18+
usages = [d for d in usages if not d.is_definition()]
1819

19-
# Filter out builtin modules
20-
return [{
21-
'uri': uris.uri_with(document.uri, path=str(d.module_path)) if d.module_path else document.uri,
22-
'range': {
23-
'start': {'line': d.line - 1, 'character': d.column},
24-
'end': {'line': d.line - 1, 'character': d.column + len(d.name)}
25-
}
26-
} for d in usages if not d.in_builtin_module()]
20+
# Filter out builtin modules
21+
return [{
22+
'uri': uris.uri_with(document.uri, path=str(d.module_path)) if d.module_path else document.uri,
23+
'range': {
24+
'start': {'line': d.line - 1, 'character': d.column},
25+
'end': {'line': d.line - 1, 'character': d.column + len(d.name)}
26+
}
27+
} for d in usages if not d.in_builtin_module()]

Diff for: pylsp/python_lsp.py

+7
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,7 @@ def _match_uri_to_workspace(self, uri):
228228
def _hook(self, hook_name, doc_uri=None, **kwargs):
229229
"""Calls hook_name and returns a list of results from all registered handlers"""
230230
workspace = self._match_uri_to_workspace(doc_uri)
231+
<<<<<<< Updated upstream
231232
progress_token = self.workspace.progress_begin(hook_name.removeprefix("pylsp_"))
232233

233234
doc = workspace.get_document(doc_uri) if doc_uri else None
@@ -236,6 +237,12 @@ def _hook(self, hook_name, doc_uri=None, **kwargs):
236237

237238
self.workspace.progress_end(progress_token)
238239
return result
240+
=======
241+
242+
doc = workspace.get_document(doc_uri) if doc_uri else None
243+
hook_handlers = self.config.plugin_manager.subset_hook_caller(hook_name, self.config.disabled_plugins)
244+
return hook_handlers(config=self.config, workspace=workspace, document=doc, **kwargs)
245+
>>>>>>> Stashed changes
239246

240247
def capabilities(self):
241248
server_capabilities = {

Diff for: pylsp/workspace.py

+17-4
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,12 @@
33

44
import io
55
import logging
6+
from contextlib import contextmanager
67
import os
78
import re
89
import uuid
910
import functools
10-
from typing import Optional
11+
from typing import Optional, Generator
1112
from threading import RLock
1213

1314
import jedi
@@ -112,7 +113,19 @@ def apply_edit(self, edit):
112113
def publish_diagnostics(self, doc_uri, diagnostics):
113114
self._endpoint.notify(self.M_PUBLISH_DIAGNOSTICS, params={'uri': doc_uri, 'diagnostics': diagnostics})
114115

115-
def progress_begin(self, title: str, message: Optional[str]=None, percentage: Optional[int]=None) -> str:
116+
@contextmanager
117+
def report_progress(self, title: str, message: Optional[str]=None, percentage: Optional[int] = None):
118+
token = self._progress_begin(title, message, percentage)
119+
120+
def progress_message(message: str, percentage: Optional[int]=None):
121+
self._progress_report(token, message, percentage)
122+
123+
try:
124+
yield progress_message
125+
finally:
126+
self._progress_end(token)
127+
128+
def _progress_begin(self, title: str, message: Optional[str]=None, percentage: Optional[int]=None) -> str:
116129
token = str(uuid.uuid4())
117130
value = {
118131
'kind': 'begin',
@@ -132,7 +145,7 @@ def progress_begin(self, title: str, message: Optional[str]=None, percentage: Op
132145
)
133146
return token
134147

135-
def progress_report(self, token: str, message: Optional[str]=None, percentage: Optional[int]=None) -> None:
148+
def _progress_report(self, token: str, message: Optional[str]=None, percentage: Optional[int]=None) -> None:
136149
value = {
137150
'kind': 'report',
138151
}
@@ -149,7 +162,7 @@ def progress_report(self, token: str, message: Optional[str]=None, percentage: O
149162
}
150163
)
151164

152-
def progress_end(self, token: str, message: Optional[str]=None) -> None:
165+
def _progress_end(self, token: str, message: Optional[str]=None) -> None:
153166
value = {
154167
'kind': 'end',
155168
}

0 commit comments

Comments
 (0)