sassc 1.8.3 → 1.8.4

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.
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)