Skip to content

Commit d2cf28c

Browse files
committed
implement localizations for robot >= 5.1
1 parent 21e4380 commit d2cf28c

File tree

7 files changed

+161
-32
lines changed

7 files changed

+161
-32
lines changed

package.json

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -312,6 +312,15 @@
312312
"description": "Specifies the environment variables for robotframework.",
313313
"scope": "resource"
314314
},
315+
"robotcode.robot.languages": {
316+
"type": "array",
317+
"default": [],
318+
"items": {
319+
"type": "string"
320+
},
321+
"markdownDescription": "Specifies the supported language(s) that can be used to write _robot_ files. Corresponds to the '`--language lang *`' option of __robot__.",
322+
"scope": "resource"
323+
},
315324
"robotcode.robot.variables": {
316325
"type": "object",
317326
"default": {},
@@ -637,6 +646,14 @@
637646
"description": "Defines a template for the python launch configuration.",
638647
"default": {}
639648
},
649+
"languages": {
650+
"type": "array",
651+
"default": [],
652+
"items": {
653+
"type": "string"
654+
},
655+
"markdownDescription": "Specifies the supported language(s) that can be used to write _robot_ files. Corresponds to the '`--language lang *`' option of __robot__."
656+
},
640657
"variables": {
641658
"type": "object",
642659
"default": {},

robotcode/debugger/launcher/server.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,7 @@ async def _launch(
145145
dryRun: Optional[bool] = None,
146146
mode: Optional[str] = None,
147147
variableFiles: Optional[List[str]] = None,
148+
languages: Optional[List[str]] = None,
148149
arguments: Optional[LaunchRequestArguments] = None,
149150
*_args: Any,
150151
**_kwargs: Any,
@@ -184,6 +185,10 @@ async def _launch(
184185

185186
run_args += ["--"]
186187

188+
if languages:
189+
for lang in languages:
190+
run_args += ["--language", lang]
191+
187192
if mode:
188193
if mode == "rpa":
189194
run_args += ["--rpa"]

robotcode/language_server/robotframework/configuration.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ class RobotConfig(ConfigBase):
3535
debug_file: Optional[str] = None
3636
log_level: Optional[str] = None
3737
mode: Optional[RpaMode] = None
38+
languages: Optional[List[str]] = None
3839

3940
def get_rpa_mode(self) -> Optional[bool]:
4041
if self.mode == RpaMode.RPA:

robotcode/language_server/robotframework/parts/discovering.py

Lines changed: 56 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,13 @@ async def _get_tests_from_workspace(
125125
SuiteStructureParser,
126126
TestSuiteBuilder,
127127
)
128-
from robot.running.builder.testsettings import TestDefaults
128+
129+
from ..utils.version import get_robot_version
130+
131+
if get_robot_version() >= (5, 1):
132+
from robot.running.builder.settings import Defaults as TestDefaults
133+
else:
134+
from robot.running.builder.testsettings import TestDefaults
129135

130136
def get_document_text(source: str) -> str:
131137
if self.parent._loop:
@@ -159,7 +165,15 @@ def _build(
159165
defaults = TestDefaults()
160166
if model is None:
161167
try:
162-
model = get_model(self._get_source(source), data_only=True, curdir=self._get_curdir(source))
168+
if get_robot_version() >= (5, 1):
169+
model = get_model(
170+
self._get_source(source),
171+
data_only=True,
172+
curdir=self._get_curdir(source),
173+
lang=self.lang,
174+
)
175+
else:
176+
model = get_model(self._get_source(source), data_only=True, curdir=self._get_curdir(source))
163177
except (asyncio.CancelledError, SystemExit, KeyboardInterrupt):
164178
raise
165179
except BaseException:
@@ -181,6 +195,24 @@ def _get_source(self, source: str) -> Any:
181195
with FileReader(source) as reader:
182196
return read_rest_data(reader)
183197

198+
class MySuiteStructureParserWithLang(SuiteStructureParser):
199+
def _get_parsers(self, extensions: List[str], lang: Any, process_curdir: bool) -> RobotParser:
200+
robot_parser = MyRobotParser(lang, process_curdir)
201+
rest_parser = MyRestParser(lang, process_curdir)
202+
parsers = {
203+
None: NoInitFileDirectoryParser(),
204+
"robot": robot_parser,
205+
"rst": rest_parser,
206+
"rest": rest_parser,
207+
}
208+
for ext in extensions:
209+
if ext not in parsers:
210+
parsers[ext] = robot_parser
211+
return parsers
212+
213+
def _validate_execution_mode(self, suite: Any) -> None:
214+
super()._validate_execution_mode(suite)
215+
184216
class MySuiteStructureParser(SuiteStructureParser):
185217
def _get_parsers(self, extensions: List[str], process_curdir: bool) -> RobotParser:
186218
robot_parser = MyRobotParser(process_curdir)
@@ -206,7 +238,12 @@ def _validate_test_counts(self, suite: TestSuite, multisource: bool = False) ->
206238

207239
def build(self, *paths: str) -> TestSuite:
208240
structure = SuiteStructureBuilder(self.included_extensions, self.included_suites).build(paths)
209-
parser = MySuiteStructureParser(self.included_extensions, self.rpa, self.process_curdir)
241+
if get_robot_version() >= (5, 1):
242+
parser = MySuiteStructureParserWithLang(
243+
self.included_extensions, self.rpa, self.lang, self.process_curdir
244+
)
245+
else:
246+
parser = MySuiteStructureParser(self.included_extensions, self.rpa, self.process_curdir)
210247
suite = parser.parse(structure)
211248
if not self.included_suites and not self.allow_empty_suite:
212249
self._validate_test_counts(suite, multisource=len(paths) > 1)
@@ -259,6 +296,7 @@ def generate(suite: TestSuite) -> TestItem:
259296
try:
260297
config = await self.get_config(workspace_folder)
261298
rpa_mode = config.get_rpa_mode() if config is not None else None
299+
languages = config.languages if config is not None else None
262300

263301
if paths is None and config is not None:
264302
paths = config.paths
@@ -290,14 +328,15 @@ def nonexisting_paths(paths: List[str]) -> Iterator[str]:
290328
yield str(p)
291329

292330
valid_paths = [i for i in normalize_paths(paths)]
293-
suite: Optional[TestSuite] = (
294-
MyTestSuiteBuilder(
295-
included_suites=suites if suites else None,
296-
rpa=rpa_mode,
297-
).build(*valid_paths)
298-
if valid_paths
299-
else None
300-
)
331+
332+
if get_robot_version() >= (5, 1):
333+
builder = MyTestSuiteBuilder(
334+
included_suites=suites if suites else None, rpa=rpa_mode, lang=languages
335+
)
336+
else:
337+
builder = MyTestSuiteBuilder(included_suites=suites if suites else None, rpa=rpa_mode)
338+
339+
suite: Optional[TestSuite] = builder.build(*valid_paths) if valid_paths else None
301340
suite_item = [generate(suite)] if suite else []
302341

303342
return [
@@ -323,13 +362,13 @@ def nonexisting_paths(paths: List[str]) -> Iterator[str]:
323362
)
324363
]
325364
else:
326-
return [
327-
generate(
328-
MyTestSuiteBuilder(included_suites=suites if suites else None, rpa=rpa_mode).build(
329-
str(workspace_path)
330-
)
365+
if get_robot_version() >= (5, 1):
366+
builder = MyTestSuiteBuilder(
367+
included_suites=suites if suites else None, rpa=rpa_mode, lang=languages
331368
)
332-
]
369+
else:
370+
builder = MyTestSuiteBuilder(included_suites=suites if suites else None, rpa=rpa_mode)
371+
return [generate(builder.build(str(workspace_path)))]
333372
except (SystemExit, KeyboardInterrupt):
334373
raise
335374
except BaseException as e:

robotcode/language_server/robotframework/parts/documents_cache.py

Lines changed: 71 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
from ..diagnostics.imports_manager import ImportsManager
2929
from ..diagnostics.namespace import DocumentType, Namespace
3030
from ..utils.ast_utils import Token
31+
from ..utils.version import get_robot_version
3132

3233
if TYPE_CHECKING:
3334
from ..protocol import RobotLanguageServerProtocol
@@ -47,6 +48,23 @@ def __init__(self, parent: RobotLanguageServerProtocol) -> None:
4748
self._imports_managers: weakref.WeakKeyDictionary[WorkspaceFolder, ImportsManager] = weakref.WeakKeyDictionary()
4849
self._default_imports_manager: Optional[ImportsManager] = None
4950

51+
async def get_languages(self, document: TextDocument) -> Optional[List[str]]:
52+
if get_robot_version() < (5, 1):
53+
return None
54+
55+
folder = self.parent.workspace.get_workspace_folder(document.uri)
56+
if folder is None:
57+
return None
58+
59+
config = await self.parent.workspace.get_configuration(RobotConfig, folder.uri)
60+
61+
lang = config.languages
62+
63+
if isinstance(lang, List) and len(lang) == 0:
64+
lang = None
65+
66+
return lang
67+
5068
async def get_document_type(self, document: TextDocument) -> DocumentType:
5169
return await document.get_cache(self.__get_document_type)
5270

@@ -95,21 +113,59 @@ async def get_general_tokens(self, document: TextDocument, data_only: bool = Fal
95113
return await document.get_cache(self.__get_general_tokens_data_only)
96114
return await document.get_cache(self.__get_general_tokens)
97115

98-
async def __get_general_tokens_data_only(self, document: TextDocument) -> List[Token]:
116+
def __internal_get_tokens(
117+
self, source: Any, data_only: bool = False, tokenize_variables: bool = False, lang: Any = None
118+
) -> Any:
99119
import robot.api
100120

121+
if get_robot_version() >= (5, 1):
122+
return robot.api.get_tokens(source, data_only=data_only, tokenize_variables=tokenize_variables, lang=lang)
123+
else:
124+
return robot.api.get_tokens(source, data_only=data_only, tokenize_variables=tokenize_variables)
125+
126+
def __internal_get_resource_tokens(
127+
self,
128+
source: Any,
129+
data_only: bool = False,
130+
tokenize_variables: bool = False,
131+
lang: Any = None,
132+
) -> Any:
133+
import robot.api
134+
135+
if get_robot_version() >= (5, 1):
136+
return robot.api.get_resource_tokens(
137+
source, data_only=data_only, tokenize_variables=tokenize_variables, lang=lang
138+
)
139+
else:
140+
return robot.api.get_resource_tokens(source, data_only=data_only, tokenize_variables=tokenize_variables)
141+
142+
def __internal_get_init_tokens(
143+
self, source: Any, data_only: bool = False, tokenize_variables: bool = False, lang: Any = None
144+
) -> Any:
145+
import robot.api
146+
147+
if get_robot_version() >= (5, 1):
148+
return robot.api.get_init_tokens(
149+
source, data_only=data_only, tokenize_variables=tokenize_variables, lang=lang
150+
)
151+
else:
152+
return robot.api.get_init_tokens(source, data_only=data_only, tokenize_variables=tokenize_variables)
153+
154+
async def __get_general_tokens_data_only(self, document: TextDocument) -> List[Token]:
155+
lang = await self.get_languages(document)
156+
101157
def get(text: str) -> List[Token]:
102158
with io.StringIO(text) as content:
103-
return [e for e in robot.api.get_tokens(content, True) if check_canceled_sync()]
159+
return [e for e in self.__internal_get_tokens(content, True, lang=lang) if check_canceled_sync()]
104160

105161
return await self.__get_tokens_internal(document, get)
106162

107163
async def __get_general_tokens(self, document: TextDocument) -> List[Token]:
108-
import robot.api
164+
lang = await self.get_languages(document)
109165

110166
def get(text: str) -> List[Token]:
111167
with io.StringIO(text) as content:
112-
return [e for e in robot.api.get_tokens(content) if check_canceled_sync()]
168+
return [e for e in self.__internal_get_tokens(content, lang=lang) if check_canceled_sync()]
113169

114170
return await self.__get_tokens_internal(document, get)
115171

@@ -128,20 +184,22 @@ async def get_resource_tokens(self, document: TextDocument, data_only: bool = Fa
128184
return await document.get_cache(self.__get_resource_tokens)
129185

130186
async def __get_resource_tokens_data_only(self, document: TextDocument) -> List[Token]:
131-
import robot.api
187+
lang = await self.get_languages(document)
132188

133189
def get(text: str) -> List[Token]:
134190
with io.StringIO(text) as content:
135-
return [e for e in robot.api.get_resource_tokens(content, True) if check_canceled_sync()]
191+
return [
192+
e for e in self.__internal_get_resource_tokens(content, True, lang=lang) if check_canceled_sync()
193+
]
136194

137195
return await self.__get_tokens_internal(document, get)
138196

139197
async def __get_resource_tokens(self, document: TextDocument) -> List[Token]:
140-
import robot.api
198+
lang = await self.get_languages(document)
141199

142200
def get(text: str) -> List[Token]:
143201
with io.StringIO(text) as content:
144-
return [e for e in robot.api.get_resource_tokens(content) if check_canceled_sync()]
202+
return [e for e in self.__internal_get_resource_tokens(content, lang=lang) if check_canceled_sync()]
145203

146204
return await self.__get_tokens_internal(document, get)
147205

@@ -151,20 +209,20 @@ async def get_init_tokens(self, document: TextDocument, data_only: bool = False)
151209
return await document.get_cache(self.__get_init_tokens)
152210

153211
async def __get_init_tokens_data_only(self, document: TextDocument) -> List[Token]:
154-
import robot.api
212+
lang = await self.get_languages(document)
155213

156214
def get(text: str) -> List[Token]:
157215
with io.StringIO(text) as content:
158-
return [e for e in robot.api.get_init_tokens(content, True) if check_canceled_sync()]
216+
return [e for e in self.__internal_get_init_tokens(content, True, lang=lang) if check_canceled_sync()]
159217

160218
return await self.__get_tokens_internal(document, get)
161219

162220
async def __get_init_tokens(self, document: TextDocument) -> List[Token]:
163-
import robot.api
221+
lang = await self.get_languages(document)
164222

165223
def get(text: str) -> List[Token]:
166224
with io.StringIO(text) as content:
167-
return [e for e in robot.api.get_init_tokens(content) if check_canceled_sync()]
225+
return [e for e in self.__internal_get_init_tokens(content, lang=lang) if check_canceled_sync()]
168226

169227
return await self.__get_tokens_internal(document, get)
170228

@@ -184,7 +242,7 @@ def __get_model(self, document: TextDocument, tokens: Iterable[Any], document_ty
184242
from robot.parsing.lexer import Token
185243
from robot.parsing.parser.parser import _get_model
186244

187-
def get_tokens(_source: str, _data_only: bool = False) -> Generator[Token, None, None]:
245+
def get_tokens(source: str, data_only: bool = False, lang: Any = None) -> Generator[Token, None, None]:
188246
for t in tokens:
189247
check_canceled_sync()
190248

robotcode/language_server/robotframework/utils/version.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,16 @@ class Version(NamedTuple):
1818
dev: Optional[int] = None
1919

2020

21+
_robot_version: Optional[Version] = None
22+
23+
2124
def get_robot_version() -> Version:
22-
import robot
25+
global _robot_version
26+
if _robot_version is None:
27+
import robot
2328

24-
return create_version_from_str(robot.get_version())
29+
return create_version_from_str(robot.get_version())
30+
return _robot_version
2531

2632

2733
def create_version_from_str(version_str: str) -> Version:

vscode-client/debugmanager.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,9 @@ class RobotCodeDebugConfigurationProvider implements vscode.DebugConfigurationPr
126126

127127
debugConfiguration.mode = debugConfiguration?.mode ?? config.get<string | undefined>("robot.mode", undefined);
128128

129+
debugConfiguration.languages =
130+
debugConfiguration?.languages ?? config.get<string | undefined>("robot.languages", undefined);
131+
129132
debugConfiguration.attachPython = debugConfiguration?.attachPython ?? config.get<boolean>("debug.attachPython");
130133

131134
debugConfiguration.outputMessages =

0 commit comments

Comments
 (0)