Skip to content

Commit

Permalink
update reference if files created, deleted, changes
Browse files Browse the repository at this point in the history
  • Loading branch information
d-biehl committed Nov 14, 2022
1 parent 95804ee commit 9e8425d
Show file tree
Hide file tree
Showing 5 changed files with 72 additions and 15 deletions.
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ All notable changes to the "robotcode" extension will be documented in this file

## [Unreleased]

- Optimize reference code lenses.
- Optimize reference handling.
- This allows updating references when creating and deleting files, if necessary.

## 0.14.4

Expand Down
18 changes: 16 additions & 2 deletions robotcode/language_server/common/parts/code_lens.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
from __future__ import annotations

import asyncio
from asyncio import CancelledError
from typing import TYPE_CHECKING, Any, List, Optional

from ....jsonrpc2.protocol import rpc_method
from ....utils.async_tools import async_tasking_event, threaded
from ....utils.async_tools import async_tasking_event, create_sub_task, threaded
from ....utils.logging import LoggingDescriptor
from ..decorators import language_id_filter
from ..has_extend_capabilities import HasExtendCapabilities
Expand All @@ -29,6 +30,7 @@ class CodeLensProtocolPart(LanguageServerProtocolPart, HasExtendCapabilities):

def __init__(self, parent: LanguageServerProtocol) -> None:
super().__init__(parent)
self.refresh_task: Optional[asyncio.Task[Any]] = None

@async_tasking_event
async def collect(sender, document: TextDocument) -> Optional[List[CodeLens]]: # NOSONAR
Expand Down Expand Up @@ -86,7 +88,19 @@ async def _code_lens_resolve(self, params: CodeLens, *args: Any, **kwargs: Any)

return params

async def refresh(self) -> None:
async def __do_refresh(self, now: bool = False) -> None:
if not now:
await asyncio.sleep(1)

await self.__refresh()

async def refresh(self, now: bool = False) -> None:
if self.refresh_task is not None and not self.refresh_task.done():
self.refresh_task.get_loop().call_soon_threadsafe(self.refresh_task.cancel)

self.refresh_task = create_sub_task(self.__do_refresh(now), loop=self.parent.diagnostics.diagnostics_loop)

async def __refresh(self) -> None:
if not (
self.parent.client_capabilities is not None
and self.parent.client_capabilities.workspace is not None
Expand Down
9 changes: 2 additions & 7 deletions robotcode/language_server/robotframework/parts/codelens.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,9 @@ def __init__(self, parent: RobotLanguageServerProtocol) -> None:
self._running_task: Set[Tuple[TextDocument, KeywordDoc]] = set()

parent.diagnostics.on_workspace_loaded.add(self.codelens_refresh)
parent.robot_references.cache_cleared.add(self.codelens_refresh)

@language_id("robotframework")
async def codelens_refresh(self, sender: Any) -> None: # NOSONAR
await self.parent.code_lens.refresh()

Expand Down Expand Up @@ -124,13 +126,6 @@ async def find_refs() -> None:
if document is None or kw_doc is None:
return

# await run_coroutine_in_thread(
# self.parent.robot_references.find_keyword_references,
# document,
# kw_doc,
# include_declaration=False,
# )

await self.parent.robot_references.find_keyword_references(
document, kw_doc, include_declaration=False
)
Expand Down
35 changes: 31 additions & 4 deletions robotcode/language_server/robotframework/parts/references.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,21 @@
from ....utils.logging import LoggingDescriptor
from ....utils.uri import Uri
from ...common.decorators import language_id
from ...common.lsp_types import Location, Position, ReferenceContext
from ...common.lsp_types import (
FileEvent,
Location,
Position,
ReferenceContext,
WatchKind,
)
from ...common.text_document import TextDocument
from ..diagnostics.entities import LocalVariableDefinition, VariableDefinition
from ..diagnostics.library_doc import KeywordDoc, LibraryDoc
from ..diagnostics.library_doc import (
RESOURCE_FILE_EXTENSION,
ROBOT_FILE_EXTENSION,
KeywordDoc,
LibraryDoc,
)
from ..utils.ast_utils import (
HasTokens,
get_nodes_at_position,
Expand All @@ -47,18 +58,34 @@ class RobotReferencesProtocolPart(RobotLanguageServerProtocolPart, ModelHelperMi
def __init__(self, parent: RobotLanguageServerProtocol) -> None:
super().__init__(parent)

parent.references.collect.add(self.collect)
parent.documents.did_change.add(self.document_did_change)
self._keyword_reference_cache = AsyncSimpleLRUCache(max_items=None)
self._variable_reference_cache = AsyncSimpleLRUCache(max_items=None)

parent.on_initialized.add(self.on_initialized)

parent.references.collect.add(self.collect)
parent.documents.did_change.add(self.document_did_change)

@async_event
async def cache_cleared(sender) -> None: # NOSONAR
...

async def on_initialized(self, sender: Any) -> None:
await self.parent.workspace.add_file_watcher(
self.on_file_changed,
f"**/*.{{{ROBOT_FILE_EXTENSION[1:]},{RESOURCE_FILE_EXTENSION[1:]}}}",
WatchKind.CREATE | WatchKind.DELETE,
)

async def on_file_changed(self, sender: Any, files: List[FileEvent]) -> None:
await self.clear_cache()

@language_id("robotframework")
@threaded()
async def document_did_change(self, sender: Any, document: TextDocument) -> None:
await self.clear_cache()

async def clear_cache(self) -> None:
await self._keyword_reference_cache.clear()
await self._variable_reference_cache.clear()

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@
from ....utils.async_tools import Event, threaded
from ....utils.glob_path import iter_files
from ....utils.logging import LoggingDescriptor
from ....utils.uri import Uri
from ....utils.uri import InvalidUriError, Uri
from ...common.decorators import language_id
from ...common.lsp_types import FileChangeType, FileEvent, WatchKind
from ...common.parts.diagnostics import (
AnalysisProgressMode,
DiagnosticsMode,
Expand Down Expand Up @@ -35,8 +36,27 @@ def __init__(self, parent: RobotLanguageServerProtocol) -> None:
self.parent.diagnostics.load_workspace_documents.add(self._load_workspace_documents)
self.parent.diagnostics.on_get_diagnostics_mode.add(self.on_get_diagnostics_mode)
self.parent.diagnostics.on_get_analysis_progress_mode.add(self.on_get_analysis_progress_mode)
self.parent.on_initialized.add(self.on_initialized)
self.workspace_loaded = Event()

async def on_initialized(self, sender: Any) -> None:
await self.parent.workspace.add_file_watcher(
self.on_file_changed, f"**/*.{{{ROBOT_FILE_EXTENSION[1:]},{RESOURCE_FILE_EXTENSION[1:]}}}", WatchKind.CREATE
)

async def on_file_changed(self, sender: Any, files: List[FileEvent]) -> None: #
for fe in [f for f in files if f.type == FileChangeType.CREATED]:
doc_uri = Uri(fe.uri)
try:
path = doc_uri.to_path()
if path.suffix in [ROBOT_FILE_EXTENSION, RESOURCE_FILE_EXTENSION]:
document = await self.parent.documents.get_or_open_document(path, "robotframework")
if not document.opened_in_editor:
await (await self.parent.documents_cache.get_namespace(document)).ensure_initialized()

except InvalidUriError:
pass

@language_id("robotframework")
async def _on_read_document_text(self, sender: Any, uri: Uri) -> Optional[str]:
from robot.utils import FileReader
Expand Down

0 comments on commit 9e8425d

Please sign in to comment.