1
1
import io
2
2
from typing import TYPE_CHECKING , Any , List , Optional
3
+ from weakref import WeakKeyDictionary
3
4
4
5
from robotcode .core .language import language_id
5
6
from robotcode .core .lsp .types import (
20
21
from .robocop_tidy_mixin import RoboCopTidyMixin
21
22
22
23
if TYPE_CHECKING :
24
+ from robocop .linter .runner import RobocopLinter
25
+
23
26
from ..protocol import RobotLanguageServerProtocol
24
27
25
28
@@ -30,8 +33,9 @@ def __init__(self, parent: "RobotLanguageServerProtocol") -> None:
30
33
super ().__init__ (parent )
31
34
32
35
self .source_name = "robocop"
36
+ self ._robocop_linters : WeakKeyDictionary [WorkspaceFolder , "RobocopLinter" ] = WeakKeyDictionary ()
33
37
34
- if self .robocop_installed and self . robocop_version < ( 6 , 0 ) :
38
+ if self .robocop_installed :
35
39
parent .diagnostics .collect .add (self .collect_diagnostics )
36
40
37
41
def get_config (self , document : TextDocument ) -> Optional [RoboCopConfig ]:
@@ -45,25 +49,96 @@ def get_config(self, document: TextDocument) -> Optional[RoboCopConfig]:
45
49
@_logger .call
46
50
def collect_diagnostics (
47
51
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
+ )
58
65
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
60
72
61
73
@_logger .call
62
74
def collect (
63
75
self ,
64
76
document : TextDocument ,
65
77
workspace_folder : WorkspaceFolder ,
66
78
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 ,
67
142
) -> List [Diagnostic ]:
68
143
from robocop import __version__
69
144
from robocop .config import Config
@@ -174,7 +249,9 @@ def get_code_description(self, version: Version, issue: Any) -> Optional[CodeDes
174
249
if version < (3 , 0 ):
175
250
return None
176
251
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 } "
178
255
179
256
if version < (4 , 0 ):
180
257
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
187
264
href = f"{ base } /rules_list.html#{ issue .name } -{ issue .severity .value } { issue .rule_id } " .lower ()
188
265
)
189
266
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