Skip to content

Commit 8dc2f3c

Browse files
committed
fix(langserver): implemented support for robocop >= 6 checks
closes #452
1 parent 3fd27d4 commit 8dc2f3c

File tree

2 files changed

+97
-15
lines changed

2 files changed

+97
-15
lines changed

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ def format(
6464
options: FormattingOptions,
6565
**further_options: Any,
6666
) -> Optional[List[TextEdit]]:
67-
if (get_robot_version() >= (5, 0)) and self.robocop_installed and self.robocop_version >= (6, 0):
67+
if self.robocop_installed and self.robocop_version >= (6, 0):
6868
if not self.is_robocop_notification_shown and self.robotidy_installed:
6969
self.parent.window.show_message(
7070
"`robotframework-robocop >= 6.0` is installed and will be used for formatting.\n\n"
@@ -201,9 +201,11 @@ def format_robocop(
201201
from robocop.formatter.runner import RobocopFormatter
202202

203203
robocop_config = self.get_robocop_config(document)
204+
workspace_folder = self.parent.workspace.get_workspace_folder(document.uri)
204205

205206
config_manager = ConfigManager(
206207
[document.uri.to_path()],
208+
root=workspace_folder.uri.to_path() if workspace_folder else None,
207209
config=robocop_config.config_file,
208210
ignore_git_dir=robocop_config.ignore_git_dir,
209211
ignore_file_config=robocop_config.ignore_file_config,

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

Lines changed: 94 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import io
22
from typing import TYPE_CHECKING, Any, List, Optional
3+
from weakref import WeakKeyDictionary
34

45
from robotcode.core.language import language_id
56
from robotcode.core.lsp.types import (
@@ -20,6 +21,8 @@
2021
from .robocop_tidy_mixin import RoboCopTidyMixin
2122

2223
if TYPE_CHECKING:
24+
from robocop.linter.runner import RobocopLinter
25+
2326
from ..protocol import RobotLanguageServerProtocol
2427

2528

@@ -30,8 +33,9 @@ def __init__(self, parent: "RobotLanguageServerProtocol") -> None:
3033
super().__init__(parent)
3134

3235
self.source_name = "robocop"
36+
self._robocop_linters: WeakKeyDictionary[WorkspaceFolder, "RobocopLinter"] = WeakKeyDictionary()
3337

34-
if self.robocop_installed and self.robocop_version < (6, 0):
38+
if self.robocop_installed:
3539
parent.diagnostics.collect.add(self.collect_diagnostics)
3640

3741
def get_config(self, document: TextDocument) -> Optional[RoboCopConfig]:
@@ -45,25 +49,96 @@ def get_config(self, document: TextDocument) -> Optional[RoboCopConfig]:
4549
@_logger.call
4650
def collect_diagnostics(
4751
self, sender: Any, document: TextDocument, diagnostics_type: DiagnosticsCollectType
48-
) -> DiagnosticsResult:
49-
workspace_folder = self.parent.workspace.get_workspace_folder(document.uri)
50-
if workspace_folder is not None:
51-
extension_config = self.get_config(document)
52-
53-
if extension_config is not None and extension_config.enabled:
54-
return DiagnosticsResult(
55-
self.collect_diagnostics,
56-
self.collect(document, workspace_folder, extension_config),
57-
)
52+
) -> Optional[DiagnosticsResult]:
53+
if self.robocop_installed:
54+
workspace_folder = self.parent.workspace.get_workspace_folder(document.uri)
55+
if workspace_folder is not None:
56+
config = self.get_config(document)
57+
58+
if config is not None and config.enabled:
59+
if self.robocop_version >= (6, 0):
60+
# In Robocop 6.0, the diagnostics are collected in a different way
61+
return DiagnosticsResult(
62+
self.collect_diagnostics,
63+
self.collect(document, workspace_folder, config),
64+
)
5865

59-
return DiagnosticsResult(self.collect_diagnostics, [])
66+
return DiagnosticsResult(
67+
self.collect_diagnostics,
68+
self.collect_old(document, workspace_folder, config),
69+
)
70+
71+
return None
6072

6173
@_logger.call
6274
def collect(
6375
self,
6476
document: TextDocument,
6577
workspace_folder: WorkspaceFolder,
6678
extension_config: RoboCopConfig,
79+
) -> List[Diagnostic]:
80+
from robocop.config import ConfigManager
81+
from robocop.linter.rules import RuleSeverity
82+
from robocop.linter.runner import RobocopLinter
83+
84+
linter = self._robocop_linters.get(workspace_folder, None)
85+
86+
if linter is None:
87+
config_manager = ConfigManager(
88+
[],
89+
root=workspace_folder.uri.to_path(),
90+
config=extension_config.config_file,
91+
ignore_git_dir=extension_config.ignore_git_dir,
92+
ignore_file_config=extension_config.ignore_file_config,
93+
)
94+
linter = RobocopLinter(config_manager)
95+
self._robocop_linters[workspace_folder] = linter
96+
97+
source = document.uri.to_path()
98+
99+
config = linter.config_manager.get_config_for_source_file(source)
100+
model = self.parent.documents_cache.get_model(document, False)
101+
diagnostics = linter.run_check(model, source, config)
102+
103+
return [
104+
Diagnostic(
105+
range=Range(
106+
start=Position(
107+
line=diagnostic.range.start.line - 1,
108+
character=diagnostic.range.start.character - 1,
109+
),
110+
end=Position(
111+
line=max(0, diagnostic.range.end.line - 1),
112+
character=max(0, diagnostic.range.end.character - 1),
113+
),
114+
),
115+
message=diagnostic.message,
116+
severity=(
117+
DiagnosticSeverity.INFORMATION
118+
if diagnostic.severity == RuleSeverity.INFO
119+
else (
120+
DiagnosticSeverity.WARNING
121+
if diagnostic.severity == RuleSeverity.WARNING
122+
else (
123+
DiagnosticSeverity.ERROR
124+
if diagnostic.severity == RuleSeverity.ERROR
125+
else DiagnosticSeverity.HINT
126+
)
127+
)
128+
),
129+
source=self.source_name,
130+
code=f"{diagnostic.rule.rule_id}-{diagnostic.rule.name}",
131+
code_description=self.get_code_description(self.robocop_version, diagnostic),
132+
)
133+
for diagnostic in diagnostics
134+
]
135+
136+
@_logger.call
137+
def collect_old(
138+
self,
139+
document: TextDocument,
140+
workspace_folder: WorkspaceFolder,
141+
extension_config: RoboCopConfig,
67142
) -> List[Diagnostic]:
68143
from robocop import __version__
69144
from robocop.config import Config
@@ -174,7 +249,9 @@ def get_code_description(self, version: Version, issue: Any) -> Optional[CodeDes
174249
if version < (3, 0):
175250
return None
176251

177-
base = f"https://robocop.readthedocs.io/en/{version.major}.{version.minor}.{version.patch}"
252+
version_letter = "v" if version.major >= 6 else ""
253+
254+
base = f"https://robocop.readthedocs.io/en/{version_letter}{version.major}.{version.minor}.{version.patch}"
178255

179256
if version < (4, 0):
180257
return CodeDescription(href=f"{base}/rules.html#{issue.name}".lower())
@@ -187,4 +264,7 @@ def get_code_description(self, version: Version, issue: Any) -> Optional[CodeDes
187264
href=f"{base}/rules_list.html#{issue.name}-{issue.severity.value}{issue.rule_id}".lower()
188265
)
189266

190-
return CodeDescription(href=f"{base}/rules_list.html#{issue.name}".lower())
267+
if version < (6, 0):
268+
return CodeDescription(href=f"{base}/rules_list.html#{issue.name}".lower())
269+
270+
return CodeDescription(href=f"{base}/rules/rules_list.html#{issue.rule.rule_id}-{issue.rule.name}".lower())

0 commit comments

Comments
 (0)