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.
- delphi_lsp/__init__.py +184 -0
- delphi_lsp/_version.py +1 -0
- delphi_lsp/agent_cache.py +1574 -0
- delphi_lsp/agent_cli.py +902 -0
- delphi_lsp/agent_context.py +3907 -0
- delphi_lsp/agent_cpg.py +349 -0
- delphi_lsp/agent_cpg_builder.py +666 -0
- delphi_lsp/agent_layers.py +1410 -0
- delphi_lsp/agent_metrics.py +526 -0
- delphi_lsp/agent_protocol.py +445 -0
- delphi_lsp/agent_relations.py +1881 -0
- delphi_lsp/agent_templates.py +614 -0
- delphi_lsp/agent_wiki.py +2853 -0
- delphi_lsp/agent_workspace.py +860 -0
- delphi_lsp/ast_serialize.py +126 -0
- delphi_lsp/binary.py +250 -0
- delphi_lsp/comment_builder.py +28 -0
- delphi_lsp/consts.py +345 -0
- delphi_lsp/delphi_lsp_native.pyd +0 -0
- delphi_lsp/delphiast_lexer.py +399 -0
- delphi_lsp/delphiast_parser.py +2189 -0
- delphi_lsp/delphiast_tokens.py +41 -0
- delphi_lsp/grammar.py +459 -0
- delphi_lsp/incremental.py +1139 -0
- delphi_lsp/lark_builder.py +2684 -0
- delphi_lsp/lark_tokens.py +236 -0
- delphi_lsp/lexical_scanner.py +30 -0
- delphi_lsp/lsp_server.py +6698 -0
- delphi_lsp/metrics.py +1452 -0
- delphi_lsp/native_bridge.py +300 -0
- delphi_lsp/navigation_cache.py +189 -0
- delphi_lsp/nodes.py +462 -0
- delphi_lsp/parallel_outline.py +662 -0
- delphi_lsp/parse_artifacts.py +969 -0
- delphi_lsp/parser.py +342 -0
- delphi_lsp/parser_backend.py +139 -0
- delphi_lsp/preprocessor.py +1122 -0
- delphi_lsp/progress.py +26 -0
- delphi_lsp/project_config.py +285 -0
- delphi_lsp/project_discovery.py +932 -0
- delphi_lsp/project_indexer.py +470 -0
- delphi_lsp/py.typed +1 -0
- delphi_lsp/response_cache.py +465 -0
- delphi_lsp/semantic.py +394 -0
- delphi_lsp/semantic_builder.py +2302 -0
- delphi_lsp/source_reader.py +17 -0
- delphi_lsp/wiki_external_sort.py +392 -0
- delphi_lsp/wiki_memory.py +548 -0
- delphi_lsp/workspace.py +83 -0
- delphi_lsp/writer.py +73 -0
- python_delphi_lsp-3.6.0.dist-info/METADATA +766 -0
- python_delphi_lsp-3.6.0.dist-info/RECORD +56 -0
- python_delphi_lsp-3.6.0.dist-info/WHEEL +4 -0
- python_delphi_lsp-3.6.0.dist-info/entry_points.txt +3 -0
- python_delphi_lsp-3.6.0.dist-info/licenses/LICENSE +373 -0
- python_delphi_lsp-3.6.0.dist-info/sboms/python-delphi-lsp.cyclonedx.json +770 -0
delphi_lsp/semantic.py
ADDED
|
@@ -0,0 +1,394 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from dataclasses import dataclass, field
|
|
4
|
+
from enum import Enum
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def normalize_name(name: str) -> str:
|
|
8
|
+
return '.'.join(
|
|
9
|
+
part.removeprefix('&')
|
|
10
|
+
for part in name.casefold().split('.')
|
|
11
|
+
)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
@dataclass(frozen=True)
|
|
15
|
+
class SourceRange:
|
|
16
|
+
file_name: str
|
|
17
|
+
start_line: int
|
|
18
|
+
start_col: int
|
|
19
|
+
end_line: int
|
|
20
|
+
end_col: int
|
|
21
|
+
|
|
22
|
+
def contains(self, line: int, col: int) -> bool:
|
|
23
|
+
if line < self.start_line or line > self.end_line:
|
|
24
|
+
return False
|
|
25
|
+
if line == self.start_line and col < self.start_col:
|
|
26
|
+
return False
|
|
27
|
+
if line == self.end_line and col > self.end_col:
|
|
28
|
+
return False
|
|
29
|
+
return True
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class Visibility(Enum):
|
|
33
|
+
UNKNOWN = 'unknown'
|
|
34
|
+
PRIVATE = 'private'
|
|
35
|
+
PROTECTED = 'protected'
|
|
36
|
+
PUBLIC = 'public'
|
|
37
|
+
PUBLISHED = 'published'
|
|
38
|
+
STRICT_PRIVATE = 'strict_private'
|
|
39
|
+
STRICT_PROTECTED = 'strict_protected'
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
class SymbolKind(Enum):
|
|
43
|
+
UNIT = 'unit'
|
|
44
|
+
MODULE = 'module'
|
|
45
|
+
NAMESPACE = 'namespace'
|
|
46
|
+
PACKAGE = 'package'
|
|
47
|
+
TYPE = 'type'
|
|
48
|
+
TYPE_PARAMETER = 'type_parameter'
|
|
49
|
+
CLASS = 'class'
|
|
50
|
+
RECORD = 'record'
|
|
51
|
+
INTERFACE = 'interface'
|
|
52
|
+
ENUM = 'enum'
|
|
53
|
+
ENUM_VALUE = 'enum_value'
|
|
54
|
+
FIELD = 'field'
|
|
55
|
+
PROPERTY = 'property'
|
|
56
|
+
METHOD = 'method'
|
|
57
|
+
FUNCTION = 'function'
|
|
58
|
+
PROCEDURE = 'procedure'
|
|
59
|
+
CONSTRUCTOR = 'constructor'
|
|
60
|
+
DESTRUCTOR = 'destructor'
|
|
61
|
+
VARIABLE = 'variable'
|
|
62
|
+
PARAMETER = 'parameter'
|
|
63
|
+
CONSTANT = 'constant'
|
|
64
|
+
LABEL = 'label'
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
class ScopeKind(Enum):
|
|
68
|
+
UNIT = 'unit'
|
|
69
|
+
TYPE = 'type'
|
|
70
|
+
ROUTINE = 'routine'
|
|
71
|
+
BLOCK = 'block'
|
|
72
|
+
WITH = 'with'
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
class Modifier(Enum):
|
|
76
|
+
ABSTRACT = 'abstract'
|
|
77
|
+
SEALED = 'sealed'
|
|
78
|
+
FINAL = 'final'
|
|
79
|
+
VIRTUAL = 'virtual'
|
|
80
|
+
OVERRIDE = 'override'
|
|
81
|
+
OVERLOAD = 'overload'
|
|
82
|
+
REINTRODUCE = 'reintroduce'
|
|
83
|
+
INLINE = 'inline'
|
|
84
|
+
STATIC = 'static'
|
|
85
|
+
CLASS = 'class'
|
|
86
|
+
EXTERNAL = 'external'
|
|
87
|
+
FORWARD = 'forward'
|
|
88
|
+
DEPRECATED = 'deprecated'
|
|
89
|
+
NORETURN = 'noreturn'
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
class ReferenceKind(Enum):
|
|
93
|
+
UNKNOWN = 'unknown'
|
|
94
|
+
VALUE = 'value'
|
|
95
|
+
TYPE = 'type'
|
|
96
|
+
TYPE_QUALIFIER = 'type_qualifier'
|
|
97
|
+
CONSTRUCTOR_CALL = 'constructor_call'
|
|
98
|
+
CALL = 'call'
|
|
99
|
+
PROPERTY = 'property'
|
|
100
|
+
UNIT = 'unit'
|
|
101
|
+
LABEL = 'label'
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
@dataclass(frozen=True)
|
|
105
|
+
class TypeRef:
|
|
106
|
+
def display_name(self) -> str:
|
|
107
|
+
return '<unknown>'
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
@dataclass(frozen=True)
|
|
111
|
+
class UnknownTypeRef(TypeRef):
|
|
112
|
+
reason: str = ''
|
|
113
|
+
|
|
114
|
+
def display_name(self) -> str:
|
|
115
|
+
return '<unknown>' if not self.reason else f'<unknown:{self.reason}>'
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
@dataclass(frozen=True)
|
|
119
|
+
class NamedTypeRef(TypeRef):
|
|
120
|
+
name: str
|
|
121
|
+
unit_name: str | None = None
|
|
122
|
+
|
|
123
|
+
def display_name(self) -> str:
|
|
124
|
+
if self.unit_name:
|
|
125
|
+
return f'{self.unit_name}.{self.name}'
|
|
126
|
+
return self.name
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
@dataclass(frozen=True)
|
|
130
|
+
class PointerTypeRef(TypeRef):
|
|
131
|
+
target: TypeRef
|
|
132
|
+
|
|
133
|
+
def display_name(self) -> str:
|
|
134
|
+
return f'^{self.target.display_name()}'
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
@dataclass(frozen=True)
|
|
138
|
+
class ClassOfTypeRef(TypeRef):
|
|
139
|
+
target: TypeRef
|
|
140
|
+
|
|
141
|
+
def display_name(self) -> str:
|
|
142
|
+
return f'class of {self.target.display_name()}'
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
@dataclass(frozen=True)
|
|
146
|
+
class ReferenceTypeRef(TypeRef):
|
|
147
|
+
target: TypeRef
|
|
148
|
+
|
|
149
|
+
def display_name(self) -> str:
|
|
150
|
+
return f'reference to {self.target.display_name()}'
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
@dataclass(frozen=True)
|
|
154
|
+
class FileTypeRef(TypeRef):
|
|
155
|
+
element_type: TypeRef | None = None
|
|
156
|
+
|
|
157
|
+
def display_name(self) -> str:
|
|
158
|
+
if self.element_type is None:
|
|
159
|
+
return 'file'
|
|
160
|
+
return f'file of {self.element_type.display_name()}'
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
@dataclass(frozen=True)
|
|
164
|
+
class GenericInstanceTypeRef(TypeRef):
|
|
165
|
+
base: NamedTypeRef
|
|
166
|
+
args: tuple[TypeRef, ...]
|
|
167
|
+
|
|
168
|
+
def display_name(self) -> str:
|
|
169
|
+
arg_list = ', '.join(arg.display_name() for arg in self.args)
|
|
170
|
+
return f'{self.base.display_name()}<{arg_list}>'
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
@dataclass(frozen=True)
|
|
174
|
+
class ArrayTypeRef(TypeRef):
|
|
175
|
+
element_type: TypeRef
|
|
176
|
+
dimensions: tuple[TypeRef, ...] = ()
|
|
177
|
+
is_dynamic: bool = False
|
|
178
|
+
|
|
179
|
+
def display_name(self) -> str:
|
|
180
|
+
if self.is_dynamic or not self.dimensions:
|
|
181
|
+
return f'array of {self.element_type.display_name()}'
|
|
182
|
+
dims = ', '.join(dim.display_name() for dim in self.dimensions)
|
|
183
|
+
return f'array[{dims}] of {self.element_type.display_name()}'
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
@dataclass(frozen=True)
|
|
187
|
+
class SetTypeRef(TypeRef):
|
|
188
|
+
element_type: TypeRef
|
|
189
|
+
|
|
190
|
+
def display_name(self) -> str:
|
|
191
|
+
return f'set of {self.element_type.display_name()}'
|
|
192
|
+
|
|
193
|
+
|
|
194
|
+
@dataclass(frozen=True)
|
|
195
|
+
class SubrangeTypeRef(TypeRef):
|
|
196
|
+
lower: str
|
|
197
|
+
upper: str
|
|
198
|
+
|
|
199
|
+
def display_name(self) -> str:
|
|
200
|
+
return f'{self.lower}..{self.upper}'
|
|
201
|
+
|
|
202
|
+
|
|
203
|
+
@dataclass(frozen=True)
|
|
204
|
+
class EnumTypeRef(TypeRef):
|
|
205
|
+
name: str
|
|
206
|
+
members: tuple[str, ...]
|
|
207
|
+
|
|
208
|
+
def display_name(self) -> str:
|
|
209
|
+
return self.name if self.name else 'enum'
|
|
210
|
+
|
|
211
|
+
|
|
212
|
+
@dataclass(frozen=True)
|
|
213
|
+
class RecordTypeRef(TypeRef):
|
|
214
|
+
name: str
|
|
215
|
+
scope: Scope | None = None
|
|
216
|
+
packed: bool = False
|
|
217
|
+
|
|
218
|
+
def display_name(self) -> str:
|
|
219
|
+
return self.name if self.name else 'record'
|
|
220
|
+
|
|
221
|
+
|
|
222
|
+
@dataclass(frozen=True)
|
|
223
|
+
class ClassTypeRef(TypeRef):
|
|
224
|
+
name: str
|
|
225
|
+
scope: Scope | None = None
|
|
226
|
+
bases: tuple[TypeRef, ...] = ()
|
|
227
|
+
is_abstract: bool = False
|
|
228
|
+
|
|
229
|
+
def display_name(self) -> str:
|
|
230
|
+
return self.name if self.name else 'class'
|
|
231
|
+
|
|
232
|
+
|
|
233
|
+
@dataclass(frozen=True)
|
|
234
|
+
class InterfaceTypeRef(TypeRef):
|
|
235
|
+
name: str
|
|
236
|
+
scope: Scope | None = None
|
|
237
|
+
bases: tuple[TypeRef, ...] = ()
|
|
238
|
+
|
|
239
|
+
def display_name(self) -> str:
|
|
240
|
+
return self.name if self.name else 'interface'
|
|
241
|
+
|
|
242
|
+
|
|
243
|
+
@dataclass(frozen=True)
|
|
244
|
+
class TypeParameterRef(TypeRef):
|
|
245
|
+
name: str
|
|
246
|
+
|
|
247
|
+
def display_name(self) -> str:
|
|
248
|
+
return self.name
|
|
249
|
+
|
|
250
|
+
|
|
251
|
+
@dataclass(frozen=True)
|
|
252
|
+
class ProcTypeRef(TypeRef):
|
|
253
|
+
name: str
|
|
254
|
+
params: tuple[TypeRef, ...] = ()
|
|
255
|
+
return_type: TypeRef | None = None
|
|
256
|
+
|
|
257
|
+
def display_name(self) -> str:
|
|
258
|
+
params = ', '.join(p.display_name() for p in self.params)
|
|
259
|
+
if self.return_type is None:
|
|
260
|
+
return f'procedure({params})'
|
|
261
|
+
return f'function({params}): {self.return_type.display_name()}'
|
|
262
|
+
|
|
263
|
+
|
|
264
|
+
@dataclass
|
|
265
|
+
class Symbol:
|
|
266
|
+
name: str
|
|
267
|
+
kind: SymbolKind
|
|
268
|
+
decl_range: SourceRange
|
|
269
|
+
name_range: SourceRange
|
|
270
|
+
scope: Scope
|
|
271
|
+
visibility: Visibility = Visibility.UNKNOWN
|
|
272
|
+
type_ref: TypeRef = field(default_factory=UnknownTypeRef)
|
|
273
|
+
modifiers: set[Modifier] = field(default_factory=set)
|
|
274
|
+
attributes: dict[str, str] = field(default_factory=dict)
|
|
275
|
+
doc: str = ''
|
|
276
|
+
overloads: list[Symbol] = field(default_factory=list)
|
|
277
|
+
member_scope: Scope | None = None
|
|
278
|
+
base_types: tuple[TypeRef, ...] = ()
|
|
279
|
+
|
|
280
|
+
def add_overload(self, symbol: Symbol) -> None:
|
|
281
|
+
self.overloads.append(symbol)
|
|
282
|
+
|
|
283
|
+
|
|
284
|
+
@dataclass
|
|
285
|
+
class SymbolReference:
|
|
286
|
+
name: str
|
|
287
|
+
kind: ReferenceKind
|
|
288
|
+
ref_range: SourceRange
|
|
289
|
+
scope: Scope
|
|
290
|
+
resolved: Symbol | None = None
|
|
291
|
+
|
|
292
|
+
|
|
293
|
+
@dataclass
|
|
294
|
+
class Scope:
|
|
295
|
+
kind: ScopeKind
|
|
296
|
+
name: str
|
|
297
|
+
parent: Scope | None = None
|
|
298
|
+
owner: Symbol | None = None
|
|
299
|
+
symbols: dict[str, list[Symbol]] = field(default_factory=dict)
|
|
300
|
+
imports: list[Scope] = field(default_factory=list)
|
|
301
|
+
with_scopes: list[Scope] = field(default_factory=list)
|
|
302
|
+
|
|
303
|
+
def define(self, symbol: Symbol) -> None:
|
|
304
|
+
key = normalize_name(symbol.name)
|
|
305
|
+
if key not in self.symbols:
|
|
306
|
+
self.symbols[key] = []
|
|
307
|
+
self.symbols[key].append(symbol)
|
|
308
|
+
|
|
309
|
+
def lookup_local(self, name: str) -> list[Symbol]:
|
|
310
|
+
return list(self.symbols.get(normalize_name(name), []))
|
|
311
|
+
|
|
312
|
+
def resolve(self, name: str) -> list[Symbol]:
|
|
313
|
+
results: list[Symbol] = []
|
|
314
|
+
results.extend(self.lookup_local(name))
|
|
315
|
+
if results:
|
|
316
|
+
return results
|
|
317
|
+
for scope in self.with_scopes:
|
|
318
|
+
scoped = scope.lookup_local(name)
|
|
319
|
+
if scoped:
|
|
320
|
+
return scoped
|
|
321
|
+
if self.parent is not None:
|
|
322
|
+
results.extend(self.parent.resolve(name))
|
|
323
|
+
if results:
|
|
324
|
+
return results
|
|
325
|
+
for scope in self.imports:
|
|
326
|
+
scoped = scope.lookup_local(name)
|
|
327
|
+
if scoped:
|
|
328
|
+
results.extend(scoped)
|
|
329
|
+
return results
|
|
330
|
+
|
|
331
|
+
def add_import(self, scope: Scope) -> None:
|
|
332
|
+
if scope not in self.imports:
|
|
333
|
+
self.imports.append(scope)
|
|
334
|
+
|
|
335
|
+
def add_with_scope(self, scope: Scope) -> None:
|
|
336
|
+
if scope not in self.with_scopes:
|
|
337
|
+
self.with_scopes.append(scope)
|
|
338
|
+
|
|
339
|
+
|
|
340
|
+
@dataclass
|
|
341
|
+
class SymbolIndex:
|
|
342
|
+
units: dict[str, Scope] = field(default_factory=dict)
|
|
343
|
+
name_index: dict[str, list[Symbol]] = field(default_factory=dict)
|
|
344
|
+
|
|
345
|
+
def register_unit(self, unit_name: str, unit_scope: Scope, *, index_symbols: bool = True) -> None:
|
|
346
|
+
self.units[normalize_name(unit_name)] = unit_scope
|
|
347
|
+
if index_symbols:
|
|
348
|
+
self._index_scope(unit_scope)
|
|
349
|
+
|
|
350
|
+
def lookup(self, name: str) -> list[Symbol]:
|
|
351
|
+
return list(self.name_index.get(normalize_name(name), []))
|
|
352
|
+
|
|
353
|
+
def lookup_unit(self, unit_name: str) -> Scope | None:
|
|
354
|
+
return self.units.get(normalize_name(unit_name))
|
|
355
|
+
|
|
356
|
+
def resolve_qualified(self, qualified_name: str) -> list[Symbol]:
|
|
357
|
+
parts = qualified_name.split('.')
|
|
358
|
+
if len(parts) < 2:
|
|
359
|
+
return self.lookup(qualified_name)
|
|
360
|
+
unit_name = '.'.join(parts[:-1])
|
|
361
|
+
symbol_name = parts[-1]
|
|
362
|
+
unit_scope = self.lookup_unit(unit_name)
|
|
363
|
+
if unit_scope is None:
|
|
364
|
+
return []
|
|
365
|
+
return unit_scope.lookup_local(symbol_name)
|
|
366
|
+
|
|
367
|
+
def _index_scope(self, scope: Scope, seen: set[int] | None = None) -> None:
|
|
368
|
+
if seen is None:
|
|
369
|
+
seen = set()
|
|
370
|
+
pending = [scope]
|
|
371
|
+
while pending:
|
|
372
|
+
current = pending.pop()
|
|
373
|
+
scope_id = id(current)
|
|
374
|
+
if scope_id in seen:
|
|
375
|
+
continue
|
|
376
|
+
seen.add(scope_id)
|
|
377
|
+
member_scopes: list[Scope] = []
|
|
378
|
+
for symbols in current.symbols.values():
|
|
379
|
+
for symbol in symbols:
|
|
380
|
+
key = normalize_name(symbol.name)
|
|
381
|
+
self.name_index.setdefault(key, []).append(symbol)
|
|
382
|
+
if (
|
|
383
|
+
symbol.member_scope is not None
|
|
384
|
+
and symbol.kind
|
|
385
|
+
in {
|
|
386
|
+
SymbolKind.CLASS,
|
|
387
|
+
SymbolKind.RECORD,
|
|
388
|
+
SymbolKind.INTERFACE,
|
|
389
|
+
SymbolKind.ENUM,
|
|
390
|
+
SymbolKind.TYPE,
|
|
391
|
+
}
|
|
392
|
+
):
|
|
393
|
+
member_scopes.append(symbol.member_scope)
|
|
394
|
+
pending.extend(reversed(member_scopes))
|