@@ -17,6 +17,43 @@ import 'package:sass/src/ast/node.dart';
17
17
import 'io.dart' ;
18
18
import 'patch.dart' ;
19
19
20
+ extension ExtendSpan on FileSpan {
21
+ /// Extends this span so it encompasses any whitespace on either side of it.
22
+ FileSpan extendThroughWhitespace () {
23
+ var text = file.getText (0 );
24
+
25
+ var newStart = start.offset - 1 ;
26
+ for (; newStart >= 0 ; newStart-- ) {
27
+ if (! isWhitespace (text.codeUnitAt (newStart))) break ;
28
+ }
29
+
30
+ var newEnd = end.offset;
31
+ for (; newEnd < text.length; newEnd++ ) {
32
+ if (! isWhitespace (text.codeUnitAt (newEnd))) break ;
33
+ }
34
+
35
+ // Add 1 to start because it's guaranteed to end on either -1 or a character
36
+ // that's not whitespace.
37
+ return file.span (newStart + 1 , newEnd);
38
+ }
39
+
40
+ /// Extends this span forward if it's followed by exactly [pattern] .
41
+ ///
42
+ /// If it doesn't match, returns the span as-is.
43
+ FileSpan extendIfMatches (Pattern pattern) {
44
+ var text = file.getText (end.offset);
45
+ var match = pattern.matchAsPrefix (text);
46
+ if (match == null ) return this ;
47
+ return file.span (start.offset, end.offset + match.end);
48
+ }
49
+
50
+ /// Returns true if this span is preceded by exactly [text] .
51
+ bool matchesBefore (String text) {
52
+ if (start.offset - text.length < 0 ) return false ;
53
+ return file.getText (start.offset - text.length, start.offset) == text;
54
+ }
55
+ }
56
+
20
57
/// Returns the default namespace for a use rule with [path] .
21
58
String namespaceForPath (String path) {
22
59
// TODO(jathak): Confirm that this is a valid Sass identifier
@@ -41,40 +78,7 @@ bool valuesAreUnique(Map<Object, Object> map) =>
41
78
/// By default, this deletes the entire span. If [start] and/or [end] are
42
79
/// provided, this deletes only the portion of the span within that range.
43
80
Patch patchDelete (FileSpan span, {int start = 0 , int end}) =>
44
- Patch (subspan (span, start: start, end: end), "" );
45
-
46
- /// Returns a subsection of [span] .
47
- FileSpan subspan (FileSpan span, {int start = 0 , int end}) => span.file
48
- .span (span.start.offset + start, span.start.offset + (end ?? span.length));
49
-
50
- /// Extends [span] so it encompasses any whitespace on either side of it.
51
- FileSpan extendThroughWhitespace (FileSpan span) {
52
- var text = span.file.getText (0 );
53
-
54
- var start = span.start.offset - 1 ;
55
- for (; start >= 0 ; start-- ) {
56
- if (! isWhitespace (text.codeUnitAt (start))) break ;
57
- }
58
-
59
- var end = span.end.offset;
60
- for (; end < text.length; end++ ) {
61
- if (! isWhitespace (text.codeUnitAt (end))) break ;
62
- }
63
-
64
- // Add 1 to start because it's guaranteed to end on either -1 or a character
65
- // that's not whitespace.
66
- return span.file.span (start + 1 , end);
67
- }
68
-
69
- /// Extends [span] forward if it's followed by exactly [text] .
70
- ///
71
- /// If [span] is followed by anything other than [text] , returns `null` .
72
- FileSpan extendForward (FileSpan span, String text) {
73
- var end = span.end.offset;
74
- if (end + text.length > span.file.length) return null ;
75
- if (span.file.getText (end, end + text.length) != text) return null ;
76
- return span.file.span (span.start.offset, end + text.length);
77
- }
81
+ Patch (span.subspan (start, end), "" );
78
82
79
83
/// Returns the next location after [import] that it would be safe to insert
80
84
/// a `@use` or `@forward` rule.
@@ -117,23 +121,6 @@ FileLocation afterImport(ImportRule import, {bool shouldHaveSemicolon = true}) {
117
121
return loc.file.location (loc.offset + i);
118
122
}
119
123
120
- /// Extends [span] backward if it's preceded by exactly [text] .
121
- ///
122
- /// If [span] is preceded by anything other than [text] , returns `null` .
123
- FileSpan extendBackward (FileSpan span, String text) {
124
- var start = span.start.offset;
125
- if (start - text.length < 0 ) return null ;
126
- if (span.file.getText (start - text.length, start) != text) return null ;
127
- return span.file.span (start - text.length, span.end.offset);
128
- }
129
-
130
- /// Returns true if [span] is preceded by exactly [text] .
131
- bool matchesBeforeSpan (FileSpan span, String text) {
132
- var start = span.start.offset;
133
- if (start - text.length < 0 ) return false ;
134
- return span.file.getText (start - text.length, start) == text;
135
- }
136
-
137
124
/// Returns whether [character] is whitespace, according to Sass's definition.
138
125
bool isWhitespace (int character) =>
139
126
character == $space ||
@@ -149,30 +136,27 @@ bool isWhitespace(int character) =>
149
136
FileSpan nameSpan (SassNode node) {
150
137
if (node is VariableDeclaration ) {
151
138
var start = node.namespace == null ? 1 : node.namespace.length + 2 ;
152
- return subspan ( node.span, start: start, end : start + node.name.length);
139
+ return node.span. subspan ( start, start + node.name.length);
153
140
} else if (node is VariableExpression ) {
154
- return subspan ( node.span,
155
- start : node.namespace == null ? 1 : node.namespace.length + 2 );
141
+ return node.span
142
+ . subspan ( node.namespace == null ? 1 : node.namespace.length + 2 );
156
143
} else if (node is FunctionRule ) {
157
144
var startName = node.span.text
158
145
.replaceAll ('_' , '-' )
159
146
.indexOf (node.name, '@function' .length);
160
- return subspan (node.span,
161
- start: startName, end: startName + node.name.length);
147
+ return node.span.subspan (startName, startName + node.name.length);
162
148
} else if (node is FunctionExpression ) {
163
149
return node.name.span;
164
150
} else if (node is MixinRule ) {
165
151
var startName = node.span.text
166
152
.replaceAll ('_' , '-' )
167
153
.indexOf (node.name, node.span.text[0 ] == '=' ? 1 : '@mixin' .length);
168
- return subspan (node.span,
169
- start: startName, end: startName + node.name.length);
154
+ return node.span.subspan (startName, startName + node.name.length);
170
155
} else if (node is IncludeRule ) {
171
156
var startName = node.span.text
172
157
.replaceAll ('_' , '-' )
173
158
.indexOf (node.name, node.span.text[0 ] == '+' ? 1 : '@include' .length);
174
- return subspan (node.span,
175
- start: startName, end: startName + node.name.length);
159
+ return node.span.subspan (startName, startName + node.name.length);
176
160
} else {
177
161
throw UnsupportedError (
178
162
"$node of type ${node .runtimeType } doesn't have a name" );
@@ -213,7 +197,7 @@ FileSpan getStaticNameForGetFunctionCall(FunctionExpression node) {
213
197
return null ;
214
198
}
215
199
return (nameArgument as StringExpression ).hasQuotes
216
- ? subspan ( nameArgument.span, start : 1 , end : nameArgument.span.length - 1 )
200
+ ? nameArgument.span. subspan ( 1 , nameArgument.span.length - 1 )
217
201
: nameArgument.span;
218
202
}
219
203
@@ -232,7 +216,7 @@ FileSpan getStaticModuleForGetFunctionCall(FunctionExpression node) {
232
216
return null ;
233
217
}
234
218
return (moduleArg as StringExpression ).hasQuotes
235
- ? subspan ( moduleArg.span, start : 1 , end : moduleArg.span.length - 2 )
219
+ ? moduleArg.span. subspan ( 1 , moduleArg.span.length - 2 )
236
220
: moduleArg.span;
237
221
}
238
222
0 commit comments