1+ import pytest
2+ from lsprotocol .types import Position
3+ from pathlib import Path
4+ from sqlmesh .core .context import Context
5+ from sqlmesh .lsp .context import LSPContext , ModelTarget
6+ from sqlmesh .lsp .reference import get_macro_definitions_for_a_path , get_references , by_position
7+ from sqlmesh .lsp .uri import URI
8+
9+
10+ @pytest .mark .fast
11+ def test_macro_references () -> None :
12+ """Test that macro references (e.g., @ADD_ONE, @MULTIPLY) have proper go-to-definition support."""
13+ context = Context (paths = ["examples/sushi" ])
14+ lsp_context = LSPContext (context )
15+
16+ # Find the top_waiters model that uses macros
17+ top_waiters_path = next (
18+ path
19+ for path , info in lsp_context .map .items ()
20+ if isinstance (info , ModelTarget ) and "sushi.top_waiters" in info .names
21+ )
22+
23+ top_waiters_uri = URI .from_path (top_waiters_path )
24+ macro_references = get_macro_definitions_for_a_path (lsp_context , top_waiters_uri )
25+
26+ # We expect 3 macro references: @ADD_ONE, @MULTIPLY, @SQL_LITERAL
27+ assert len (macro_references ) == 3
28+
29+ # Check that all references point to the utils.py file
30+ for ref in macro_references :
31+ assert ref .uri .endswith ("macros/utils.py" )
32+ assert ref .target_range is not None # Should have target range for go-to-definition
33+
34+ # Read the SQL file to verify macro positions
35+ with open (top_waiters_path , "r" ) as file :
36+ content = file .read ()
37+
38+ # Verify that the references are at the expected macro invocations
39+ assert "@ADD_ONE" in content
40+ assert "@MULTIPLY" in content
41+ assert "@SQL_LITERAL" in content
42+
43+
44+ @pytest .mark .fast
45+ def test_macro_go_to_definition_with_position () -> None :
46+ """Test go-to-definition for specific macro positions."""
47+ context = Context (paths = ["examples/sushi" ])
48+ lsp_context = LSPContext (context )
49+
50+ # Find the top_waiters model
51+ top_waiters_path = next (
52+ path
53+ for path , info in lsp_context .map .items ()
54+ if isinstance (info , ModelTarget ) and "sushi.top_waiters" in info .names
55+ )
56+
57+ # Read the file to find exact positions
58+ with open (top_waiters_path , "r" ) as file :
59+ lines = file .readlines ()
60+
61+ # Find line with @ADD_ONE
62+ add_one_line = None
63+ add_one_char = None
64+ for i , line in enumerate (lines ):
65+ if "@ADD_ONE" in line :
66+ add_one_line = i
67+ add_one_char = line .index ("@ADD_ONE" ) + 4 # Position inside the macro name
68+ break
69+
70+ assert add_one_line is not None
71+
72+ # Test go-to-definition at the @ADD_ONE position
73+ position = Position (line = add_one_line , character = add_one_char )
74+ references = get_references (lsp_context , URI .from_path (top_waiters_path ), position )
75+
76+ # Should find exactly one reference
77+ assert len (references ) == 1
78+ assert references [0 ].uri .endswith ("macros/utils.py" )
79+ assert references [0 ].target_range is not None
80+
81+ # The target should be at the line where add_one is defined
82+ # (approximately line 6 based on the utils.py file)
83+ assert references [0 ].target_range .start .line >= 5 # Zero-indexed, so line 6 is index 5
84+
85+
86+ @pytest .mark .fast
87+ def test_all_three_macros_positions () -> None :
88+ """Test that all three macros (@ADD_ONE, @MULTIPLY, @SQL_LITERAL) work with position-based lookup."""
89+ context = Context (paths = ["examples/sushi" ])
90+ lsp_context = LSPContext (context )
91+
92+ # Find the top_waiters model
93+ top_waiters_path = next (
94+ path
95+ for path , info in lsp_context .map .items ()
96+ if isinstance (info , ModelTarget ) and "sushi.top_waiters" in info .names
97+ )
98+
99+ top_waiters_uri = URI .from_path (top_waiters_path )
100+
101+ # Get all references (models and macros)
102+ with open (top_waiters_path , "r" ) as file :
103+ lines = file .readlines ()
104+
105+ macro_names = ["@ADD_ONE" , "@MULTIPLY" , "@SQL_LITERAL" ]
106+ found_macros = []
107+
108+ for macro_name in macro_names :
109+ for i , line in enumerate (lines ):
110+ if macro_name in line :
111+ char_pos = line .index (macro_name ) + len (macro_name ) // 2
112+ position = Position (line = i , character = char_pos )
113+ refs = get_references (lsp_context , top_waiters_uri , position )
114+
115+ # Filter to only macro references
116+ macro_refs = [r for r in refs if r .uri .endswith ("utils.py" )]
117+ if macro_refs :
118+ found_macros .append (macro_name )
119+ assert len (macro_refs ) == 1
120+ assert macro_refs [0 ].markdown_description == f"Macro: `{ macro_name } `"
121+
122+ # Should find all three macros
123+ assert len (found_macros ) == 3
124+ assert set (found_macros ) == set (macro_names )
0 commit comments