# A visitor for checking that all nodes are properly nested.classSass::Tree::Visitors::CheckNesting<Sass::Tree::Visitors::Baseprotecteddefinitialize@parents=[]enddefvisit(node)if(error=@parent&&(try_send(@parent.class.invalid_child_method_name,@parent,node)||try_send(node.class.invalid_parent_method_name,@parent,node)))raiseSass::SyntaxError.new(error)endsuperrescueSass::SyntaxError=>ee.modify_backtrace(:filename=>node.filename,:line=>node.line)raiseeendCONTROL_NODES=[Sass::Tree::EachNode,Sass::Tree::ForNode,Sass::Tree::IfNode,Sass::Tree::WhileNode,Sass::Tree::TraceNode]SCRIPT_NODES=[Sass::Tree::ImportNode]+CONTROL_NODESdefvisit_children(parent)old_parent=@parent# When checking a static tree, resolve at-roots to be sure they won't send# nodes where they don't belong.ifparent.is_a?(Sass::Tree::AtRootNode)&&parent.resolved_valueold_parents=@parents@parents=@parents.reject{|p|parent.exclude_node?(p)}@parent=Sass::Util.enum_with_index(@parents.reverse).find{|p,i|!transparent_parent?(p,@parents[-i-2])}.firstbeginreturnsuperensure@parents=old_parents@parent=old_parentendendunlesstransparent_parent?(parent,old_parent)@parent=parentend@parents.pushparentbeginsuperensure@parent=old_parent@parents.popendenddefvisit_root(node)yieldrescueSass::SyntaxError=>ee.sass_template||=node.templateraiseeenddefvisit_import(node)yieldrescueSass::SyntaxError=>ee.modify_backtrace(:filename=>node.children.first.filename)e.add_backtrace(:filename=>node.filename,:line=>node.line)raiseeenddefvisit_mixindef(node)@current_mixin_def,old_mixin_def=node,@current_mixin_defyieldensure@current_mixin_def=old_mixin_defenddefinvalid_content_parent?(parent,child)if@current_mixin_def@current_mixin_def.has_content=truenilelse"@content may only be used within a mixin."endenddefinvalid_charset_parent?(parent,child)"@charset may only be used at the root of a document."unlessparent.is_a?(Sass::Tree::RootNode)endVALID_EXTEND_PARENTS=[Sass::Tree::RuleNode,Sass::Tree::MixinDefNode,Sass::Tree::MixinNode]definvalid_extend_parent?(parent,child)unlessis_any_of?(parent,VALID_EXTEND_PARENTS)return"Extend directives may only be used within rules."endendINVALID_IMPORT_PARENTS=CONTROL_NODES+[Sass::Tree::MixinDefNode,Sass::Tree::MixinNode]definvalid_import_parent?(parent,child)unless(@parents.map{|p|p.class}&INVALID_IMPORT_PARENTS).empty?return"Import directives may not be used within control directives or mixins."endreturnifparent.is_a?(Sass::Tree::RootNode)return"CSS import directives may only be used at the root of a document."ifchild.css_import?rescueSass::SyntaxError=>ee.modify_backtrace(:filename=>child.imported_file.options[:filename])e.add_backtrace(:filename=>child.filename,:line=>child.line)raiseeenddefinvalid_mixindef_parent?(parent,child)unless(@parents.map{|p|p.class}&INVALID_IMPORT_PARENTS).empty?return"Mixins may not be defined within control directives or other mixins."endenddefinvalid_function_parent?(parent,child)unless(@parents.map{|p|p.class}&INVALID_IMPORT_PARENTS).empty?return"Functions may not be defined within control directives or other mixins."endendVALID_FUNCTION_CHILDREN=[Sass::Tree::CommentNode,Sass::Tree::DebugNode,Sass::Tree::ReturnNode,Sass::Tree::VariableNode,Sass::Tree::WarnNode]+CONTROL_NODESdefinvalid_function_child?(parent,child)unlessis_any_of?(child,VALID_FUNCTION_CHILDREN)"Functions can only contain variable declarations and control directives."endendVALID_PROP_CHILDREN=CONTROL_NODES+[Sass::Tree::CommentNode,Sass::Tree::PropNode,Sass::Tree::MixinNode]definvalid_prop_child?(parent,child)unlessis_any_of?(child,VALID_PROP_CHILDREN)"Illegal nesting: Only properties may be nested beneath properties."endendVALID_PROP_PARENTS=[Sass::Tree::RuleNode,Sass::Tree::PropNode,Sass::Tree::MixinDefNode,Sass::Tree::DirectiveNode,Sass::Tree::MixinNode]definvalid_prop_parent?(parent,child)unlessis_any_of?(parent,VALID_PROP_PARENTS)"Properties are only allowed within rules, directives, mixin includes, or other properties."+child.pseudo_class_selector_messageendenddefinvalid_return_parent?(parent,child)"@return may only be used within a function."unlessparent.is_a?(Sass::Tree::FunctionNode)endprivate# Whether `parent` should be assigned to `@parent`.deftransparent_parent?(parent,grandparent)is_any_of?(parent,SCRIPT_NODES)||(parent.bubbles?&&!grandparent.is_a?(Sass::Tree::RootNode)&&!grandparent.is_a?(Sass::Tree::AtRootNode))enddefis_any_of?(val,classes)classes.eachdo|c|returntrueifval.is_a?(c)endfalseenddeftry_send(method,*args)returnunlessrespond_to?(method,true)send(method,*args)endend