robotcode-language-server 1.2.0__tar.gz → 1.3.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (77) hide show
  1. {robotcode_language_server-1.2.0 → robotcode_language_server-1.3.0}/PKG-INFO +5 -5
  2. {robotcode_language_server-1.2.0 → robotcode_language_server-1.3.0}/pyproject.toml +4 -4
  3. robotcode_language_server-1.3.0/src/robotcode/language_server/__version__.py +1 -0
  4. {robotcode_language_server-1.2.0 → robotcode_language_server-1.3.0}/src/robotcode/language_server/robotframework/configuration.py +4 -1
  5. {robotcode_language_server-1.2.0 → robotcode_language_server-1.3.0}/src/robotcode/language_server/robotframework/parts/document_symbols.py +1 -1
  6. {robotcode_language_server-1.2.0 → robotcode_language_server-1.3.0}/src/robotcode/language_server/robotframework/parts/formatting.py +84 -34
  7. {robotcode_language_server-1.2.0 → robotcode_language_server-1.3.0}/src/robotcode/language_server/robotframework/parts/hover.py +1 -1
  8. {robotcode_language_server-1.2.0 → robotcode_language_server-1.3.0}/src/robotcode/language_server/robotframework/parts/keywords_treeview.py +122 -8
  9. {robotcode_language_server-1.2.0 → robotcode_language_server-1.3.0}/src/robotcode/language_server/robotframework/parts/project_info.py +15 -12
  10. {robotcode_language_server-1.2.0 → robotcode_language_server-1.3.0}/src/robotcode/language_server/robotframework/parts/robocop_diagnostics.py +96 -23
  11. robotcode_language_server-1.3.0/src/robotcode/language_server/robotframework/parts/robocop_tidy_mixin.py +49 -0
  12. {robotcode_language_server-1.2.0 → robotcode_language_server-1.3.0}/src/robotcode/language_server/robotframework/parts/semantic_tokens.py +8 -42
  13. robotcode_language_server-1.2.0/src/robotcode/language_server/__version__.py +0 -1
  14. {robotcode_language_server-1.2.0 → robotcode_language_server-1.3.0}/.gitignore +0 -0
  15. {robotcode_language_server-1.2.0 → robotcode_language_server-1.3.0}/LICENSE.txt +0 -0
  16. {robotcode_language_server-1.2.0 → robotcode_language_server-1.3.0}/README.md +0 -0
  17. {robotcode_language_server-1.2.0 → robotcode_language_server-1.3.0}/src/robotcode/language_server/__init__.py +0 -0
  18. {robotcode_language_server-1.2.0 → robotcode_language_server-1.3.0}/src/robotcode/language_server/cli.py +0 -0
  19. {robotcode_language_server-1.2.0 → robotcode_language_server-1.3.0}/src/robotcode/language_server/common/__init__.py +0 -0
  20. {robotcode_language_server-1.2.0 → robotcode_language_server-1.3.0}/src/robotcode/language_server/common/decorators.py +0 -0
  21. {robotcode_language_server-1.2.0 → robotcode_language_server-1.3.0}/src/robotcode/language_server/common/parts/__init__.py +0 -0
  22. {robotcode_language_server-1.2.0 → robotcode_language_server-1.3.0}/src/robotcode/language_server/common/parts/code_action.py +0 -0
  23. {robotcode_language_server-1.2.0 → robotcode_language_server-1.3.0}/src/robotcode/language_server/common/parts/code_lens.py +0 -0
  24. {robotcode_language_server-1.2.0 → robotcode_language_server-1.3.0}/src/robotcode/language_server/common/parts/commands.py +0 -0
  25. {robotcode_language_server-1.2.0 → robotcode_language_server-1.3.0}/src/robotcode/language_server/common/parts/completion.py +0 -0
  26. {robotcode_language_server-1.2.0 → robotcode_language_server-1.3.0}/src/robotcode/language_server/common/parts/declaration.py +0 -0
  27. {robotcode_language_server-1.2.0 → robotcode_language_server-1.3.0}/src/robotcode/language_server/common/parts/definition.py +0 -0
  28. {robotcode_language_server-1.2.0 → robotcode_language_server-1.3.0}/src/robotcode/language_server/common/parts/diagnostics.py +0 -0
  29. {robotcode_language_server-1.2.0 → robotcode_language_server-1.3.0}/src/robotcode/language_server/common/parts/document_highlight.py +0 -0
  30. {robotcode_language_server-1.2.0 → robotcode_language_server-1.3.0}/src/robotcode/language_server/common/parts/document_symbols.py +0 -0
  31. {robotcode_language_server-1.2.0 → robotcode_language_server-1.3.0}/src/robotcode/language_server/common/parts/documents.py +0 -0
  32. {robotcode_language_server-1.2.0 → robotcode_language_server-1.3.0}/src/robotcode/language_server/common/parts/folding_range.py +0 -0
  33. {robotcode_language_server-1.2.0 → robotcode_language_server-1.3.0}/src/robotcode/language_server/common/parts/formatting.py +0 -0
  34. {robotcode_language_server-1.2.0 → robotcode_language_server-1.3.0}/src/robotcode/language_server/common/parts/hover.py +0 -0
  35. {robotcode_language_server-1.2.0 → robotcode_language_server-1.3.0}/src/robotcode/language_server/common/parts/implementation.py +0 -0
  36. {robotcode_language_server-1.2.0 → robotcode_language_server-1.3.0}/src/robotcode/language_server/common/parts/inlay_hint.py +0 -0
  37. {robotcode_language_server-1.2.0 → robotcode_language_server-1.3.0}/src/robotcode/language_server/common/parts/inline_value.py +0 -0
  38. {robotcode_language_server-1.2.0 → robotcode_language_server-1.3.0}/src/robotcode/language_server/common/parts/linked_editing_ranges.py +0 -0
  39. {robotcode_language_server-1.2.0 → robotcode_language_server-1.3.0}/src/robotcode/language_server/common/parts/protocol_part.py +0 -0
  40. {robotcode_language_server-1.2.0 → robotcode_language_server-1.3.0}/src/robotcode/language_server/common/parts/references.py +0 -0
  41. {robotcode_language_server-1.2.0 → robotcode_language_server-1.3.0}/src/robotcode/language_server/common/parts/rename.py +0 -0
  42. {robotcode_language_server-1.2.0 → robotcode_language_server-1.3.0}/src/robotcode/language_server/common/parts/selection_range.py +0 -0
  43. {robotcode_language_server-1.2.0 → robotcode_language_server-1.3.0}/src/robotcode/language_server/common/parts/semantic_tokens.py +0 -0
  44. {robotcode_language_server-1.2.0 → robotcode_language_server-1.3.0}/src/robotcode/language_server/common/parts/signature_help.py +0 -0
  45. {robotcode_language_server-1.2.0 → robotcode_language_server-1.3.0}/src/robotcode/language_server/common/parts/window.py +0 -0
  46. {robotcode_language_server-1.2.0 → robotcode_language_server-1.3.0}/src/robotcode/language_server/common/parts/workspace.py +0 -0
  47. {robotcode_language_server-1.2.0 → robotcode_language_server-1.3.0}/src/robotcode/language_server/common/parts/workspace_symbols.py +0 -0
  48. {robotcode_language_server-1.2.0 → robotcode_language_server-1.3.0}/src/robotcode/language_server/common/protocol.py +0 -0
  49. {robotcode_language_server-1.2.0 → robotcode_language_server-1.3.0}/src/robotcode/language_server/common/server.py +0 -0
  50. {robotcode_language_server-1.2.0 → robotcode_language_server-1.3.0}/src/robotcode/language_server/hooks.py +0 -0
  51. {robotcode_language_server-1.2.0 → robotcode_language_server-1.3.0}/src/robotcode/language_server/py.typed +0 -0
  52. {robotcode_language_server-1.2.0 → robotcode_language_server-1.3.0}/src/robotcode/language_server/robotframework/__init__.py +0 -0
  53. {robotcode_language_server-1.2.0 → robotcode_language_server-1.3.0}/src/robotcode/language_server/robotframework/parts/__init__.py +0 -0
  54. {robotcode_language_server-1.2.0 → robotcode_language_server-1.3.0}/src/robotcode/language_server/robotframework/parts/code_action_documentation.py +0 -0
  55. {robotcode_language_server-1.2.0 → robotcode_language_server-1.3.0}/src/robotcode/language_server/robotframework/parts/code_action_helper_mixin.py +0 -0
  56. {robotcode_language_server-1.2.0 → robotcode_language_server-1.3.0}/src/robotcode/language_server/robotframework/parts/code_action_quick_fixes.py +0 -0
  57. {robotcode_language_server-1.2.0 → robotcode_language_server-1.3.0}/src/robotcode/language_server/robotframework/parts/code_action_refactor.py +0 -0
  58. {robotcode_language_server-1.2.0 → robotcode_language_server-1.3.0}/src/robotcode/language_server/robotframework/parts/code_lens.py +0 -0
  59. {robotcode_language_server-1.2.0 → robotcode_language_server-1.3.0}/src/robotcode/language_server/robotframework/parts/completion.py +0 -0
  60. {robotcode_language_server-1.2.0 → robotcode_language_server-1.3.0}/src/robotcode/language_server/robotframework/parts/debugging_utils.py +0 -0
  61. {robotcode_language_server-1.2.0 → robotcode_language_server-1.3.0}/src/robotcode/language_server/robotframework/parts/diagnostics.py +0 -0
  62. {robotcode_language_server-1.2.0 → robotcode_language_server-1.3.0}/src/robotcode/language_server/robotframework/parts/document_highlight.py +0 -0
  63. {robotcode_language_server-1.2.0 → robotcode_language_server-1.3.0}/src/robotcode/language_server/robotframework/parts/documents_cache.py +0 -0
  64. {robotcode_language_server-1.2.0 → robotcode_language_server-1.3.0}/src/robotcode/language_server/robotframework/parts/folding_range.py +0 -0
  65. {robotcode_language_server-1.2.0 → robotcode_language_server-1.3.0}/src/robotcode/language_server/robotframework/parts/goto.py +0 -0
  66. {robotcode_language_server-1.2.0 → robotcode_language_server-1.3.0}/src/robotcode/language_server/robotframework/parts/http_server.py +0 -0
  67. {robotcode_language_server-1.2.0 → robotcode_language_server-1.3.0}/src/robotcode/language_server/robotframework/parts/inlay_hint.py +0 -0
  68. {robotcode_language_server-1.2.0 → robotcode_language_server-1.3.0}/src/robotcode/language_server/robotframework/parts/inline_value.py +0 -0
  69. {robotcode_language_server-1.2.0 → robotcode_language_server-1.3.0}/src/robotcode/language_server/robotframework/parts/protocol_part.py +0 -0
  70. {robotcode_language_server-1.2.0 → robotcode_language_server-1.3.0}/src/robotcode/language_server/robotframework/parts/references.py +0 -0
  71. {robotcode_language_server-1.2.0 → robotcode_language_server-1.3.0}/src/robotcode/language_server/robotframework/parts/rename.py +0 -0
  72. {robotcode_language_server-1.2.0 → robotcode_language_server-1.3.0}/src/robotcode/language_server/robotframework/parts/robot_workspace.py +0 -0
  73. {robotcode_language_server-1.2.0 → robotcode_language_server-1.3.0}/src/robotcode/language_server/robotframework/parts/selection_range.py +0 -0
  74. {robotcode_language_server-1.2.0 → robotcode_language_server-1.3.0}/src/robotcode/language_server/robotframework/parts/signature_help.py +0 -0
  75. {robotcode_language_server-1.2.0 → robotcode_language_server-1.3.0}/src/robotcode/language_server/robotframework/parts/workspace_symbols.py +0 -0
  76. {robotcode_language_server-1.2.0 → robotcode_language_server-1.3.0}/src/robotcode/language_server/robotframework/protocol.py +0 -0
  77. {robotcode_language_server-1.2.0 → robotcode_language_server-1.3.0}/src/robotcode/language_server/robotframework/server.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: robotcode-language-server
3
- Version: 1.2.0
3
+ Version: 1.3.0
4
4
  Summary: RobotCode Language Server for Robot Framework
5
5
  Project-URL: Homepage, https://robotcode.io
6
6
  Project-URL: Donate, https://opencollective.com/robotcode
@@ -25,10 +25,10 @@ Classifier: Programming Language :: Python :: Implementation :: PyPy
25
25
  Classifier: Topic :: Utilities
26
26
  Classifier: Typing :: Typed
27
27
  Requires-Python: >=3.8
28
- Requires-Dist: robotcode-analyze==1.2.0
29
- Requires-Dist: robotcode-jsonrpc2==1.2.0
30
- Requires-Dist: robotcode-robot==1.2.0
31
- Requires-Dist: robotcode==1.2.0
28
+ Requires-Dist: robotcode-analyze==1.3.0
29
+ Requires-Dist: robotcode-jsonrpc2==1.3.0
30
+ Requires-Dist: robotcode-robot==1.3.0
31
+ Requires-Dist: robotcode==1.3.0
32
32
  Requires-Dist: robotframework>=4.1.0
33
33
  Description-Content-Type: text/markdown
34
34
 
@@ -27,10 +27,10 @@ classifiers = [
27
27
  ]
28
28
  dependencies = [
29
29
  "robotframework>=4.1.0",
30
- "robotcode-jsonrpc2==1.2.0",
31
- "robotcode-robot==1.2.0",
32
- "robotcode-analyze==1.2.0",
33
- "robotcode==1.2.0",
30
+ "robotcode-jsonrpc2==1.3.0",
31
+ "robotcode-robot==1.3.0",
32
+ "robotcode-analyze==1.3.0",
33
+ "robotcode==1.3.0",
34
34
  ]
35
35
  dynamic = ["version"]
36
36
 
@@ -33,6 +33,9 @@ class RoboCopConfig(ConfigBase):
33
33
  enabled: bool = True
34
34
  include: List[str] = field(default_factory=list)
35
35
  exclude: List[str] = field(default_factory=list)
36
+ ignore_git_dir: bool = False
37
+ ignore_file_config: bool = False
38
+ config_file: Optional[str] = None
36
39
  configurations: List[str] = field(default_factory=list)
37
40
 
38
41
 
@@ -49,7 +52,7 @@ class RoboTidyConfig(ConfigBase):
49
52
  class DocumentationServerConfig(ConfigBase):
50
53
  start_port: int = 3100
51
54
  end_port: int = 3199
52
- start_on_demand: bool = True
55
+ start_on_demand: bool = False
53
56
 
54
57
 
55
58
  @config_section("robotcode.inlayHints")
@@ -6,7 +6,6 @@ from robot.errors import VariableError
6
6
  from robot.parsing.lexer.tokens import Token
7
7
  from robot.parsing.model.blocks import Keyword, Section, TestCase
8
8
  from robot.parsing.model.statements import Statement
9
- from robot.variables import search_variable
10
9
 
11
10
  from robotcode.core.language import language_id
12
11
  from robotcode.core.lsp.types import (
@@ -21,6 +20,7 @@ from robotcode.robot.utils.ast import (
21
20
  range_from_token,
22
21
  tokenize_variables,
23
22
  )
23
+ from robotcode.robot.utils.variables import search_variable
24
24
  from robotcode.robot.utils.visitor import Visitor
25
25
 
26
26
  from .protocol_part import RobotLanguageServerProtocolPart
@@ -1,6 +1,5 @@
1
1
  import io
2
2
  import os
3
- import re
4
3
  from concurrent.futures import CancelledError
5
4
  from typing import TYPE_CHECKING, Any, List, Optional, cast
6
5
 
@@ -14,26 +13,17 @@ from robotcode.core.lsp.types import (
14
13
  )
15
14
  from robotcode.core.text_document import TextDocument
16
15
  from robotcode.core.utils.logging import LoggingDescriptor
17
- from robotcode.core.utils.version import create_version_from_str
18
- from robotcode.robot.diagnostics.model_helper import ModelHelper
19
16
  from robotcode.robot.utils import get_robot_version
20
17
 
21
- from ..configuration import RoboTidyConfig
18
+ from ..configuration import RoboCopConfig, RoboTidyConfig
22
19
  from .protocol_part import RobotLanguageServerProtocolPart
20
+ from .robocop_tidy_mixin import RoboCopTidyMixin
23
21
 
24
22
  if TYPE_CHECKING:
25
23
  from ..protocol import RobotLanguageServerProtocol
26
24
 
27
25
 
28
- def robotidy_installed() -> bool:
29
- try:
30
- __import__("robotidy")
31
- except ImportError:
32
- return False
33
- return True
34
-
35
-
36
- class RobotFormattingProtocolPart(RobotLanguageServerProtocolPart, ModelHelper):
26
+ class RobotFormattingProtocolPart(RobotLanguageServerProtocolPart, RoboCopTidyMixin):
37
27
  _logger = LoggingDescriptor()
38
28
 
39
29
  def __init__(self, parent: "RobotLanguageServerProtocol") -> None:
@@ -41,7 +31,7 @@ class RobotFormattingProtocolPart(RobotLanguageServerProtocolPart, ModelHelper):
41
31
 
42
32
  parent.formatting.format.add(self.format)
43
33
 
44
- if robotidy_installed():
34
+ if self.robotidy_installed or (self.robocop_installed and self.robocop_version >= (6, 0)):
45
35
  parent.formatting.format_range.add(self.format_range)
46
36
 
47
37
  self.space_count = 4
@@ -49,14 +39,22 @@ class RobotFormattingProtocolPart(RobotLanguageServerProtocolPart, ModelHelper):
49
39
  self.line_separator = os.linesep
50
40
  self.short_test_name_length = 18
51
41
  self.setting_and_variable_name_length = 14
42
+ self.is_robocop_notification_shown = False
52
43
 
53
- def get_config(self, document: TextDocument) -> RoboTidyConfig:
44
+ def get_tidy_config(self, document: TextDocument) -> RoboTidyConfig:
54
45
  folder = self.parent.workspace.get_workspace_folder(document.uri)
55
46
  if folder is None:
56
47
  return RoboTidyConfig()
57
48
 
58
49
  return self.parent.workspace.get_configuration(RoboTidyConfig, folder.uri)
59
50
 
51
+ def get_robocop_config(self, document: TextDocument) -> RoboCopConfig:
52
+ folder = self.parent.workspace.get_workspace_folder(document.uri)
53
+ if folder is None:
54
+ return RoboCopConfig()
55
+
56
+ return self.parent.workspace.get_configuration(RoboCopConfig, folder.uri)
57
+
60
58
  @language_id("robotframework")
61
59
  @_logger.call
62
60
  def format(
@@ -66,23 +64,33 @@ class RobotFormattingProtocolPart(RobotLanguageServerProtocolPart, ModelHelper):
66
64
  options: FormattingOptions,
67
65
  **further_options: Any,
68
66
  ) -> Optional[List[TextEdit]]:
69
- config = self.get_config(document)
67
+ if self.robocop_installed and self.robocop_version >= (6, 0):
68
+ if not self.is_robocop_notification_shown and self.robotidy_installed:
69
+ self.parent.window.show_message(
70
+ "`robotframework-robocop >= 6.0` is installed and will be used for formatting.\n\n"
71
+ "`robotframework-tidy` is also detected in the workspace, but its use is redundant.\n"
72
+ "Robocop fully supports all formatting tasks and provides a more comprehensive solution.\n\n"
73
+ "Note: The use of `robotframework-tidy` is deprecated and should be avoided in favor of Robocop.",
74
+ MessageType.INFO,
75
+ )
76
+ self.is_robocop_notification_shown = True
70
77
 
71
- if (config.enabled or get_robot_version() >= (5, 0)) and robotidy_installed():
72
- return self.format_robot_tidy(document, options, config=config, **further_options)
78
+ return self.format_robocop(document, options, **further_options)
79
+
80
+ tidy_config = self.get_tidy_config(document)
81
+ if (tidy_config.enabled or get_robot_version() >= (5, 0)) and self.robotidy_installed:
82
+ return self.format_robot_tidy(document, options, config=tidy_config, **further_options)
73
83
 
74
84
  if get_robot_version() < (5, 0):
75
85
  return self.format_internal(document, options, **further_options)
76
86
 
77
87
  self.parent.window.show_message(
78
- "RobotFramework formatter is not available, please install 'robotframework-tidy'.",
88
+ "RobotFramework formatter is not available, please install 'robotframework-robocop'.",
79
89
  MessageType.ERROR,
80
90
  )
81
91
 
82
92
  return None
83
93
 
84
- RE_LINEBREAKS = re.compile(r"\r\n|\r|\n")
85
-
86
94
  def format_robot_tidy(
87
95
  self,
88
96
  document: TextDocument,
@@ -91,28 +99,24 @@ class RobotFormattingProtocolPart(RobotLanguageServerProtocolPart, ModelHelper):
91
99
  config: Optional[RoboTidyConfig] = None,
92
100
  **further_options: Any,
93
101
  ) -> Optional[List[TextEdit]]:
94
- from robotidy.version import __version__
95
-
96
102
  try:
97
103
  if config is None:
98
- config = self.get_config(document)
99
-
100
- robotidy_version = create_version_from_str(__version__)
104
+ config = self.get_tidy_config(document)
101
105
 
102
106
  model = self.parent.documents_cache.get_model(document, False)
103
107
 
104
- if robotidy_version >= (3, 0):
108
+ if self.robotidy_version >= (3, 0):
105
109
  from robotidy.api import get_robotidy
106
110
  from robotidy.disablers import RegisterDisablers
107
111
 
108
- if robotidy_version >= (4, 2):
112
+ if self.robotidy_version >= (4, 2):
109
113
  robot_tidy = get_robotidy(
110
114
  document.uri.to_path(),
111
115
  None,
112
116
  ignore_git_dir=config.ignore_git_dir,
113
117
  config=config.config,
114
118
  )
115
- elif robotidy_version >= (4, 1):
119
+ elif self.robotidy_version >= (4, 1):
116
120
  robot_tidy = get_robotidy(
117
121
  document.uri.to_path(),
118
122
  None,
@@ -131,14 +135,14 @@ class RobotFormattingProtocolPart(RobotLanguageServerProtocolPart, ModelHelper):
131
135
  )
132
136
  disabler_finder.visit(model)
133
137
 
134
- if robotidy_version >= (4, 11):
138
+ if self.robotidy_version >= (4, 11):
135
139
  if disabler_finder.is_disabled_in_file():
136
140
  return None
137
141
  else:
138
142
  if disabler_finder.file_disabled:
139
143
  return None
140
144
 
141
- if robotidy_version >= (4, 0):
145
+ if self.robotidy_version >= (4, 0):
142
146
  _, _, new, _ = robot_tidy.transform_until_stable(model, disabler_finder)
143
147
  else:
144
148
  _, _, new = robot_tidy.transform(model, disabler_finder.disablers)
@@ -152,7 +156,7 @@ class RobotFormattingProtocolPart(RobotLanguageServerProtocolPart, ModelHelper):
152
156
  robot_tidy.formatting_config.start_line = range.start.line + 1
153
157
  robot_tidy.formatting_config.end_line = range.end.line + 1
154
158
 
155
- if robotidy_version >= (2, 2):
159
+ if self.robotidy_version >= (2, 2):
156
160
  from robotidy.disablers import RegisterDisablers
157
161
 
158
162
  disabler_finder = RegisterDisablers(
@@ -186,6 +190,52 @@ class RobotFormattingProtocolPart(RobotLanguageServerProtocolPart, ModelHelper):
186
190
  self.parent.window.show_message(f"Executing `robotidy` failed: {e}", MessageType.ERROR)
187
191
  return None
188
192
 
193
+ def format_robocop(
194
+ self,
195
+ document: TextDocument,
196
+ options: FormattingOptions,
197
+ range: Optional[Range] = None,
198
+ **further_options: Any,
199
+ ) -> Optional[List[TextEdit]]:
200
+ from robocop.config import ConfigManager
201
+ from robocop.formatter.runner import RobocopFormatter
202
+
203
+ robocop_config = self.get_robocop_config(document)
204
+ workspace_folder = self.parent.workspace.get_workspace_folder(document.uri)
205
+
206
+ config_manager = ConfigManager(
207
+ [document.uri.to_path()],
208
+ root=workspace_folder.uri.to_path() if workspace_folder else None,
209
+ config=robocop_config.config_file,
210
+ ignore_git_dir=robocop_config.ignore_git_dir,
211
+ ignore_file_config=robocop_config.ignore_file_config,
212
+ )
213
+
214
+ config = config_manager.get_config_for_source_file(document.uri.to_path())
215
+
216
+ if range is not None:
217
+ config.formatter.start_line = range.start.line + 1
218
+ config.formatter.end_line = range.end.line + 1
219
+
220
+ runner = RobocopFormatter(config_manager)
221
+ runner.config = config
222
+
223
+ model = self.parent.documents_cache.get_model(document, False)
224
+ _, _, new, _ = runner.format_until_stable(model)
225
+
226
+ if new.text == document.text():
227
+ return None
228
+
229
+ return [
230
+ TextEdit(
231
+ range=Range(
232
+ start=Position(line=0, character=0),
233
+ end=Position(line=len(document.get_lines()), character=0),
234
+ ),
235
+ new_text=new.text,
236
+ )
237
+ ]
238
+
189
239
  def format_internal(
190
240
  self,
191
241
  document: TextDocument,
@@ -233,8 +283,8 @@ class RobotFormattingProtocolPart(RobotLanguageServerProtocolPart, ModelHelper):
233
283
  options: FormattingOptions,
234
284
  **further_options: Any,
235
285
  ) -> Optional[List[TextEdit]]:
236
- config = self.get_config(document)
237
- if config.enabled and robotidy_installed():
286
+ config = self.get_tidy_config(document)
287
+ if (config.enabled and self.robotidy_installed) or (self.robocop_installed and self.robocop_version >= (6, 0)):
238
288
  return self.format_robot_tidy(document, options, range=range, config=config, **further_options)
239
289
 
240
290
  return None
@@ -163,7 +163,7 @@ class RobotHoverProtocolPart(RobotLanguageServerProtocolPart, ModelHelper):
163
163
  else:
164
164
  value = ""
165
165
 
166
- text = f"### {variable.type.value.title()} `{variable.name}`\n\n"
166
+ text = f"### {variable.type.value.title()} `{variable.convertable_name}`\n\n"
167
167
 
168
168
  if value:
169
169
  text += "```python\n"
@@ -2,6 +2,7 @@ from dataclasses import dataclass
2
2
  from typing import TYPE_CHECKING, Any, List, Optional
3
3
 
4
4
  from robotcode.core.lsp.types import TextDocumentIdentifier
5
+ from robotcode.core.uri import Uri
5
6
  from robotcode.core.utils.dataclasses import CamelSnakeMixin
6
7
  from robotcode.core.utils.logging import LoggingDescriptor
7
8
  from robotcode.jsonrpc2.protocol import rpc_method
@@ -16,6 +17,26 @@ if TYPE_CHECKING:
16
17
  @dataclass(repr=False)
17
18
  class GetDocumentImportsParams(CamelSnakeMixin):
18
19
  text_document: TextDocumentIdentifier
20
+ no_documentation: Optional[bool] = None
21
+
22
+
23
+ @dataclass(repr=False)
24
+ class GetDocumentKeywordsParams(CamelSnakeMixin):
25
+ text_document: TextDocumentIdentifier
26
+ no_documentation: Optional[bool] = None
27
+
28
+
29
+ @dataclass(repr=False)
30
+ class GetLibraryDocumentationParams(CamelSnakeMixin):
31
+ workspace_folder_uri: str
32
+ library_name: str
33
+
34
+
35
+ @dataclass(repr=False)
36
+ class GetKeywordDocumentationParams(CamelSnakeMixin):
37
+ workspace_folder_uri: str
38
+ library_name: str
39
+ keyword_name: str
19
40
 
20
41
 
21
42
  @dataclass(repr=False)
@@ -26,6 +47,14 @@ class Keyword(CamelSnakeMixin):
26
47
  documentation: Optional[str] = None
27
48
 
28
49
 
50
+ @dataclass(repr=False)
51
+ class LibraryDocumentation(CamelSnakeMixin):
52
+ name: str
53
+ documentation: Optional[str] = None
54
+ keywords: Optional[List[Keyword]] = None
55
+ initializers: Optional[List[Keyword]] = None
56
+
57
+
29
58
  @dataclass(repr=False)
30
59
  class DocumentImport(CamelSnakeMixin):
31
60
  name: str
@@ -54,6 +83,7 @@ class RobotKeywordsTreeViewPart(RobotLanguageServerProtocolPart, ModelHelper):
54
83
  def _get_document_imports(
55
84
  self,
56
85
  text_document: TextDocumentIdentifier,
86
+ no_documentation: Optional[bool] = None,
57
87
  *args: Any,
58
88
  **kwargs: Any,
59
89
  ) -> Optional[List[DocumentImport]]:
@@ -72,16 +102,18 @@ class RobotKeywordsTreeViewPart(RobotLanguageServerProtocolPart, ModelHelper):
72
102
  alias=v.alias,
73
103
  id=str(hash(v)),
74
104
  type="library",
75
- documentation=v.library_doc.to_markdown(add_signature=False),
105
+ documentation=v.library_doc.to_markdown(add_signature=False) if not no_documentation else None,
76
106
  keywords=[
77
107
  Keyword(
78
108
  l.name,
79
109
  str(hash(l)),
80
110
  l.parameter_signature(),
81
- l.to_markdown(add_signature=False),
111
+ l.to_markdown(add_signature=False) if not no_documentation else None,
82
112
  )
83
113
  for l in v.library_doc.keywords.values()
84
- ],
114
+ ]
115
+ if not no_documentation
116
+ else None,
85
117
  )
86
118
  )
87
119
  for _k, v in namespace.get_resources().items():
@@ -91,21 +123,29 @@ class RobotKeywordsTreeViewPart(RobotLanguageServerProtocolPart, ModelHelper):
91
123
  alias=None,
92
124
  id=str(hash(v)),
93
125
  type="resource",
94
- documentation=v.library_doc.to_markdown(add_signature=False),
126
+ documentation=v.library_doc.to_markdown(add_signature=False) if not no_documentation else None,
95
127
  keywords=[
96
- Keyword(l.name, str(hash(l)), l.parameter_signature(), l.to_markdown(add_signature=False))
128
+ Keyword(
129
+ l.name,
130
+ str(hash(l)),
131
+ l.parameter_signature(),
132
+ l.to_markdown(add_signature=False) if not no_documentation else None,
133
+ )
97
134
  for l in v.library_doc.keywords.values()
98
- ],
135
+ ]
136
+ if not no_documentation
137
+ else None,
99
138
  )
100
139
  )
101
140
 
102
141
  return result
103
142
 
104
- @rpc_method(name="robot/keywordsview/getDocumentKeywords", param_type=GetDocumentImportsParams, threaded=True)
143
+ @rpc_method(name="robot/keywordsview/getDocumentKeywords", param_type=GetDocumentKeywordsParams, threaded=True)
105
144
  @_logger.call
106
145
  def _get_document_keywords(
107
146
  self,
108
147
  text_document: TextDocumentIdentifier,
148
+ no_documentation: Optional[bool] = None,
109
149
  *args: Any,
110
150
  **kwargs: Any,
111
151
  ) -> Optional[List[Keyword]]:
@@ -116,7 +156,12 @@ class RobotKeywordsTreeViewPart(RobotLanguageServerProtocolPart, ModelHelper):
116
156
  namespace = self.parent.documents_cache.get_namespace(document)
117
157
 
118
158
  return [
119
- Keyword(l.name, str(hash(l)), l.parameter_signature(), l.to_markdown(add_signature=False))
159
+ Keyword(
160
+ l.name,
161
+ str(hash(l)),
162
+ l.parameter_signature(),
163
+ l.to_markdown(add_signature=False) if not no_documentation else None,
164
+ )
120
165
  for l in namespace.get_library_doc().keywords.values()
121
166
  ]
122
167
 
@@ -165,3 +210,72 @@ class RobotKeywordsTreeViewPart(RobotLanguageServerProtocolPart, ModelHelper):
165
210
  )
166
211
 
167
212
  return None
213
+
214
+ @rpc_method(
215
+ name="robot/keywordsview/getLibraryDocumentation", param_type=GetLibraryDocumentationParams, threaded=True
216
+ )
217
+ @_logger.call
218
+ def _get_library_documentation(
219
+ self,
220
+ workspace_folder_uri: str,
221
+ library_name: str,
222
+ *args: Any,
223
+ **kwargs: Any,
224
+ ) -> Optional[LibraryDocumentation]:
225
+ imports_manager = self.parent.documents_cache.get_imports_manager_for_uri(Uri(workspace_folder_uri))
226
+
227
+ libdoc = imports_manager.get_libdoc_for_library_import(library_name, (), ".")
228
+ if libdoc.errors:
229
+ raise ValueError(f"Errors while loading library documentation: {libdoc.errors}")
230
+
231
+ return LibraryDocumentation(
232
+ name=libdoc.name,
233
+ documentation=libdoc.to_markdown(),
234
+ keywords=[
235
+ Keyword(
236
+ l.name,
237
+ str(hash(l)),
238
+ l.parameter_signature(),
239
+ l.to_markdown(),
240
+ )
241
+ for l in libdoc.keywords.values()
242
+ ],
243
+ initializers=[
244
+ Keyword(
245
+ s.name,
246
+ str(hash(s)),
247
+ s.parameter_signature(),
248
+ s.to_markdown(),
249
+ )
250
+ for s in libdoc.inits.values()
251
+ ],
252
+ )
253
+
254
+ @rpc_method(
255
+ name="robot/keywordsview/getKeywordDocumentation", param_type=GetKeywordDocumentationParams, threaded=True
256
+ )
257
+ @_logger.call
258
+ def _get_keyword_documentation(
259
+ self,
260
+ workspace_folder_uri: str,
261
+ library_name: str,
262
+ keyword_name: str,
263
+ *args: Any,
264
+ **kwargs: Any,
265
+ ) -> Optional[Keyword]:
266
+ imports_manager = self.parent.documents_cache.get_imports_manager_for_uri(Uri(workspace_folder_uri))
267
+
268
+ libdoc = imports_manager.get_libdoc_for_library_import(library_name, (), ".")
269
+ if libdoc.errors:
270
+ raise ValueError(f"Errors while loading library documentation: {libdoc.errors}")
271
+
272
+ kw = libdoc.keywords.get(keyword_name, None)
273
+ if kw is None:
274
+ raise ValueError(f"Keyword '{keyword_name}' not found in library '{library_name}'.")
275
+
276
+ return Keyword(
277
+ name=kw.name,
278
+ id=str(hash(kw)),
279
+ signature=kw.parameter_signature(),
280
+ documentation=kw.to_markdown(),
281
+ )
@@ -1,3 +1,4 @@
1
+ import sys
1
2
  from dataclasses import dataclass
2
3
  from typing import TYPE_CHECKING, Any, Optional
3
4
 
@@ -7,9 +8,9 @@ from robotcode.core.utils.dataclasses import CamelSnakeMixin
7
8
  from robotcode.core.utils.logging import LoggingDescriptor
8
9
  from robotcode.jsonrpc2.protocol import rpc_method
9
10
 
10
- from .formatting import robotidy_installed
11
+ from ...__version__ import __version__ as robotcode_version
11
12
  from .protocol_part import RobotLanguageServerProtocolPart
12
- from .robocop_diagnostics import robocop_installed
13
+ from .robocop_tidy_mixin import RoboCopTidyMixin
13
14
 
14
15
  if TYPE_CHECKING:
15
16
  from ..protocol import RobotLanguageServerProtocol
@@ -20,9 +21,12 @@ class ProjectInfo(CamelSnakeMixin):
20
21
  robot_version_string: str
21
22
  robocop_version_string: Optional[str]
22
23
  tidy_version_string: Optional[str] = None
24
+ python_version_string: Optional[str] = None
25
+ python_executable: Optional[str] = None
26
+ robot_code_version_string: Optional[str] = None
23
27
 
24
28
 
25
- class ProjectInfoPart(RobotLanguageServerProtocolPart):
29
+ class ProjectInfoPart(RobotLanguageServerProtocolPart, RoboCopTidyMixin):
26
30
  _logger = LoggingDescriptor()
27
31
 
28
32
  def __init__(self, parent: "RobotLanguageServerProtocol") -> None:
@@ -30,25 +34,24 @@ class ProjectInfoPart(RobotLanguageServerProtocolPart):
30
34
 
31
35
  @rpc_method(name="robot/projectInfo", threaded=True)
32
36
  @_logger.call
33
- def _get_document_imports(
37
+ def _robot_project_info(
34
38
  self,
35
39
  *args: Any,
36
40
  **kwargs: Any,
37
41
  ) -> ProjectInfo:
38
42
  robocop_version_string = None
39
- if robocop_installed():
40
- from robocop.version import __version__
41
-
42
- robocop_version_string = __version__
43
+ if self.robocop_installed:
44
+ robocop_version_string = self.robocop_version_str
43
45
 
44
46
  tidy_version_string = None
45
- if robotidy_installed():
46
- from robotidy.version import __version__
47
-
48
- tidy_version_string = __version__
47
+ if self.robotidy_installed:
48
+ tidy_version_string = self.robotidy_version_str
49
49
 
50
50
  return ProjectInfo(
51
51
  robot_version_string=get_version(),
52
52
  robocop_version_string=robocop_version_string,
53
53
  tidy_version_string=tidy_version_string,
54
+ python_version_string=sys.version,
55
+ python_executable=sys.executable,
56
+ robot_code_version_string=robotcode_version,
54
57
  )
@@ -1,5 +1,6 @@
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 (
@@ -17,28 +18,24 @@ from robotcode.core.workspace import WorkspaceFolder
17
18
  from ...common.parts.diagnostics import DiagnosticsCollectType, DiagnosticsResult
18
19
  from ..configuration import RoboCopConfig
19
20
  from .protocol_part import RobotLanguageServerProtocolPart
21
+ from .robocop_tidy_mixin import RoboCopTidyMixin
20
22
 
21
23
  if TYPE_CHECKING:
22
- from ..protocol import RobotLanguageServerProtocol
23
-
24
+ from robocop.linter.runner import RobocopLinter
24
25
 
25
- def robocop_installed() -> bool:
26
- try:
27
- __import__("robocop")
28
- except ImportError:
29
- return False
30
- return True
26
+ from ..protocol import RobotLanguageServerProtocol
31
27
 
32
28
 
33
- class RobotRoboCopDiagnosticsProtocolPart(RobotLanguageServerProtocolPart):
29
+ class RobotRoboCopDiagnosticsProtocolPart(RobotLanguageServerProtocolPart, RoboCopTidyMixin):
34
30
  _logger = LoggingDescriptor()
35
31
 
36
32
  def __init__(self, parent: "RobotLanguageServerProtocol") -> None:
37
33
  super().__init__(parent)
38
34
 
39
35
  self.source_name = "robocop"
36
+ self._robocop_linters: WeakKeyDictionary[WorkspaceFolder, "RobocopLinter"] = WeakKeyDictionary()
40
37
 
41
- if robocop_installed():
38
+ if self.robocop_installed:
42
39
  parent.diagnostics.collect.add(self.collect_diagnostics)
43
40
 
44
41
  def get_config(self, document: TextDocument) -> Optional[RoboCopConfig]:
@@ -52,18 +49,26 @@ class RobotRoboCopDiagnosticsProtocolPart(RobotLanguageServerProtocolPart):
52
49
  @_logger.call
53
50
  def collect_diagnostics(
54
51
  self, sender: Any, document: TextDocument, diagnostics_type: DiagnosticsCollectType
55
- ) -> DiagnosticsResult:
56
- workspace_folder = self.parent.workspace.get_workspace_folder(document.uri)
57
- if workspace_folder is not None:
58
- extension_config = self.get_config(document)
59
-
60
- if extension_config is not None and extension_config.enabled:
61
- return DiagnosticsResult(
62
- self.collect_diagnostics,
63
- self.collect(document, workspace_folder, extension_config),
64
- )
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
+ )
65
+
66
+ return DiagnosticsResult(
67
+ self.collect_diagnostics,
68
+ self.collect_old(document, workspace_folder, config),
69
+ )
65
70
 
66
- return DiagnosticsResult(self.collect_diagnostics, [])
71
+ return None
67
72
 
68
73
  @_logger.call
69
74
  def collect(
@@ -71,6 +76,69 @@ class RobotRoboCopDiagnosticsProtocolPart(RobotLanguageServerProtocolPart):
71
76
  document: TextDocument,
72
77
  workspace_folder: WorkspaceFolder,
73
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,
74
142
  ) -> List[Diagnostic]:
75
143
  from robocop import __version__
76
144
  from robocop.config import Config
@@ -181,7 +249,9 @@ class RobotRoboCopDiagnosticsProtocolPart(RobotLanguageServerProtocolPart):
181
249
  if version < (3, 0):
182
250
  return None
183
251
 
184
- 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}"
185
255
 
186
256
  if version < (4, 0):
187
257
  return CodeDescription(href=f"{base}/rules.html#{issue.name}".lower())
@@ -194,4 +264,7 @@ class RobotRoboCopDiagnosticsProtocolPart(RobotLanguageServerProtocolPart):
194
264
  href=f"{base}/rules_list.html#{issue.name}-{issue.severity.value}{issue.rule_id}".lower()
195
265
  )
196
266
 
197
- 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,0 +1,49 @@
1
+ import functools
2
+
3
+ from robotcode.core.utils.version import Version, create_version_from_str
4
+
5
+
6
+ class RoboCopTidyMixin:
7
+ """
8
+ Mixin class for handling Robocop tidy operations.
9
+ """
10
+
11
+ @functools.cached_property
12
+ def robotidy_installed(self) -> bool:
13
+ try:
14
+ __import__("robotidy")
15
+ except ImportError:
16
+ return False
17
+ return True
18
+
19
+ @functools.cached_property
20
+ def robotidy_version(self) -> Version:
21
+ from robotidy.version import __version__
22
+
23
+ return create_version_from_str(__version__)
24
+
25
+ @functools.cached_property
26
+ def robotidy_version_str(self) -> str:
27
+ from robotidy.version import __version__
28
+
29
+ return str(__version__)
30
+
31
+ @functools.cached_property
32
+ def robocop_installed(self) -> bool:
33
+ try:
34
+ __import__("robocop")
35
+ except ImportError:
36
+ return False
37
+ return True
38
+
39
+ @functools.cached_property
40
+ def robocop_version(self) -> Version:
41
+ from robocop import __version__
42
+
43
+ return create_version_from_str(__version__)
44
+
45
+ @functools.cached_property
46
+ def robocop_version_str(self) -> str:
47
+ from robocop import __version__
48
+
49
+ return str(__version__)
@@ -70,7 +70,7 @@ from robotcode.robot.utils.ast import (
70
70
  iter_over_keyword_names_and_owners,
71
71
  token_in_range,
72
72
  )
73
- from robotcode.robot.utils.variables import is_variable, split_from_equals
73
+ from robotcode.robot.utils.variables import split_from_equals
74
74
 
75
75
  from .protocol_part import RobotLanguageServerProtocolPart
76
76
 
@@ -116,6 +116,8 @@ class RobotSemTokenTypes(Enum):
116
116
  FOR_SEPARATOR = "forSeparator"
117
117
  VARIABLE_BEGIN = "variableBegin"
118
118
  VARIABLE_END = "variableEnd"
119
+ EXPRESSION_BEGIN = "expressionBegin"
120
+ EXPRESSION_END = "expressionEnd"
119
121
  VARIABLE_EXPRESSION = "variableExpression"
120
122
  ESCAPE = "escape"
121
123
  NAMESPACE = "namespace"
@@ -362,46 +364,8 @@ class RobotSemanticTokenProtocolPart(RobotLanguageServerProtocolPart):
362
364
  sem_mod = {SemanticTokenModifiers.DOCUMENTATION}
363
365
 
364
366
  if token.type in [Token.VARIABLE, Token.ASSIGN]:
365
- if is_variable(token.value, "$@&%"):
366
- if col_offset is None:
367
- col_offset = token.col_offset
368
- if length is None:
369
- length = token.end_col_offset - token.col_offset
370
-
371
- last_index = token.value.rfind("}")
372
-
373
- is_expr = token.value[1:2] == "{" and token.value[last_index - 1 : last_index] == "}"
374
-
375
- if last_index >= 0:
376
- yield SemTokenInfo(
377
- token.lineno,
378
- col_offset,
379
- 3 if is_expr else 2,
380
- RobotSemTokenTypes.VARIABLE_BEGIN,
381
- sem_mod,
382
- )
383
-
384
- yield SemTokenInfo(
385
- token.lineno,
386
- col_offset + ((last_index - 1) if is_expr else last_index),
387
- 2 if is_expr else 1,
388
- RobotSemTokenTypes.VARIABLE_END,
389
- sem_mod,
390
- )
391
-
392
- if length - last_index - 1 > 0:
393
- yield SemTokenInfo.from_token(
394
- token,
395
- sem_type,
396
- sem_mod,
397
- col_offset + last_index + 1,
398
- length - last_index - 1,
399
- )
400
- else:
401
- yield SemTokenInfo.from_token(token, sem_type, sem_mod)
402
-
403
- else:
404
- yield SemTokenInfo.from_token(token, sem_type, sem_mod)
367
+ # TODO: maybe we can distinguish between local and global variables, by default all variables are global
368
+ pass
405
369
 
406
370
  elif token.type in [Token.KEYWORD, ROBOT_KEYWORD_INNER] or (
407
371
  token.type == Token.NAME and cached_isinstance(node, Fixture, Template, TestTemplate)
@@ -507,7 +471,9 @@ class RobotSemanticTokenProtocolPart(RobotLanguageServerProtocolPart):
507
471
  sem_mod.add(RobotSemTokenModifiers.BUILTIN)
508
472
 
509
473
  if kw_doc is not None and kw_doc.is_embedded and kw_doc.matcher.embedded_arguments:
510
- if get_robot_version() >= (6, 0):
474
+ if get_robot_version() >= (7, 3):
475
+ m = kw_doc.matcher.embedded_arguments.name.fullmatch(kw)
476
+ elif get_robot_version() >= (6, 0):
511
477
  m = kw_doc.matcher.embedded_arguments.match(kw)
512
478
  else:
513
479
  m = kw_doc.matcher.embedded_arguments.name.match(kw)
@@ -1 +0,0 @@
1
- __version__ = "1.2.0"