sassc 1.8.3 → 1.8.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (96) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +3 -1
  3. data/ext/libsass/.editorconfig +1 -1
  4. data/ext/libsass/.gitignore +1 -0
  5. data/ext/libsass/LICENSE +1 -1
  6. data/ext/libsass/Makefile +20 -14
  7. data/ext/libsass/Makefile.conf +0 -1
  8. data/ext/libsass/Readme.md +3 -1
  9. data/ext/libsass/appveyor.yml +19 -11
  10. data/ext/libsass/docs/api-importer-example.md +2 -1235
  11. data/ext/libsass/docs/build-with-autotools.md +10 -0
  12. data/ext/libsass/docs/build-with-makefiles.md +18 -0
  13. data/ext/libsass/include/sass/base.h +4 -1
  14. data/ext/libsass/include/sass/values.h +2 -1
  15. data/ext/libsass/src/ast.cpp +279 -346
  16. data/ext/libsass/src/ast.hpp +234 -60
  17. data/ext/libsass/src/base64vlq.cpp +1 -0
  18. data/ext/libsass/src/bind.cpp +35 -45
  19. data/ext/libsass/src/bind.hpp +1 -0
  20. data/ext/libsass/src/color_maps.cpp +1 -0
  21. data/ext/libsass/src/constants.cpp +4 -1
  22. data/ext/libsass/src/constants.hpp +2 -1
  23. data/ext/libsass/src/context.cpp +41 -31
  24. data/ext/libsass/src/context.hpp +10 -10
  25. data/ext/libsass/src/cssize.cpp +7 -4
  26. data/ext/libsass/src/cssize.hpp +1 -3
  27. data/ext/libsass/src/debugger.hpp +73 -14
  28. data/ext/libsass/src/emitter.cpp +37 -25
  29. data/ext/libsass/src/emitter.hpp +10 -9
  30. data/ext/libsass/src/environment.cpp +16 -5
  31. data/ext/libsass/src/environment.hpp +5 -3
  32. data/ext/libsass/src/error_handling.cpp +91 -14
  33. data/ext/libsass/src/error_handling.hpp +105 -4
  34. data/ext/libsass/src/eval.cpp +519 -330
  35. data/ext/libsass/src/eval.hpp +12 -13
  36. data/ext/libsass/src/expand.cpp +92 -56
  37. data/ext/libsass/src/expand.hpp +5 -3
  38. data/ext/libsass/src/extend.cpp +60 -51
  39. data/ext/libsass/src/extend.hpp +1 -3
  40. data/ext/libsass/src/file.cpp +37 -27
  41. data/ext/libsass/src/functions.cpp +78 -62
  42. data/ext/libsass/src/functions.hpp +1 -0
  43. data/ext/libsass/src/inspect.cpp +293 -64
  44. data/ext/libsass/src/inspect.hpp +2 -0
  45. data/ext/libsass/src/lexer.cpp +1 -0
  46. data/ext/libsass/src/listize.cpp +14 -15
  47. data/ext/libsass/src/listize.hpp +3 -5
  48. data/ext/libsass/src/memory_manager.cpp +1 -0
  49. data/ext/libsass/src/node.cpp +2 -3
  50. data/ext/libsass/src/operation.hpp +70 -71
  51. data/ext/libsass/src/output.cpp +28 -32
  52. data/ext/libsass/src/output.hpp +1 -2
  53. data/ext/libsass/src/parser.cpp +402 -183
  54. data/ext/libsass/src/parser.hpp +19 -9
  55. data/ext/libsass/src/plugins.cpp +1 -0
  56. data/ext/libsass/src/position.cpp +1 -0
  57. data/ext/libsass/src/prelexer.cpp +134 -56
  58. data/ext/libsass/src/prelexer.hpp +51 -3
  59. data/ext/libsass/src/remove_placeholders.cpp +35 -9
  60. data/ext/libsass/src/remove_placeholders.hpp +4 -3
  61. data/ext/libsass/src/sass.cpp +1 -0
  62. data/ext/libsass/src/sass.hpp +129 -0
  63. data/ext/libsass/src/sass_context.cpp +31 -14
  64. data/ext/libsass/src/sass_context.hpp +2 -31
  65. data/ext/libsass/src/sass_functions.cpp +1 -0
  66. data/ext/libsass/src/sass_interface.cpp +5 -6
  67. data/ext/libsass/src/sass_util.cpp +1 -2
  68. data/ext/libsass/src/sass_util.hpp +5 -5
  69. data/ext/libsass/src/sass_values.cpp +13 -10
  70. data/ext/libsass/src/source_map.cpp +4 -3
  71. data/ext/libsass/src/source_map.hpp +2 -2
  72. data/ext/libsass/src/subset_map.hpp +0 -1
  73. data/ext/libsass/src/to_c.cpp +1 -0
  74. data/ext/libsass/src/to_c.hpp +1 -3
  75. data/ext/libsass/src/to_value.cpp +3 -5
  76. data/ext/libsass/src/to_value.hpp +1 -1
  77. data/ext/libsass/src/units.cpp +96 -59
  78. data/ext/libsass/src/units.hpp +10 -8
  79. data/ext/libsass/src/utf8_string.cpp +5 -0
  80. data/ext/libsass/src/util.cpp +23 -156
  81. data/ext/libsass/src/util.hpp +10 -14
  82. data/ext/libsass/src/values.cpp +1 -0
  83. data/ext/libsass/test/test_node.cpp +2 -6
  84. data/ext/libsass/test/test_selector_difference.cpp +1 -3
  85. data/ext/libsass/test/test_specificity.cpp +0 -2
  86. data/ext/libsass/test/test_superselector.cpp +0 -2
  87. data/ext/libsass/test/test_unification.cpp +1 -3
  88. data/ext/libsass/win/libsass.targets +18 -5
  89. data/ext/libsass/win/libsass.vcxproj +9 -7
  90. data/ext/libsass/win/libsass.vcxproj.filters +148 -106
  91. data/lib/sassc/version.rb +1 -1
  92. data/test/engine_test.rb +12 -0
  93. data/test/native_test.rb +1 -1
  94. metadata +3 -4
  95. data/ext/libsass/src/to_string.cpp +0 -48
  96. data/ext/libsass/src/to_string.hpp +0 -38
@@ -1,15 +1,15 @@
1
1
  #ifndef SASS_EVAL_H
2
2
  #define SASS_EVAL_H
3
3
 
4
+ #include "ast.hpp"
4
5
  #include "context.hpp"
5
- #include "listize.hpp"
6
6
  #include "operation.hpp"
7
+ #include "environment.hpp"
7
8
 
8
9
  namespace Sass {
9
10
 
10
11
  class Expand;
11
12
  class Context;
12
- class Listize;
13
13
 
14
14
  class Eval : public Operation_CRTP<Expression*, Eval> {
15
15
 
@@ -19,17 +19,16 @@ namespace Sass {
19
19
  public:
20
20
  Expand& exp;
21
21
  Context& ctx;
22
- Listize listize;
23
22
  Eval(Expand& exp);
24
- virtual ~Eval();
23
+ ~Eval();
24
+
25
+ bool is_in_comment;
25
26
 
26
27
  Env* environment();
27
28
  Context& context();
28
29
  Selector_List* selector();
29
30
  Backtrace* backtrace();
30
31
 
31
- using Operation<Expression*>::operator();
32
-
33
32
  // for evaluating function bodies
34
33
  Expression* operator()(Block*);
35
34
  Expression* operator()(Assignment*);
@@ -87,16 +86,16 @@ namespace Sass {
87
86
 
88
87
  // -- only need to define two comparisons, and the rest can be implemented in terms of them
89
88
  static bool eq(Expression*, Expression*);
90
- static bool lt(Expression*, Expression*);
89
+ static bool lt(Expression*, Expression*, std::string op);
91
90
  // -- arithmetic on the combinations that matter
92
- static Value* op_numbers(Memory_Manager&, enum Sass_OP, const Number&, const Number&, bool compressed = false, int precision = 5, ParserState* pstate = 0);
93
- static Value* op_number_color(Memory_Manager&, enum Sass_OP, const Number&, const Color&, bool compressed = false, int precision = 5, ParserState* pstate = 0);
94
- static Value* op_color_number(Memory_Manager&, enum Sass_OP, const Color&, const Number&, bool compressed = false, int precision = 5, ParserState* pstate = 0);
95
- static Value* op_colors(Memory_Manager&, enum Sass_OP, const Color&, const Color&, bool compressed = false, int precision = 5, ParserState* pstate = 0);
96
- static Value* op_strings(Memory_Manager&, enum Sass_OP, Value&, Value&, bool compressed = false, int precision = 5, ParserState* pstate = 0);
91
+ static Value* op_numbers(Memory_Manager&, enum Sass_OP, const Number&, const Number&, struct Sass_Inspect_Options opt, ParserState* pstate = 0);
92
+ static Value* op_number_color(Memory_Manager&, enum Sass_OP, const Number&, const Color&, struct Sass_Inspect_Options opt, ParserState* pstate = 0);
93
+ static Value* op_color_number(Memory_Manager&, enum Sass_OP, const Color&, const Number&, struct Sass_Inspect_Options opt, ParserState* pstate = 0);
94
+ static Value* op_colors(Memory_Manager&, enum Sass_OP, const Color&, const Color&, struct Sass_Inspect_Options opt, ParserState* pstate = 0);
95
+ static Value* op_strings(Memory_Manager&, Sass::Operand, Value&, Value&, struct Sass_Inspect_Options opt, ParserState* pstate = 0, bool interpolant = false);
97
96
 
98
97
  private:
99
- std::string interpolation(Expression* s, bool into_quotes = false);
98
+ void interpolation(Context& ctx, std::string& res, Expression* ex, bool into_quotes, bool was_itpl = false);
100
99
 
101
100
  };
102
101
 
@@ -1,14 +1,10 @@
1
- #ifdef _MSC_VER
2
- #pragma warning(disable : 4503)
3
- #endif
4
-
1
+ #include "sass.hpp"
5
2
  #include <iostream>
6
3
  #include <typeinfo>
7
4
 
8
5
  #include "expand.hpp"
9
6
  #include "bind.hpp"
10
7
  #include "eval.hpp"
11
- #include "to_string.hpp"
12
8
  #include "backtrace.hpp"
13
9
  #include "context.hpp"
14
10
  #include "parser.hpp"
@@ -20,6 +16,7 @@ namespace Sass {
20
16
  eval(Eval(*this)),
21
17
  env_stack(std::vector<Env*>()),
22
18
  block_stack(std::vector<Block*>()),
19
+ call_stack(std::vector<AST_Node*>()),
23
20
  property_stack(std::vector<String*>()),
24
21
  selector_stack(std::vector<Selector_List*>()),
25
22
  backtrace_stack(std::vector<Backtrace*>()),
@@ -28,6 +25,7 @@ namespace Sass {
28
25
  env_stack.push_back(0);
29
26
  env_stack.push_back(env);
30
27
  block_stack.push_back(0);
28
+ call_stack.push_back(0);
31
29
  // import_stack.push_back(0);
32
30
  property_stack.push_back(0);
33
31
  selector_stack.push_back(0);
@@ -106,7 +104,7 @@ namespace Sass {
106
104
  while (tail) {
107
105
  if (tail->head()) for (Simple_Selector* header : tail->head()->elements()) {
108
106
  if (dynamic_cast<Parent_Selector*>(header) == NULL) continue; // skip all others
109
- To_String to_string(&ctx); std::string sel_str(complex_selector->perform(&to_string));
107
+ std::string sel_str(complex_selector->to_string(ctx.c_options));
110
108
  error("Base-level rules cannot contain the parent-selector-referencing character '&'.", header->pstate(), backtrace());
111
109
  }
112
110
  tail = tail->tail();
@@ -120,12 +118,21 @@ namespace Sass {
120
118
  if (sel == 0) throw std::runtime_error("Expanded null selector");
121
119
 
122
120
  selector_stack.push_back(sel);
121
+ Env* env = 0;
122
+ if (block_stack.back()->is_root()) {
123
+ env = new Env(environment());
124
+ env_stack.push_back(env);
125
+ }
123
126
  Block* blk = r->block()->perform(this)->block();
124
127
  Ruleset* rr = SASS_MEMORY_NEW(ctx.mem, Ruleset,
125
128
  r->pstate(),
126
129
  sel,
127
130
  blk);
128
131
  selector_stack.pop_back();
132
+ if (block_stack.back()->is_root()) {
133
+ env_stack.pop_back();
134
+ delete env;
135
+ }
129
136
  rr->tabs(r->tabs());
130
137
 
131
138
  return rr;
@@ -177,12 +184,15 @@ namespace Sass {
177
184
 
178
185
  Statement* Expand::operator()(Media_Block* m)
179
186
  {
180
- To_String to_string(&ctx);
181
187
  Expression* mq = m->media_queries()->perform(&eval);
182
- mq = Parser::from_c_str(mq->perform(&to_string).c_str(), ctx, mq->pstate()).parse_media_queries();
188
+ std::string str_mq(mq->to_string(ctx.c_options));
189
+ char* str = sass_strdup(str_mq.c_str());
190
+ ctx.strings.push_back(str);
191
+ Parser p(Parser::from_c_str(str, ctx, mq->pstate()));
192
+ mq = p.parse_media_queries();
183
193
  Media_Block* mm = SASS_MEMORY_NEW(ctx.mem, Media_Block,
184
194
  m->pstate(),
185
- static_cast<List*>(mq),
195
+ static_cast<List*>(mq->perform(&eval)),
186
196
  m->block()->perform(this)->block(),
187
197
  0);
188
198
  mm->tabs(m->tabs());
@@ -318,6 +328,11 @@ namespace Sass {
318
328
 
319
329
  Statement* Expand::operator()(Import_Stub* i)
320
330
  {
331
+ // get parent node from call stack
332
+ AST_Node* parent = call_stack.back();
333
+ if (parent && dynamic_cast<Block*>(parent) == NULL) {
334
+ error("Import directives may not be used within control directives or mixins.", i->pstate());
335
+ }
321
336
  // we don't seem to need that actually afterall
322
337
  Sass_Import_Entry import = sass_make_import(
323
338
  i->imp_path().c_str(),
@@ -355,12 +370,18 @@ namespace Sass {
355
370
 
356
371
  Statement* Expand::operator()(Comment* c)
357
372
  {
373
+ eval.is_in_comment = true;
374
+ auto rv = SASS_MEMORY_NEW(ctx.mem, Comment, c->pstate(), static_cast<String*>(c->text()->perform(&eval)), c->is_important());
375
+ eval.is_in_comment = false;
358
376
  // TODO: eval the text, once we're parsing/storing it as a String_Schema
359
- return SASS_MEMORY_NEW(ctx.mem, Comment, c->pstate(), static_cast<String*>(c->text()->perform(&eval)), c->is_important());
377
+ return rv;
360
378
  }
361
379
 
362
380
  Statement* Expand::operator()(If* i)
363
381
  {
382
+ Env env(environment(), true);
383
+ env_stack.push_back(&env);
384
+ call_stack.push_back(i);
364
385
  if (*i->predicate()->perform(&eval)) {
365
386
  append_block(i->block());
366
387
  }
@@ -368,6 +389,8 @@ namespace Sass {
368
389
  Block* alt = i->alternative();
369
390
  if (alt) append_block(alt);
370
391
  }
392
+ call_stack.pop_back();
393
+ env_stack.pop_back();
371
394
  return 0;
372
395
  }
373
396
 
@@ -378,11 +401,11 @@ namespace Sass {
378
401
  std::string variable(f->variable());
379
402
  Expression* low = f->lower_bound()->perform(&eval);
380
403
  if (low->concrete_type() != Expression::NUMBER) {
381
- error("lower bound of `@for` directive must be numeric", low->pstate(), backtrace());
404
+ throw Exception::TypeMismatch(*low, "integer");
382
405
  }
383
406
  Expression* high = f->upper_bound()->perform(&eval);
384
407
  if (high->concrete_type() != Expression::NUMBER) {
385
- error("upper bound of `@for` directive must be numeric", high->pstate(), backtrace());
408
+ throw Exception::TypeMismatch(*high, "integer");
386
409
  }
387
410
  Number* sass_start = static_cast<Number*>(low);
388
411
  Number* sass_end = static_cast<Number*>(high);
@@ -396,10 +419,11 @@ namespace Sass {
396
419
  double start = sass_start->value();
397
420
  double end = sass_end->value();
398
421
  // only create iterator once in this environment
399
- Env* env = environment();
400
- Number* it = SASS_MEMORY_NEW(env->mem, Number, low->pstate(), start, sass_end->unit());
401
- AST_Node* old_var = env->has_local(variable) ? env->get_local(variable) : 0;
402
- env->set_local(variable, it);
422
+ Env env(environment(), true);
423
+ env_stack.push_back(&env);
424
+ call_stack.push_back(f);
425
+ Number* it = SASS_MEMORY_NEW(env.mem, Number, low->pstate(), start, sass_end->unit());
426
+ env.set_local(variable, it);
403
427
  Block* body = f->block();
404
428
  if (start < end) {
405
429
  if (f->is_inclusive()) ++end;
@@ -407,7 +431,7 @@ namespace Sass {
407
431
  i < end;
408
432
  ++i) {
409
433
  it->value(i);
410
- env->set_local(variable, it);
434
+ env.set_local(variable, it);
411
435
  append_block(body);
412
436
  }
413
437
  } else {
@@ -416,13 +440,12 @@ namespace Sass {
416
440
  i > end;
417
441
  --i) {
418
442
  it->value(i);
419
- env->set_local(variable, it);
443
+ env.set_local(variable, it);
420
444
  append_block(body);
421
445
  }
422
446
  }
423
- // restore original environment
424
- if (!old_var) env->del_local(variable);
425
- else env->set_local(variable, old_var);
447
+ call_stack.pop_back();
448
+ env_stack.pop_back();
426
449
  return 0;
427
450
  }
428
451
 
@@ -432,11 +455,15 @@ namespace Sass {
432
455
  {
433
456
  std::vector<std::string> variables(e->variables());
434
457
  Expression* expr = e->list()->perform(&eval);
435
- List* list = 0;
458
+ Vectorized<Expression*>* list = 0;
436
459
  Map* map = 0;
437
460
  if (expr->concrete_type() == Expression::MAP) {
438
461
  map = static_cast<Map*>(expr);
439
462
  }
463
+ else if (Selector_List* ls = dynamic_cast<Selector_List*>(expr)) {
464
+ Listize listize(ctx.mem);
465
+ list = dynamic_cast<List*>(ls->perform(&listize));
466
+ }
440
467
  else if (expr->concrete_type() != Expression::LIST) {
441
468
  list = SASS_MEMORY_NEW(ctx.mem, List, expr->pstate(), 1, SASS_COMMA);
442
469
  *list << expr;
@@ -445,12 +472,9 @@ namespace Sass {
445
472
  list = static_cast<List*>(expr);
446
473
  }
447
474
  // remember variables and then reset them
448
- Env* env = environment();
449
- std::vector<AST_Node*> old_vars(variables.size());
450
- for (size_t i = 0, L = variables.size(); i < L; ++i) {
451
- old_vars[i] = env->has_local(variables[i]) ? env->get_local(variables[i]) : 0;
452
- env->set_local(variables[i], 0);
453
- }
475
+ Env env(environment(), true);
476
+ env_stack.push_back(&env);
477
+ call_stack.push_back(e);
454
478
  Block* body = e->block();
455
479
 
456
480
  if (map) {
@@ -462,16 +486,19 @@ namespace Sass {
462
486
  List* variable = SASS_MEMORY_NEW(ctx.mem, List, map->pstate(), 2, SASS_SPACE);
463
487
  *variable << k;
464
488
  *variable << v;
465
- env->set_local(variables[0], variable);
489
+ env.set_local(variables[0], variable);
466
490
  } else {
467
- env->set_local(variables[0], k);
468
- env->set_local(variables[1], v);
491
+ env.set_local(variables[0], k);
492
+ env.set_local(variables[1], v);
469
493
  }
470
494
  append_block(body);
471
495
  }
472
496
  }
473
497
  else {
474
- bool arglist = list->is_arglist();
498
+ // bool arglist = list->is_arglist();
499
+ if (list->length() == 1 && dynamic_cast<Selector_List*>(list)) {
500
+ list = dynamic_cast<Vectorized<Expression*>*>(list);
501
+ }
475
502
  for (size_t i = 0, L = list->length(); i < L; ++i) {
476
503
  Expression* e = (*list)[i];
477
504
  // unwrap value if the expression is an argument
@@ -480,33 +507,30 @@ namespace Sass {
480
507
  if (List* scalars = dynamic_cast<List*>(e)) {
481
508
  if (variables.size() == 1) {
482
509
  Expression* var = scalars;
483
- if (arglist) var = (*scalars)[0];
484
- env->set_local(variables[0], var);
510
+ // if (arglist) var = (*scalars)[0];
511
+ env.set_local(variables[0], var);
485
512
  } else {
486
513
  for (size_t j = 0, K = variables.size(); j < K; ++j) {
487
514
  Expression* res = j >= scalars->length()
488
515
  ? SASS_MEMORY_NEW(ctx.mem, Null, expr->pstate())
489
516
  : (*scalars)[j]->perform(&eval);
490
- env->set_local(variables[j], res);
517
+ env.set_local(variables[j], res);
491
518
  }
492
519
  }
493
520
  } else {
494
521
  if (variables.size() > 0) {
495
- env->set_local(variables[0], e);
522
+ env.set_local(variables[0], e);
496
523
  for (size_t j = 1, K = variables.size(); j < K; ++j) {
497
524
  Expression* res = SASS_MEMORY_NEW(ctx.mem, Null, expr->pstate());
498
- env->set_local(variables[j], res);
525
+ env.set_local(variables[j], res);
499
526
  }
500
527
  }
501
528
  }
502
529
  append_block(body);
503
530
  }
504
531
  }
505
- // restore original environment
506
- for (size_t j = 0, K = variables.size(); j < K; ++j) {
507
- if(!old_vars[j]) env->del_local(variables[j]);
508
- else env->set_local(variables[j], old_vars[j]);
509
- }
532
+ call_stack.pop_back();
533
+ env_stack.pop_back();
510
534
  return 0;
511
535
  }
512
536
 
@@ -514,9 +538,14 @@ namespace Sass {
514
538
  {
515
539
  Expression* pred = w->predicate();
516
540
  Block* body = w->block();
541
+ Env env(environment(), true);
542
+ env_stack.push_back(&env);
543
+ call_stack.push_back(w);
517
544
  while (*pred->perform(&eval)) {
518
545
  append_block(body);
519
546
  }
547
+ call_stack.pop_back();
548
+ env_stack.pop_back();
520
549
  return 0;
521
550
  }
522
551
 
@@ -526,20 +555,16 @@ namespace Sass {
526
555
  return 0;
527
556
  }
528
557
 
529
- Statement* Expand::operator()(Extension* e)
530
- {
531
- To_String to_string(&ctx);
532
- Selector_List* extender = dynamic_cast<Selector_List*>(selector());
533
- if (!extender) return 0;
534
- selector_stack.push_back(0);
535
558
 
536
- if (Selector_List* selector_list = dynamic_cast<Selector_List*>(e->selector())) {
537
- for (Complex_Selector* complex_selector : selector_list->elements()) {
559
+ void Expand::expand_selector_list(Selector* s, Selector_List* extender) {
560
+
561
+ if (Selector_List* sl = dynamic_cast<Selector_List*>(s)) {
562
+ for (Complex_Selector* complex_selector : sl->elements()) {
538
563
  Complex_Selector* tail = complex_selector;
539
564
  while (tail) {
540
565
  if (tail->head()) for (Simple_Selector* header : tail->head()->elements()) {
541
566
  if (dynamic_cast<Parent_Selector*>(header) == NULL) continue; // skip all others
542
- To_String to_string(&ctx); std::string sel_str(complex_selector->perform(&to_string));
567
+ std::string sel_str(complex_selector->to_string(ctx.c_options));
543
568
  error("Can't extend " + sel_str + ": can't extend parent selectors", header->pstate(), backtrace());
544
569
  }
545
570
  tail = tail->tail();
@@ -547,16 +572,17 @@ namespace Sass {
547
572
  }
548
573
  }
549
574
 
550
- Selector_List* contextualized = dynamic_cast<Selector_List*>(e->selector()->perform(&eval));
551
- if (contextualized == NULL) return 0;
575
+
576
+ Selector_List* contextualized = dynamic_cast<Selector_List*>(s->perform(&eval));
577
+ if (contextualized == NULL) return;
552
578
  for (auto complex_sel : contextualized->elements()) {
553
579
  Complex_Selector* c = complex_sel;
554
580
  if (!c->head() || c->tail()) {
555
- To_String to_string(&ctx); std::string sel_str(contextualized->perform(&to_string));
581
+ std::string sel_str(contextualized->to_string(ctx.c_options));
556
582
  error("Can't extend " + sel_str + ": can't extend nested selectors", c->pstate(), backtrace());
557
583
  }
558
584
  Compound_Selector* placeholder = c->head();
559
- placeholder->is_optional(e->selector()->is_optional());
585
+ placeholder->is_optional(s->is_optional());
560
586
  for (size_t i = 0, L = extender->length(); i < L; ++i) {
561
587
  Complex_Selector* sel = (*extender)[i];
562
588
  if (!(sel->head() && sel->head()->length() > 0 &&
@@ -579,8 +605,16 @@ namespace Sass {
579
605
  }
580
606
  }
581
607
 
582
- selector_stack.pop_back();
608
+ }
583
609
 
610
+ Statement* Expand::operator()(Extension* e)
611
+ {
612
+ if (Selector_List* extender = dynamic_cast<Selector_List*>(selector())) {
613
+ selector_stack.push_back(0);
614
+ Selector* s = e->selector();
615
+ expand_selector_list(s, extender);
616
+ selector_stack.pop_back();
617
+ }
584
618
  return 0;
585
619
  }
586
620
 
@@ -680,10 +714,12 @@ namespace Sass {
680
714
  // process and add to last block on stack
681
715
  inline void Expand::append_block(Block* b)
682
716
  {
717
+ if (b->is_root()) call_stack.push_back(b);
683
718
  for (size_t i = 0, L = b->length(); i < L; ++i) {
684
719
  Statement* ith = (*b)[i]->perform(this);
685
720
  if (ith) *block_stack.back() << ith;
686
721
  }
722
+ if (b->is_root()) call_stack.pop_back();
687
723
  }
688
724
 
689
725
  }
@@ -30,6 +30,7 @@ namespace Sass {
30
30
  // it's easier to work with vectors
31
31
  std::vector<Env*> env_stack;
32
32
  std::vector<Block*> block_stack;
33
+ std::vector<AST_Node*> call_stack;
33
34
  std::vector<String*> property_stack;
34
35
  std::vector<Selector_List*> selector_stack;
35
36
  std::vector<Backtrace*>backtrace_stack;
@@ -37,11 +38,12 @@ namespace Sass {
37
38
 
38
39
  Statement* fallback_impl(AST_Node* n);
39
40
 
41
+ private:
42
+ void expand_selector_list(Selector*, Selector_List* extender);
43
+
40
44
  public:
41
45
  Expand(Context&, Env*, Backtrace*);
42
- virtual ~Expand() { }
43
-
44
- using Operation<Statement*>::operator();
46
+ ~Expand() { }
45
47
 
46
48
  Statement* operator()(Block*);
47
49
  Statement* operator()(Ruleset*);
@@ -1,10 +1,6 @@
1
- #ifdef _MSC_VER
2
- #pragma warning(disable : 4503)
3
- #endif
4
-
1
+ #include "sass.hpp"
5
2
  #include "extend.hpp"
6
3
  #include "context.hpp"
7
- #include "to_string.hpp"
8
4
  #include "backtrace.hpp"
9
5
  #include "paths.hpp"
10
6
  #include "parser.hpp"
@@ -85,23 +81,20 @@ namespace Sass {
85
81
 
86
82
 
87
83
  std::ostream& operator<<(std::ostream& os, Compound_Selector& compoundSelector) {
88
- To_String to_string;
89
84
  for (size_t i = 0, L = compoundSelector.length(); i < L; ++i) {
90
85
  if (i > 0) os << ", ";
91
- os << compoundSelector[i]->perform(&to_string);
86
+ os << compoundSelector[i]->to_string();
92
87
  }
93
88
  return os;
94
89
  }
95
90
 
96
91
  std::ostream& operator<<(std::ostream& os, Simple_Selector& simpleSelector) {
97
- To_String to_string;
98
- os << simpleSelector.perform(&to_string);
92
+ os << simpleSelector.to_string();
99
93
  return os;
100
94
  }
101
95
 
102
96
  // Print a string representation of a Compound_Selector
103
97
  static void printSimpleSelector(Simple_Selector* pSimpleSelector, const char* message=NULL, bool newline=true) {
104
- To_String to_string;
105
98
 
106
99
  if (message) {
107
100
  std::cerr << message;
@@ -125,7 +118,6 @@ namespace Sass {
125
118
 
126
119
  // Print a string representation of a Compound_Selector
127
120
  static void printCompoundSelector(Compound_Selector* pCompoundSelector, const char* message=NULL, bool newline=true) {
128
- To_String to_string;
129
121
 
130
122
  if (message) {
131
123
  std::cerr << message;
@@ -144,7 +136,6 @@ namespace Sass {
144
136
 
145
137
 
146
138
  std::ostream& operator<<(std::ostream& os, Complex_Selector& complexSelector) {
147
- To_String to_string;
148
139
 
149
140
  os << "[";
150
141
  Complex_Selector* pIter = &complexSelector;
@@ -164,7 +155,7 @@ namespace Sass {
164
155
  first = false;
165
156
 
166
157
  if (pIter->head()) {
167
- os << pIter->head()->perform(&to_string);
158
+ os << pIter->head()->to_string();
168
159
  } else {
169
160
  os << "NULL_HEAD";
170
161
  }
@@ -179,7 +170,6 @@ namespace Sass {
179
170
 
180
171
  // Print a string representation of a Complex_Selector
181
172
  static void printComplexSelector(Complex_Selector* pComplexSelector, const char* message=NULL, bool newline=true) {
182
- To_String to_string;
183
173
 
184
174
  if (message) {
185
175
  std::cerr << message;
@@ -197,7 +187,6 @@ namespace Sass {
197
187
  }
198
188
 
199
189
  static void printSelsNewSeqPairCollection(SelsNewSeqPairCollection& collection, const char* message=NULL, bool newline=true) {
200
- To_String to_string;
201
190
 
202
191
  if (message) {
203
192
  std::cerr << message;
@@ -225,7 +214,6 @@ namespace Sass {
225
214
 
226
215
  // Print a string representation of a SourcesSet
227
216
  static void printSourcesSet(SourcesSet& sources, Context& ctx, const char* message=NULL, bool newline=true) {
228
- To_String to_string;
229
217
 
230
218
  if (message) {
231
219
  std::cerr << message;
@@ -1558,8 +1546,6 @@ namespace Sass {
1558
1546
  Node extendedSelectors = Node::createCollection();
1559
1547
  // extendedSelectors.got_line_feed = true;
1560
1548
 
1561
- To_String to_string;
1562
-
1563
1549
  SubsetMapEntries entries = subset_map.get_v(pSelector->to_str_vec());
1564
1550
 
1565
1551
  typedef std::vector<std::pair<Complex_Selector, std::vector<ExtensionPair> > > GroupedByToAResult;
@@ -1591,6 +1577,7 @@ namespace Sass {
1591
1577
  for (size_t index = 0; index < pCompound->length(); index++) {
1592
1578
  Simple_Selector* pSimpleSelector = (*pCompound)[index];
1593
1579
  (*pSels) << pSimpleSelector;
1580
+ pCompound->extended(true);
1594
1581
  }
1595
1582
  }
1596
1583
 
@@ -1732,18 +1719,32 @@ namespace Sass {
1732
1719
  Compound_Selector* pHead = pIter->head();
1733
1720
 
1734
1721
  if (pHead) {
1722
+ for (Simple_Selector* pSimple : *pHead) {
1723
+ if (Wrapped_Selector* ws = dynamic_cast<Wrapped_Selector*>(pSimple)) {
1724
+ if (Selector_List* sl = dynamic_cast<Selector_List*>(ws->selector())) {
1725
+ for (Complex_Selector* cs : sl->elements()) {
1726
+ while (cs) {
1727
+ if (complexSelectorHasExtension(cs, ctx, subset_map)) {
1728
+ hasExtension = true;
1729
+ break;
1730
+ }
1731
+ cs = cs->tail();
1732
+ }
1733
+ }
1734
+ }
1735
+ }
1736
+ }
1735
1737
  SubsetMapEntries entries = subset_map.get_v(pHead->to_str_vec());
1736
1738
  for (ExtensionPair ext : entries) {
1737
1739
  // check if both selectors have the same media block parent
1738
1740
  if (ext.first->media_block() == pComplexSelector->media_block()) continue;
1739
- To_String to_string(&ctx);
1740
1741
  if (ext.second->media_block() == 0) continue;
1741
1742
  if (pComplexSelector->media_block() &&
1742
1743
  ext.second->media_block()->media_queries() &&
1743
1744
  pComplexSelector->media_block()->media_queries()
1744
1745
  ) {
1745
- std::string query_left(ext.second->media_block()->media_queries()->perform(&to_string));
1746
- std::string query_right(pComplexSelector->media_block()->media_queries()->perform(&to_string));
1746
+ std::string query_left(ext.second->media_block()->media_queries()->to_string(ctx.c_options));
1747
+ std::string query_right(pComplexSelector->media_block()->media_queries()->to_string(ctx.c_options));
1747
1748
  if (query_left == query_right) continue;
1748
1749
  }
1749
1750
 
@@ -1754,7 +1755,7 @@ namespace Sass {
1754
1755
  std::string rel_path(Sass::File::abs2rel(pstate.path, cwd, cwd));
1755
1756
  err << "You may not @extend an outer selector from within @media.\n";
1756
1757
  err << "You may only @extend selectors within the same directive.\n";
1757
- err << "From \"@extend " << ext.second->perform(&to_string) << "\"";
1758
+ err << "From \"@extend " << ext.second->to_string(ctx.c_options) << "\"";
1758
1759
  err << " on line " << pstate.line+1 << " of " << rel_path << "\n";
1759
1760
  error(err.str(), pComplexSelector->pstate());
1760
1761
  }
@@ -1764,29 +1765,6 @@ namespace Sass {
1764
1765
  pIter = pIter->tail();
1765
1766
  }
1766
1767
 
1767
- if (!hasExtension) {
1768
- /* ToDo: don't break stuff
1769
- std::stringstream err;
1770
- To_String to_string(&ctx);
1771
- std::string cwd(Sass::File::get_cwd());
1772
- std::string sel1(pComplexSelector->perform(&to_string));
1773
- Compound_Selector* pExtendSelector = 0;
1774
- for (auto i : subset_map.values()) {
1775
- if (i.first == pComplexSelector) {
1776
- pExtendSelector = i.second;
1777
- break;
1778
- }
1779
- }
1780
- if (!pExtendSelector || !pExtendSelector->is_optional()) {
1781
- std::string sel2(pExtendSelector ? pExtendSelector->perform(&to_string) : "[unknown]");
1782
- err << "\"" << sel1 << "\" failed to @extend \"" << sel2 << "\"\n";
1783
- err << "The selector \"" << sel2 << "\" was not found.\n";
1784
- err << "Use \"@extend " << sel2 << " !optional\" if the extend should be able to fail.";
1785
- error(err.str(), pExtendSelector ? pExtendSelector->pstate() : pComplexSelector->pstate());
1786
- }
1787
- */
1788
- }
1789
-
1790
1768
  return hasExtension;
1791
1769
  }
1792
1770
 
@@ -1928,8 +1906,6 @@ namespace Sass {
1928
1906
  */
1929
1907
  Selector_List* Extend::extendSelectorList(Selector_List* pSelectorList, Context& ctx, ExtensionSubsetMap& subset_map, bool isReplace, bool& extendedSomething) {
1930
1908
 
1931
- To_String to_string(&ctx);
1932
-
1933
1909
  Selector_List* pNewSelectors = SASS_MEMORY_NEW(ctx.mem, Selector_List, pSelectorList->pstate(), pSelectorList->length());
1934
1910
 
1935
1911
  extendedSomething = false;
@@ -1967,6 +1943,21 @@ namespace Sass {
1967
1943
  }
1968
1944
  }
1969
1945
 
1946
+ for (Complex_Selector* cs : *pNewSelectors) {
1947
+ while (cs) {
1948
+ if (cs->head()) {
1949
+ for (Simple_Selector* ss : *cs->head()) {
1950
+ if (Wrapped_Selector* ws = dynamic_cast<Wrapped_Selector*>(ss)) {
1951
+ if (Selector_List* sl = dynamic_cast<Selector_List*>(ws->selector())) {
1952
+ bool extended = false;
1953
+ ws->selector(extendSelectorList(sl, ctx, subset_map, false, extended));
1954
+ }
1955
+ }
1956
+ }
1957
+ }
1958
+ cs = cs->tail();
1959
+ }
1960
+ }
1970
1961
  return pNewSelectors;
1971
1962
 
1972
1963
  }
@@ -2006,9 +1997,8 @@ namespace Sass {
2006
1997
  // Extend a ruleset by extending the selectors and updating them on the ruleset. The block's rules don't need to change.
2007
1998
  template <typename ObjectType>
2008
1999
  static void extendObjectWithSelectorAndBlock(ObjectType* pObject, Context& ctx, ExtensionSubsetMap& subset_map) {
2009
- To_String to_string(&ctx);
2010
2000
 
2011
- DEBUG_PRINTLN(EXTEND_OBJECT, "FOUND SELECTOR: " << static_cast<Selector_List*>(pObject->selector())->perform(&to_string))
2001
+ DEBUG_PRINTLN(EXTEND_OBJECT, "FOUND SELECTOR: " << static_cast<Selector_List*>(pObject->selector())->to_string(ctx.c_options))
2012
2002
 
2013
2003
  // Ruby sass seems to filter nodes that don't have any content well before we get here. I'm not sure the repercussions
2014
2004
  // of doing so, so for now, let's just not extend things that won't be output later.
@@ -2021,8 +2011,8 @@ namespace Sass {
2021
2011
  Selector_List* pNewSelectorList = Extend::extendSelectorList(static_cast<Selector_List*>(pObject->selector()), ctx, subset_map, false, extendedSomething);
2022
2012
 
2023
2013
  if (extendedSomething && pNewSelectorList) {
2024
- DEBUG_PRINTLN(EXTEND_OBJECT, "EXTEND ORIGINAL SELECTORS: " << static_cast<Selector_List*>(pObject->selector())->perform(&to_string))
2025
- DEBUG_PRINTLN(EXTEND_OBJECT, "EXTEND SETTING NEW SELECTORS: " << pNewSelectorList->perform(&to_string))
2014
+ DEBUG_PRINTLN(EXTEND_OBJECT, "EXTEND ORIGINAL SELECTORS: " << static_cast<Selector_List*>(pObject->selector())->to_string(ctx.c_options))
2015
+ DEBUG_PRINTLN(EXTEND_OBJECT, "EXTEND SETTING NEW SELECTORS: " << pNewSelectorList->to_string(ctx.c_options))
2026
2016
  pNewSelectorList->remove_parent_selectors();
2027
2017
  pObject->selector(pNewSelectorList);
2028
2018
  } else {
@@ -2041,6 +2031,25 @@ namespace Sass {
2041
2031
  for (size_t i = 0, L = b->length(); i < L; ++i) {
2042
2032
  (*b)[i]->perform(this);
2043
2033
  }
2034
+ // do final check if everything was extended
2035
+ // we set `extended` flag on extended selectors
2036
+ if (b->is_root()) {
2037
+ // debug_subset_map(subset_map);
2038
+ for(auto const &it : subset_map.values()) {
2039
+ Complex_Selector* sel = it.first ? it.first->first() : NULL;
2040
+ Compound_Selector* ext = it.second ? it.second : NULL;
2041
+ if (ext && (ext->extended() || ext->is_optional())) continue;
2042
+ std::string str_sel(sel->to_string({ NESTED, 5 }));
2043
+ std::string str_ext(ext->to_string({ NESTED, 5 }));
2044
+ // debug_ast(sel, "sel: ");
2045
+ // debug_ast(ext, "ext: ");
2046
+ error("\"" + str_sel + "\" failed to @extend \"" + str_ext + "\".\n"
2047
+ "The selector \"" + str_ext + "\" was not found.\n"
2048
+ "Use \"@extend " + str_ext + " !optional\" if the"
2049
+ " extend should be able to fail.", ext->pstate());
2050
+ }
2051
+ }
2052
+
2044
2053
  }
2045
2054
 
2046
2055
  void Extend::operator()(Ruleset* pRuleset)