python-delphi-lsp 3.6.0__cp310-abi3-win_amd64.whl

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 (56) hide show
  1. delphi_lsp/__init__.py +184 -0
  2. delphi_lsp/_version.py +1 -0
  3. delphi_lsp/agent_cache.py +1574 -0
  4. delphi_lsp/agent_cli.py +902 -0
  5. delphi_lsp/agent_context.py +3907 -0
  6. delphi_lsp/agent_cpg.py +349 -0
  7. delphi_lsp/agent_cpg_builder.py +666 -0
  8. delphi_lsp/agent_layers.py +1410 -0
  9. delphi_lsp/agent_metrics.py +526 -0
  10. delphi_lsp/agent_protocol.py +445 -0
  11. delphi_lsp/agent_relations.py +1881 -0
  12. delphi_lsp/agent_templates.py +614 -0
  13. delphi_lsp/agent_wiki.py +2853 -0
  14. delphi_lsp/agent_workspace.py +860 -0
  15. delphi_lsp/ast_serialize.py +126 -0
  16. delphi_lsp/binary.py +250 -0
  17. delphi_lsp/comment_builder.py +28 -0
  18. delphi_lsp/consts.py +345 -0
  19. delphi_lsp/delphi_lsp_native.pyd +0 -0
  20. delphi_lsp/delphiast_lexer.py +399 -0
  21. delphi_lsp/delphiast_parser.py +2189 -0
  22. delphi_lsp/delphiast_tokens.py +41 -0
  23. delphi_lsp/grammar.py +459 -0
  24. delphi_lsp/incremental.py +1139 -0
  25. delphi_lsp/lark_builder.py +2684 -0
  26. delphi_lsp/lark_tokens.py +236 -0
  27. delphi_lsp/lexical_scanner.py +30 -0
  28. delphi_lsp/lsp_server.py +6698 -0
  29. delphi_lsp/metrics.py +1452 -0
  30. delphi_lsp/native_bridge.py +300 -0
  31. delphi_lsp/navigation_cache.py +189 -0
  32. delphi_lsp/nodes.py +462 -0
  33. delphi_lsp/parallel_outline.py +662 -0
  34. delphi_lsp/parse_artifacts.py +969 -0
  35. delphi_lsp/parser.py +342 -0
  36. delphi_lsp/parser_backend.py +139 -0
  37. delphi_lsp/preprocessor.py +1122 -0
  38. delphi_lsp/progress.py +26 -0
  39. delphi_lsp/project_config.py +285 -0
  40. delphi_lsp/project_discovery.py +932 -0
  41. delphi_lsp/project_indexer.py +470 -0
  42. delphi_lsp/py.typed +1 -0
  43. delphi_lsp/response_cache.py +465 -0
  44. delphi_lsp/semantic.py +394 -0
  45. delphi_lsp/semantic_builder.py +2302 -0
  46. delphi_lsp/source_reader.py +17 -0
  47. delphi_lsp/wiki_external_sort.py +392 -0
  48. delphi_lsp/wiki_memory.py +548 -0
  49. delphi_lsp/workspace.py +83 -0
  50. delphi_lsp/writer.py +73 -0
  51. python_delphi_lsp-3.6.0.dist-info/METADATA +766 -0
  52. python_delphi_lsp-3.6.0.dist-info/RECORD +56 -0
  53. python_delphi_lsp-3.6.0.dist-info/WHEEL +4 -0
  54. python_delphi_lsp-3.6.0.dist-info/entry_points.txt +3 -0
  55. python_delphi_lsp-3.6.0.dist-info/licenses/LICENSE +373 -0
  56. python_delphi_lsp-3.6.0.dist-info/sboms/python-delphi-lsp.cyclonedx.json +770 -0
delphi_lsp/nodes.py ADDED
@@ -0,0 +1,462 @@
1
+ from __future__ import annotations
2
+
3
+ from collections.abc import Callable, Iterable, Sequence
4
+ from dataclasses import dataclass
5
+ from enum import Enum
6
+ from typing import Any
7
+
8
+ from .consts import AttributeName, SyntaxNodeType
9
+
10
+
11
+ class ParserException(Exception):
12
+ def __init__(self, line: int, col: int, file_name: str, message: str) -> None:
13
+ super().__init__(message)
14
+ self.file_name = file_name
15
+ self.line = line
16
+ self.col = col
17
+
18
+
19
+ class SyntaxTreeException(ParserException):
20
+ def __init__(self, line: int, col: int, file_name: str, message: str, syntax_tree: SyntaxNode) -> None:
21
+ super().__init__(line, col, file_name, message)
22
+ self.syntax_tree = syntax_tree
23
+
24
+
25
+ class SyntaxNode:
26
+ __slots__ = (
27
+ "_attributes",
28
+ "_child_loader",
29
+ "_child_nodes",
30
+ "_col",
31
+ "_file_name",
32
+ "_incremental_source_positions_normalized",
33
+ "_line",
34
+ "_parent_node",
35
+ "_position_anchor",
36
+ "_source_positions",
37
+ "_token_end_col",
38
+ "_token_end_line",
39
+ "_typ",
40
+ )
41
+
42
+ def __init__(self, typ: SyntaxNodeType) -> None:
43
+ self._typ = typ
44
+ self._col = 0
45
+ self._line = 0
46
+ self._file_name = ''
47
+ self._attributes: list[tuple[AttributeName, str]] = []
48
+ self._child_nodes: list[SyntaxNode] = []
49
+ self._child_loader: Callable[[], list[SyntaxNode]] | None = None
50
+ self._parent_node: SyntaxNode | None = None
51
+ self._source_positions: tuple[tuple[int, int], ...] = ()
52
+ self._position_anchor: Any = None
53
+ self._incremental_source_positions_normalized = False
54
+ self._token_end_line = 0
55
+ self._token_end_col = 0
56
+
57
+ @property
58
+ def typ(self) -> SyntaxNodeType:
59
+ return self._typ
60
+
61
+ @property
62
+ def col(self) -> int:
63
+ return self._col
64
+
65
+ @col.setter
66
+ def col(self, value: int) -> None:
67
+ self._col = value
68
+
69
+ @property
70
+ def line(self) -> int:
71
+ return self._line
72
+
73
+ @line.setter
74
+ def line(self, value: int) -> None:
75
+ self._line = value
76
+
77
+ @property
78
+ def file_name(self) -> str:
79
+ return self._file_name
80
+
81
+ @file_name.setter
82
+ def file_name(self, value: str) -> None:
83
+ self._file_name = value
84
+
85
+ @property
86
+ def attributes(self) -> list[tuple[AttributeName, str]]:
87
+ return self._attributes
88
+
89
+ @property
90
+ def child_nodes(self) -> list[SyntaxNode]:
91
+ self._materialize_children()
92
+ return self._child_nodes
93
+
94
+ @property
95
+ def has_attributes(self) -> bool:
96
+ return len(self._attributes) > 0
97
+
98
+ @property
99
+ def has_children(self) -> bool:
100
+ return self._child_loader is not None or len(self._child_nodes) > 0
101
+
102
+ @property
103
+ def parent_node(self) -> SyntaxNode | None:
104
+ return self._parent_node
105
+
106
+ @property
107
+ def source_positions(self) -> tuple[tuple[int, int], ...]:
108
+ """Positions for compact source text characters plus its end position."""
109
+ if self._position_anchor is not None:
110
+ return self._position_anchor.positions
111
+ return self._source_positions
112
+
113
+ @source_positions.setter
114
+ def source_positions(self, value: Iterable[tuple[int, int]]) -> None:
115
+ self._position_anchor = None
116
+ self._source_positions = tuple(value)
117
+
118
+ @property
119
+ def token_end_line(self) -> int:
120
+ return self._token_end_line
121
+
122
+ @token_end_line.setter
123
+ def token_end_line(self, value: int) -> None:
124
+ self._token_end_line = value
125
+
126
+ @property
127
+ def token_end_col(self) -> int:
128
+ return self._token_end_col
129
+
130
+ @token_end_col.setter
131
+ def token_end_col(self, value: int) -> None:
132
+ self._token_end_col = value
133
+
134
+ def assign_position_from(self, node: SyntaxNode) -> None:
135
+ self._col = node.col
136
+ self._line = node.line
137
+ self._file_name = node.file_name
138
+ self._position_anchor = node._position_anchor
139
+ self._source_positions = node._source_positions
140
+ self._token_end_line = node.token_end_line
141
+ self._token_end_col = node.token_end_col
142
+
143
+ def clone(self) -> SyntaxNode:
144
+ self._materialize_children()
145
+ clone_node = self.__class__(self._typ)
146
+ clone_node._col = self._col
147
+ clone_node._line = self._line
148
+ clone_node._file_name = self._file_name
149
+ clone_node._attributes = list(self._attributes)
150
+ clone_node._position_anchor = self._position_anchor
151
+ clone_node._source_positions = self._source_positions
152
+ clone_node._token_end_line = self._token_end_line
153
+ clone_node._token_end_col = self._token_end_col
154
+ clone_node._child_nodes = [child.clone() for child in self._child_nodes]
155
+ for child in clone_node._child_nodes:
156
+ child._parent_node = clone_node
157
+ return clone_node
158
+
159
+ def get_attribute(self, key: AttributeName) -> str:
160
+ for attr_key, attr_value in self._attributes:
161
+ if attr_key == key:
162
+ return attr_value
163
+ return ''
164
+
165
+ def has_attribute(self, key: AttributeName) -> bool:
166
+ return any(attr_key == key for attr_key, _ in self._attributes)
167
+
168
+ def set_attribute(self, key: AttributeName, value: str) -> None:
169
+ for index, (attr_key, _) in enumerate(self._attributes):
170
+ if attr_key == key:
171
+ self._attributes[index] = (key, value)
172
+ return
173
+ self._attributes.append((key, value))
174
+
175
+ def clear_attributes(self) -> None:
176
+ self._attributes = []
177
+
178
+ def add_child(self, node_or_type: SyntaxNode | SyntaxNodeType) -> SyntaxNode:
179
+ self._materialize_children()
180
+ if isinstance(node_or_type, SyntaxNodeType):
181
+ node = SyntaxNode(node_or_type)
182
+ else:
183
+ node = node_or_type
184
+ if node is None:
185
+ raise ValueError('node must not be None')
186
+ self._child_nodes.append(node)
187
+ node._parent_node = self
188
+ return node
189
+
190
+ def extract_child(self, node: SyntaxNode) -> None:
191
+ self._materialize_children()
192
+ try:
193
+ index = self._child_nodes.index(node)
194
+ except ValueError:
195
+ return
196
+ self._child_nodes.pop(index)
197
+ node._parent_node = None
198
+
199
+ def delete_child(self, node: SyntaxNode) -> None:
200
+ self.extract_child(node)
201
+
202
+ def find_node(self, typ_or_path: SyntaxNodeType | Sequence[SyntaxNodeType]) -> SyntaxNode | None:
203
+ self._materialize_children()
204
+ if isinstance(typ_or_path, SyntaxNodeType):
205
+ for child in self._child_nodes:
206
+ if child.typ == typ_or_path:
207
+ return child
208
+ return None
209
+
210
+ types_path = list(typ_or_path)
211
+ if not types_path:
212
+ return None
213
+ if types_path[-1] == SyntaxNodeType.ntUnknown:
214
+ return None
215
+ return self._find_node_recursively(self, types_path, 0)
216
+
217
+ def _set_child_loader(self, loader: Callable[[], list[SyntaxNode]]) -> None:
218
+ if self._child_nodes:
219
+ raise ValueError('cannot defer children after materialization')
220
+ self._child_loader = loader
221
+
222
+ def _materialize_children(self) -> None:
223
+ loader = self._child_loader
224
+ if loader is None:
225
+ return
226
+ self._child_loader = None
227
+ children: list[SyntaxNode] | None = None
228
+ try:
229
+ children = loader()
230
+ finally:
231
+ if children is None:
232
+ self._child_loader = loader
233
+ assert children is not None
234
+ self._child_nodes.extend(children)
235
+ for child in children:
236
+ child._parent_node = self
237
+
238
+ def _find_node_recursively(
239
+ self,
240
+ node: SyntaxNode,
241
+ types_path: Sequence[SyntaxNodeType],
242
+ type_index: int,
243
+ ) -> SyntaxNode | None:
244
+ for child in node.child_nodes:
245
+ if types_path[type_index] in (child.typ, SyntaxNodeType.ntUnknown):
246
+ if type_index < len(types_path) - 1:
247
+ found = self._find_node_recursively(child, types_path, type_index + 1)
248
+ else:
249
+ found = child
250
+ if found is not None:
251
+ return found
252
+ return None
253
+
254
+
255
+ class CompoundSyntaxNode(SyntaxNode):
256
+ __slots__ = ("end_col", "end_line")
257
+
258
+ def __init__(self, typ: SyntaxNodeType) -> None:
259
+ super().__init__(typ)
260
+ self.end_col = 0
261
+ self.end_line = 0
262
+
263
+ def clone(self) -> SyntaxNode:
264
+ clone_node = super().clone()
265
+ clone_node.end_col = self.end_col
266
+ clone_node.end_line = self.end_line
267
+ return clone_node
268
+
269
+
270
+ class ValuedSyntaxNode(SyntaxNode):
271
+ __slots__ = ("value",)
272
+
273
+ def __init__(self, typ: SyntaxNodeType) -> None:
274
+ super().__init__(typ)
275
+ self.value = ''
276
+
277
+ def clone(self) -> SyntaxNode:
278
+ clone_node = super().clone()
279
+ clone_node.value = self.value
280
+ return clone_node
281
+
282
+
283
+ class CommentNode(SyntaxNode):
284
+ __slots__ = ("text",)
285
+
286
+ def __init__(self, typ: SyntaxNodeType) -> None:
287
+ super().__init__(typ)
288
+ self.text = ''
289
+
290
+ def clone(self) -> SyntaxNode:
291
+ clone_node = super().clone()
292
+ clone_node.text = self.text
293
+ return clone_node
294
+
295
+
296
+ class OperatorKind(Enum):
297
+ UNARY = 'unary'
298
+ BINARY = 'binary'
299
+
300
+
301
+ class OperatorAssoc(Enum):
302
+ LEFT = 'left'
303
+ RIGHT = 'right'
304
+
305
+
306
+ @dataclass(frozen=True)
307
+ class OperatorInfo:
308
+ typ: SyntaxNodeType
309
+ priority: int
310
+ kind: OperatorKind
311
+ assoc: OperatorAssoc
312
+
313
+
314
+ _OPERATOR_INFO = (
315
+ OperatorInfo(SyntaxNodeType.ntAddr, 1, OperatorKind.UNARY, OperatorAssoc.RIGHT),
316
+ OperatorInfo(SyntaxNodeType.ntDeref, 1, OperatorKind.UNARY, OperatorAssoc.LEFT),
317
+ OperatorInfo(SyntaxNodeType.ntGeneric, 1, OperatorKind.BINARY, OperatorAssoc.RIGHT),
318
+ OperatorInfo(SyntaxNodeType.ntIndexed, 1, OperatorKind.UNARY, OperatorAssoc.LEFT),
319
+ OperatorInfo(SyntaxNodeType.ntDot, 2, OperatorKind.BINARY, OperatorAssoc.RIGHT),
320
+ OperatorInfo(SyntaxNodeType.ntCall, 3, OperatorKind.BINARY, OperatorAssoc.RIGHT),
321
+ OperatorInfo(SyntaxNodeType.ntUnaryMinus, 5, OperatorKind.UNARY, OperatorAssoc.RIGHT),
322
+ OperatorInfo(SyntaxNodeType.ntNot, 6, OperatorKind.UNARY, OperatorAssoc.RIGHT),
323
+ OperatorInfo(SyntaxNodeType.ntMul, 7, OperatorKind.BINARY, OperatorAssoc.RIGHT),
324
+ OperatorInfo(SyntaxNodeType.ntFDiv, 7, OperatorKind.BINARY, OperatorAssoc.RIGHT),
325
+ OperatorInfo(SyntaxNodeType.ntDiv, 7, OperatorKind.BINARY, OperatorAssoc.RIGHT),
326
+ OperatorInfo(SyntaxNodeType.ntMod, 7, OperatorKind.BINARY, OperatorAssoc.RIGHT),
327
+ OperatorInfo(SyntaxNodeType.ntAnd, 7, OperatorKind.BINARY, OperatorAssoc.RIGHT),
328
+ OperatorInfo(SyntaxNodeType.ntShl, 7, OperatorKind.BINARY, OperatorAssoc.RIGHT),
329
+ OperatorInfo(SyntaxNodeType.ntShr, 7, OperatorKind.BINARY, OperatorAssoc.RIGHT),
330
+ OperatorInfo(SyntaxNodeType.ntAs, 7, OperatorKind.BINARY, OperatorAssoc.RIGHT),
331
+ OperatorInfo(SyntaxNodeType.ntAdd, 8, OperatorKind.BINARY, OperatorAssoc.RIGHT),
332
+ OperatorInfo(SyntaxNodeType.ntSub, 8, OperatorKind.BINARY, OperatorAssoc.RIGHT),
333
+ OperatorInfo(SyntaxNodeType.ntOr, 8, OperatorKind.BINARY, OperatorAssoc.RIGHT),
334
+ OperatorInfo(SyntaxNodeType.ntXor, 8, OperatorKind.BINARY, OperatorAssoc.RIGHT),
335
+ OperatorInfo(SyntaxNodeType.ntEqual, 9, OperatorKind.BINARY, OperatorAssoc.RIGHT),
336
+ OperatorInfo(SyntaxNodeType.ntNotEqual, 9, OperatorKind.BINARY, OperatorAssoc.RIGHT),
337
+ OperatorInfo(SyntaxNodeType.ntLower, 9, OperatorKind.BINARY, OperatorAssoc.RIGHT),
338
+ OperatorInfo(SyntaxNodeType.ntGreater, 9, OperatorKind.BINARY, OperatorAssoc.RIGHT),
339
+ OperatorInfo(SyntaxNodeType.ntLowerEqual, 9, OperatorKind.BINARY, OperatorAssoc.RIGHT),
340
+ OperatorInfo(SyntaxNodeType.ntGreaterEqual, 9, OperatorKind.BINARY, OperatorAssoc.RIGHT),
341
+ OperatorInfo(SyntaxNodeType.ntIn, 9, OperatorKind.BINARY, OperatorAssoc.RIGHT),
342
+ OperatorInfo(SyntaxNodeType.ntIs, 9, OperatorKind.BINARY, OperatorAssoc.RIGHT),
343
+ OperatorInfo(SyntaxNodeType.ntNotIn, 9, OperatorKind.BINARY, OperatorAssoc.RIGHT),
344
+ OperatorInfo(SyntaxNodeType.ntIsNot, 9, OperatorKind.BINARY, OperatorAssoc.RIGHT),
345
+ )
346
+
347
+ _OPERATORS = {info.typ: info for info in _OPERATOR_INFO}
348
+
349
+
350
+ def _is_round_close(typ: SyntaxNodeType) -> bool:
351
+ return typ == SyntaxNodeType.ntRoundClose
352
+
353
+
354
+ def _is_round_open(typ: SyntaxNodeType) -> bool:
355
+ return typ == SyntaxNodeType.ntRoundOpen
356
+
357
+
358
+ def is_operator(typ: SyntaxNodeType) -> bool:
359
+ return typ in _OPERATORS
360
+
361
+
362
+ def operator_info(typ: SyntaxNodeType) -> OperatorInfo:
363
+ return _OPERATORS[typ]
364
+
365
+
366
+ def expr_to_reverse_notation(expr: Iterable[SyntaxNode]) -> list[SyntaxNode]:
367
+ output: list[SyntaxNode] = []
368
+ stack: list[SyntaxNode] = []
369
+ for node in expr:
370
+ if is_operator(node.typ):
371
+ while stack and is_operator(stack[-1].typ):
372
+ current = operator_info(node.typ)
373
+ top = operator_info(stack[-1].typ)
374
+ if (
375
+ (current.assoc == OperatorAssoc.LEFT and current.priority >= top.priority)
376
+ or (current.assoc == OperatorAssoc.RIGHT and current.priority > top.priority)
377
+ ):
378
+ output.append(stack.pop())
379
+ else:
380
+ break
381
+ stack.append(node)
382
+ elif _is_round_open(node.typ):
383
+ stack.append(node)
384
+ elif _is_round_close(node.typ):
385
+ while stack and not _is_round_open(stack[-1].typ):
386
+ output.append(stack.pop())
387
+ if stack:
388
+ stack.pop()
389
+ if stack and is_operator(stack[-1].typ):
390
+ output.append(stack.pop())
391
+ else:
392
+ output.append(node)
393
+ while stack:
394
+ output.append(stack.pop())
395
+ return output
396
+
397
+
398
+ def node_list_to_tree(expr: Iterable[SyntaxNode], root: SyntaxNode) -> None:
399
+ stack: list[SyntaxNode] = []
400
+ for node in expr:
401
+ if is_operator(node.typ):
402
+ info = operator_info(node.typ)
403
+ if info.kind == OperatorKind.UNARY:
404
+ node.add_child(stack.pop())
405
+ else:
406
+ second = stack.pop()
407
+ node.add_child(stack.pop())
408
+ node.add_child(second)
409
+ stack.append(node)
410
+ root.add_child(stack.pop())
411
+ if stack:
412
+ raise ValueError('expression stack not empty after parsing')
413
+
414
+
415
+ def prepare_expr(expr_nodes: Iterable[SyntaxNode]) -> list[SyntaxNode]:
416
+ prepared: list[SyntaxNode] = []
417
+ prev_node: SyntaxNode | None = None
418
+ for node in expr_nodes:
419
+ if node.typ == SyntaxNodeType.ntCall:
420
+ continue
421
+
422
+ if prev_node is not None and _is_round_open(node.typ):
423
+ if not is_operator(prev_node.typ) and not _is_round_open(prev_node.typ):
424
+ prepared.append(create_node_with_parents_position(SyntaxNodeType.ntCall, node.parent_node))
425
+ if (
426
+ is_operator(prev_node.typ)
427
+ and operator_info(prev_node.typ).kind == OperatorKind.UNARY
428
+ and operator_info(prev_node.typ).assoc == OperatorAssoc.LEFT
429
+ ):
430
+ prepared.append(create_node_with_parents_position(SyntaxNodeType.ntCall, node.parent_node))
431
+
432
+ if prev_node is not None and node.typ == SyntaxNodeType.ntTypeArgs:
433
+ if not is_operator(prev_node.typ) and prev_node.typ != SyntaxNodeType.ntTypeArgs:
434
+ prepared.append(create_node_with_parents_position(SyntaxNodeType.ntGeneric, node.parent_node))
435
+ if (
436
+ is_operator(prev_node.typ)
437
+ and operator_info(prev_node.typ).kind == OperatorKind.UNARY
438
+ and operator_info(prev_node.typ).assoc == OperatorAssoc.LEFT
439
+ ):
440
+ prepared.append(create_node_with_parents_position(SyntaxNodeType.ntGeneric, node.parent_node))
441
+
442
+ if node.typ != SyntaxNodeType.ntAlignmentParam:
443
+ prepared.append(node.clone())
444
+ prev_node = node
445
+
446
+ return prepared
447
+
448
+
449
+ def create_node_with_parents_position(node_type: SyntaxNodeType, parent_node: SyntaxNode | None) -> SyntaxNode:
450
+ node = SyntaxNode(node_type)
451
+ if parent_node is not None:
452
+ node.assign_position_from(parent_node)
453
+ return node
454
+
455
+
456
+ def raw_node_list_to_tree(raw_parent_node: SyntaxNode, raw_node_list: Iterable[SyntaxNode], new_root: SyntaxNode) -> None:
457
+ try:
458
+ prepared = prepare_expr(raw_node_list)
459
+ reverse = expr_to_reverse_notation(prepared)
460
+ node_list_to_tree(reverse, new_root)
461
+ except Exception as exc: # pragma: no cover - parity with Pascal error handling
462
+ raise ParserException(new_root.line, new_root.col, new_root.file_name, str(exc)) from exc