Skip to content

Commit a732b85

Browse files
committed
correct completion of bdd prefixes
1 parent 74ddd45 commit a732b85

File tree

3 files changed

+85
-10
lines changed

3 files changed

+85
-10
lines changed

robotcode/language_server/robotframework/diagnostics/namespace.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1431,11 +1431,12 @@ async def get_keywords(self) -> List[KeywordDoc]:
14311431
current_time = time.monotonic()
14321432
self._logger.debug("start collecting keywords")
14331433
try:
1434+
i = 0
1435+
14341436
await self.ensure_initialized()
14351437

14361438
result: Dict[KeywordMatcher, KeywordDoc] = {}
14371439

1438-
i = 0
14391440
async for doc in self.iter_all_keywords():
14401441
i += 1
14411442
result[KeywordMatcher(doc.name)] = doc

robotcode/language_server/robotframework/parts/completion.py

Lines changed: 44 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -466,6 +466,24 @@ async def create_testcase_settings_completion_items(self, range: Optional[Range]
466466
for setting in settings
467467
]
468468

469+
async def create_bdd_prefix_completion_items(self, range: Optional[Range]) -> List[CompletionItem]:
470+
prefixes = {"Given", "When", "Then", "And", "But"}
471+
472+
if self.namespace.languages is not None:
473+
prefixes.update(self.namespace.languages.bdd_prefixes)
474+
475+
return [
476+
CompletionItem(
477+
label=prefix,
478+
kind=CompletionItemKind.UNIT,
479+
detail="BDD Prefix",
480+
sort_text=f"080_{prefix}",
481+
insert_text_format=InsertTextFormat.PLAINTEXT,
482+
text_edit=TextEdit(range=range, new_text=f"{prefix} ") if range is not None else None,
483+
)
484+
for prefix in prefixes
485+
]
486+
469487
async def create_keyword_settings_completion_items(self, range: Optional[Range]) -> List[CompletionItem]:
470488
from robot.parsing.lexer.settings import KeywordSettings
471489

@@ -521,13 +539,30 @@ async def create_keyword_completion_items(
521539
add_reserverd: bool = True,
522540
add_none: bool = False,
523541
in_template: bool = False,
542+
add_bdd_prefixes: bool = True,
524543
) -> List[CompletionItem]:
525544
result: List[CompletionItem] = []
526545
if self.document is None:
527546
return []
528547

529548
r: Optional[Range] = None
530549

550+
has_bdd = False
551+
bdd_token = None
552+
553+
if token is not None:
554+
old_token = token
555+
bdd_token, token = self.split_bdd_prefix(self.namespace, token)
556+
557+
if token is not None and token.value == "":
558+
token = None
559+
560+
if bdd_token is not None and position.character > range_from_token(bdd_token).end.character:
561+
has_bdd = True
562+
563+
if not has_bdd and token is None:
564+
token = old_token
565+
531566
if token is not None:
532567
r = range_from_token(token)
533568

@@ -708,6 +743,11 @@ def enumerate_indexes(s: str, c: str) -> Iterator[int]:
708743
)
709744
)
710745

746+
if add_bdd_prefixes and not has_bdd:
747+
result += await self.create_bdd_prefix_completion_items(
748+
range_from_token(token) if token is not None else None
749+
)
750+
711751
if add_reserverd:
712752
for k in get_reserved_keywords():
713753
result.append(
@@ -934,8 +974,6 @@ async def _complete_TestCase_or_Keyword( # noqa: N802
934974
if len(statement_node.tokens) > index:
935975
token = statement_node.tokens[index]
936976

937-
token = self.strip_bdd_prefix(self.namespace, token)
938-
939977
r = range_from_token(token)
940978
if position.is_in_range(r):
941979
return await create_items(in_assign, in_template, r, token, position)
@@ -952,7 +990,7 @@ async def _complete_TestCase_or_Keyword( # noqa: N802
952990
in_assign,
953991
in_template,
954992
r,
955-
None if self.is_bdd_token(self.namespace, token) else token,
993+
token,
956994
position,
957995
)
958996

@@ -1080,7 +1118,7 @@ async def _complete_SuiteSetup_or_SuiteTeardown_or_TestTemplate( # noqa: N802
10801118
r = range_from_token(token)
10811119
if position.is_in_range(r):
10821120
return await self.create_keyword_completion_items(
1083-
None if self.is_bdd_token(self.namespace, token) else token,
1121+
token,
10841122
position,
10851123
add_reserverd=False,
10861124
add_none=True,
@@ -1096,7 +1134,7 @@ async def _complete_SuiteSetup_or_SuiteTeardown_or_TestTemplate( # noqa: N802
10961134
r.end.character += 1
10971135
if position.is_in_range(r):
10981136
return await self.create_keyword_completion_items(
1099-
None if self.is_bdd_token(self.namespace, token) else token,
1137+
token,
11001138
position,
11011139
add_reserverd=False,
11021140
add_none=True,
@@ -1223,7 +1261,7 @@ async def complete_Setup_or_Teardown_or_Template( # noqa: N802
12231261
r.end.character += 1
12241262
if position.is_in_range(r):
12251263
return await self.create_keyword_completion_items(
1226-
None if self.is_bdd_token(self.namespace, token) else token,
1264+
token,
12271265
position,
12281266
add_reserverd=False,
12291267
add_none=True,

robotcode/language_server/robotframework/parts/model_helper.py

Lines changed: 39 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -492,6 +492,41 @@ def get_expression_statement_types(cls) -> Tuple[Type[Any]]:
492492
BDD_TOKEN_REGEX = re.compile(r"^(Given|When|Then|And|But)\s", flags=re.IGNORECASE)
493493
BDD_TOKEN = re.compile(r"^(Given|When|Then|And|But)$", flags=re.IGNORECASE)
494494

495+
@classmethod
496+
def split_bdd_prefix(cls, namespace: Namespace, token: Token) -> Tuple[Optional[Token], Optional[Token]]:
497+
from robot.parsing.lexer import Token as RobotToken
498+
499+
bdd_token = None
500+
501+
parts = token.value.split(maxsplit=1)
502+
if len(parts) < 1:
503+
return None, token
504+
505+
prefix = parts[0]
506+
if prefix.title() in (
507+
namespace.languages.bdd_prefixes
508+
if namespace.languages is not None
509+
else {"Given ", "When ", "Then ", "And ", "But "}
510+
):
511+
bdd_len = len(prefix)
512+
bdd_token = RobotToken(
513+
token.type,
514+
token.value[:bdd_len],
515+
token.lineno,
516+
token.col_offset,
517+
token.error,
518+
)
519+
520+
token = RobotToken(
521+
token.type,
522+
token.value[bdd_len + 1 :],
523+
token.lineno,
524+
token.col_offset + bdd_len + 1,
525+
token.error,
526+
)
527+
528+
return bdd_token, token
529+
495530
@classmethod
496531
def strip_bdd_prefix(cls, namespace: Namespace, token: Token) -> Token:
497532
from robot.parsing.lexer import Token as RobotToken
@@ -514,7 +549,7 @@ def strip_bdd_prefix(cls, namespace: Namespace, token: Token) -> Token:
514549
if len(parts) < 2:
515550
return token
516551

517-
prefix, _ = parts
552+
prefix = parts[0]
518553
if prefix.title() in (
519554
namespace.languages.bdd_prefixes
520555
if namespace.languages is not None
@@ -538,10 +573,11 @@ def is_bdd_token(cls, namespace: Namespace, token: Token) -> bool:
538573
return bool(bdd_match)
539574
else:
540575
parts = token.value.split(maxsplit=1)
541-
if len(parts) < 2:
576+
if len(parts) < 1:
542577
return False
543578

544-
prefix, _ = parts
579+
prefix = parts[0]
580+
545581
if prefix.title() in (
546582
namespace.languages.bdd_prefixes
547583
if namespace.languages is not None

0 commit comments

Comments
 (0)