|
1 | 1 | import 'package:sass_api/sass_api.dart' as sass;
|
2 | 2 |
|
| 3 | +sass.AstNode? getNodeAtOffset(sass.ParentStatement node, int offset) { |
| 4 | + if (node.span.start.offset > offset || offset > node.span.end.offset) { |
| 5 | + return null; |
| 6 | + } |
| 7 | + var visitor = NodeAtOffsetVisitor(offset); |
| 8 | + var result = node.accept(visitor); |
| 9 | + // The visitor might have reached the end of the syntax tree, |
| 10 | + // in which case result is null. We still might have a candidate. |
| 11 | + return result ?? visitor.candidate; |
| 12 | +} |
| 13 | + |
3 | 14 | class NodeAtOffsetVisitor
|
4 | 15 | with
|
5 | 16 | sass.StatementSearchVisitor<sass.AstNode>,
|
6 | 17 | sass.AstSearchVisitor<sass.AstNode> {
|
7 |
| - sass.AstNode? _candidate; |
| 18 | + sass.AstNode? candidate; |
8 | 19 | final int _offset;
|
9 | 20 |
|
10 | 21 | /// Finds the node with the shortest span at [offset].
|
11 | 22 | NodeAtOffsetVisitor(int offset) : _offset = offset;
|
12 | 23 |
|
13 | 24 | sass.AstNode? _process(sass.AstNode node) {
|
14 |
| - var spanContainsOffset = |
| 25 | + var containsOffset = |
15 | 26 | node.span.start.offset <= _offset && node.span.end.offset >= _offset;
|
16 | 27 |
|
17 |
| - if (spanContainsOffset) { |
18 |
| - if (_candidate == null) { |
19 |
| - _candidate = node; |
20 |
| - } else if (node.span.length <= _candidate!.span.length) { |
21 |
| - _candidate = node; |
| 28 | + if (containsOffset) { |
| 29 | + if (candidate == null) { |
| 30 | + candidate = node; |
| 31 | + } else if (node.span.length <= candidate!.span.length) { |
| 32 | + candidate = node; |
22 | 33 | }
|
23 | 34 | }
|
24 | 35 |
|
25 |
| - if (node.span.start.offset > _offset || node is sass.Stylesheet) { |
26 |
| - return _candidate; |
| 36 | + if (node.span.start.offset > _offset) { |
| 37 | + return candidate; |
27 | 38 | }
|
28 | 39 |
|
29 | 40 | return null;
|
30 | 41 | }
|
31 | 42 |
|
32 | 43 | @override
|
33 | 44 | sass.AstNode? visitArgumentInvocation(sass.ArgumentInvocation invocation) {
|
34 |
| - return super.visitArgumentInvocation(invocation) ?? _process(invocation); |
| 45 | + return _process(invocation) ?? super.visitArgumentInvocation(invocation); |
35 | 46 | }
|
36 | 47 |
|
37 | 48 | @override
|
38 | 49 | sass.AstNode? visitAtRootRule(sass.AtRootRule node) {
|
39 |
| - return super.visitAtRootRule(node) ?? _process(node); |
| 50 | + return _process(node) ?? super.visitAtRootRule(node); |
40 | 51 | }
|
41 | 52 |
|
42 | 53 | @override
|
43 | 54 | sass.AstNode? visitAtRule(sass.AtRule node) {
|
44 |
| - return super.visitAtRule(node) ?? _process(node); |
| 55 | + return _process(node) ?? super.visitAtRule(node); |
45 | 56 | }
|
46 | 57 |
|
47 | 58 | @override
|
48 | 59 | sass.AstNode? visitBinaryOperationExpression(
|
49 | 60 | sass.BinaryOperationExpression node) {
|
50 |
| - return super.visitBinaryOperationExpression(node) ?? _process(node); |
| 61 | + return _process(node) ?? super.visitBinaryOperationExpression(node); |
51 | 62 | }
|
52 | 63 |
|
53 | 64 | @override
|
54 | 65 | sass.AstNode? visitBooleanExpression(sass.BooleanExpression node) {
|
55 |
| - return super.visitBooleanExpression(node) ?? _process(node); |
| 66 | + return _process(node) ?? super.visitBooleanExpression(node); |
56 | 67 | }
|
57 | 68 |
|
58 | 69 | @override
|
59 | 70 | sass.AstNode? visitCallableDeclaration(sass.CallableDeclaration node) {
|
60 |
| - return super.visitCallableDeclaration(node) ?? _process(node); |
| 71 | + return _process(node) ?? super.visitCallableDeclaration(node); |
61 | 72 | }
|
62 | 73 |
|
63 | 74 | @override
|
64 | 75 | sass.AstNode? visitColorExpression(sass.ColorExpression node) {
|
65 |
| - return super.visitColorExpression(node) ?? _process(node); |
| 76 | + return _process(node) ?? super.visitColorExpression(node); |
66 | 77 | }
|
67 | 78 |
|
68 | 79 | @override
|
69 | 80 | sass.AstNode? visitContentBlock(sass.ContentBlock node) {
|
70 |
| - return super.visitContentBlock(node) ?? _process(node); |
| 81 | + return _process(node) ?? super.visitContentBlock(node); |
71 | 82 | }
|
72 | 83 |
|
73 | 84 | @override
|
74 | 85 | sass.AstNode? visitContentRule(sass.ContentRule node) {
|
75 |
| - return super.visitContentRule(node) ?? _process(node); |
| 86 | + return _process(node) ?? super.visitContentRule(node); |
76 | 87 | }
|
77 | 88 |
|
78 | 89 | @override
|
79 | 90 | sass.AstNode? visitDebugRule(sass.DebugRule node) {
|
80 |
| - return super.visitDebugRule(node) ?? _process(node); |
| 91 | + return _process(node) ?? super.visitDebugRule(node); |
81 | 92 | }
|
82 | 93 |
|
83 | 94 | @override
|
84 | 95 | sass.AstNode? visitDeclaration(sass.Declaration node) {
|
85 |
| - return super.visitDeclaration(node) ?? _process(node); |
| 96 | + return _process(node) ?? super.visitDeclaration(node); |
86 | 97 | }
|
87 | 98 |
|
88 | 99 | @override
|
89 | 100 | sass.AstNode? visitEachRule(sass.EachRule node) {
|
90 |
| - return super.visitEachRule(node) ?? _process(node); |
| 101 | + return _process(node) ?? super.visitEachRule(node); |
91 | 102 | }
|
92 | 103 |
|
93 | 104 | @override
|
94 | 105 | sass.AstNode? visitErrorRule(sass.ErrorRule node) {
|
95 |
| - return super.visitErrorRule(node) ?? _process(node); |
| 106 | + return _process(node) ?? super.visitErrorRule(node); |
96 | 107 | }
|
97 | 108 |
|
98 | 109 | @override
|
99 | 110 | sass.AstNode? visitExpression(sass.Expression expression) {
|
100 |
| - return super.visitExpression(expression) ?? _process(expression); |
| 111 | + return _process(expression) ?? super.visitExpression(expression); |
101 | 112 | }
|
102 | 113 |
|
103 | 114 | @override
|
104 | 115 | sass.AstNode? visitExtendRule(sass.ExtendRule node) {
|
105 |
| - return super.visitExtendRule(node) ?? _process(node); |
| 116 | + return _process(node) ?? super.visitExtendRule(node); |
106 | 117 | }
|
107 | 118 |
|
108 | 119 | @override
|
109 | 120 | sass.AstNode? visitForRule(sass.ForRule node) {
|
110 |
| - return super.visitForRule(node) ?? _process(node); |
| 121 | + return _process(node) ?? super.visitForRule(node); |
111 | 122 | }
|
112 | 123 |
|
113 | 124 | @override
|
114 | 125 | sass.AstNode? visitForwardRule(sass.ForwardRule node) {
|
115 |
| - return super.visitForwardRule(node) ?? _process(node); |
| 126 | + return _process(node) ?? super.visitForwardRule(node); |
116 | 127 | }
|
117 | 128 |
|
118 | 129 | @override
|
119 | 130 | sass.AstNode? visitFunctionExpression(sass.FunctionExpression node) {
|
120 |
| - return super.visitFunctionExpression(node) ?? _process(node); |
| 131 | + return _process(node) ?? super.visitFunctionExpression(node); |
121 | 132 | }
|
122 | 133 |
|
123 | 134 | @override
|
124 | 135 | sass.AstNode? visitFunctionRule(sass.FunctionRule node) {
|
125 |
| - return super.visitFunctionRule(node) ?? _process(node); |
| 136 | + return _process(node) ?? super.visitFunctionRule(node); |
126 | 137 | }
|
127 | 138 |
|
128 | 139 | @override
|
129 | 140 | sass.AstNode? visitIfExpression(sass.IfExpression node) {
|
130 |
| - return super.visitIfExpression(node) ?? _process(node); |
| 141 | + return _process(node) ?? super.visitIfExpression(node); |
131 | 142 | }
|
132 | 143 |
|
133 | 144 | @override
|
134 | 145 | sass.AstNode? visitIfRule(sass.IfRule node) {
|
135 |
| - return super.visitIfRule(node) ?? _process(node); |
| 146 | + return _process(node) ?? super.visitIfRule(node); |
136 | 147 | }
|
137 | 148 |
|
138 | 149 | @override
|
139 | 150 | sass.AstNode? visitImportRule(sass.ImportRule node) {
|
140 |
| - return super.visitImportRule(node) ?? _process(node); |
| 151 | + return _process(node) ?? super.visitImportRule(node); |
141 | 152 | }
|
142 | 153 |
|
143 | 154 | @override
|
144 | 155 | sass.AstNode? visitIncludeRule(sass.IncludeRule node) {
|
145 |
| - return super.visitIncludeRule(node) ?? _process(node); |
| 156 | + return _process(node) ?? super.visitIncludeRule(node); |
146 | 157 | }
|
147 | 158 |
|
148 | 159 | @override
|
149 | 160 | sass.AstNode? visitListExpression(sass.ListExpression node) {
|
150 |
| - return super.visitListExpression(node) ?? _process(node); |
| 161 | + return _process(node) ?? super.visitListExpression(node); |
151 | 162 | }
|
152 | 163 |
|
153 | 164 | @override
|
154 | 165 | sass.AstNode? visitLoudComment(sass.LoudComment node) {
|
155 |
| - return super.visitLoudComment(node) ?? _process(node); |
| 166 | + return _process(node) ?? super.visitLoudComment(node); |
156 | 167 | }
|
157 | 168 |
|
158 | 169 | @override
|
159 | 170 | sass.AstNode? visitMapExpression(sass.MapExpression node) {
|
160 |
| - return super.visitMapExpression(node) ?? _process(node); |
| 171 | + return _process(node) ?? super.visitMapExpression(node); |
161 | 172 | }
|
162 | 173 |
|
163 | 174 | @override
|
164 | 175 | sass.AstNode? visitMediaRule(sass.MediaRule node) {
|
165 |
| - return super.visitMediaRule(node) ?? _process(node); |
| 176 | + return _process(node) ?? super.visitMediaRule(node); |
166 | 177 | }
|
167 | 178 |
|
168 | 179 | @override
|
169 | 180 | sass.AstNode? visitMixinRule(sass.MixinRule node) {
|
170 |
| - return super.visitMixinRule(node) ?? _process(node); |
| 181 | + return _process(node) ?? super.visitMixinRule(node); |
171 | 182 | }
|
172 | 183 |
|
173 | 184 | @override
|
174 | 185 | sass.AstNode? visitNullExpression(sass.NullExpression node) {
|
175 |
| - return super.visitNullExpression(node) ?? _process(node); |
| 186 | + return _process(node) ?? super.visitNullExpression(node); |
176 | 187 | }
|
177 | 188 |
|
178 | 189 | @override
|
179 | 190 | sass.AstNode? visitNumberExpression(sass.NumberExpression node) {
|
180 |
| - return super.visitNumberExpression(node) ?? _process(node); |
| 191 | + return _process(node) ?? super.visitNumberExpression(node); |
181 | 192 | }
|
182 | 193 |
|
183 | 194 | @override
|
184 | 195 | sass.AstNode? visitParenthesizedExpression(
|
185 | 196 | sass.ParenthesizedExpression node) {
|
186 |
| - return super.visitParenthesizedExpression(node) ?? _process(node); |
| 197 | + return _process(node) ?? super.visitParenthesizedExpression(node); |
187 | 198 | }
|
188 | 199 |
|
189 | 200 | @override
|
190 | 201 | sass.AstNode? visitReturnRule(sass.ReturnRule node) {
|
191 |
| - return super.visitReturnRule(node) ?? _process(node); |
| 202 | + return _process(node) ?? super.visitReturnRule(node); |
192 | 203 | }
|
193 | 204 |
|
194 | 205 | @override
|
195 | 206 | sass.AstNode? visitSelectorExpression(sass.SelectorExpression node) {
|
196 |
| - return super.visitSelectorExpression(node) ?? _process(node); |
| 207 | + return _process(node) ?? super.visitSelectorExpression(node); |
197 | 208 | }
|
198 | 209 |
|
199 | 210 | @override
|
200 | 211 | sass.AstNode? visitSilentComment(sass.SilentComment node) {
|
201 |
| - return super.visitSilentComment(node) ?? _process(node); |
| 212 | + return _process(node) ?? super.visitSilentComment(node); |
202 | 213 | }
|
203 | 214 |
|
204 | 215 | @override
|
205 | 216 | sass.AstNode? visitStringExpression(sass.StringExpression node) {
|
206 |
| - return super.visitStringExpression(node) ?? _process(node); |
| 217 | + return _process(node) ?? super.visitStringExpression(node); |
207 | 218 | }
|
208 | 219 |
|
209 | 220 | @override
|
210 | 221 | sass.AstNode? visitStyleRule(sass.StyleRule node) {
|
211 |
| - return super.visitStyleRule(node) ?? _process(node); |
| 222 | + return _process(node) ?? super.visitStyleRule(node); |
212 | 223 | }
|
213 | 224 |
|
214 | 225 | @override
|
215 | 226 | sass.AstNode? visitStylesheet(sass.Stylesheet node) {
|
216 |
| - return super.visitStylesheet(node) ?? _process(node); |
| 227 | + return _process(node) ?? super.visitStylesheet(node); |
217 | 228 | }
|
218 | 229 |
|
219 | 230 | @override
|
220 | 231 | sass.AstNode? visitSupportsCondition(sass.SupportsCondition condition) {
|
221 |
| - return super.visitSupportsCondition(condition) ?? _process(condition); |
| 232 | + return _process(condition) ?? super.visitSupportsCondition(condition); |
222 | 233 | }
|
223 | 234 |
|
224 | 235 | @override
|
225 | 236 | sass.AstNode? visitSupportsExpression(sass.SupportsExpression node) {
|
226 |
| - return super.visitSupportsExpression(node) ?? _process(node); |
| 237 | + return _process(node) ?? super.visitSupportsExpression(node); |
227 | 238 | }
|
228 | 239 |
|
229 | 240 | @override
|
230 | 241 | sass.AstNode? visitSupportsRule(sass.SupportsRule node) {
|
231 |
| - return super.visitSupportsRule(node) ?? _process(node); |
| 242 | + return _process(node) ?? super.visitSupportsRule(node); |
232 | 243 | }
|
233 | 244 |
|
234 | 245 | @override
|
235 | 246 | sass.AstNode? visitUnaryOperationExpression(
|
236 | 247 | sass.UnaryOperationExpression node) {
|
237 |
| - return super.visitUnaryOperationExpression(node) ?? _process(node); |
| 248 | + return _process(node) ?? super.visitUnaryOperationExpression(node); |
238 | 249 | }
|
239 | 250 |
|
240 | 251 | @override
|
241 | 252 | sass.AstNode? visitUseRule(sass.UseRule node) {
|
242 |
| - return super.visitUseRule(node) ?? _process(node); |
| 253 | + return _process(node) ?? super.visitUseRule(node); |
243 | 254 | }
|
244 | 255 |
|
245 | 256 | @override
|
246 | 257 | sass.AstNode? visitValueExpression(sass.ValueExpression node) {
|
247 |
| - return super.visitValueExpression(node) ?? _process(node); |
| 258 | + return _process(node) ?? super.visitValueExpression(node); |
248 | 259 | }
|
249 | 260 |
|
250 | 261 | @override
|
251 | 262 | sass.AstNode? visitVariableDeclaration(sass.VariableDeclaration node) {
|
252 |
| - return super.visitVariableDeclaration(node) ?? _process(node); |
| 263 | + return _process(node) ?? super.visitVariableDeclaration(node); |
253 | 264 | }
|
254 | 265 |
|
255 | 266 | @override
|
256 | 267 | sass.AstNode? visitVariableExpression(sass.VariableExpression node) {
|
257 |
| - return super.visitVariableExpression(node) ?? _process(node); |
| 268 | + return _process(node) ?? super.visitVariableExpression(node); |
258 | 269 | }
|
259 | 270 |
|
260 | 271 | @override
|
261 | 272 | sass.AstNode? visitWarnRule(sass.WarnRule node) {
|
262 |
| - return super.visitWarnRule(node) ?? _process(node); |
| 273 | + return _process(node) ?? super.visitWarnRule(node); |
263 | 274 | }
|
264 | 275 |
|
265 | 276 | @override
|
266 | 277 | sass.AstNode? visitWhileRule(sass.WhileRule node) {
|
267 |
| - return super.visitWhileRule(node) ?? _process(node); |
| 278 | + return _process(node) ?? super.visitWhileRule(node); |
268 | 279 | }
|
269 | 280 | }
|
0 commit comments