Skip to content

Commit

Permalink
Fix illegal extending when no blocks are found
Browse files Browse the repository at this point in the history
Prints the exact error message as ruby sass.
Implements optional flag to suppress message.
  • Loading branch information
mgreter committed Mar 8, 2015
1 parent d68cc86 commit a61ec99
Show file tree
Hide file tree
Showing 6 changed files with 38 additions and 5 deletions.
3 changes: 3 additions & 0 deletions ast.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -1704,6 +1704,8 @@ namespace Sass {
ADD_PROPERTY(bool, has_line_feed);
// line break after list separator
ADD_PROPERTY(bool, has_line_break);
// maybe we have optional flag
ADD_PROPERTY(bool, is_optional);
// parent media block (for extend check)
ADD_PROPERTY(Media_Block*, media_block);
public:
Expand All @@ -1713,6 +1715,7 @@ namespace Sass {
has_placeholder_(h),
has_line_feed_(false),
has_line_break_(false),
is_optional_(false),
media_block_(0)
{ }
virtual ~Selector() = 0;
Expand Down
4 changes: 4 additions & 0 deletions debugger.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ inline void debug_ast(AST_Node* node, string ind = "", Env* env = 0)

cerr << ind << "Selector_List " << selector
<< " [mq:" << selector->media_block() << "]"
<< (selector->is_optional() ? " [is_optional]": " -")
<< (selector->has_line_break() ? " [line-break]": " -")
<< (selector->has_line_feed() ? " [line-feed]": " -")
<< endl;
Expand All @@ -54,6 +55,7 @@ inline void debug_ast(AST_Node* node, string ind = "", Env* env = 0)
Complex_Selector* selector = dynamic_cast<Complex_Selector*>(node);
cerr << ind << "Complex_Selector " << selector
<< " [mq:" << selector->media_block() << "]"
<< (selector->is_optional() ? " [is_optional]": " -")
<< (selector->has_line_break() ? " [line-break]": " -")
<< (selector->has_line_feed() ? " [line-feed]": " -") << " -> ";
switch (selector->combinator()) {
Expand All @@ -69,6 +71,7 @@ inline void debug_ast(AST_Node* node, string ind = "", Env* env = 0)
Compound_Selector* selector = dynamic_cast<Compound_Selector*>(node);
cerr << ind << "Compound_Selector " << selector
<< " [mq:" << selector->media_block() << "]"
<< (selector->is_optional() ? " [is_optional]": " -")
<< (selector->has_line_break() ? " [line-break]": " -")
<< (selector->has_line_feed() ? " [line-feed]": " -") <<
" <" << prettyprint(selector->pstate().token.ws_before()) << "> X <" << prettyprint(selector->pstate().token.ws_after()) << ">" << endl;
Expand Down Expand Up @@ -101,6 +104,7 @@ inline void debug_ast(AST_Node* node, string ind = "", Env* env = 0)
Selector_Placeholder* selector = dynamic_cast<Selector_Placeholder*>(node);
cerr << ind << "Selector_Placeholder [" << selector->name() << "] " << selector
<< " [mq:" << selector->media_block() << "]"
<< (selector->is_optional() ? " [is_optional]": " -")
<< (selector->has_line_break() ? " [line-break]": " -")
<< (selector->has_line_feed() ? " [line-feed]": " -")
<< endl;
Expand Down
5 changes: 3 additions & 2 deletions expand.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -404,7 +404,8 @@ namespace Sass {
To_String to_string(&ctx);
Selector_List* extender = static_cast<Selector_List*>(selector_stack.back());
if (!extender) return 0;
Selector_List* extendee = static_cast<Selector_List*>(e->selector()->perform(contextualize->with(0, env, backtrace)));
Selector_List* org_extendee = static_cast<Selector_List*>(e->selector());
Selector_List* extendee = static_cast<Selector_List*>(org_extendee->perform(contextualize->with(0, env, backtrace)));
if (extendee->length() != 1) {
error("selector groups may not be extended", extendee->pstate(), backtrace);
}
Expand All @@ -413,7 +414,7 @@ namespace Sass {
error("nested selectors may not be extended", c->pstate(), backtrace);
}
Compound_Selector* s = c->head();

s->is_optional(org_extendee->is_optional());
// // need to convert the compound selector into a by-value data structure
// vector<string> target_vec;
// for (size_t i = 0, L = s->length(); i < L; ++i)
Expand Down
26 changes: 24 additions & 2 deletions extend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include "backtrace.hpp"
#include "paths.hpp"
#include "parser.hpp"
#include "debugger.hpp"
#include "node.hpp"
#include "sass_util.hpp"
#include "debug.hpp"
Expand Down Expand Up @@ -1678,10 +1679,10 @@ namespace Sass {
for (ExtensionPair ext : entries) {
// check if both selectors have the same media block parent
if (ext.first->media_block() == pComplexSelector->media_block()) continue;
// fail if one goes across media block boundaries
stringstream err;
To_String to_string(&ctx);
string cwd(Sass::File::get_cwd());
// make path relative to the current directory
ParserState pstate(ext.second->pstate());
string rel_path(Sass::File::resolve_relative_path(pstate.path, cwd, cwd));
err << "You may not @extend an outer selector from within @media.\n";
Expand All @@ -1690,12 +1691,33 @@ namespace Sass {
err << " on line " << pstate.line+1 << " of " << rel_path << "\n";
error(err.str(), pComplexSelector->pstate());
}
hasExtension = entries.size() > 0;
if (entries.size() > 0) hasExtension = true;
}

pIter = pIter->tail();
}

if (!hasExtension) {
stringstream err;
To_String to_string(&ctx);
string cwd(Sass::File::get_cwd());
string sel1(pComplexSelector->perform(&to_string));
Compound_Selector* pExtendSelector = 0;
for (auto i : subsetMap.values()) {
if (i.first == pComplexSelector) {
pExtendSelector = i.second;
break;
}
}
if (!pExtendSelector->is_optional()) {
string sel2(pExtendSelector ? pExtendSelector->perform(&to_string) : "[unknown]");
err << "\"" << sel1 << "\" failed to @extend \"" << sel2 << "\"\n";
err << "The selector \"" << sel2 << "\" was not found.\n";
err << "Use \"@extend " << sel2 << " !optional\" if the extend should be able to fail.";
error(err.str(), pExtendSelector ? pExtendSelector->pstate() : pComplexSelector->pstate());
}
}

return hasExtension;
}

Expand Down
4 changes: 3 additions & 1 deletion parser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -497,7 +497,9 @@ namespace Sass {
(*group) << comb;
}
while (reloop);
while (lex< optional >()); // JMA - ignore optional flag if it follows the selector group
while (lex< optional >()) {
group->is_optional(true);
}
return group;
}

Expand Down
1 change: 1 addition & 0 deletions subset_map.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ namespace Sass {
vector<V> get_v(const vector<K>& s);
bool empty() { return values_.empty(); }
void clear() { values_.clear(); hash_.clear(); }
const vector<V> values(void) { return values_; }
};

template<typename K, typename V>
Expand Down

0 comments on commit a61ec99

Please sign in to comment.