sqlmesh 0.205.1.dev7__py3-none-any.whl → 0.205.1.dev9__py3-none-any.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.
- sqlmesh/_version.py +2 -2
- sqlmesh/core/linter/helpers.py +19 -13
- sqlmesh/core/linter/rules/builtin.py +76 -4
- sqlmesh/lsp/completions.py +1 -1
- sqlmesh/lsp/main.py +10 -6
- sqlmesh/lsp/reference.py +42 -376
- sqlmesh/lsp/rename.py +2 -2
- sqlmesh/utils/lineage.py +404 -0
- {sqlmesh-0.205.1.dev7.dist-info → sqlmesh-0.205.1.dev9.dist-info}/METADATA +1 -1
- {sqlmesh-0.205.1.dev7.dist-info → sqlmesh-0.205.1.dev9.dist-info}/RECORD +14 -14
- sqlmesh/lsp/description.py +0 -29
- {sqlmesh-0.205.1.dev7.dist-info → sqlmesh-0.205.1.dev9.dist-info}/WHEEL +0 -0
- {sqlmesh-0.205.1.dev7.dist-info → sqlmesh-0.205.1.dev9.dist-info}/entry_points.txt +0 -0
- {sqlmesh-0.205.1.dev7.dist-info → sqlmesh-0.205.1.dev9.dist-info}/licenses/LICENSE +0 -0
- {sqlmesh-0.205.1.dev7.dist-info → sqlmesh-0.205.1.dev9.dist-info}/top_level.txt +0 -0
sqlmesh/lsp/reference.py
CHANGED
|
@@ -1,74 +1,27 @@
|
|
|
1
1
|
import typing as t
|
|
2
2
|
from pathlib import Path
|
|
3
|
-
from pydantic import Field
|
|
4
3
|
|
|
5
4
|
from sqlmesh.core.audit import StandaloneAudit
|
|
6
|
-
from sqlmesh.core.dialect import normalize_model_name
|
|
7
5
|
from sqlmesh.core.linter.helpers import (
|
|
8
6
|
TokenPositionDetails,
|
|
9
7
|
)
|
|
10
8
|
from sqlmesh.core.linter.rule import Range, Position
|
|
11
|
-
from sqlmesh.core.model.definition import SqlModel
|
|
9
|
+
from sqlmesh.core.model.definition import SqlModel
|
|
12
10
|
from sqlmesh.lsp.context import LSPContext, ModelTarget, AuditTarget
|
|
13
11
|
from sqlglot import exp
|
|
14
|
-
from sqlmesh.lsp.description import generate_markdown_description
|
|
15
|
-
from sqlglot.optimizer.scope import build_scope
|
|
16
12
|
|
|
17
13
|
from sqlmesh.lsp.uri import URI
|
|
18
|
-
from sqlmesh.utils.
|
|
19
|
-
|
|
14
|
+
from sqlmesh.utils.lineage import (
|
|
15
|
+
MacroReference,
|
|
16
|
+
CTEReference,
|
|
17
|
+
Reference,
|
|
18
|
+
ModelReference,
|
|
19
|
+
extract_references_from_query,
|
|
20
|
+
)
|
|
20
21
|
import ast
|
|
21
22
|
from sqlmesh.core.model import Model
|
|
22
23
|
from sqlmesh import macro
|
|
23
24
|
import inspect
|
|
24
|
-
from ruamel.yaml import YAML
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
class LSPModelReference(PydanticModel):
|
|
28
|
-
"""A LSP reference to a model, excluding external models."""
|
|
29
|
-
|
|
30
|
-
type: t.Literal["model"] = "model"
|
|
31
|
-
path: Path
|
|
32
|
-
range: Range
|
|
33
|
-
markdown_description: t.Optional[str] = None
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
class LSPExternalModelReference(PydanticModel):
|
|
37
|
-
"""A LSP reference to an external model."""
|
|
38
|
-
|
|
39
|
-
type: t.Literal["external_model"] = "external_model"
|
|
40
|
-
range: Range
|
|
41
|
-
target_range: t.Optional[Range] = None
|
|
42
|
-
path: t.Optional[Path] = None
|
|
43
|
-
"""The path of the external model, typically a YAML file, it is optional because
|
|
44
|
-
external models can be unregistered and so the path is not available."""
|
|
45
|
-
|
|
46
|
-
markdown_description: t.Optional[str] = None
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
class LSPCteReference(PydanticModel):
|
|
50
|
-
"""A LSP reference to a CTE."""
|
|
51
|
-
|
|
52
|
-
type: t.Literal["cte"] = "cte"
|
|
53
|
-
path: Path
|
|
54
|
-
range: Range
|
|
55
|
-
target_range: Range
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
class LSPMacroReference(PydanticModel):
|
|
59
|
-
"""A LSP reference to a macro."""
|
|
60
|
-
|
|
61
|
-
type: t.Literal["macro"] = "macro"
|
|
62
|
-
path: Path
|
|
63
|
-
range: Range
|
|
64
|
-
target_range: Range
|
|
65
|
-
markdown_description: t.Optional[str] = None
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
Reference = t.Annotated[
|
|
69
|
-
t.Union[LSPModelReference, LSPCteReference, LSPMacroReference, LSPExternalModelReference],
|
|
70
|
-
Field(discriminator="type"),
|
|
71
|
-
]
|
|
72
25
|
|
|
73
26
|
|
|
74
27
|
def by_position(position: Position) -> t.Callable[[Reference], bool]:
|
|
@@ -158,7 +111,6 @@ def get_model_definitions_for_a_path(
|
|
|
158
111
|
audit = lint_context.context.standalone_audits.get(file_info.name)
|
|
159
112
|
if audit is None:
|
|
160
113
|
return []
|
|
161
|
-
|
|
162
114
|
query = audit.query
|
|
163
115
|
dialect = audit.dialect
|
|
164
116
|
depends_on = audit.depends_on
|
|
@@ -169,177 +121,17 @@ def get_model_definitions_for_a_path(
|
|
|
169
121
|
if file_path is None:
|
|
170
122
|
return []
|
|
171
123
|
|
|
172
|
-
# Find all possible references
|
|
173
|
-
references: t.List[Reference] = []
|
|
174
|
-
|
|
175
124
|
with open(file_path, "r", encoding="utf-8") as file:
|
|
176
125
|
read_file = file.readlines()
|
|
177
126
|
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
# Traverse all scopes to find CTE definitions and table references
|
|
187
|
-
for scope in root_scope.traverse():
|
|
188
|
-
for table in scope.tables:
|
|
189
|
-
table_name = table.name
|
|
190
|
-
|
|
191
|
-
# Check if this table reference is a CTE in the current scope
|
|
192
|
-
if cte_scope := scope.cte_sources.get(table_name):
|
|
193
|
-
cte = cte_scope.expression.parent
|
|
194
|
-
alias = cte.args["alias"]
|
|
195
|
-
if isinstance(alias, exp.TableAlias):
|
|
196
|
-
identifier = alias.this
|
|
197
|
-
if isinstance(identifier, exp.Identifier):
|
|
198
|
-
target_range_sqlmesh = TokenPositionDetails.from_meta(
|
|
199
|
-
identifier.meta
|
|
200
|
-
).to_range(read_file)
|
|
201
|
-
table_range_sqlmesh = TokenPositionDetails.from_meta(
|
|
202
|
-
table.this.meta
|
|
203
|
-
).to_range(read_file)
|
|
204
|
-
|
|
205
|
-
references.append(
|
|
206
|
-
LSPCteReference(
|
|
207
|
-
path=document_uri.to_path(), # Same file
|
|
208
|
-
range=table_range_sqlmesh,
|
|
209
|
-
target_range=target_range_sqlmesh,
|
|
210
|
-
)
|
|
211
|
-
)
|
|
212
|
-
|
|
213
|
-
column_references = _process_column_references(
|
|
214
|
-
scope=scope,
|
|
215
|
-
reference_name=table.name,
|
|
216
|
-
read_file=read_file,
|
|
217
|
-
referenced_model_path=document_uri.to_path(),
|
|
218
|
-
description="",
|
|
219
|
-
reference_type="cte",
|
|
220
|
-
cte_target_range=target_range_sqlmesh,
|
|
221
|
-
)
|
|
222
|
-
references.extend(column_references)
|
|
223
|
-
continue
|
|
224
|
-
|
|
225
|
-
# For non-CTE tables, process these as before (external model references)
|
|
226
|
-
# Normalize the table reference
|
|
227
|
-
unaliased = table.copy()
|
|
228
|
-
if unaliased.args.get("alias") is not None:
|
|
229
|
-
unaliased.set("alias", None)
|
|
230
|
-
reference_name = unaliased.sql(dialect=dialect)
|
|
231
|
-
try:
|
|
232
|
-
normalized_reference_name = normalize_model_name(
|
|
233
|
-
reference_name,
|
|
234
|
-
default_catalog=lint_context.context.default_catalog,
|
|
235
|
-
dialect=dialect,
|
|
236
|
-
)
|
|
237
|
-
if normalized_reference_name not in depends_on:
|
|
238
|
-
continue
|
|
239
|
-
except Exception:
|
|
240
|
-
# Skip references that cannot be normalized
|
|
241
|
-
continue
|
|
242
|
-
|
|
243
|
-
# Get the referenced model uri
|
|
244
|
-
referenced_model = lint_context.context.get_model(
|
|
245
|
-
model_or_snapshot=normalized_reference_name, raise_if_missing=False
|
|
246
|
-
)
|
|
247
|
-
if referenced_model is None:
|
|
248
|
-
table_meta = TokenPositionDetails.from_meta(table.this.meta)
|
|
249
|
-
table_range_sqlmesh = table_meta.to_range(read_file)
|
|
250
|
-
start_pos_sqlmesh = table_range_sqlmesh.start
|
|
251
|
-
end_pos_sqlmesh = table_range_sqlmesh.end
|
|
252
|
-
references.append(
|
|
253
|
-
LSPExternalModelReference(
|
|
254
|
-
range=Range(
|
|
255
|
-
start=start_pos_sqlmesh,
|
|
256
|
-
end=end_pos_sqlmesh,
|
|
257
|
-
),
|
|
258
|
-
markdown_description="Unregistered external model",
|
|
259
|
-
)
|
|
260
|
-
)
|
|
261
|
-
continue
|
|
262
|
-
referenced_model_path = referenced_model._path
|
|
263
|
-
if referenced_model_path is None:
|
|
264
|
-
continue
|
|
265
|
-
# Check whether the path exists
|
|
266
|
-
if not referenced_model_path.is_file():
|
|
267
|
-
continue
|
|
268
|
-
|
|
269
|
-
# Extract metadata for positioning
|
|
270
|
-
table_meta = TokenPositionDetails.from_meta(table.this.meta)
|
|
271
|
-
table_range_sqlmesh = table_meta.to_range(read_file)
|
|
272
|
-
start_pos_sqlmesh = table_range_sqlmesh.start
|
|
273
|
-
end_pos_sqlmesh = table_range_sqlmesh.end
|
|
274
|
-
|
|
275
|
-
# If there's a catalog or database qualifier, adjust the start position
|
|
276
|
-
catalog_or_db = table.args.get("catalog") or table.args.get("db")
|
|
277
|
-
if catalog_or_db is not None:
|
|
278
|
-
catalog_or_db_meta = TokenPositionDetails.from_meta(catalog_or_db.meta)
|
|
279
|
-
catalog_or_db_range_sqlmesh = catalog_or_db_meta.to_range(read_file)
|
|
280
|
-
start_pos_sqlmesh = catalog_or_db_range_sqlmesh.start
|
|
281
|
-
|
|
282
|
-
description = generate_markdown_description(referenced_model)
|
|
283
|
-
|
|
284
|
-
# For external models in YAML files, find the specific model block
|
|
285
|
-
if isinstance(referenced_model, ExternalModel):
|
|
286
|
-
yaml_target_range: t.Optional[Range] = None
|
|
287
|
-
if (
|
|
288
|
-
referenced_model_path.suffix in (".yaml", ".yml")
|
|
289
|
-
and referenced_model_path.is_file()
|
|
290
|
-
):
|
|
291
|
-
yaml_target_range = _get_yaml_model_range(
|
|
292
|
-
referenced_model_path, referenced_model.name
|
|
293
|
-
)
|
|
294
|
-
references.append(
|
|
295
|
-
LSPExternalModelReference(
|
|
296
|
-
path=referenced_model_path,
|
|
297
|
-
range=Range(
|
|
298
|
-
start=start_pos_sqlmesh,
|
|
299
|
-
end=end_pos_sqlmesh,
|
|
300
|
-
),
|
|
301
|
-
markdown_description=description,
|
|
302
|
-
target_range=yaml_target_range,
|
|
303
|
-
)
|
|
304
|
-
)
|
|
305
|
-
|
|
306
|
-
column_references = _process_column_references(
|
|
307
|
-
scope=scope,
|
|
308
|
-
reference_name=normalized_reference_name,
|
|
309
|
-
read_file=read_file,
|
|
310
|
-
referenced_model_path=referenced_model_path,
|
|
311
|
-
description=description,
|
|
312
|
-
yaml_target_range=yaml_target_range,
|
|
313
|
-
reference_type="external_model",
|
|
314
|
-
default_catalog=lint_context.context.default_catalog,
|
|
315
|
-
dialect=dialect,
|
|
316
|
-
)
|
|
317
|
-
references.extend(column_references)
|
|
318
|
-
else:
|
|
319
|
-
references.append(
|
|
320
|
-
LSPModelReference(
|
|
321
|
-
path=referenced_model_path,
|
|
322
|
-
range=Range(
|
|
323
|
-
start=start_pos_sqlmesh,
|
|
324
|
-
end=end_pos_sqlmesh,
|
|
325
|
-
),
|
|
326
|
-
markdown_description=description,
|
|
327
|
-
)
|
|
328
|
-
)
|
|
329
|
-
|
|
330
|
-
column_references = _process_column_references(
|
|
331
|
-
scope=scope,
|
|
332
|
-
reference_name=normalized_reference_name,
|
|
333
|
-
read_file=read_file,
|
|
334
|
-
referenced_model_path=referenced_model_path,
|
|
335
|
-
description=description,
|
|
336
|
-
reference_type="model",
|
|
337
|
-
default_catalog=lint_context.context.default_catalog,
|
|
338
|
-
dialect=dialect,
|
|
339
|
-
)
|
|
340
|
-
references.extend(column_references)
|
|
341
|
-
|
|
342
|
-
return references
|
|
127
|
+
return extract_references_from_query(
|
|
128
|
+
query=query,
|
|
129
|
+
context=lint_context.context,
|
|
130
|
+
document_path=document_uri.to_path(),
|
|
131
|
+
read_file=read_file,
|
|
132
|
+
depends_on=depends_on,
|
|
133
|
+
dialect=dialect,
|
|
134
|
+
)
|
|
343
135
|
|
|
344
136
|
|
|
345
137
|
def get_macro_definitions_for_a_path(
|
|
@@ -476,7 +268,7 @@ def get_macro_reference(
|
|
|
476
268
|
|
|
477
269
|
# Create a reference to the macro definition
|
|
478
270
|
|
|
479
|
-
return
|
|
271
|
+
return MacroReference(
|
|
480
272
|
path=path,
|
|
481
273
|
range=macro_range,
|
|
482
274
|
target_range=Range(
|
|
@@ -509,7 +301,7 @@ def get_built_in_macro_reference(macro_name: str, macro_range: Range) -> t.Optio
|
|
|
509
301
|
# Calculate the end line number by counting the number of source lines
|
|
510
302
|
end_line_number = line_number + len(source_lines) - 1
|
|
511
303
|
|
|
512
|
-
return
|
|
304
|
+
return MacroReference(
|
|
513
305
|
path=Path(filename),
|
|
514
306
|
range=macro_range,
|
|
515
307
|
target_range=Range(
|
|
@@ -522,7 +314,7 @@ def get_built_in_macro_reference(macro_name: str, macro_range: Range) -> t.Optio
|
|
|
522
314
|
|
|
523
315
|
def get_model_find_all_references(
|
|
524
316
|
lint_context: LSPContext, document_uri: URI, position: Position
|
|
525
|
-
) -> t.List[
|
|
317
|
+
) -> t.List[ModelReference]:
|
|
526
318
|
"""
|
|
527
319
|
Get all references to a model across the entire project.
|
|
528
320
|
|
|
@@ -540,7 +332,7 @@ def get_model_find_all_references(
|
|
|
540
332
|
# Find the model reference at the cursor position
|
|
541
333
|
model_at_position = next(
|
|
542
334
|
filter(
|
|
543
|
-
lambda ref: isinstance(ref,
|
|
335
|
+
lambda ref: isinstance(ref, ModelReference)
|
|
544
336
|
and _position_within_range(position, ref.range),
|
|
545
337
|
get_model_definitions_for_a_path(lint_context, document_uri),
|
|
546
338
|
),
|
|
@@ -550,13 +342,13 @@ def get_model_find_all_references(
|
|
|
550
342
|
if not model_at_position:
|
|
551
343
|
return []
|
|
552
344
|
|
|
553
|
-
assert isinstance(model_at_position,
|
|
345
|
+
assert isinstance(model_at_position, ModelReference) # for mypy
|
|
554
346
|
|
|
555
347
|
target_model_path = model_at_position.path
|
|
556
348
|
|
|
557
349
|
# Start with the model definition
|
|
558
|
-
all_references: t.List[
|
|
559
|
-
|
|
350
|
+
all_references: t.List[ModelReference] = [
|
|
351
|
+
ModelReference(
|
|
560
352
|
path=model_at_position.path,
|
|
561
353
|
range=Range(
|
|
562
354
|
start=Position(line=0, character=0),
|
|
@@ -568,15 +360,15 @@ def get_model_find_all_references(
|
|
|
568
360
|
|
|
569
361
|
# Then add references from the current file
|
|
570
362
|
current_file_refs = filter(
|
|
571
|
-
lambda ref: isinstance(ref,
|
|
363
|
+
lambda ref: isinstance(ref, ModelReference) and ref.path == target_model_path,
|
|
572
364
|
get_model_definitions_for_a_path(lint_context, document_uri),
|
|
573
365
|
)
|
|
574
366
|
|
|
575
367
|
for ref in current_file_refs:
|
|
576
|
-
assert isinstance(ref,
|
|
368
|
+
assert isinstance(ref, ModelReference) # for mypy
|
|
577
369
|
|
|
578
370
|
all_references.append(
|
|
579
|
-
|
|
371
|
+
ModelReference(
|
|
580
372
|
path=document_uri.to_path(),
|
|
581
373
|
range=ref.range,
|
|
582
374
|
markdown_description=ref.markdown_description,
|
|
@@ -593,15 +385,15 @@ def get_model_find_all_references(
|
|
|
593
385
|
|
|
594
386
|
# Get model references that point to the target model
|
|
595
387
|
matching_refs = filter(
|
|
596
|
-
lambda ref: isinstance(ref,
|
|
388
|
+
lambda ref: isinstance(ref, ModelReference) and ref.path == target_model_path,
|
|
597
389
|
get_model_definitions_for_a_path(lint_context, file_uri),
|
|
598
390
|
)
|
|
599
391
|
|
|
600
392
|
for ref in matching_refs:
|
|
601
|
-
assert isinstance(ref,
|
|
393
|
+
assert isinstance(ref, ModelReference) # for mypy
|
|
602
394
|
|
|
603
395
|
all_references.append(
|
|
604
|
-
|
|
396
|
+
ModelReference(
|
|
605
397
|
path=path,
|
|
606
398
|
range=ref.range,
|
|
607
399
|
markdown_description=ref.markdown_description,
|
|
@@ -613,7 +405,7 @@ def get_model_find_all_references(
|
|
|
613
405
|
|
|
614
406
|
def get_cte_references(
|
|
615
407
|
lint_context: LSPContext, document_uri: URI, position: Position
|
|
616
|
-
) -> t.List[
|
|
408
|
+
) -> t.List[CTEReference]:
|
|
617
409
|
"""
|
|
618
410
|
Get all references to a CTE at a specific position in a document.
|
|
619
411
|
|
|
@@ -629,10 +421,10 @@ def get_cte_references(
|
|
|
629
421
|
"""
|
|
630
422
|
|
|
631
423
|
# Filter to get the CTE references
|
|
632
|
-
cte_references: t.List[
|
|
424
|
+
cte_references: t.List[CTEReference] = [
|
|
633
425
|
ref
|
|
634
426
|
for ref in get_model_definitions_for_a_path(lint_context, document_uri)
|
|
635
|
-
if isinstance(ref,
|
|
427
|
+
if isinstance(ref, CTEReference)
|
|
636
428
|
]
|
|
637
429
|
|
|
638
430
|
if not cte_references:
|
|
@@ -654,7 +446,7 @@ def get_cte_references(
|
|
|
654
446
|
|
|
655
447
|
# Add the CTE definition
|
|
656
448
|
matching_references = [
|
|
657
|
-
|
|
449
|
+
CTEReference(
|
|
658
450
|
path=document_uri.to_path(),
|
|
659
451
|
range=target_cte_definition_range,
|
|
660
452
|
target_range=target_cte_definition_range,
|
|
@@ -665,7 +457,7 @@ def get_cte_references(
|
|
|
665
457
|
for ref in cte_references:
|
|
666
458
|
if ref.target_range == target_cte_definition_range:
|
|
667
459
|
matching_references.append(
|
|
668
|
-
|
|
460
|
+
CTEReference(
|
|
669
461
|
path=document_uri.to_path(),
|
|
670
462
|
range=ref.range,
|
|
671
463
|
target_range=ref.target_range,
|
|
@@ -677,7 +469,7 @@ def get_cte_references(
|
|
|
677
469
|
|
|
678
470
|
def get_macro_find_all_references(
|
|
679
471
|
lsp_context: LSPContext, document_uri: URI, position: Position
|
|
680
|
-
) -> t.List[
|
|
472
|
+
) -> t.List[MacroReference]:
|
|
681
473
|
"""
|
|
682
474
|
Get all references to a macro at a specific position in a document.
|
|
683
475
|
|
|
@@ -694,7 +486,7 @@ def get_macro_find_all_references(
|
|
|
694
486
|
# Find the macro reference at the cursor position
|
|
695
487
|
macro_at_position = next(
|
|
696
488
|
filter(
|
|
697
|
-
lambda ref: isinstance(ref,
|
|
489
|
+
lambda ref: isinstance(ref, MacroReference)
|
|
698
490
|
and _position_within_range(position, ref.range),
|
|
699
491
|
get_macro_definitions_for_a_path(lsp_context, document_uri),
|
|
700
492
|
),
|
|
@@ -704,14 +496,14 @@ def get_macro_find_all_references(
|
|
|
704
496
|
if not macro_at_position:
|
|
705
497
|
return []
|
|
706
498
|
|
|
707
|
-
assert isinstance(macro_at_position,
|
|
499
|
+
assert isinstance(macro_at_position, MacroReference) # for mypy
|
|
708
500
|
|
|
709
501
|
target_macro_path = macro_at_position.path
|
|
710
502
|
target_macro_target_range = macro_at_position.target_range
|
|
711
503
|
|
|
712
504
|
# Start with the macro definition
|
|
713
|
-
all_references: t.List[
|
|
714
|
-
|
|
505
|
+
all_references: t.List[MacroReference] = [
|
|
506
|
+
MacroReference(
|
|
715
507
|
path=target_macro_path,
|
|
716
508
|
range=target_macro_target_range,
|
|
717
509
|
target_range=target_macro_target_range,
|
|
@@ -725,16 +517,16 @@ def get_macro_find_all_references(
|
|
|
725
517
|
|
|
726
518
|
# Get macro references that point to the same macro definition
|
|
727
519
|
matching_refs = filter(
|
|
728
|
-
lambda ref: isinstance(ref,
|
|
520
|
+
lambda ref: isinstance(ref, MacroReference)
|
|
729
521
|
and ref.path == target_macro_path
|
|
730
522
|
and ref.target_range == target_macro_target_range,
|
|
731
523
|
get_macro_definitions_for_a_path(lsp_context, file_uri),
|
|
732
524
|
)
|
|
733
525
|
|
|
734
526
|
for ref in matching_refs:
|
|
735
|
-
assert isinstance(ref,
|
|
527
|
+
assert isinstance(ref, MacroReference) # for mypy
|
|
736
528
|
all_references.append(
|
|
737
|
-
|
|
529
|
+
MacroReference(
|
|
738
530
|
path=path,
|
|
739
531
|
range=ref.range,
|
|
740
532
|
target_range=ref.target_range,
|
|
@@ -786,129 +578,3 @@ def _position_within_range(position: Position, range: Range) -> bool:
|
|
|
786
578
|
range.end.line > position.line
|
|
787
579
|
or (range.end.line == position.line and range.end.character >= position.character)
|
|
788
580
|
)
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
def _get_column_table_range(column: exp.Column, read_file: t.List[str]) -> Range:
|
|
792
|
-
"""
|
|
793
|
-
Get the range for a column's table reference, handling both simple and qualified table names.
|
|
794
|
-
|
|
795
|
-
Args:
|
|
796
|
-
column: The column expression
|
|
797
|
-
read_file: The file content as list of lines
|
|
798
|
-
|
|
799
|
-
Returns:
|
|
800
|
-
The Range covering the table reference in the column
|
|
801
|
-
"""
|
|
802
|
-
|
|
803
|
-
table_parts = column.parts[:-1]
|
|
804
|
-
|
|
805
|
-
start_range = TokenPositionDetails.from_meta(table_parts[0].meta).to_range(read_file)
|
|
806
|
-
end_range = TokenPositionDetails.from_meta(table_parts[-1].meta).to_range(read_file)
|
|
807
|
-
|
|
808
|
-
return Range(
|
|
809
|
-
start=start_range.start,
|
|
810
|
-
end=end_range.end,
|
|
811
|
-
)
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
def _process_column_references(
|
|
815
|
-
scope: t.Any,
|
|
816
|
-
reference_name: str,
|
|
817
|
-
read_file: t.List[str],
|
|
818
|
-
referenced_model_path: Path,
|
|
819
|
-
description: t.Optional[str] = None,
|
|
820
|
-
yaml_target_range: t.Optional[Range] = None,
|
|
821
|
-
reference_type: t.Literal["model", "external_model", "cte"] = "model",
|
|
822
|
-
default_catalog: t.Optional[str] = None,
|
|
823
|
-
dialect: t.Optional[str] = None,
|
|
824
|
-
cte_target_range: t.Optional[Range] = None,
|
|
825
|
-
) -> t.List[Reference]:
|
|
826
|
-
"""
|
|
827
|
-
Process column references for a given table and create appropriate reference objects.
|
|
828
|
-
|
|
829
|
-
Args:
|
|
830
|
-
scope: The SQL scope to search for columns
|
|
831
|
-
reference_name: The full reference name (may include database/catalog)
|
|
832
|
-
read_file: The file content as list of lines
|
|
833
|
-
referenced_model_path: Path of the referenced model
|
|
834
|
-
description: Markdown description for the reference
|
|
835
|
-
yaml_target_range: Target range for external models (YAML files)
|
|
836
|
-
reference_type: Type of reference - "model", "external_model", or "cte"
|
|
837
|
-
default_catalog: Default catalog for normalization
|
|
838
|
-
dialect: SQL dialect for normalization
|
|
839
|
-
cte_target_range: Target range for CTE references
|
|
840
|
-
|
|
841
|
-
Returns:
|
|
842
|
-
List of table references for column usages
|
|
843
|
-
"""
|
|
844
|
-
|
|
845
|
-
references: t.List[Reference] = []
|
|
846
|
-
for column in scope.find_all(exp.Column):
|
|
847
|
-
if column.table:
|
|
848
|
-
if reference_type == "cte":
|
|
849
|
-
if column.table == reference_name:
|
|
850
|
-
table_range = _get_column_table_range(column, read_file)
|
|
851
|
-
references.append(
|
|
852
|
-
LSPCteReference(
|
|
853
|
-
path=referenced_model_path,
|
|
854
|
-
range=table_range,
|
|
855
|
-
target_range=cte_target_range,
|
|
856
|
-
)
|
|
857
|
-
)
|
|
858
|
-
else:
|
|
859
|
-
table_parts = [part.sql(dialect) for part in column.parts[:-1]]
|
|
860
|
-
table_ref = ".".join(table_parts)
|
|
861
|
-
normalized_reference_name = normalize_model_name(
|
|
862
|
-
table_ref,
|
|
863
|
-
default_catalog=default_catalog,
|
|
864
|
-
dialect=dialect,
|
|
865
|
-
)
|
|
866
|
-
if normalized_reference_name == reference_name:
|
|
867
|
-
table_range = _get_column_table_range(column, read_file)
|
|
868
|
-
if reference_type == "external_model":
|
|
869
|
-
references.append(
|
|
870
|
-
LSPExternalModelReference(
|
|
871
|
-
path=referenced_model_path,
|
|
872
|
-
range=table_range,
|
|
873
|
-
markdown_description=description,
|
|
874
|
-
target_range=yaml_target_range,
|
|
875
|
-
)
|
|
876
|
-
)
|
|
877
|
-
else:
|
|
878
|
-
references.append(
|
|
879
|
-
LSPModelReference(
|
|
880
|
-
path=referenced_model_path,
|
|
881
|
-
range=table_range,
|
|
882
|
-
markdown_description=description,
|
|
883
|
-
)
|
|
884
|
-
)
|
|
885
|
-
|
|
886
|
-
return references
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
def _get_yaml_model_range(path: Path, model_name: str) -> t.Optional[Range]:
|
|
890
|
-
"""
|
|
891
|
-
Find the range of a specific model block in a YAML file.
|
|
892
|
-
|
|
893
|
-
Args:
|
|
894
|
-
yaml_path: Path to the YAML file
|
|
895
|
-
model_name: Name of the model to find
|
|
896
|
-
|
|
897
|
-
Returns:
|
|
898
|
-
The Range of the model block in the YAML file, or None if not found
|
|
899
|
-
"""
|
|
900
|
-
yaml = YAML()
|
|
901
|
-
with path.open("r", encoding="utf-8") as f:
|
|
902
|
-
data = yaml.load(f)
|
|
903
|
-
|
|
904
|
-
if not isinstance(data, list):
|
|
905
|
-
return None
|
|
906
|
-
|
|
907
|
-
for item in data:
|
|
908
|
-
if isinstance(item, dict) and item.get("name") == model_name:
|
|
909
|
-
# Get size of block by taking the earliest line/col in the items block and the last line/col of the block
|
|
910
|
-
position_data = item.lc.data["name"] # type: ignore
|
|
911
|
-
start = Position(line=position_data[2], character=position_data[3])
|
|
912
|
-
end = Position(line=position_data[2], character=position_data[3] + len(item["name"]))
|
|
913
|
-
return Range(start=start, end=end)
|
|
914
|
-
return None
|
sqlmesh/lsp/rename.py
CHANGED
|
@@ -13,7 +13,7 @@ from sqlmesh.lsp.helpers import to_sqlmesh_position, to_lsp_range
|
|
|
13
13
|
from sqlmesh.lsp.reference import (
|
|
14
14
|
_position_within_range,
|
|
15
15
|
get_cte_references,
|
|
16
|
-
|
|
16
|
+
CTEReference,
|
|
17
17
|
)
|
|
18
18
|
from sqlmesh.lsp.uri import URI
|
|
19
19
|
|
|
@@ -82,7 +82,7 @@ def rename_symbol(
|
|
|
82
82
|
return None
|
|
83
83
|
|
|
84
84
|
|
|
85
|
-
def _rename_cte(cte_references: t.List[
|
|
85
|
+
def _rename_cte(cte_references: t.List[CTEReference], new_name: str) -> WorkspaceEdit:
|
|
86
86
|
"""
|
|
87
87
|
Create a WorkspaceEdit for renaming a CTE.
|
|
88
88
|
|