Skip to content

Commit e13641e

Browse files
committed
fix(langserver): speedup diagnostics, unused references and codelenses updates
1 parent 189e22c commit e13641e

File tree

4 files changed

+68
-14
lines changed

4 files changed

+68
-14
lines changed

packages/language_server/src/robotcode/language_server/common/parts/diagnostics.py

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import functools
12
import itertools
23
import time
34
import uuid
@@ -75,6 +76,7 @@ class DiagnosticsData:
7576
version: Optional[int] = None
7677
future: Optional[Task[Any]] = None
7778
force: bool = False
79+
single: bool = False
7880

7981

8082
class DiagnosticsProtocolPart(LanguageServerProtocolPart):
@@ -174,6 +176,10 @@ def on_workspace_diagnostics_collect(sender: Any) -> None:
174176
def on_workspace_diagnostics_end(sender: Any) -> None:
175177
...
176178

179+
@event
180+
def on_workspace_diagnostics_break(sender: Any) -> None:
181+
...
182+
177183
def ensure_workspace_loaded(self) -> None:
178184
with self._workspace_load_lock:
179185
if not self._workspace_loaded and not self.workspace_loaded_event.is_set():
@@ -246,9 +252,12 @@ def run_workspace_diagnostics(self) -> None:
246252
doc
247253
for doc in self.parent.documents.documents
248254
if (
249-
(data := self.get_diagnostics_data(doc)).force
250-
or doc.version != data.version
251-
or data.future is None
255+
(
256+
(data := self.get_diagnostics_data(doc)).force
257+
or doc.version != data.version
258+
or data.future is None
259+
)
260+
and not data.single
252261
)
253262
],
254263
key=lambda d: not d.opened_in_editor,
@@ -276,6 +285,7 @@ def run_workspace_diagnostics(self) -> None:
276285
check_current_task_canceled()
277286

278287
if self._break_diagnostics_loop_event.is_set():
288+
self.on_workspace_diagnostics_break(self)
279289
break
280290

281291
done_something = True
@@ -333,6 +343,7 @@ def run_workspace_diagnostics(self) -> None:
333343
check_current_task_canceled()
334344

335345
if self._break_diagnostics_loop_event.is_set():
346+
self.on_workspace_diagnostics_break(self)
336347
break
337348

338349
mode = self.get_diagnostics_mode(document.uri)
@@ -393,23 +404,28 @@ def run_workspace_diagnostics(self) -> None:
393404
finally:
394405
self.on_workspace_diagnostics_end(self)
395406

407+
def _diagnostics_task_done(self, document: TextDocument, data: DiagnosticsData, t: Task[Any]) -> None:
408+
self._logger.debug(lambda: f"diagnostics for {document} task {'canceled' if t.cancelled() else 'ended'}")
409+
410+
data.force = data.single
411+
data.single = False
412+
if data.force:
413+
self.break_workspace_diagnostics_loop()
414+
396415
def create_document_diagnostics_task(
397416
self,
398417
document: TextDocument,
399418
single: bool,
400419
debounce: bool = True,
401420
send_diagnostics: bool = True,
402421
) -> Task[Any]:
403-
def done(t: Task[Any]) -> None:
404-
self._logger.debug(lambda: f"diagnostics for {document} {'canceled' if t.cancelled() else 'ended'}")
405-
406422
data = self.get_diagnostics_data(document)
407423

408424
if data.force or document.version != data.version or data.future is None:
409425
future = data.future
410426

411427
data.force = False
412-
428+
data.single = single
413429
if future is not None and not future.done():
414430
self._logger.debug(lambda: f"try to cancel diagnostics for {document}")
415431

@@ -424,7 +440,7 @@ def done(t: Task[Any]) -> None:
424440
send_diagnostics,
425441
)
426442

427-
data.future.add_done_callback(done)
443+
data.future.add_done_callback(functools.partial(self._diagnostics_task_done, document, data))
428444

429445
return data.future
430446

packages/language_server/src/robotcode/language_server/robotframework/diagnostics/imports_manager.py

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
List,
2121
Mapping,
2222
Optional,
23+
Set,
2324
Tuple,
2425
final,
2526
)
@@ -564,6 +565,11 @@ def __init__(
564565
self._executor_lock = threading.RLock()
565566
self._executor: Optional[ProcessPoolExecutor] = None
566567

568+
self._resource_document_changed_timer_lock = threading.RLock()
569+
self._resource_document_changed_timer: Optional[threading.Timer] = None
570+
self._resource_document_changed_timer_interval = 1
571+
self._resource_document_changed_documents: Set[TextDocument] = set()
572+
567573
def __del__(self) -> None:
568574
try:
569575
if self._executor is not None:
@@ -684,9 +690,32 @@ def _do_imports_changed(self, sender: Any, uri: DocumentUri) -> None:
684690

685691
@language_id("robotframework")
686692
def resource_document_changed(self, sender: Any, document: TextDocument) -> None:
687-
run_as_task(self._resource_document_changed, document)
693+
with self._resource_document_changed_timer_lock:
694+
if document in self._resource_document_changed_documents:
695+
return
696+
697+
if self._resource_document_changed_timer is not None:
698+
self._resource_document_changed_timer.cancel()
699+
self._resource_document_changed_timer = None
700+
701+
self._resource_document_changed_documents.add(document)
702+
703+
self._resource_document_changed_timer = threading.Timer(
704+
self._resource_document_changed_timer_interval, self.__resource_documents_changed
705+
)
706+
self._resource_document_changed_timer.start()
707+
708+
def __resource_documents_changed(self) -> None:
709+
with self._resource_document_changed_timer_lock:
710+
self._resource_document_changed_timer = None
711+
712+
documents = self._resource_document_changed_documents
713+
self._resource_document_changed_documents = set()
714+
715+
for document in documents:
716+
run_as_task(self.__resource_document_changed, document).result()
688717

689-
def _resource_document_changed(self, document: TextDocument) -> None:
718+
def __resource_document_changed(self, document: TextDocument) -> None:
690719
resource_changed: List[LibraryDoc] = []
691720

692721
with self._resources_lock:

packages/language_server/src/robotcode/language_server/robotframework/parts/references.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
from ...common.decorators import language_id
4242
from ...common.text_document import TextDocument
4343
from ..diagnostics.model_helper import ModelHelper
44+
from ..diagnostics.namespace import Namespace
4445
from .protocol_part import RobotLanguageServerProtocolPart
4546

4647
if TYPE_CHECKING:
@@ -65,6 +66,8 @@ def __init__(self, parent: "RobotLanguageServerProtocol") -> None:
6566

6667
parent.references.collect.add(self.collect)
6768
parent.documents.did_change.add(self.document_did_change)
69+
parent.documents_cache.namespace_invalidated(self.namespace_invalidated)
70+
parent.diagnostics.on_workspace_diagnostics_break.add(self.on_workspace_diagnostics_break)
6871

6972
@event
7073
def cache_cleared(sender) -> None:
@@ -84,6 +87,12 @@ def do_on_file_changed(self, sender: Any, files: List[FileEvent]) -> None:
8487
def document_did_change(self, sender: Any, document: TextDocument) -> None:
8588
self.clear_cache()
8689

90+
def namespace_invalidated(self, sender: Any, namespace: Namespace) -> None:
91+
self.clear_cache()
92+
93+
def on_workspace_diagnostics_break(self, sender: Any) -> None:
94+
self.clear_cache()
95+
8796
def clear_cache(self) -> None:
8897
self._keyword_reference_cache.clear()
8998
self._variable_reference_cache.clear()

tests/robotcode/language_server/robotframework/parts/data/.vscode/settings.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
// "--log",
1919
// "--log-level", "TRACE",
2020
],
21-
"robotcode.robocop.enabled": false,
21+
"robotcode.robocop.enabled": true,
2222
// "robotcode.debug.groupOutput": false,
2323
// "robotcode.robot.args": [
2424
// "-L", "TRACE"
@@ -28,9 +28,9 @@
2828
//"python.analysis.diagnosticMode": "workspace"
2929
//"robotcode.robot.paths": ["./tests", "./tests1"]
3030
"robotcode.analysis.referencesCodeLens": true,
31-
"robotcode.analysis.diagnosticMode": "workspace",
32-
"robotcode.analysis.progressMode": "simple",
33-
"robotcode.analysis.findUnusedReferences": true,
31+
"robotcode.analysis.diagnosticMode": "openFilesOnly",
32+
"robotcode.analysis.progressMode": "off",
33+
"robotcode.analysis.findUnusedReferences": false,
3434
"robotcode.analysis.cache.saveLocation": "workspaceFolder",
3535
"robotcode.analysis.cache.ignoredLibraries": [
3636
//"robot.libraries.Remote",

0 commit comments

Comments
 (0)