robotcode-robot 0.68.1__py3-none-any.whl → 0.68.2__py3-none-any.whl

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,377 @@
1
+ from dataclasses import dataclass, field
2
+ from enum import Enum
3
+ from typing import (
4
+ TYPE_CHECKING,
5
+ Any,
6
+ Callable,
7
+ List,
8
+ Optional,
9
+ Tuple,
10
+ TypeVar,
11
+ cast,
12
+ )
13
+
14
+ from robot.parsing.lexer.tokens import Token
15
+ from robotcode.core.lsp.types import Position, Range
16
+ from robotcode.robot.utils.ast import range_from_token
17
+
18
+ if TYPE_CHECKING:
19
+ from robotcode.robot.diagnostics.library_doc import KeywordDoc, LibraryDoc
20
+
21
+ _F = TypeVar("_F", bound=Callable[..., Any])
22
+
23
+
24
+ _NOT_SET = object()
25
+
26
+
27
+ def single_call(func: _F) -> _F:
28
+ name = f"__single_result_{func.__name__}__"
29
+
30
+ def wrapper(self: Any, *args: Any, **kwargs: Any) -> Any:
31
+ result = self.__dict__.get(name, _NOT_SET)
32
+ if result is _NOT_SET:
33
+ result = func(self, *args, **kwargs)
34
+ self.__dict__[name] = result
35
+ return result
36
+
37
+ return cast(_F, wrapper)
38
+
39
+
40
+ @dataclass
41
+ class SourceEntity:
42
+ line_no: int
43
+ col_offset: int
44
+ end_line_no: int
45
+ end_col_offset: int
46
+ source: Optional[str]
47
+
48
+ @property
49
+ def range(self) -> Range:
50
+ return Range(
51
+ start=Position(line=self.line_no - 1, character=self.col_offset),
52
+ end=Position(line=self.end_line_no - 1, character=self.end_col_offset),
53
+ )
54
+
55
+ @single_call
56
+ def __hash__(self) -> int:
57
+ return hash(
58
+ (
59
+ self.line_no,
60
+ self.col_offset,
61
+ self.end_line_no,
62
+ self.end_col_offset,
63
+ self.source,
64
+ )
65
+ )
66
+
67
+
68
+ @dataclass
69
+ class Import(SourceEntity):
70
+ name: Optional[str]
71
+ name_token: Optional[Token]
72
+
73
+ @property
74
+ def range(self) -> Range:
75
+ return Range(
76
+ start=Position(
77
+ line=self.name_token.lineno - 1 if self.name_token is not None else self.line_no - 1,
78
+ character=self.name_token.col_offset if self.name_token is not None else self.col_offset,
79
+ ),
80
+ end=Position(
81
+ line=self.name_token.lineno - 1 if self.name_token is not None else self.end_line_no - 1,
82
+ character=self.name_token.end_col_offset if self.name_token is not None else self.end_col_offset,
83
+ ),
84
+ )
85
+
86
+
87
+ @dataclass
88
+ class LibraryImport(Import):
89
+ args: Tuple[str, ...] = ()
90
+ alias: Optional[str] = None
91
+ alias_token: Optional[Token] = None
92
+
93
+ @property
94
+ def alias_range(self) -> Range:
95
+ return Range(
96
+ start=Position(
97
+ line=self.alias_token.lineno - 1 if self.alias_token is not None else -1,
98
+ character=self.alias_token.col_offset if self.alias_token is not None else -1,
99
+ ),
100
+ end=Position(
101
+ line=self.alias_token.lineno - 1 if self.alias_token is not None else -1,
102
+ character=self.alias_token.end_col_offset if self.alias_token is not None else -1,
103
+ ),
104
+ )
105
+
106
+ @single_call
107
+ def __hash__(self) -> int:
108
+ return hash((type(self), self.name, self.args, self.alias))
109
+
110
+
111
+ @dataclass
112
+ class ResourceImport(Import):
113
+ @single_call
114
+ def __hash__(self) -> int:
115
+ return hash((type(self), self.name))
116
+
117
+
118
+ @dataclass
119
+ class VariablesImport(Import):
120
+ args: Tuple[str, ...] = ()
121
+
122
+ @single_call
123
+ def __hash__(self) -> int:
124
+ return hash((type(self), self.name, self.args))
125
+
126
+
127
+ class InvalidVariableError(Exception):
128
+ pass
129
+
130
+
131
+ class VariableMatcher:
132
+ def __init__(self, name: str) -> None:
133
+ from robot.variables.search import search_variable
134
+ from robotcode.robot.utils.match import normalize
135
+
136
+ self.name = name
137
+
138
+ match = search_variable(name, "$@&%", ignore_errors=True)
139
+
140
+ if match.base is None:
141
+ raise InvalidVariableError(f"Invalid variable '{name}'")
142
+
143
+ self.base = match.base
144
+
145
+ self.normalized_name = str(normalize(self.base))
146
+
147
+ def __eq__(self, o: object) -> bool:
148
+ from robot.utils.normalizing import normalize
149
+ from robot.variables.search import search_variable
150
+
151
+ if isinstance(o, VariableMatcher):
152
+ return o.normalized_name == self.normalized_name
153
+
154
+ if isinstance(o, str):
155
+ match = search_variable(o, "$@&%", ignore_errors=True)
156
+ base = match.base
157
+ normalized = str(normalize(base))
158
+ return self.normalized_name == normalized
159
+
160
+ return False
161
+
162
+ def __hash__(self) -> int:
163
+ return hash(self.name)
164
+
165
+ def __str__(self) -> str:
166
+ return self.name
167
+
168
+ def __repr__(self) -> str:
169
+ return f"{type(self).__name__}(name={self.name!r})"
170
+
171
+
172
+ class VariableDefinitionType(Enum):
173
+ VARIABLE = "suite variable"
174
+ LOCAL_VARIABLE = "local variable"
175
+ ARGUMENT = "argument"
176
+ COMMAND_LINE_VARIABLE = "global variable [command line]"
177
+ BUILTIN_VARIABLE = "builtin variable"
178
+ IMPORTED_VARIABLE = "suite variable [imported]"
179
+ ENVIRONMENT_VARIABLE = "environment variable"
180
+ VARIABLE_NOT_FOUND = "variable not found"
181
+
182
+
183
+ @dataclass
184
+ class VariableDefinition(SourceEntity):
185
+ name: str
186
+ name_token: Optional[Token]
187
+ type: VariableDefinitionType = VariableDefinitionType.VARIABLE
188
+
189
+ has_value: bool = field(default=False, compare=False)
190
+ resolvable: bool = field(default=False, compare=False)
191
+
192
+ value: Any = field(default=None, compare=False)
193
+ value_is_native: bool = field(default=False, compare=False)
194
+
195
+ @property
196
+ def matcher(self) -> VariableMatcher:
197
+ if not hasattr(self, "__matcher"):
198
+ self.__matcher = VariableMatcher(self.name)
199
+ return self.__matcher
200
+
201
+ @single_call
202
+ def __hash__(self) -> int:
203
+ return hash((type(self), self.name, self.type, self.range, self.source))
204
+
205
+ @property
206
+ def name_range(self) -> Range:
207
+ if self.name_token is not None:
208
+ return range_from_token(self.name_token)
209
+
210
+ return self.range
211
+
212
+ @property
213
+ def range(self) -> Range:
214
+ return Range(
215
+ start=Position(line=self.line_no - 1, character=self.col_offset),
216
+ end=Position(line=self.end_line_no - 1, character=self.end_col_offset),
217
+ )
218
+
219
+
220
+ @dataclass
221
+ class LocalVariableDefinition(VariableDefinition):
222
+ type: VariableDefinitionType = VariableDefinitionType.LOCAL_VARIABLE
223
+
224
+ @single_call
225
+ def __hash__(self) -> int:
226
+ return hash((type(self), self.name, self.type, self.range, self.source))
227
+
228
+
229
+ @dataclass
230
+ class BuiltInVariableDefinition(VariableDefinition):
231
+ type: VariableDefinitionType = VariableDefinitionType.BUILTIN_VARIABLE
232
+ resolvable: bool = True
233
+
234
+ @single_call
235
+ def __hash__(self) -> int:
236
+ return hash((type(self), self.name, self.type))
237
+
238
+
239
+ @dataclass
240
+ class CommandLineVariableDefinition(VariableDefinition):
241
+ type: VariableDefinitionType = VariableDefinitionType.COMMAND_LINE_VARIABLE
242
+ resolvable: bool = True
243
+
244
+ @single_call
245
+ def __hash__(self) -> int:
246
+ return hash((type(self), self.name, self.type))
247
+
248
+
249
+ @dataclass
250
+ class ArgumentDefinition(VariableDefinition):
251
+ type: VariableDefinitionType = VariableDefinitionType.ARGUMENT
252
+ keyword_doc: Optional["KeywordDoc"] = field(default=None, compare=False, metadata={"nosave": True})
253
+
254
+ @single_call
255
+ def __hash__(self) -> int:
256
+ return hash((type(self), self.name, self.type, self.range, self.source))
257
+
258
+
259
+ @dataclass
260
+ class LibraryArgumentDefinition(ArgumentDefinition):
261
+ @single_call
262
+ def __hash__(self) -> int:
263
+ return hash((type(self), self.name, self.type, self.range, self.source))
264
+
265
+
266
+ @dataclass(frozen=True, eq=False, repr=False)
267
+ class NativeValue:
268
+ value: Any
269
+
270
+ def __repr__(self) -> str:
271
+ return repr(self.value)
272
+
273
+ def __str__(self) -> str:
274
+ return str(self.value)
275
+
276
+
277
+ @dataclass
278
+ class ImportedVariableDefinition(VariableDefinition):
279
+ type: VariableDefinitionType = VariableDefinitionType.IMPORTED_VARIABLE
280
+ value: Optional[NativeValue] = field(default=None, compare=False)
281
+
282
+ @single_call
283
+ def __hash__(self) -> int:
284
+ return hash((type(self), self.name, self.type, self.source))
285
+
286
+
287
+ @dataclass
288
+ class EnvironmentVariableDefinition(VariableDefinition):
289
+ type: VariableDefinitionType = VariableDefinitionType.ENVIRONMENT_VARIABLE
290
+ resolvable: bool = True
291
+
292
+ default_value: Any = field(default=None, compare=False)
293
+
294
+ @single_call
295
+ def __hash__(self) -> int:
296
+ return hash((type(self), self.name, self.type))
297
+
298
+
299
+ @dataclass
300
+ class VariableNotFoundDefinition(VariableDefinition):
301
+ type: VariableDefinitionType = VariableDefinitionType.VARIABLE_NOT_FOUND
302
+ resolvable: bool = False
303
+
304
+ @single_call
305
+ def __hash__(self) -> int:
306
+ return hash((type(self), self.name, self.type))
307
+
308
+
309
+ @dataclass
310
+ class LibraryEntry:
311
+ name: str
312
+ import_name: str
313
+ library_doc: "LibraryDoc" = field(compare=False)
314
+ args: Tuple[Any, ...] = ()
315
+ alias: Optional[str] = None
316
+ import_range: Range = field(default_factory=Range.zero)
317
+ import_source: Optional[str] = None
318
+ alias_range: Range = field(default_factory=Range.zero)
319
+
320
+ def __str__(self) -> str:
321
+ result = self.import_name
322
+ if self.args:
323
+ result += f" {self.args!s}"
324
+ if self.alias:
325
+ result += f" WITH NAME {self.alias}"
326
+ return result
327
+
328
+ @single_call
329
+ def __hash__(self) -> int:
330
+ return hash(
331
+ (
332
+ type(self),
333
+ self.name,
334
+ self.import_name,
335
+ self.args,
336
+ self.alias,
337
+ self.import_range,
338
+ self.import_source,
339
+ self.alias_range,
340
+ )
341
+ )
342
+
343
+
344
+ @dataclass
345
+ class ResourceEntry(LibraryEntry):
346
+ imports: List[Import] = field(default_factory=list, compare=False)
347
+ variables: List[VariableDefinition] = field(default_factory=list, compare=False)
348
+
349
+ @single_call
350
+ def __hash__(self) -> int:
351
+ return hash(
352
+ (
353
+ type(self),
354
+ self.name,
355
+ self.import_name,
356
+ self.import_range,
357
+ self.import_source,
358
+ )
359
+ )
360
+
361
+
362
+ @dataclass
363
+ class VariablesEntry(LibraryEntry):
364
+ variables: List[ImportedVariableDefinition] = field(default_factory=list, compare=False)
365
+
366
+ @single_call
367
+ def __hash__(self) -> int:
368
+ return hash(
369
+ (
370
+ type(self),
371
+ self.name,
372
+ self.import_name,
373
+ self.args,
374
+ self.import_range,
375
+ self.import_source,
376
+ )
377
+ )