Skip to content

Commit 96fbe90

Browse files
committed
perf(analyzer): restructured code for handling bdd prefixes
1 parent b622c42 commit 96fbe90

File tree

2 files changed

+45
-29
lines changed

2 files changed

+45
-29
lines changed

packages/robot/src/robotcode/robot/diagnostics/keyword_finder.py

Lines changed: 43 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import re
12
from itertools import chain
23
from typing import TYPE_CHECKING, Dict, Iterable, Iterator, List, NamedTuple, Optional, Sequence, Tuple
34

@@ -51,10 +52,11 @@ def __init__(self, namespace: "Namespace", library_doc: LibraryDoc) -> None:
5152
Optional[List[KeywordDoc]],
5253
],
5354
] = {}
54-
self.handle_bdd_style = True
55+
5556
self._all_keywords: Optional[List[LibraryEntry]] = None
5657
self._resource_keywords: Optional[List[ResourceEntry]] = None
5758
self._library_keywords: Optional[List[LibraryEntry]] = None
59+
self._bdd_prefix_regexp: Optional["re.Pattern[str]"] = None
5860

5961
def reset_diagnostics(self) -> None:
6062
self.diagnostics = []
@@ -70,17 +72,15 @@ def find_keyword(
7072
try:
7173
self.reset_diagnostics()
7274

73-
self.handle_bdd_style = handle_bdd_style
74-
75-
cached = self._cache.get((name, self.handle_bdd_style), None)
75+
cached = self._cache.get((name, handle_bdd_style), None)
7676

7777
if cached is not None:
7878
self.diagnostics = cached[1]
7979
self.multiple_keywords_result = cached[2]
8080
return cached[0]
8181

8282
try:
83-
result = self._find_keyword(name)
83+
result = self._find_keyword(name, handle_bdd_style)
8484
if result is None:
8585
self.diagnostics.append(
8686
DiagnosticsEntry(
@@ -99,7 +99,7 @@ def find_keyword(
9999
result = None
100100
self.diagnostics.append(DiagnosticsEntry(str(e), DiagnosticSeverity.ERROR, Error.KEYWORD_ERROR))
101101

102-
self._cache[(name, self.handle_bdd_style)] = (
102+
self._cache[(name, handle_bdd_style)] = (
103103
result,
104104
self.diagnostics,
105105
self.multiple_keywords_result,
@@ -109,7 +109,11 @@ def find_keyword(
109109
except CancelSearchError:
110110
return None
111111

112-
def _find_keyword(self, name: Optional[str]) -> Optional[KeywordDoc]:
112+
def _find_keyword(
113+
self,
114+
name: Optional[str],
115+
handle_bdd_style: bool = True,
116+
) -> Optional[KeywordDoc]:
113117
if not name:
114118
self.diagnostics.append(
115119
DiagnosticsEntry(
@@ -129,14 +133,21 @@ def _find_keyword(self, name: Optional[str]) -> Optional[KeywordDoc]:
129133
)
130134
raise CancelSearchError
131135

132-
result = self._get_keyword_from_self(name)
136+
result: Optional[KeywordDoc] = None
137+
138+
if get_robot_version() >= (7, 0) and handle_bdd_style:
139+
result = self._get_bdd_style_keyword(name)
140+
141+
if not result:
142+
result = self._get_keyword_from_self(name)
143+
133144
if not result and "." in name:
134145
result = self._get_explicit_keyword(name)
135146

136147
if not result:
137148
result = self._get_implicit_keyword(name)
138149

139-
if not result and self.handle_bdd_style:
150+
if get_robot_version() < (7, 0) and not result and handle_bdd_style:
140151
return self._get_bdd_style_keyword(name)
141152

142153
return result
@@ -264,6 +275,9 @@ def _prioritize_same_file_or_public(
264275
def _select_best_matches(
265276
self, entries: List[Tuple[Optional[LibraryEntry], KeywordDoc]]
266277
) -> List[Tuple[Optional[LibraryEntry], KeywordDoc]]:
278+
if len(entries) < 2:
279+
return entries
280+
267281
normal = [hand for hand in entries if not hand[1].is_embedded]
268282
if normal:
269283
return normal
@@ -438,21 +452,25 @@ def _create_custom_and_standard_keyword_conflict_warning_message(
438452
f"or '{'' if standard[0] is None else standard[0].alias or standard[0].name}.{standard[1].name}'."
439453
)
440454

441-
def _get_bdd_style_keyword(self, name: str) -> Optional[KeywordDoc]:
442-
if get_robot_version() < (6, 0):
443-
lower = name.lower()
444-
for prefix in ["given ", "when ", "then ", "and ", "but "]:
445-
if lower.startswith(prefix):
446-
return self._find_keyword(name[len(prefix) :])
447-
return None
455+
@property
456+
def bdd_prefix_regexp(self) -> "re.Pattern[str]":
457+
if not self._bdd_prefix_regexp:
458+
prefixes = (
459+
"|".join(
460+
self.namespace.languages.bdd_prefixes
461+
if self.namespace.languages is not None
462+
else ["given", "when", "then", "and", "but"]
463+
)
464+
.replace(" ", r"\s")
465+
.lower()
466+
)
467+
self._bdd_prefix_regexp = re.compile(rf"({prefixes})\s", re.IGNORECASE)
468+
return self._bdd_prefix_regexp
448469

449-
parts = name.split()
450-
if len(parts) < 2:
451-
return None
452-
for index in range(1, len(parts)):
453-
prefix = " ".join(parts[:index]).title()
454-
if prefix.title() in (
455-
self.namespace.languages.bdd_prefixes if self.namespace.languages is not None else DEFAULT_BDD_PREFIXES
456-
):
457-
return self._find_keyword(" ".join(parts[index:]))
470+
def _get_bdd_style_keyword(self, name: str) -> Optional[KeywordDoc]:
471+
match = self.bdd_prefix_regexp.match(name)
472+
if match:
473+
return self._find_keyword(
474+
name[match.end() :], handle_bdd_style=False if get_robot_version() >= (7, 0) else True
475+
)
458476
return None

packages/robot/src/robotcode/robot/diagnostics/library_doc.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -908,8 +908,7 @@ def _matchers(self) -> Dict[KeywordMatcher, KeywordDoc]:
908908
return self.__matchers
909909

910910
def __getitem__(self, key: str) -> KeywordDoc:
911-
key_matcher = KeywordMatcher(key)
912-
items = [(k, v) for k, v in self._matchers.items() if k == key_matcher]
911+
items = [(k, v) for k, v in self._matchers.items() if k == key]
913912

914913
if not items:
915914
raise KeyError
@@ -968,8 +967,7 @@ def get_all(self, key: str) -> List[KeywordDoc]:
968967
return list(self.iter_all(key))
969968

970969
def iter_all(self, key: str) -> Iterable[KeywordDoc]:
971-
key_matcher = KeywordMatcher(key)
972-
yield from (v for k, v in self._matchers.items() if k == key_matcher)
970+
yield from (v for k, v in self._matchers.items() if k == key)
973971

974972

975973
@dataclass

0 commit comments

Comments
 (0)