Skip to content

Commit bdac340

Browse files
committed
implement find references for libraries, resources, variables import, refactor find references
1 parent bd78807 commit bdac340

File tree

7 files changed

+260
-89
lines changed

7 files changed

+260
-89
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ All notable changes to the "robotcode" extension will be documented in this file
66

77
### added
88

9+
- implement find references for libraries, resources, variables import
10+
911
## 0.4.2
1012

1113
### added

robotcode/language_server/common/lsp_types.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1073,6 +1073,11 @@ def extend(self, start_line: int = 0, start_character: int = 0, end_line: int =
10731073
end=Position(line=self.end.line + end_line, character=self.end.character + end_character),
10741074
)
10751075

1076+
def __contains__(self, x: object) -> bool:
1077+
if isinstance(x, Position):
1078+
return x.is_in_range(self)
1079+
return False
1080+
10761081

10771082
@dataclass(repr=False)
10781083
class TextDocumentItem(Model):

robotcode/language_server/robotframework/diagnostics/library_doc.py

Lines changed: 27 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -177,18 +177,24 @@ def __init__(self, name: str, extended: bool = False) -> None:
177177
from robot.utils.normalizing import normalize
178178
from robot.variables.search import VariableSearcher
179179

180+
self.name = name
181+
self.extended = extended
182+
180183
searcher = VariableSearcher("$@&%", ignore_errors=True)
181184
match = searcher.search(name)
182-
self.name = name
185+
183186
if match.base is None:
184187
raise InvalidVariableError(f"Invalid variable '{name}'")
185188

186189
self.base = match.base
187190

191+
self.extended_base: Optional[str] = None
192+
self.normalize_extended: Optional[str] = None
188193
if extended:
189194
ext_match = self._match_extended.match(self.name[2:-1])
190195
if ext_match is not None:
191-
self.base, _ = ext_match.groups()
196+
self.extended_base, _ = ext_match.groups()
197+
self.normalize_extended = str(normalize(self.extended_base, "_"))
192198

193199
self.normalized_name = str(normalize(self.base, "_"))
194200

@@ -197,16 +203,16 @@ def __eq__(self, o: object) -> bool:
197203
from robot.variables.search import VariableSearcher
198204

199205
if isinstance(o, VariableMatcher):
200-
base = o.base
206+
return o.normalized_name == self.normalized_name or (o.extended and self.normalized_name == o.extended_base)
201207
elif isinstance(o, str):
202208
searcher = VariableSearcher("$@&%", ignore_errors=True)
203209
match = searcher.search(o)
204210
base = match.base
211+
normalized = str(normalize(base, "_"))
212+
return self.normalized_name == normalized or (self.extended and self.normalize_extended == normalized)
205213
else:
206214
return False
207215

208-
return self.normalized_name == str(normalize(base, "_"))
209-
210216
def __hash__(self) -> int:
211217
return hash(self.normalized_name)
212218

@@ -475,11 +481,11 @@ class LibraryDoc(Model):
475481
line_no: int = -1
476482
end_line_no: int = -1
477483
inits: KeywordStore = KeywordStore()
478-
keywords: KeywordStore = KeywordStore()
484+
keywords: KeywordStore = field(default_factory=KeywordStore, compare=False)
479485
module_spec: Optional[ModuleSpec] = None
480-
errors: Optional[List[Error]] = None
486+
errors: Optional[List[Error]] = field(default=None, compare=False)
481487
python_path: Optional[List[str]] = None
482-
stdout: Optional[str] = None
488+
stdout: Optional[str] = field(default=None, compare=False)
483489
has_listener: Optional[bool] = None
484490

485491
@property
@@ -1123,10 +1129,15 @@ def get_test_library(
11231129
except BaseException:
11241130
pass
11251131

1132+
real_source = lib.source if lib is not None else source
11261133
libdoc = LibraryDoc(
11271134
name=library_name,
1128-
source=lib.source if lib is not None else source,
1129-
module_spec=module_spec,
1135+
source=real_source,
1136+
module_spec=module_spec
1137+
if module_spec is not None
1138+
and module_spec.origin != real_source
1139+
and module_spec.submodule_search_locations is None
1140+
else None,
11301141
python_path=sys.path,
11311142
type="LIBRARY",
11321143
)
@@ -1151,8 +1162,10 @@ def get_test_library(
11511162
source=kw[0].source,
11521163
line_no=kw[0].lineno,
11531164
type="library",
1154-
libname=kw[1].libname,
1155-
longname=kw[1].longname,
1165+
# libname=kw[1].libname,
1166+
# longname=kw[1].longname,
1167+
libname=libdoc.name,
1168+
longname=f"{libdoc.name}.{kw[0].name}",
11561169
doc_format=str(lib.doc_format) or DEFAULT_DOC_FORMAT,
11571170
is_initializer=True,
11581171
)
@@ -1187,8 +1200,8 @@ def get_test_library(
11871200
tags=tuple(kw[0].tags),
11881201
source=kw[0].source,
11891202
line_no=kw[0].lineno,
1190-
libname=kw[1].libname,
1191-
longname=kw[1].longname,
1203+
libname=libdoc.name,
1204+
longname=f"{libdoc.name}.{kw[0].name}",
11921205
is_embedded=is_embedded_keyword(kw[0].name),
11931206
doc_format=str(lib.doc_format) or DEFAULT_DOC_FORMAT,
11941207
is_error_handler=kw[1].is_error_handler,

robotcode/language_server/robotframework/diagnostics/namespace.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -475,6 +475,11 @@ async def get_resources_matchers(self) -> Dict[KeywordMatcher, ResourceEntry]:
475475
}
476476
return self._resources_matchers
477477

478+
async def get_imported_variables(self) -> OrderedDict[str, VariablesEntry]:
479+
await self.ensure_initialized()
480+
481+
return self._variables
482+
478483
@_logger.call
479484
async def get_library_doc(self) -> LibraryDoc:
480485
if self._library_doc is None:

robotcode/language_server/robotframework/parts/goto.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,13 +81,17 @@ async def run() -> Union[Location, List[Location], List[LocationLink], None]:
8181
if result_node is None:
8282
return None
8383

84+
result = await self._definition_default(result_nodes, document, position)
85+
if result:
86+
return result
87+
8488
method = self._find_method(type(result_node))
8589
if method is not None:
8690
result = await method(result_node, document, position)
8791
if result is not None:
8892
return result
8993

90-
return await self._definition_default(result_nodes, document, position)
94+
return None
9195

9296
return await run_coroutine_in_thread(run)
9397

robotcode/language_server/robotframework/parts/hover.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,14 +75,18 @@ async def run() -> Optional[Hover]:
7575
if not result_nodes:
7676
return None
7777

78+
result = await self._hover_default(result_nodes, document, position)
79+
if result:
80+
return result
81+
7882
for result_node in reversed(result_nodes):
7983
method = self._find_method(type(result_node))
8084
if method is not None:
8185
result = await method(result_node, document, position)
8286
if result is not None:
8387
return result
8488

85-
return await self._hover_default(result_nodes, document, position)
89+
return None
8690

8791
return await run_coroutine_in_thread(run)
8892

@@ -118,6 +122,7 @@ async def _hover_default(self, nodes: List[ast.AST], document: TextDocument, pos
118122
),
119123
range=range,
120124
)
125+
121126
except (SystemExit, KeyboardInterrupt, asyncio.CancelledError):
122127
raise
123128
except BaseException:

0 commit comments

Comments
 (0)