sassc 1.10.1 → 1.11.0
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.
- checksums.yaml +4 -4
- data/README.md +5 -2
- data/ext/libsass/.github/CONTRIBUTING.md +65 -0
- data/ext/libsass/.github/ISSUE_TEMPLATE.md +29 -0
- data/ext/libsass/Makefile +8 -3
- data/ext/libsass/Makefile.conf +28 -22
- data/ext/libsass/Readme.md +14 -7
- data/ext/libsass/configure.ac +5 -8
- data/ext/libsass/docs/api-context-internal.md +3 -0
- data/ext/libsass/docs/api-context.md +7 -0
- data/ext/libsass/docs/api-doc.md +4 -0
- data/ext/libsass/docs/api-importer.md +2 -0
- data/ext/libsass/docs/api-value-example.md +55 -0
- data/ext/libsass/docs/api-value.md +49 -22
- data/ext/libsass/docs/implementations.md +4 -0
- data/ext/libsass/include/sass/base.h +5 -4
- data/ext/libsass/include/sass/context.h +3 -0
- data/ext/libsass/include/sass/values.h +28 -27
- data/ext/libsass/include/sass/version.h +1 -1
- data/ext/libsass/include/sass2scss.h +1 -1
- data/ext/libsass/script/ci-build-libsass +3 -3
- data/ext/libsass/script/ci-install-deps +12 -3
- data/ext/libsass/src/ast.cpp +321 -212
- data/ext/libsass/src/ast.hpp +273 -165
- data/ext/libsass/src/ast_factory.hpp +4 -5
- data/ext/libsass/src/ast_fwd_decl.hpp +8 -7
- data/ext/libsass/src/bind.cpp +2 -7
- data/ext/libsass/src/bind.hpp +0 -1
- data/ext/libsass/src/check_nesting.cpp +379 -0
- data/ext/libsass/src/check_nesting.hpp +60 -0
- data/ext/libsass/src/constants.cpp +7 -6
- data/ext/libsass/src/constants.hpp +2 -1
- data/ext/libsass/src/context.cpp +7 -1
- data/ext/libsass/src/context.hpp +1 -1
- data/ext/libsass/src/cssize.cpp +76 -32
- data/ext/libsass/src/cssize.hpp +7 -8
- data/ext/libsass/src/debugger.hpp +70 -40
- data/ext/libsass/src/error_handling.cpp +15 -2
- data/ext/libsass/src/error_handling.hpp +19 -0
- data/ext/libsass/src/eval.cpp +107 -161
- data/ext/libsass/src/eval.hpp +12 -8
- data/ext/libsass/src/expand.cpp +81 -74
- data/ext/libsass/src/expand.hpp +13 -12
- data/ext/libsass/src/extend.cpp +149 -142
- data/ext/libsass/src/extend.hpp +10 -3
- data/ext/libsass/src/file.cpp +2 -1
- data/ext/libsass/src/functions.cpp +96 -59
- data/ext/libsass/src/functions.hpp +2 -2
- data/ext/libsass/src/inspect.cpp +33 -45
- data/ext/libsass/src/inspect.hpp +7 -7
- data/ext/libsass/src/json.cpp +17 -5
- data/ext/libsass/src/lexer.cpp +3 -3
- data/ext/libsass/src/listize.cpp +10 -10
- data/ext/libsass/src/listize.hpp +3 -3
- data/ext/libsass/src/node.cpp +30 -30
- data/ext/libsass/src/node.hpp +13 -13
- data/ext/libsass/src/operation.hpp +21 -19
- data/ext/libsass/src/output.cpp +48 -103
- data/ext/libsass/src/output.hpp +0 -1
- data/ext/libsass/src/parser.cpp +161 -133
- data/ext/libsass/src/parser.hpp +10 -7
- data/ext/libsass/src/remove_placeholders.cpp +6 -6
- data/ext/libsass/src/remove_placeholders.hpp +1 -1
- data/ext/libsass/src/sass.cpp +21 -0
- data/ext/libsass/src/sass.hpp +8 -1
- data/ext/libsass/src/sass2scss.cpp +14 -3
- data/ext/libsass/src/sass_context.cpp +69 -24
- data/ext/libsass/src/sass_context.hpp +3 -0
- data/ext/libsass/src/source_map.cpp +22 -10
- data/ext/libsass/src/to_value.cpp +2 -2
- data/ext/libsass/src/to_value.hpp +1 -1
- data/ext/libsass/src/units.hpp +3 -1
- data/ext/libsass/src/util.cpp +20 -16
- data/ext/libsass/src/util.hpp +2 -1
- data/ext/libsass/win/libsass.targets +2 -0
- data/ext/libsass/win/libsass.vcxproj.filters +6 -0
- data/lib/sassc/engine.rb +5 -0
- data/lib/sassc/native/native_functions_api.rb +13 -1
- data/lib/sassc/script/value_conversion.rb +11 -1
- data/lib/sassc/script/value_conversion/list.rb +23 -0
- data/lib/sassc/version.rb +1 -1
- data/test/engine_test.rb +18 -2
- data/test/functions_test.rb +30 -0
- data/test/native_test.rb +1 -1
- metadata +8 -3
@@ -13,13 +13,12 @@ namespace Sass {
|
|
13
13
|
// statements
|
14
14
|
Block* new_Block(std::string p, size_t l, size_t s = 0, bool r = false);
|
15
15
|
Ruleset* new_Ruleset(std::string p, size_t l, Selector* s, Block* b);
|
16
|
-
Propset* new_Propset(std::string p, size_t l, String* pf, Block* b);
|
17
16
|
Supports_Query* new_Supports_Query(std::string p, size_t l, Supports_Query* f, Block* b);
|
18
17
|
Media_Query* new_Media_Query(std::string p, size_t l, List* q, Block* b);
|
19
18
|
At_Root_Block* new_At_Root_Block(std::string p, size_t l, Selector* sel, Block* b);
|
20
19
|
Directive* new_At_Rule(std::string p, size_t l, std::string kwd, Selector* sel, Block* b);
|
21
20
|
Keyframe_Rule* new_Keyframe_Rule(std::string p, size_t l, Block* b);
|
22
|
-
Declaration* new_Declaration(std::string p, size_t l, String* prop, List* vals);
|
21
|
+
Declaration* new_Declaration(std::string p, size_t l, String* prop, List* vals, Block* b);
|
23
22
|
Assignment* new_Assignment(std::string p, size_t l, std::string var, Expression* val, bool guarded = false);
|
24
23
|
Import<Function_Call*>* new_CSS_Import(std::string p, size_t l, Function_Call* loc);
|
25
24
|
Import<String*>* new_SASS_Import(std::string p, size_t l, String* loc);
|
@@ -84,9 +83,9 @@ namespace Sass {
|
|
84
83
|
Placeholder_Selector* new_Placeholder_Selector(std::string p, size_t l, std::string n);
|
85
84
|
Pseudo_Selector* new_Pseudo_Selector(std::string p, size_t l, std::string n, Expression* expr = 0);
|
86
85
|
Wrapped_Selector* new_Wrapped_Selector(std::string p, size_t l, std::string n, Simple_Base* sel);
|
87
|
-
|
88
|
-
|
89
|
-
|
86
|
+
SimpleSequence_Selector* new_SimpleSequence_Selector(std::string p, size_t l, size_t s = 0);
|
87
|
+
Sequence_Selector* new_Sequence_Selector(std::string p, size_t l, Sequence_Selector::Combinator c, Sequence_Selector* ctx, SimpleSequence_Selector* sel);
|
88
|
+
CommaSequence_Selector* new_CommaSequence_Selector(std::string p, size_t l, size_t s = 0);
|
90
89
|
};
|
91
90
|
}
|
92
91
|
|
@@ -11,8 +11,8 @@ namespace Sass {
|
|
11
11
|
class Statement;
|
12
12
|
class Block;
|
13
13
|
class Ruleset;
|
14
|
-
class Propset;
|
15
14
|
class Bubble;
|
15
|
+
class Trace;
|
16
16
|
class Media_Block;
|
17
17
|
class Supports_Block;
|
18
18
|
class Directive;
|
@@ -73,15 +73,16 @@ namespace Sass {
|
|
73
73
|
// selectors
|
74
74
|
class Selector;
|
75
75
|
class Selector_Schema;
|
76
|
-
class
|
77
|
-
class
|
78
|
-
class
|
76
|
+
class Placeholder_Selector;
|
77
|
+
class Element_Selector;
|
78
|
+
class Class_Selector;
|
79
|
+
class Id_Selector;
|
79
80
|
class Attribute_Selector;
|
80
81
|
class Pseudo_Selector;
|
81
82
|
class Wrapped_Selector;
|
82
|
-
class
|
83
|
-
class
|
84
|
-
class
|
83
|
+
class SimpleSequence_Selector;
|
84
|
+
class Sequence_Selector;
|
85
|
+
class CommaSequence_Selector;
|
85
86
|
|
86
87
|
// common classes
|
87
88
|
class Context;
|
data/ext/libsass/src/bind.cpp
CHANGED
@@ -13,7 +13,6 @@ namespace Sass {
|
|
13
13
|
{
|
14
14
|
std::string callee(type + " " + name);
|
15
15
|
|
16
|
-
Listize listize(ctx->mem);
|
17
16
|
std::map<std::string, Parameter*> param_map;
|
18
17
|
|
19
18
|
for (size_t i = 0, L = as->length(); i < L; ++i) {
|
@@ -21,7 +20,6 @@ namespace Sass {
|
|
21
20
|
// force optional quotes (only if needed)
|
22
21
|
if (str->quote_mark()) {
|
23
22
|
str->quote_mark('*');
|
24
|
-
str->is_delayed(true);
|
25
23
|
}
|
26
24
|
}
|
27
25
|
}
|
@@ -172,7 +170,7 @@ namespace Sass {
|
|
172
170
|
break;
|
173
171
|
} else {
|
174
172
|
if (arglist->length() > LP - ip && !ps->has_rest_parameter()) {
|
175
|
-
|
173
|
+
size_t arg_count = (arglist->length() + LA - 1);
|
176
174
|
std::stringstream msg;
|
177
175
|
msg << callee << " takes " << LP;
|
178
176
|
msg << (LP == 1 ? " argument" : " arguments");
|
@@ -276,10 +274,7 @@ namespace Sass {
|
|
276
274
|
}
|
277
275
|
else {
|
278
276
|
// param is unbound and has no default value -- error
|
279
|
-
|
280
|
-
msg << "required parameter " << leftover->name()
|
281
|
-
<< " is missing in call to " << callee;
|
282
|
-
error(msg.str(), as->pstate());
|
277
|
+
throw Exception::MissingArgument(as->pstate(), name, leftover->name(), type);
|
283
278
|
}
|
284
279
|
}
|
285
280
|
}
|
data/ext/libsass/src/bind.hpp
CHANGED
@@ -0,0 +1,379 @@
|
|
1
|
+
#include "sass.hpp"
|
2
|
+
#include <vector>
|
3
|
+
|
4
|
+
#include "check_nesting.hpp"
|
5
|
+
|
6
|
+
namespace Sass {
|
7
|
+
|
8
|
+
CheckNesting::CheckNesting()
|
9
|
+
: parents(std::vector<Statement*>()),
|
10
|
+
parent(0),
|
11
|
+
current_mixin_definition(0)
|
12
|
+
{ }
|
13
|
+
|
14
|
+
Statement* CheckNesting::before(Statement* s) {
|
15
|
+
if (this->should_visit(s)) return s;
|
16
|
+
return 0;
|
17
|
+
}
|
18
|
+
|
19
|
+
Statement* CheckNesting::visit_children(Statement* parent) {
|
20
|
+
|
21
|
+
Statement* old_parent = this->parent;
|
22
|
+
|
23
|
+
if (dynamic_cast<At_Root_Block*>(parent)) {
|
24
|
+
std::vector<Statement*> old_parents = this->parents;
|
25
|
+
std::vector<Statement*> new_parents;
|
26
|
+
|
27
|
+
for (size_t i = 0, L = this->parents.size(); i < L; i++) {
|
28
|
+
Statement* p = this->parents.at(i);
|
29
|
+
if (!dynamic_cast<At_Root_Block*>(parent)->exclude_node(p)) {
|
30
|
+
new_parents.push_back(p);
|
31
|
+
}
|
32
|
+
}
|
33
|
+
this->parents = new_parents;
|
34
|
+
|
35
|
+
for (size_t i = this->parents.size(); i > 0; i--) {
|
36
|
+
Statement* p = 0;
|
37
|
+
Statement* gp = 0;
|
38
|
+
if (i > 0) p = this->parents.at(i - 1);
|
39
|
+
if (i > 1) gp = this->parents.at(i - 2);
|
40
|
+
|
41
|
+
if (!this->is_transparent_parent(p, gp)) {
|
42
|
+
this->parent = p;
|
43
|
+
break;
|
44
|
+
}
|
45
|
+
}
|
46
|
+
|
47
|
+
At_Root_Block* ar = dynamic_cast<At_Root_Block*>(parent);
|
48
|
+
Statement* ret = this->visit_children(ar->block());
|
49
|
+
|
50
|
+
this->parent = old_parent;
|
51
|
+
this->parents = old_parents;
|
52
|
+
|
53
|
+
return ret;
|
54
|
+
}
|
55
|
+
|
56
|
+
|
57
|
+
if (!this->is_transparent_parent(parent, old_parent)) {
|
58
|
+
this->parent = parent;
|
59
|
+
}
|
60
|
+
|
61
|
+
this->parents.push_back(parent);
|
62
|
+
|
63
|
+
Block* b = dynamic_cast<Block*>(parent);
|
64
|
+
|
65
|
+
if (!b) {
|
66
|
+
if (Has_Block* bb = dynamic_cast<Has_Block*>(parent)) {
|
67
|
+
b = bb->block();
|
68
|
+
}
|
69
|
+
}
|
70
|
+
|
71
|
+
if (b) {
|
72
|
+
for (auto n : *b) {
|
73
|
+
n->perform(this);
|
74
|
+
}
|
75
|
+
}
|
76
|
+
|
77
|
+
this->parent = old_parent;
|
78
|
+
this->parents.pop_back();
|
79
|
+
|
80
|
+
return b;
|
81
|
+
}
|
82
|
+
|
83
|
+
|
84
|
+
Statement* CheckNesting::operator()(Block* b)
|
85
|
+
{
|
86
|
+
return this->visit_children(b);
|
87
|
+
}
|
88
|
+
|
89
|
+
Statement* CheckNesting::operator()(Definition* n)
|
90
|
+
{
|
91
|
+
if (!is_mixin(n)) return n;
|
92
|
+
|
93
|
+
Definition* old_mixin_definition = this->current_mixin_definition;
|
94
|
+
this->current_mixin_definition = n;
|
95
|
+
|
96
|
+
visit_children(n);
|
97
|
+
|
98
|
+
this->current_mixin_definition = old_mixin_definition;
|
99
|
+
|
100
|
+
return n;
|
101
|
+
}
|
102
|
+
|
103
|
+
Statement* CheckNesting::fallback_impl(Statement* s)
|
104
|
+
{
|
105
|
+
if (dynamic_cast<Block*>(s) || dynamic_cast<Has_Block*>(s)) {
|
106
|
+
return visit_children(s);
|
107
|
+
}
|
108
|
+
return s;
|
109
|
+
}
|
110
|
+
|
111
|
+
bool CheckNesting::should_visit(Statement* node)
|
112
|
+
{
|
113
|
+
if (!this->parent) return true;
|
114
|
+
|
115
|
+
if (dynamic_cast<Content*>(node))
|
116
|
+
{ this->invalid_content_parent(this->parent); }
|
117
|
+
|
118
|
+
if (is_charset(node))
|
119
|
+
{ this->invalid_charset_parent(this->parent); }
|
120
|
+
|
121
|
+
if (dynamic_cast<Extension*>(node))
|
122
|
+
{ this->invalid_extend_parent(this->parent); }
|
123
|
+
|
124
|
+
// if (dynamic_cast<Import*>(node))
|
125
|
+
// { this->invalid_import_parent(this->parent); }
|
126
|
+
|
127
|
+
if (this->is_mixin(node))
|
128
|
+
{ this->invalid_mixin_definition_parent(this->parent); }
|
129
|
+
|
130
|
+
if (this->is_function(node))
|
131
|
+
{ this->invalid_function_parent(this->parent); }
|
132
|
+
|
133
|
+
if (this->is_function(this->parent))
|
134
|
+
{ this->invalid_function_child(node); }
|
135
|
+
|
136
|
+
if (dynamic_cast<Declaration*>(node))
|
137
|
+
{ this->invalid_prop_parent(this->parent); }
|
138
|
+
|
139
|
+
if (
|
140
|
+
dynamic_cast<Declaration*>(this->parent)
|
141
|
+
) { this->invalid_prop_child(node); }
|
142
|
+
|
143
|
+
if (dynamic_cast<Return*>(node))
|
144
|
+
{ this->invalid_return_parent(this->parent); }
|
145
|
+
|
146
|
+
return true;
|
147
|
+
}
|
148
|
+
|
149
|
+
void CheckNesting::invalid_content_parent(Statement* parent)
|
150
|
+
{
|
151
|
+
if (!this->current_mixin_definition) {
|
152
|
+
throw Exception::InvalidSass(
|
153
|
+
parent->pstate(),
|
154
|
+
"@content may only be used within a mixin."
|
155
|
+
);
|
156
|
+
}
|
157
|
+
}
|
158
|
+
|
159
|
+
void CheckNesting::invalid_charset_parent(Statement* parent)
|
160
|
+
{
|
161
|
+
if (!(
|
162
|
+
is_root_node(parent)
|
163
|
+
)) {
|
164
|
+
throw Exception::InvalidSass(
|
165
|
+
parent->pstate(),
|
166
|
+
"@charset may only be used at the root of a document."
|
167
|
+
);
|
168
|
+
}
|
169
|
+
}
|
170
|
+
|
171
|
+
void CheckNesting::invalid_extend_parent(Statement* parent)
|
172
|
+
{
|
173
|
+
if (!(
|
174
|
+
dynamic_cast<Ruleset*>(parent) ||
|
175
|
+
dynamic_cast<Mixin_Call*>(parent) ||
|
176
|
+
is_mixin(parent)
|
177
|
+
)) {
|
178
|
+
throw Exception::InvalidSass(
|
179
|
+
parent->pstate(),
|
180
|
+
"Extend directives may only be used within rules."
|
181
|
+
);
|
182
|
+
}
|
183
|
+
}
|
184
|
+
|
185
|
+
// void CheckNesting::invalid_import_parent(Statement* parent)
|
186
|
+
// {
|
187
|
+
// for (auto pp : this->parents) {
|
188
|
+
// if (
|
189
|
+
// dynamic_cast<Each*>(pp) ||
|
190
|
+
// dynamic_cast<For*>(pp) ||
|
191
|
+
// dynamic_cast<If*>(pp) ||
|
192
|
+
// dynamic_cast<While*>(pp) ||
|
193
|
+
// dynamic_cast<Trace*>(pp) ||
|
194
|
+
// dynamic_cast<Mixin_Call*>(pp) ||
|
195
|
+
// is_mixin(pp)
|
196
|
+
// ) {
|
197
|
+
// throw Exception::InvalidSass(
|
198
|
+
// parent->pstate(),
|
199
|
+
// "Import directives may not be defined within control directives or other mixins."
|
200
|
+
// );
|
201
|
+
// }
|
202
|
+
// }
|
203
|
+
|
204
|
+
// if (this->is_root_node(parent)) {
|
205
|
+
// return;
|
206
|
+
// }
|
207
|
+
|
208
|
+
// if (false/*n.css_import?*/) {
|
209
|
+
// throw Exception::InvalidSass(
|
210
|
+
// parent->pstate(),
|
211
|
+
// "CSS import directives may only be used at the root of a document."
|
212
|
+
// );
|
213
|
+
// }
|
214
|
+
// }
|
215
|
+
|
216
|
+
void CheckNesting::invalid_mixin_definition_parent(Statement* parent)
|
217
|
+
{
|
218
|
+
for (auto pp : this->parents) {
|
219
|
+
if (
|
220
|
+
dynamic_cast<Each*>(pp) ||
|
221
|
+
dynamic_cast<For*>(pp) ||
|
222
|
+
dynamic_cast<If*>(pp) ||
|
223
|
+
dynamic_cast<While*>(pp) ||
|
224
|
+
dynamic_cast<Trace*>(pp) ||
|
225
|
+
dynamic_cast<Mixin_Call*>(pp) ||
|
226
|
+
is_mixin(pp)
|
227
|
+
) {
|
228
|
+
throw Exception::InvalidSass(
|
229
|
+
parent->pstate(),
|
230
|
+
"Mixins may not be defined within control directives or other mixins."
|
231
|
+
);
|
232
|
+
}
|
233
|
+
}
|
234
|
+
}
|
235
|
+
|
236
|
+
void CheckNesting::invalid_function_parent(Statement* parent)
|
237
|
+
{
|
238
|
+
for (auto pp : this->parents) {
|
239
|
+
if (
|
240
|
+
dynamic_cast<Each*>(pp) ||
|
241
|
+
dynamic_cast<For*>(pp) ||
|
242
|
+
dynamic_cast<If*>(pp) ||
|
243
|
+
dynamic_cast<While*>(pp) ||
|
244
|
+
dynamic_cast<Trace*>(pp) ||
|
245
|
+
dynamic_cast<Mixin_Call*>(pp) ||
|
246
|
+
is_mixin(pp)
|
247
|
+
) {
|
248
|
+
throw Exception::InvalidSass(
|
249
|
+
parent->pstate(),
|
250
|
+
"Functions may not be defined within control directives or other mixins."
|
251
|
+
);
|
252
|
+
}
|
253
|
+
}
|
254
|
+
}
|
255
|
+
|
256
|
+
void CheckNesting::invalid_function_child(Statement* child)
|
257
|
+
{
|
258
|
+
if (!(
|
259
|
+
dynamic_cast<Each*>(child) ||
|
260
|
+
dynamic_cast<For*>(child) ||
|
261
|
+
dynamic_cast<If*>(child) ||
|
262
|
+
dynamic_cast<While*>(child) ||
|
263
|
+
dynamic_cast<Trace*>(child) ||
|
264
|
+
dynamic_cast<Comment*>(child) ||
|
265
|
+
dynamic_cast<Debug*>(child) ||
|
266
|
+
dynamic_cast<Return*>(child) ||
|
267
|
+
dynamic_cast<Variable*>(child) ||
|
268
|
+
dynamic_cast<Warning*>(child) ||
|
269
|
+
dynamic_cast<Error*>(child)
|
270
|
+
)) {
|
271
|
+
throw Exception::InvalidSass(
|
272
|
+
child->pstate(),
|
273
|
+
"Functions can only contain variable declarations and control directives."
|
274
|
+
);
|
275
|
+
}
|
276
|
+
}
|
277
|
+
|
278
|
+
void CheckNesting::invalid_prop_child(Statement* child)
|
279
|
+
{
|
280
|
+
if (!(
|
281
|
+
dynamic_cast<Each*>(child) ||
|
282
|
+
dynamic_cast<For*>(child) ||
|
283
|
+
dynamic_cast<If*>(child) ||
|
284
|
+
dynamic_cast<While*>(child) ||
|
285
|
+
dynamic_cast<Trace*>(child) ||
|
286
|
+
dynamic_cast<Comment*>(child) ||
|
287
|
+
dynamic_cast<Declaration*>(child) ||
|
288
|
+
dynamic_cast<Mixin_Call*>(child)
|
289
|
+
)) {
|
290
|
+
throw Exception::InvalidSass(
|
291
|
+
child->pstate(),
|
292
|
+
"Illegal nesting: Only properties may be nested beneath properties."
|
293
|
+
);
|
294
|
+
}
|
295
|
+
}
|
296
|
+
|
297
|
+
void CheckNesting::invalid_prop_parent(Statement* parent)
|
298
|
+
{
|
299
|
+
if (!(
|
300
|
+
is_mixin(parent) ||
|
301
|
+
is_directive_node(parent) ||
|
302
|
+
dynamic_cast<Ruleset*>(parent) ||
|
303
|
+
dynamic_cast<Keyframe_Rule*>(parent) ||
|
304
|
+
dynamic_cast<Declaration*>(parent) ||
|
305
|
+
dynamic_cast<Mixin_Call*>(parent)
|
306
|
+
)) {
|
307
|
+
throw Exception::InvalidSass(
|
308
|
+
parent->pstate(),
|
309
|
+
"Properties are only allowed within rules, directives, mixin includes, or other properties."
|
310
|
+
);
|
311
|
+
}
|
312
|
+
}
|
313
|
+
|
314
|
+
void CheckNesting::invalid_return_parent(Statement* parent)
|
315
|
+
{
|
316
|
+
if (!this->is_function(parent)) {
|
317
|
+
throw Exception::InvalidSass(
|
318
|
+
parent->pstate(),
|
319
|
+
"@return may only be used within a function."
|
320
|
+
);
|
321
|
+
}
|
322
|
+
}
|
323
|
+
|
324
|
+
bool CheckNesting::is_transparent_parent(Statement* parent, Statement* grandparent)
|
325
|
+
{
|
326
|
+
bool parent_bubbles = parent && parent->bubbles();
|
327
|
+
|
328
|
+
bool valid_bubble_node = parent_bubbles &&
|
329
|
+
!is_root_node(grandparent) &&
|
330
|
+
!is_at_root_node(grandparent);
|
331
|
+
|
332
|
+
return dynamic_cast<Import*>(parent) ||
|
333
|
+
dynamic_cast<Each*>(parent) ||
|
334
|
+
dynamic_cast<For*>(parent) ||
|
335
|
+
dynamic_cast<If*>(parent) ||
|
336
|
+
dynamic_cast<While*>(parent) ||
|
337
|
+
dynamic_cast<Trace*>(parent) ||
|
338
|
+
valid_bubble_node;
|
339
|
+
}
|
340
|
+
|
341
|
+
bool CheckNesting::is_charset(Statement* n)
|
342
|
+
{
|
343
|
+
Directive* d = dynamic_cast<Directive*>(n);
|
344
|
+
return d && d->keyword() == "charset";
|
345
|
+
}
|
346
|
+
|
347
|
+
bool CheckNesting::is_mixin(Statement* n)
|
348
|
+
{
|
349
|
+
Definition* def = dynamic_cast<Definition*>(n);
|
350
|
+
return def && def->type() == Definition::MIXIN;
|
351
|
+
}
|
352
|
+
|
353
|
+
bool CheckNesting::is_function(Statement* n)
|
354
|
+
{
|
355
|
+
Definition* def = dynamic_cast<Definition*>(n);
|
356
|
+
return def && def->type() == Definition::FUNCTION;
|
357
|
+
}
|
358
|
+
|
359
|
+
bool CheckNesting::is_root_node(Statement* n)
|
360
|
+
{
|
361
|
+
if (dynamic_cast<Ruleset*>(n)) return false;
|
362
|
+
|
363
|
+
Block* b = dynamic_cast<Block*>(n);
|
364
|
+
return b && b->is_root();
|
365
|
+
}
|
366
|
+
|
367
|
+
bool CheckNesting::is_at_root_node(Statement* n)
|
368
|
+
{
|
369
|
+
return dynamic_cast<At_Root_Block*>(n) != NULL;
|
370
|
+
}
|
371
|
+
|
372
|
+
bool CheckNesting::is_directive_node(Statement* n)
|
373
|
+
{
|
374
|
+
return dynamic_cast<Directive*>(n) ||
|
375
|
+
dynamic_cast<Import*>(n) ||
|
376
|
+
dynamic_cast<Media_Block*>(n) ||
|
377
|
+
dynamic_cast<Supports_Block*>(n);
|
378
|
+
}
|
379
|
+
}
|