Skip to content

Commit f226091

Browse files
committed
feat(analyze): allow shortforms of warning and information, warn and info in diagnostic modifiers
1 parent 5cca59f commit f226091

File tree

2 files changed

+105
-32
lines changed

2 files changed

+105
-32
lines changed

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

Lines changed: 32 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
from ast import AST
44
from collections import defaultdict
55
from dataclasses import dataclass, field
6+
from enum import Enum
67
from typing import Dict, List, Optional, Set, Union
78

89
from robot.parsing.lexer.tokens import Token
@@ -12,23 +13,40 @@
1213

1314
from ..utils.visitor import Visitor
1415

15-
ACTIONS = ["ignore", "error", "warning", "information", "hint", "reset"]
16+
ACTIONS = ["ignore", "error", "warn", "warning", "info", "information", "hint", "reset"]
1617

1718
ROBOTCODE_ACTION_AND_CODES_PATTERN = re.compile(rf"(?P<action>{'|'.join(ACTIONS)})(\[(?P<codes>[^\]]*?)\])?")
1819

1920

21+
class ModifierAction(Enum):
22+
IGNORE = "ignore"
23+
ERROR = "error"
24+
WARNING = "warning"
25+
INFORMATION = "information"
26+
HINT = "hint"
27+
RESET = "reset"
28+
29+
@classmethod
30+
def from_str(cls, value: str) -> "ModifierAction":
31+
if value == "warn":
32+
value = "warning"
33+
elif value == "info":
34+
value = "information"
35+
return cls(value)
36+
37+
2038
@dataclass
2139
class RulesAndCodes:
2240
codes: Dict[Union[str, int], Set[int]]
23-
actions: Dict[int, Dict[Union[str, int], str]]
41+
actions: Dict[int, Dict[Union[str, int], ModifierAction]]
2442

2543

2644
_translation_table = str.maketrans("", "", "_- ")
2745

2846
ROBOTCODE_MARKER = "robotcode:"
2947

3048

31-
class DisablersVisitor(Visitor):
49+
class ModifiersVisitor(Visitor):
3250

3351
def __init__(self) -> None:
3452
super().__init__()
@@ -65,16 +83,17 @@ def visit_Statement(self, node: Statement) -> None: # noqa: N802
6583
self._handle_statement_comments(node)
6684
self.generic_visit(node)
6785

68-
def _parse_robotcode_disabler(self, comment: str) -> Dict[str, List[str]]:
69-
result: Dict[str, List[str]] = {}
86+
def _parse_robotcode_disabler(self, comment: str) -> Dict[ModifierAction, List[str]]:
87+
result: Dict[ModifierAction, List[str]] = {}
7088

7189
comment = comment.strip()
7290
m = ROBOTCODE_ACTION_AND_CODES_PATTERN.match(comment)
7391
if m is None:
7492
return result
7593

7694
for m in ROBOTCODE_ACTION_AND_CODES_PATTERN.finditer(comment):
77-
action = m.group("action")
95+
action_str = m.group("action")
96+
action = ModifierAction.from_str(action_str)
7897
messages = m.group("codes")
7998
result[action] = (
8099
[m.strip().translate(_translation_table).lower() for m in messages.split(",")]
@@ -176,7 +195,7 @@ def __init__(self, model: AST, config: Optional[DiagnosticModifiersConfig] = Non
176195

177196
@functools.cached_property
178197
def rules_and_codes(self) -> RulesAndCodes:
179-
visitor = DisablersVisitor()
198+
visitor = ModifiersVisitor()
180199
visitor.visit(self.model)
181200
return visitor.rules_and_codes
182201

@@ -200,20 +219,20 @@ def modify_diagnostic(self, diagnostic: Diagnostic) -> Optional[Diagnostic]:
200219
if actions is not None:
201220
action = actions.get(code)
202221
if action is not None:
203-
if action == "ignore":
222+
if action == ModifierAction.IGNORE:
204223
return None
205-
if action == "reset":
224+
if action == ModifierAction.RESET:
206225
pass
207-
elif action == "error":
226+
elif action == ModifierAction.ERROR:
208227
modified = True
209228
diagnostic.severity = DiagnosticSeverity.ERROR
210-
elif action == "warning":
229+
elif action == ModifierAction.WARNING:
211230
modified = True
212231
diagnostic.severity = DiagnosticSeverity.WARNING
213-
elif action == "information":
232+
elif action == ModifierAction.INFORMATION:
214233
modified = True
215234
diagnostic.severity = DiagnosticSeverity.INFORMATION
216-
elif action == "hint":
235+
elif action == ModifierAction.HINT:
217236
modified = True
218237
diagnostic.severity = DiagnosticSeverity.HINT
219238

tests/robotcode/robot/diagnostics/test_modifiers.py

Lines changed: 73 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -8,32 +8,36 @@
88
from robotcode.robot.diagnostics.diagnostics_modifier import (
99
DiagnosticModifiersConfig,
1010
DiagnosticsModifier,
11-
DisablersVisitor,
11+
ModifierAction,
12+
ModifiersVisitor,
1213
)
1314

1415

1516
@pytest.mark.parametrize(
1617
("text", "expected_action_and_codes"),
1718
[
18-
("ignore", {"ignore": ["*"]}),
19-
("warn", {"warn": ["*"]}),
20-
("error", {"error": ["*"]}),
21-
("hint", {"hint": ["*"]}),
19+
("ignore", {ModifierAction.IGNORE: ["*"]}),
20+
("warn", {ModifierAction.WARNING: ["*"]}),
21+
("warning", {ModifierAction.WARNING: ["*"]}),
22+
("info", {ModifierAction.INFORMATION: ["*"]}),
23+
("information", {ModifierAction.INFORMATION: ["*"]}),
24+
("error", {ModifierAction.ERROR: ["*"]}),
25+
("hint", {ModifierAction.HINT: ["*"]}),
2226
("garbage", {}),
23-
("ignore[message]", {"ignore": ["message"]}),
24-
("ignore[message1, message2]", {"ignore": ["message1", "message2"]}),
27+
("ignore[message]", {ModifierAction.IGNORE: ["message"]}),
28+
("ignore[message1, message2]", {ModifierAction.IGNORE: ["message1", "message2"]}),
2529
(
2630
"ignore[message1, message2] hint[message3, message4]",
27-
{"ignore": ["message1", "message2"], "hint": ["message3", "message4"]},
31+
{ModifierAction.IGNORE: ["message1", "message2"], ModifierAction.HINT: ["message3", "message4"]},
2832
),
2933
(
3034
" ignore[message1, message2] hint[message3, message4] garbage ",
31-
{"ignore": ["message1", "message2"], "hint": ["message3", "message4"]},
35+
{ModifierAction.IGNORE: ["message1", "message2"], ModifierAction.HINT: ["message3", "message4"]},
3236
),
3337
],
3438
)
35-
def test_disabler_parser_should_work(text: str, expected_action_and_codes: Dict[str, List[str]]) -> None:
36-
visitor = DisablersVisitor()
39+
def test_disabler_parser_should_work(text: str, expected_action_and_codes: Dict[ModifierAction, List[str]]) -> None:
40+
visitor = ModifiersVisitor()
3741
assert dict(visitor._parse_robotcode_disabler(text)) == expected_action_and_codes
3842

3943

@@ -49,7 +53,7 @@ def test_find_disablers_at_line_end() -> None:
4953
"""
5054

5155
model = get_model(io.StringIO(file))
52-
visitor = DisablersVisitor()
56+
visitor = ModifiersVisitor()
5357
visitor.visit(model)
5458
assert visitor.rules_and_codes.codes == {
5559
"*": {2, 3},
@@ -60,14 +64,14 @@ def test_find_disablers_at_line_end() -> None:
6064
"message4": {6},
6165
}
6266
assert visitor.rules_and_codes.actions == {
63-
2: {"*": "ignore"},
64-
3: {"*": "warn"},
65-
5: {"unknownvariable": "ignore"},
67+
2: {"*": ModifierAction.IGNORE},
68+
3: {"*": ModifierAction.WARNING},
69+
5: {"unknownvariable": ModifierAction.IGNORE},
6670
6: {
67-
"message1": "ignore",
68-
"message2": "ignore",
69-
"message3": "hint",
70-
"message4": "hint",
71+
"message1": ModifierAction.IGNORE,
72+
"message2": ModifierAction.IGNORE,
73+
"message3": ModifierAction.HINT,
74+
"message4": ModifierAction.HINT,
7175
},
7276
}
7377

@@ -361,3 +365,53 @@ def test_diagnostics_modifier_should_be_configurable() -> None:
361365
severity=DiagnosticSeverity.HINT,
362366
)
363367
]
368+
369+
370+
def test_diagnostics_modifier_should_work_as_option_in_implicit_comment() -> None:
371+
file = """\
372+
language: en
373+
robotcode: ignore[unknown-variable]
374+
*** Test Cases ***
375+
first
376+
# robotcode: ignore[message_1, message_2] hint[message 3, message 4]
377+
378+
unknown keyword
379+
unknown keyword1
380+
log ${unknown}
381+
log hello
382+
383+
"""
384+
model = get_model(io.StringIO(file))
385+
modifier = DiagnosticsModifier(model)
386+
387+
diagnostics = [
388+
Diagnostic(
389+
range=Range(start=Position(line=5, character=4), end=Position(line=5, character=12)),
390+
message="UnknownVariable",
391+
code="UnknownVariable",
392+
severity=DiagnosticSeverity.INFORMATION,
393+
),
394+
Diagnostic(
395+
range=Range(start=Position(line=6, character=4), end=Position(line=6, character=12)),
396+
message="Message1",
397+
code="message1",
398+
severity=DiagnosticSeverity.ERROR,
399+
),
400+
Diagnostic(
401+
range=Range(start=Position(line=6, character=4), end=Position(line=6, character=12)),
402+
message="Message3",
403+
code="Message3",
404+
severity=DiagnosticSeverity.ERROR,
405+
),
406+
]
407+
408+
result = modifier.modify_diagnostics(diagnostics)
409+
410+
assert result == [
411+
Diagnostic(
412+
range=Range(start=Position(line=6, character=4), end=Position(line=6, character=12)),
413+
message="Message3",
414+
code="Message3",
415+
severity=DiagnosticSeverity.HINT,
416+
)
417+
]

0 commit comments

Comments
 (0)