# A visitor for checking that all nodes are properly nested.classSass::Tree::Visitors::CheckNesting<Sass::Tree::Visitors::Baseprotecteddefinitialize@parents=[]enddefvisit(node)iferror=@parent&&(try_send("invalid_#{node_name@parent}_child?",@parent,node)||try_send("invalid_#{node_namenode}_parent?",@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@parent=parentunlessis_any_of?(parent,SCRIPT_NODES)@parents.pushparentsuperensure@parent=old_parent@parents.popenddefvisit_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."endenddefinvalid_function_parent?(parent,child)"Functions may only be defined at the root of a document."unlessparent.is_a?(Sass::Tree::RootNode)endVALID_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."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?# If this is a nested @import, we need to make sure it doesn't have anything# that's legal at top-level but not in the current context (e.g. mixin defs).child.imported_file.to_tree.children.each{|c|visit(c)}nilrescueSass::SyntaxError=>ee.modify_backtrace(:filename=>child.imported_file.options[:filename])e.add_backtrace(:filename=>child.filename,:line=>child.line)raiseeenddefinvalid_mixindef_parent?(parent,child)"Mixins may only be defined at the root of a document."unlessparent.is_a?(Sass::Tree::RootNode)endVALID_PROP_CHILDREN=[Sass::Tree::CommentNode,Sass::Tree::PropNode,Sass::Tree::MixinNode]+CONTROL_NODESdefinvalid_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)endprivatedefis_any_of?(val,classes)forcinclassesreturntrueifval.is_a?(c)endreturnfalseenddeftry_send(method,*args)returnunlessrespond_to?(method)send(method,*args)endend