Skip to content

Commit 8c49df5

Browse files
committed
optimize hover, goto and signature of imports
1 parent 0966e83 commit 8c49df5

File tree

5 files changed

+150
-47
lines changed

5 files changed

+150
-47
lines changed

robotcode/language_server/robotframework/diagnostics/imports_manager.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -809,7 +809,7 @@ async def _get_libdoc() -> VariablesDoc:
809809

810810
@_logger.call
811811
async def find_file(self, name: str, base_dir: str, file_type: str = "Resource") -> str:
812-
return await asyncio.wait_for(
812+
result = await asyncio.wait_for(
813813
asyncio.get_running_loop().run_in_executor(
814814
self.process_pool,
815815
find_file,
@@ -824,6 +824,8 @@ async def find_file(self, name: str, base_dir: str, file_type: str = "Resource")
824824
FIND_FILE_TIME_OUT,
825825
)
826826

827+
return result
828+
827829
@_logger.call
828830
async def _get_entry_for_resource_import(self, name: str, base_dir: str, sentinel: Any = None) -> _ResourcesEntry:
829831
source = await self.find_file(name, base_dir)

robotcode/language_server/robotframework/diagnostics/namespace.py

Lines changed: 52 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -379,6 +379,7 @@ def __init__(
379379
self._library_doc: Optional[LibraryDoc] = None
380380
self._library_doc_lock = Lock()
381381
self._imports: Optional[List[Import]] = None
382+
self._import_entries: OrderedDict[Import, LibraryEntry] = OrderedDict()
382383
self._own_variables: Optional[List[VariableDefinition]] = None
383384
self._own_variables_lock = Lock()
384385
self._diagnostics: List[Diagnostic] = []
@@ -431,6 +432,7 @@ async def invalidate(self) -> None:
431432
self._resources_matchers = None
432433
self._variables = OrderedDict()
433434
self._imports = None
435+
self._import_entries = OrderedDict()
434436
self._own_variables = None
435437
self._keywords = None
436438
self._library_doc = None
@@ -489,6 +491,7 @@ class DataEntry(NamedTuple):
489491
resources: OrderedDict[str, ResourceEntry] = OrderedDict()
490492
variables: OrderedDict[str, VariablesEntry] = OrderedDict()
491493
diagnostics: List[Diagnostic] = []
494+
import_entries: OrderedDict[Import, LibraryEntry] = OrderedDict()
492495

493496
@_logger.call
494497
async def ensure_initialized(self) -> bool:
@@ -525,6 +528,7 @@ async def ensure_initialized(self) -> bool:
525528
self._resources = data_entry.resources.copy()
526529
self._variables = data_entry.variables.copy()
527530
self._diagnostics = data_entry.diagnostics.copy()
531+
self._import_entries = data_entry.import_entries.copy()
528532
else:
529533
await self._import_default_libraries()
530534
await self._import_imports(imports, str(Path(self.source).parent), top_level=True)
@@ -537,6 +541,7 @@ async def ensure_initialized(self) -> bool:
537541
self._resources.copy(),
538542
self._variables.copy(),
539543
self._diagnostics.copy(),
544+
self._import_entries.copy(),
540545
),
541546
)
542547

@@ -631,6 +636,8 @@ async def _import(value: Import) -> Optional[LibraryEntry]:
631636
result.import_range = value.range()
632637
result.import_source = value.source
633638

639+
self._import_entries[value] = result
640+
634641
if (
635642
top_level
636643
and result.library_doc.errors is None
@@ -657,6 +664,8 @@ async def _import(value: Import) -> Optional[LibraryEntry]:
657664
result.import_range = value.range()
658665
result.import_source = value.source
659666

667+
self._import_entries[value] = result
668+
660669
if top_level and (
661670
not result.library_doc.errors
662671
and top_level
@@ -674,7 +683,6 @@ async def _import(value: Import) -> Optional[LibraryEntry]:
674683
)
675684

676685
elif isinstance(value, VariablesImport):
677-
# TODO: variables
678686

679687
if value.name is None:
680688
raise NameSpaceError("Variables setting requires value.")
@@ -683,6 +691,8 @@ async def _import(value: Import) -> Optional[LibraryEntry]:
683691

684692
result.import_range = value.range()
685693
result.import_source = value.source
694+
695+
self._import_entries[value] = result
686696
else:
687697
raise DiagnosticsError("Unknown import type.")
688698

@@ -950,6 +960,21 @@ async def _get_library_entry(
950960

951961
return LibraryEntry(name=library_doc.name, import_name=name, library_doc=library_doc, args=args, alias=alias)
952962

963+
@_logger.call
964+
async def get_imported_library_libdoc(
965+
self, name: str, args: Tuple[str, ...] = (), alias: Optional[str] = None
966+
) -> Optional[LibraryDoc]:
967+
await self.ensure_initialized()
968+
969+
return next(
970+
(
971+
v.library_doc
972+
for e, v in self._import_entries.items()
973+
if isinstance(e, LibraryImport) and v.import_name == name and v.args == args and v.alias == alias
974+
),
975+
None,
976+
)
977+
953978
@_logger.call
954979
async def _get_resource_entry(self, name: str, base_dir: str, sentinel: Any = None) -> ResourceEntry:
955980
namespace = await self.imports_manager.get_namespace_for_resource_import(name, base_dir, sentinel=sentinel)
@@ -963,6 +988,19 @@ async def _get_resource_entry(self, name: str, base_dir: str, sentinel: Any = No
963988
variables=await namespace.get_own_variables(),
964989
)
965990

991+
@_logger.call
992+
async def get_imported_resource_libdoc(self, name: str) -> Optional[LibraryDoc]:
993+
await self.ensure_initialized()
994+
995+
return next(
996+
(
997+
v.library_doc
998+
for e, v in self._import_entries.items()
999+
if isinstance(e, ResourceImport) and v.import_name == name
1000+
),
1001+
None,
1002+
)
1003+
9661004
@_logger.call
9671005
async def _get_variables_entry(
9681006
self,
@@ -979,6 +1017,19 @@ async def _get_variables_entry(
9791017
name=library_doc.name, import_name=name, library_doc=library_doc, args=args, variables=library_doc.variables
9801018
)
9811019

1020+
@_logger.call
1021+
async def get_imported_variables_libdoc(self, name: str, args: Tuple[str, ...] = ()) -> Optional[LibraryDoc]:
1022+
await self.ensure_initialized()
1023+
1024+
return next(
1025+
(
1026+
v.library_doc
1027+
for e, v in self._import_entries.items()
1028+
if isinstance(e, VariablesImport) and v.import_name == name and v.args == args
1029+
),
1030+
None,
1031+
)
1032+
9821033
@_logger.call
9831034
async def get_keywords(self) -> List[KeywordDoc]:
9841035
if self._keywords is None:

robotcode/language_server/robotframework/parts/goto.py

Lines changed: 28 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -289,10 +289,18 @@ async def definition_LibraryImport( # noqa: N802
289289
return None
290290

291291
try:
292-
libdoc = await namespace.imports_manager.get_libdoc_for_library_import(
293-
library_node.name, library_node.args, str(document.uri.to_path().parent)
292+
libdoc = await namespace.get_imported_library_libdoc(
293+
library_node.name, library_node.args, library_node.alias
294294
)
295295

296+
if libdoc is None or libdoc.errors:
297+
libdoc = await namespace.imports_manager.get_libdoc_for_library_import(
298+
str(library_node.name), (), str(document.uri.to_path().parent)
299+
)
300+
301+
if libdoc is None:
302+
return None
303+
296304
python_source = libdoc.source_or_origin
297305
if python_source is not None:
298306
return [
@@ -328,9 +336,15 @@ async def definition_ResourceImport( # noqa: N802
328336
return None
329337

330338
try:
331-
libdoc = await namespace.imports_manager.get_libdoc_for_resource_import(
332-
resource_node.name, str(document.uri.to_path().parent)
333-
)
339+
libdoc = await namespace.get_imported_resource_libdoc(resource_node.name)
340+
341+
if libdoc is None or libdoc.errors:
342+
libdoc = await namespace.imports_manager.get_libdoc_for_resource_import(
343+
str(resource_node.name), str(document.uri.to_path().parent)
344+
)
345+
346+
if libdoc is None:
347+
return None
334348

335349
python_source = libdoc.source_or_origin
336350
if python_source is not None:
@@ -367,9 +381,15 @@ async def definition_VariablesImport( # noqa: N802
367381
return None
368382

369383
try:
370-
libdoc = await namespace.imports_manager.get_libdoc_for_variables_import(
371-
variables_node.name, variables_node.args, str(document.uri.to_path().parent)
372-
)
384+
libdoc = await namespace.get_imported_variables_libdoc(variables_node.name, variables_node.args)
385+
386+
if libdoc is None or libdoc.errors:
387+
libdoc = await namespace.imports_manager.get_libdoc_for_variables_import(
388+
str(variables_node.name), (), str(document.uri.to_path().parent)
389+
)
390+
391+
if libdoc is None:
392+
return None
373393

374394
python_source = libdoc.source_or_origin
375395
if python_source is not None:

robotcode/language_server/robotframework/parts/hover.py

Lines changed: 49 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -231,17 +231,25 @@ async def hover_LibraryImport( # noqa: N802
231231
return None
232232

233233
try:
234-
libdoc = await namespace.imports_manager.get_libdoc_for_library_import(
235-
library_node.name, library_node.args, str(document.uri.to_path().parent)
234+
libdoc = await namespace.get_imported_library_libdoc(
235+
library_node.name, library_node.args, library_node.alias
236236
)
237-
if not libdoc.errors:
238-
return Hover(
239-
contents=MarkupContent(
240-
kind=MarkupKind.MARKDOWN,
241-
value=libdoc.to_markdown(),
242-
),
243-
range=range_from_token_or_node(library_node, name_token),
237+
238+
if libdoc is None or libdoc.errors:
239+
libdoc = await namespace.imports_manager.get_libdoc_for_library_import(
240+
str(library_node.name), (), str(document.uri.to_path().parent)
244241
)
242+
243+
if libdoc is None or libdoc.errors:
244+
return None
245+
246+
return Hover(
247+
contents=MarkupContent(
248+
kind=MarkupKind.MARKDOWN,
249+
value=libdoc.to_markdown(),
250+
),
251+
range=range_from_token_or_node(library_node, name_token),
252+
)
245253
except (SystemExit, KeyboardInterrupt, asyncio.CancelledError):
246254
raise
247255
except BaseException:
@@ -267,17 +275,23 @@ async def hover_ResourceImport( # noqa: N802
267275
return None
268276

269277
try:
270-
libdoc = await namespace.imports_manager.get_libdoc_for_resource_import(
271-
resource_node.name, str(document.uri.to_path().parent)
272-
)
273-
if not libdoc.errors:
274-
return Hover(
275-
contents=MarkupContent(
276-
kind=MarkupKind.MARKDOWN,
277-
value=libdoc.to_markdown(),
278-
),
279-
range=range_from_token_or_node(resource_node, name_token),
278+
libdoc = await namespace.get_imported_resource_libdoc(resource_node.name)
279+
280+
if libdoc is None or libdoc.errors:
281+
libdoc = await namespace.imports_manager.get_libdoc_for_resource_import(
282+
str(resource_node.name), str(document.uri.to_path().parent)
280283
)
284+
285+
if libdoc is None or libdoc.errors:
286+
return None
287+
288+
return Hover(
289+
contents=MarkupContent(
290+
kind=MarkupKind.MARKDOWN,
291+
value=libdoc.to_markdown(),
292+
),
293+
range=range_from_token_or_node(resource_node, name_token),
294+
)
281295
except (SystemExit, KeyboardInterrupt, asyncio.CancelledError):
282296
raise
283297
except BaseException:
@@ -303,17 +317,23 @@ async def hover_VariablesImport( # noqa: N802
303317
return None
304318

305319
try:
306-
libdoc = await namespace.imports_manager.get_libdoc_for_variables_import(
307-
variables_node.name, variables_node.args, str(document.uri.to_path().parent)
308-
)
309-
if not libdoc.errors:
310-
return Hover(
311-
contents=MarkupContent(
312-
kind=MarkupKind.MARKDOWN,
313-
value=libdoc.to_markdown(),
314-
),
315-
range=range_from_token_or_node(variables_node, name_token),
320+
libdoc = await namespace.get_imported_variables_libdoc(variables_node.name, variables_node.args)
321+
322+
if libdoc is None or libdoc.errors:
323+
libdoc = await namespace.imports_manager.get_libdoc_for_variables_import(
324+
str(variables_node.name), (), str(document.uri.to_path().parent)
316325
)
326+
327+
if libdoc is None or libdoc.errors:
328+
return None
329+
330+
return Hover(
331+
contents=MarkupContent(
332+
kind=MarkupKind.MARKDOWN,
333+
value=libdoc.to_markdown(),
334+
),
335+
range=range_from_token_or_node(variables_node, name_token),
336+
)
317337
except (SystemExit, KeyboardInterrupt, asyncio.CancelledError):
318338
raise
319339
except BaseException:

robotcode/language_server/robotframework/parts/signature_help.py

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
SignatureInformation,
2828
)
2929
from ...common.text_document import TextDocument
30-
from ..diagnostics.library_doc import KeywordDoc
30+
from ..diagnostics.library_doc import KeywordDoc, LibraryDoc
3131
from ..utils.ast import (
3232
Token,
3333
get_node_at_position,
@@ -217,6 +217,10 @@ async def signature_help_LibraryImport( # noqa: N802
217217

218218
# TODO from robot.utils.escaping import split_from_equals
219219

220+
namespace = await self.parent.documents_cache.get_namespace(document)
221+
if namespace is None:
222+
return None
223+
220224
library_node = cast(LibraryImport, node)
221225

222226
if (
@@ -225,22 +229,28 @@ async def signature_help_LibraryImport( # noqa: N802
225229
):
226230
return None
227231

228-
with_name_token = next((v for v in library_node.tokens if v.value == "WITH NAME"), None)
229-
if with_name_token is not None and position >= range_from_token(with_name_token).start:
230-
return None
231-
232-
imports_manager = await self.parent.documents_cache.get_imports_manager(document)
232+
lib_doc: Optional[LibraryDoc] = None
233233
try:
234-
lib_doc = await imports_manager.get_libdoc_for_library_import(
235-
str(library_node.name), library_node.args, str(document.uri.to_path().parent)
234+
lib_doc = await namespace.get_imported_library_libdoc(
235+
library_node.name, library_node.args, library_node.alias
236236
)
237+
238+
if lib_doc is None or lib_doc.errors:
239+
lib_doc = await namespace.imports_manager.get_libdoc_for_library_import(
240+
str(library_node.name), (), str(document.uri.to_path().parent)
241+
)
242+
237243
if lib_doc is None:
238244
return None
239245
except (asyncio.CancelledError, SystemExit, KeyboardInterrupt):
240246
raise
241247
except BaseException:
242248
return None
243249

250+
with_name_token = next((v for v in library_node.tokens if v.value == "WITH NAME"), None)
251+
if with_name_token is not None and position >= range_from_token(with_name_token).start:
252+
return None
253+
244254
tokens_at_position = tokens_at_position = get_tokens_at_position(library_node, position)
245255
if not tokens_at_position:
246256
return None

0 commit comments

Comments
 (0)