Skip to content

Commit 3e472e6

Browse files
committed
feat(lsp): go to definition/hover for variable macros
[ci skip]
1 parent 5285753 commit 3e472e6

2 files changed

Lines changed: 71 additions & 0 deletions

File tree

sqlmesh/lsp/reference.py

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,10 @@ def get_references(
8383
macro_references = get_macro_definitions_for_a_path(lint_context, document_uri)
8484
references.extend(macro_references)
8585

86+
# Get single variable references
87+
variable_references = get_macro_variables_definitions(lint_context, document_uri)
88+
references.extend(variable_references)
89+
8690
filtered_references = list(filter(by_position(position), references))
8791
return filtered_references
8892

@@ -478,3 +482,41 @@ def get_built_in_macro_reference(macro_name: str, macro_range: Range) -> t.Optio
478482
),
479483
markdown_description=func.__doc__ if func.__doc__ else None,
480484
)
485+
486+
487+
def get_macro_variables_definitions(
488+
lsp_context: LSPContext, document_uri: URI
489+
) -> t.List[Reference]:
490+
"""
491+
Get references to all macro variables.
492+
493+
This function returns a list of references to all macro variables defined in the SQLMesh
494+
environment. It is used for autocompletion and hover information in the LSP.
495+
"""
496+
references: t.List[Reference] = []
497+
path = document_uri.to_path()
498+
499+
file_info = lsp_context.map[path]
500+
# Process based on whether it's a model or standalone audit
501+
if isinstance(file_info, ModelTarget):
502+
# It's a model
503+
target: t.Optional[t.Union[Model, StandaloneAudit]] = lsp_context.context.get_model(
504+
model_or_snapshot=file_info.names[0], raise_if_missing=False
505+
)
506+
if target is None or not isinstance(target, SqlModel):
507+
return []
508+
query = target.query
509+
file_path = target._path
510+
elif isinstance(file_info, AuditTarget):
511+
# It's a standalone audit
512+
target = lsp_context.context.standalone_audits.get(file_info.name)
513+
if target is None:
514+
return []
515+
query = target.query
516+
file_path = target._path
517+
else:
518+
return []
519+
520+
521+
522+
return references
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import pytest
2+
from sqlmesh.core.context import Context
3+
from sqlmesh.lsp.context import LSPContext, ModelTarget
4+
from sqlmesh.lsp.reference import get_macro_definitions_for_a_path, get_references, get_macro_variables_definitions
5+
from sqlmesh.lsp.uri import URI
6+
7+
8+
@pytest.mark.fast
9+
def test_macro_references() -> None:
10+
"""Test that macro references (e.g., @ADD_ONE, @MULTIPLY) have proper go-to-definition support."""
11+
context = Context(paths=["examples/sushi"])
12+
lsp_context = LSPContext(context)
13+
14+
# Find the top_waiters model that uses macros
15+
waiter_revenue_path = next(
16+
path
17+
for path, info in lsp_context.map.items()
18+
if isinstance(info, ModelTarget) and "sushi.waiter_revenue_by_day" in info.names
19+
)
20+
waiter_revenue_uri = URI.from_path(waiter_revenue_path)
21+
macro_references = get_macro_variables_definitions(lsp_context, waiter_revenue_uri)
22+
23+
# We expect 3 macro references: @ADD_ONE, @MULTIPLY, @SQL_LITERAL
24+
assert len(macro_references) == 2
25+
26+
# Check that all references point to the utils.py file
27+
for ref in macro_references:
28+
assert ref.uri.endswith("sushi/macros/utils.py")
29+
assert ref.target_range is not None

0 commit comments

Comments
 (0)