Skip to content

Commit e24603f

Browse files
committed
feat(robotlangserver): support for robot:private keywords for RF>6.0.0
Show warnings if you use a private keyword and prioritize not private keywords over private keywords
1 parent 29959ea commit e24603f

File tree

2 files changed

+60
-0
lines changed

2 files changed

+60
-0
lines changed

robotcode/language_server/robotframework/diagnostics/analyzer.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -465,6 +465,16 @@ async def _analyze_keyword_call(
465465
code="ReservedKeyword",
466466
)
467467

468+
if get_robot_version() >= (6, 0, 0) and result.is_resource_keyword and result.is_private():
469+
if self.namespace.source != result.source:
470+
await self.append_diagnostics(
471+
range=kw_range,
472+
message=f"Keyword '{result.longname}' is private and should only be called by"
473+
f" keywords in the same file.",
474+
severity=DiagnosticSeverity.WARNING,
475+
code="PrivateKeyword",
476+
)
477+
468478
if not isinstance(node, (Template, TestTemplate)):
469479
try:
470480
if result.arguments is not None:

robotcode/language_server/robotframework/diagnostics/namespace.py

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1783,6 +1783,49 @@ async def _get_implicit_keyword(self, name: str) -> Optional[KeywordDoc]:
17831783
result = await self._get_keyword_from_libraries(name)
17841784
return result
17851785

1786+
def _prioritize_same_file_or_public(
1787+
self, entries: List[Tuple[LibraryEntry, KeywordDoc]]
1788+
) -> List[Tuple[LibraryEntry, KeywordDoc]]:
1789+
1790+
matches = [h for h in entries if h[1].source == self.namespace.source]
1791+
if matches:
1792+
return matches
1793+
1794+
matches = [handler for handler in entries if not handler[1].is_private()]
1795+
1796+
return matches or entries
1797+
1798+
def _select_best_matches(
1799+
self, entries: List[Tuple[LibraryEntry, KeywordDoc]]
1800+
) -> List[Tuple[LibraryEntry, KeywordDoc]]:
1801+
1802+
normal = [hand for hand in entries if not hand[1].is_embedded]
1803+
if normal:
1804+
return normal
1805+
1806+
matches = [hand for hand in entries if not self._is_worse_match_than_others(hand, entries)]
1807+
return matches or entries
1808+
1809+
def _is_worse_match_than_others(
1810+
self, candidate: Tuple[LibraryEntry, KeywordDoc], alternatives: List[Tuple[LibraryEntry, KeywordDoc]]
1811+
) -> bool:
1812+
for other in alternatives:
1813+
if (
1814+
candidate[1] is not other[1]
1815+
and self._is_better_match(other, candidate)
1816+
and not self._is_better_match(candidate, other)
1817+
):
1818+
return True
1819+
return False
1820+
1821+
def _is_better_match(
1822+
self, candidate: Tuple[LibraryEntry, KeywordDoc], other: Tuple[LibraryEntry, KeywordDoc]
1823+
) -> bool:
1824+
return (
1825+
other[1].matcher.embedded_arguments.match(candidate[1].name) is not None
1826+
and candidate[1].matcher.embedded_arguments.match(other[1].name) is None
1827+
)
1828+
17861829
async def _get_keyword_from_resource_files(self, name: str) -> Optional[KeywordDoc]:
17871830
if self._resource_keywords is None:
17881831
self._resource_keywords = [v for v in chain(self.namespace._resources.values())]
@@ -1792,6 +1835,13 @@ async def _get_keyword_from_resource_files(self, name: str) -> Optional[KeywordD
17921835
]
17931836
if not found:
17941837
return None
1838+
if get_robot_version() >= (6, 0, 0):
1839+
if len(found) > 1:
1840+
found = self._prioritize_same_file_or_public(found)
1841+
1842+
if len(found) > 1:
1843+
found = self._select_best_matches(found)
1844+
17951845
if len(found) > 1:
17961846
found = await self._get_keyword_based_on_search_order(found)
17971847
if len(found) == 1:

0 commit comments

Comments
 (0)