Skip to content

Commit fdba5b9

Browse files
committed
feat: new code action refactor rewrite: surroundings for TRY/EXCEPT/FINALLY
1 parent 19ed3e1 commit fdba5b9

File tree

8 files changed

+445
-50
lines changed

8 files changed

+445
-50
lines changed

packages/core/src/robotcode/core/lsp/types.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3993,8 +3993,8 @@ def __contains__(self, x: object) -> bool:
39933993
return x.is_in_range(self)
39943994
return False
39953995

3996-
def is_in_range(self, range: Range) -> bool:
3997-
return self.start.is_in_range(range) and self.end.is_in_range(range)
3996+
def is_in_range(self, range: Range, include_end: bool = True) -> bool:
3997+
return self.start.is_in_range(range, include_end) and self.end.is_in_range(range, include_end)
39983998

39993999
def __hash__(self) -> int:
40004000
return hash((self.start, self.end))

packages/language_server/src/robotcode/language_server/robotframework/diagnostics/errors.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
class Error:
88
VARIABLE_NOT_FOUND = "VariableNotFound"
99
ENVIROMMENT_VARIABLE_NOT_FOUND = "EnvirommentVariableNotFound"
10-
KEYWORD_NOT_FOUND = "KeywordNotFoundError"
10+
KEYWORD_NOT_FOUND = "KeywordNotFound"
1111
LIBRARY_CONTAINS_NO_KEYWORDS = "LibraryContainsNoKeywords"
1212
POSSIBLE_CIRCULAR_IMPORT = "PossibleCircularImport"
1313
RESOURCE_EMPTY = "ResourceEmpty"
@@ -28,3 +28,4 @@ class Error:
2828
KEYWORD_CONTAINS_NORMAL_AND_EMBBEDED_ARGUMENTS = "KeywordContainsNormalAndEmbbededArguments"
2929
DEPRECATED_HYPHEN_TAG = "DeprecatedHyphenTag"
3030
IMPORT_REQUIRES_VALUE = "ImportRequiresValue"
31+
KEYWORD_ERROR = "KeywordError"

packages/language_server/src/robotcode/language_server/robotframework/diagnostics/namespace.py

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1720,7 +1720,7 @@ def find_keyword(
17201720
DiagnosticsEntry(
17211721
f"No keyword with name '{name}' found.",
17221722
DiagnosticSeverity.ERROR,
1723-
"KeywordNotFoundError",
1723+
Error.KEYWORD_NOT_FOUND,
17241724
)
17251725
)
17261726
except KeywordError as e:
@@ -1731,7 +1731,7 @@ def find_keyword(
17311731
raise
17321732

17331733
result = None
1734-
self.diagnostics.append(DiagnosticsEntry(str(e), DiagnosticSeverity.ERROR, "KeywordError"))
1734+
self.diagnostics.append(DiagnosticsEntry(str(e), DiagnosticSeverity.ERROR, Error.KEYWORD_ERROR))
17351735

17361736
self._cache[(name, self.handle_bdd_style)] = (result, self.diagnostics, self.multiple_keywords_result)
17371737

@@ -1742,12 +1742,12 @@ def find_keyword(
17421742
def _find_keyword(self, name: Optional[str]) -> Optional[KeywordDoc]:
17431743
if not name:
17441744
self.diagnostics.append(
1745-
DiagnosticsEntry("Keyword name cannot be empty.", DiagnosticSeverity.ERROR, "KeywordError")
1745+
DiagnosticsEntry("Keyword name cannot be empty.", DiagnosticSeverity.ERROR, Error.KEYWORD_ERROR)
17461746
)
17471747
raise CancelSearchError
17481748
if not isinstance(name, str):
17491749
self.diagnostics.append( # type: ignore
1750-
DiagnosticsEntry("Keyword name must be a string.", DiagnosticSeverity.ERROR, "KeywordError")
1750+
DiagnosticsEntry("Keyword name must be a string.", DiagnosticSeverity.ERROR, Error.KEYWORD_ERROR)
17511751
)
17521752
raise CancelSearchError
17531753

@@ -1775,7 +1775,7 @@ def _get_keyword_from_self(self, name: str) -> Optional[KeywordDoc]:
17751775
DiagnosticsEntry(
17761776
self._create_multiple_keywords_found_message(name, found, implicit=False),
17771777
DiagnosticSeverity.ERROR,
1778-
"KeywordError",
1778+
Error.KEYWORD_ERROR,
17791779
)
17801780
)
17811781
raise CancelSearchError
@@ -1793,7 +1793,7 @@ def _get_keyword_from_self(self, name: str) -> Optional[KeywordDoc]:
17931793
DiagnosticsEntry(
17941794
str(e),
17951795
DiagnosticSeverity.ERROR,
1796-
"KeywordError",
1796+
Error.KEYWORD_ERROR,
17971797
)
17981798
)
17991799
raise CancelSearchError from e
@@ -1816,7 +1816,7 @@ def _get_explicit_keyword(self, name: str) -> Optional[KeywordDoc]:
18161816
DiagnosticsEntry(
18171817
self._create_multiple_keywords_found_message(name, found, implicit=False),
18181818
DiagnosticSeverity.ERROR,
1819-
"KeywordError",
1819+
Error.KEYWORD_ERROR,
18201820
)
18211821
)
18221822
raise CancelSearchError
@@ -1954,7 +1954,7 @@ def _get_keyword_from_resource_files(self, name: str) -> Optional[KeywordDoc]:
19541954
DiagnosticsEntry(
19551955
self._create_multiple_keywords_found_message(name, found),
19561956
DiagnosticSeverity.ERROR,
1957-
"KeywordError",
1957+
Error.KEYWORD_ERROR,
19581958
)
19591959
)
19601960
raise CancelSearchError
@@ -2008,7 +2008,7 @@ def _get_keyword_from_libraries(self, name: str) -> Optional[KeywordDoc]:
20082008
DiagnosticsEntry(
20092009
self._create_multiple_keywords_found_message(name, found),
20102010
DiagnosticSeverity.ERROR,
2011-
"KeywordError",
2011+
Error.KEYWORD_ERROR,
20122012
)
20132013
)
20142014
raise CancelSearchError
@@ -2030,7 +2030,7 @@ def _filter_stdlib_runner(
20302030
DiagnosticsEntry(
20312031
self._create_custom_and_standard_keyword_conflict_warning_message(custom, standard),
20322032
DiagnosticSeverity.WARNING,
2033-
"KeywordError",
2033+
Error.KEYWORD_ERROR,
20342034
)
20352035
)
20362036

packages/language_server/src/robotcode/language_server/robotframework/parts/code_action_quick_fixes.py

Lines changed: 11 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
from robotcode.language_server.common.text_document import TextDocument
2626
from robotcode.language_server.robotframework.diagnostics.errors import DIAGNOSTICS_SOURCE_NAME, Error
2727
from robotcode.language_server.robotframework.utils.ast_utils import (
28+
FirstAndLastRealStatementFinder,
2829
Token,
2930
get_node_at_position,
3031
get_nodes_at_position,
@@ -39,6 +40,7 @@
3940
if TYPE_CHECKING:
4041
from robotcode.language_server.robotframework.protocol import RobotLanguageServerProtocol # pragma: no cover
4142

43+
QUICK_FIX_OTHER = "other"
4244

4345
KEYWORD_WITH_ARGS_TEMPLATE = Template(
4446
"""\
@@ -60,23 +62,6 @@
6062
)
6163

6264

63-
class LastRealStatementFinder(Visitor):
64-
def __init__(self) -> None:
65-
self.statement: Optional[ast.AST] = None
66-
67-
@classmethod
68-
def find_from(cls, model: ast.AST) -> Optional[ast.AST]:
69-
finder = cls()
70-
finder.visit(model)
71-
return finder.statement
72-
73-
def visit_Statement(self, statement: ast.AST) -> None: # noqa: N802
74-
from robot.parsing.model.statements import EmptyLine
75-
76-
if not isinstance(statement, EmptyLine):
77-
self.statement = statement
78-
79-
8065
class FindSectionsVisitor(Visitor):
8166
def __init__(self) -> None:
8267
self.keyword_sections: List[ast.AST] = []
@@ -111,7 +96,7 @@ def find_keyword_sections(node: ast.AST) -> Optional[List[ast.AST]]:
11196
return visitor.keyword_sections if visitor.keyword_sections else None
11297

11398

114-
class RobotCodeActionFixesProtocolPart(RobotLanguageServerProtocolPart, ModelHelperMixin):
99+
class RobotCodeActionQuickFixesProtocolPart(RobotLanguageServerProtocolPart, ModelHelperMixin):
115100
_logger = LoggingDescriptor()
116101

117102
def __init__(self, parent: RobotLanguageServerProtocol) -> None:
@@ -122,7 +107,7 @@ def __init__(self, parent: RobotLanguageServerProtocol) -> None:
122107
self.parent.commands.register_all(self)
123108

124109
@language_id("robotframework")
125-
@code_action_kinds([CodeActionKind.QUICK_FIX, "other"])
110+
@code_action_kinds([CodeActionKind.QUICK_FIX, QUICK_FIX_OTHER])
126111
async def collect(
127112
self, sender: Any, document: TextDocument, range: Range, context: CodeActionContext
128113
) -> Optional[List[Union[Command, CodeAction]]]:
@@ -283,7 +268,7 @@ async def code_action_assign_result_to_variable(
283268
range.start.line == range.end.line
284269
and range.start.character <= range.end.character
285270
and (
286-
(context.only and "other" in context.only)
271+
(context.only and QUICK_FIX_OTHER in context.only)
287272
or context.trigger_kind in [CodeActionTriggerKind.INVOKED, CodeActionTriggerKind.AUTOMATIC]
288273
)
289274
):
@@ -305,7 +290,7 @@ async def code_action_assign_result_to_variable(
305290
return [
306291
CodeAction(
307292
"Assign result to variable",
308-
kind="other",
293+
kind=QUICK_FIX_OTHER,
309294
command=Command(
310295
self.parent.commands.get_command_name(self.assign_result_to_variable_command),
311296
self.parent.commands.get_command_name(self.assign_result_to_variable_command),
@@ -475,9 +460,8 @@ async def code_action_disable_robotcode_diagnostics_for_line(
475460
or context.trigger_kind in [CodeActionTriggerKind.INVOKED, CodeActionTriggerKind.AUTOMATIC]
476461
)
477462
):
478-
diagnostics = next((d for d in context.diagnostics if d.source and d.source.startswith("robotcode.")), None)
479-
480-
if diagnostics is not None:
463+
all_diagnostics = [d for d in context.diagnostics if d.source and d.source.startswith("robotcode.")]
464+
if all_diagnostics:
481465
return [
482466
CodeAction(
483467
f"Disable '{diagnostics.code}' for this line",
@@ -489,6 +473,7 @@ async def code_action_disable_robotcode_diagnostics_for_line(
489473
),
490474
diagnostics=[diagnostics],
491475
)
476+
for diagnostics in all_diagnostics
492477
]
493478

494479
return None
@@ -594,7 +579,7 @@ async def create_suite_variable_command(self, document_uri: DocumentUri, range:
594579
if finder.variable_sections:
595580
section = finder.variable_sections[-1]
596581

597-
last_stmt = LastRealStatementFinder.find_from(section)
582+
_, last_stmt = FirstAndLastRealStatementFinder.find_from(section)
598583
end_lineno = last_stmt.end_lineno if last_stmt else section.end_lineno
599584
if end_lineno is None:
600585
return
@@ -607,7 +592,7 @@ async def create_suite_variable_command(self, document_uri: DocumentUri, range:
607592
insert_range_suffix = "\n\n"
608593
section = finder.setting_sections[-1]
609594

610-
last_stmt = LastRealStatementFinder.find_from(section)
595+
_, last_stmt = FirstAndLastRealStatementFinder.find_from(section)
611596
end_lineno = last_stmt.end_lineno if last_stmt else section.end_lineno
612597
if end_lineno is None:
613598
return

0 commit comments

Comments
 (0)