Class: Sass::Tree::Visitors::CheckNesting

Inherits:
Base
  • Object
show all
Defined in:
lib/sass/tree/visitors/check_nesting.rb

Overview

A visitor for checking that all nodes are properly nested.

Constant Summary collapse

CONTROL_NODES =
[Sass::Tree::EachNode, Sass::Tree::ForNode, Sass::Tree::IfNode,
Sass::Tree::WhileNode, Sass::Tree::TraceNode]
SCRIPT_NODES =
[Sass::Tree::ImportNode] + CONTROL_NODES
VALID_EXTEND_PARENTS =
[Sass::Tree::RuleNode, Sass::Tree::MixinDefNode, Sass::Tree::MixinNode]
INVALID_IMPORT_PARENTS =
CONTROL_NODES +
[Sass::Tree::MixinDefNode, Sass::Tree::MixinNode]
VALID_FUNCTION_CHILDREN =
[
  Sass::Tree::CommentNode,  Sass::Tree::DebugNode, Sass::Tree::ReturnNode,
  Sass::Tree::VariableNode, Sass::Tree::WarnNode
] + CONTROL_NODES
VALID_PROP_CHILDREN =
CONTROL_NODES + [Sass::Tree::CommentNode,
Sass::Tree::PropNode,
Sass::Tree::MixinNode]
VALID_PROP_PARENTS =
[Sass::Tree::RuleNode, Sass::Tree::PropNode,
Sass::Tree::MixinDefNode, Sass::Tree::DirectiveNode,
Sass::Tree::MixinNode]

Instance Method Summary collapse

Methods inherited from Base

node_name, visit, #visit_if

Constructor Details

#initializeCheckNesting (protected)

Returns a new instance of CheckNesting.



5
6
7
# File 'lib/sass/tree/visitors/check_nesting.rb', line 5

def initialize
  @parents = []
end

Instance Method Details

#invalid_charset_parent?(parent, child) ⇒ Boolean (protected)

Returns:

  • (Boolean)


70
71
72
# File 'lib/sass/tree/visitors/check_nesting.rb', line 70

def invalid_charset_parent?(parent, child)
  "@charset may only be used at the root of a document." unless parent.is_a?(Sass::Tree::RootNode)
end

#invalid_content_parent?(parent, child) ⇒ Boolean (protected)

Returns:

  • (Boolean)


61
62
63
64
65
66
67
68
# File 'lib/sass/tree/visitors/check_nesting.rb', line 61

def invalid_content_parent?(parent, child)
  if @current_mixin_def
    @current_mixin_def.has_content = true
    nil
  else
    "@content may only be used within a mixin."
  end
end

#invalid_extend_parent?(parent, child) ⇒ Boolean (protected)

Returns:

  • (Boolean)


75
76
77
78
79
# File 'lib/sass/tree/visitors/check_nesting.rb', line 75

def invalid_extend_parent?(parent, child)
  unless is_any_of?(parent, VALID_EXTEND_PARENTS)
    return "Extend directives may only be used within rules."
  end
end

#invalid_function_child?(parent, child) ⇒ Boolean (protected)

Returns:

  • (Boolean)


111
112
113
114
115
# File 'lib/sass/tree/visitors/check_nesting.rb', line 111

def invalid_function_child?(parent, child)
  unless is_any_of?(child, VALID_FUNCTION_CHILDREN)
    "Functions can only contain variable declarations and control directives."
  end
end

#invalid_function_parent?(parent, child) ⇒ Boolean (protected)

Returns:

  • (Boolean)


101
102
103
104
105
# File 'lib/sass/tree/visitors/check_nesting.rb', line 101

def invalid_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."
  end
end

#invalid_import_parent?(parent, child) ⇒ Boolean (protected)

Returns:

  • (Boolean)


83
84
85
86
87
88
89
90
91
92
93
# File 'lib/sass/tree/visitors/check_nesting.rb', line 83

def invalid_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."
  end
  return if parent.is_a?(Sass::Tree::RootNode)
  return "CSS import directives may only be used at the root of a document." if child.css_import?
rescue Sass::SyntaxError => e
  e.modify_backtrace(:filename => child.imported_file.options[:filename])
  e.add_backtrace(:filename => child.filename, :line => child.line)
  raise e
end

#invalid_mixindef_parent?(parent, child) ⇒ Boolean (protected)

Returns:

  • (Boolean)


95
96
97
98
99
# File 'lib/sass/tree/visitors/check_nesting.rb', line 95

def invalid_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."
  end
end

#invalid_prop_child?(parent, child) ⇒ Boolean (protected)

Returns:

  • (Boolean)


120
121
122
123
124
# File 'lib/sass/tree/visitors/check_nesting.rb', line 120

def invalid_prop_child?(parent, child)
  unless is_any_of?(child, VALID_PROP_CHILDREN)
    "Illegal nesting: Only properties may be nested beneath properties."
  end
end

#invalid_prop_parent?(parent, child) ⇒ Boolean (protected)

Returns:

  • (Boolean)


129
130
131
132
133
134
# File 'lib/sass/tree/visitors/check_nesting.rb', line 129

def invalid_prop_parent?(parent, child)
  unless is_any_of?(parent, VALID_PROP_PARENTS)
    "Properties are only allowed within rules, directives, mixin includes, or other properties." +
      child.pseudo_class_selector_message
  end
end

#invalid_return_parent?(parent, child) ⇒ Boolean (protected)

Returns:

  • (Boolean)


136
137
138
# File 'lib/sass/tree/visitors/check_nesting.rb', line 136

def invalid_return_parent?(parent, child)
  "@return may only be used within a function." unless parent.is_a?(Sass::Tree::FunctionNode)
end

#visit(node) (protected)



9
10
11
12
13
14
15
16
17
18
19
# File 'lib/sass/tree/visitors/check_nesting.rb', line 9

def visit(node)
  if (error = @parent && (
      try_send(@parent.class.invalid_child_method_name, @parent, node) ||
      try_send(node.class.invalid_parent_method_name, @parent, node)))
    raise Sass::SyntaxError.new(error)
  end
  super
rescue Sass::SyntaxError => e
  e.modify_backtrace(:filename => node.filename, :line => node.line)
  raise e
end

#visit_children(parent) (protected)



24
25
26
27
28
29
30
31
32
33
34
35
36
37
# File 'lib/sass/tree/visitors/check_nesting.rb', line 24

def visit_children(parent)
  old_parent = @parent
  unless is_any_of?(parent, SCRIPT_NODES) ||
      (parent.bubbles? &&
      !old_parent.is_a?(Sass::Tree::RootNode) &&
      !old_parent.is_a?(Sass::Tree::AtRootNode))
    @parent = parent
  end
  @parents.push parent
  super
ensure
  @parent = old_parent
  @parents.pop
end

#visit_import(node) (protected)



46
47
48
49
50
51
52
# File 'lib/sass/tree/visitors/check_nesting.rb', line 46

def visit_import(node)
  yield
rescue Sass::SyntaxError => e
  e.modify_backtrace(:filename => node.children.first.filename)
  e.add_backtrace(:filename => node.filename, :line => node.line)
  raise e
end

#visit_mixindef(node) (protected)



54
55
56
57
58
59
# File 'lib/sass/tree/visitors/check_nesting.rb', line 54

def visit_mixindef(node)
  @current_mixin_def, old_mixin_def = node, @current_mixin_def
  yield
ensure
  @current_mixin_def = old_mixin_def
end

#visit_root(node) (protected)



39
40
41
42
43
44
# File 'lib/sass/tree/visitors/check_nesting.rb', line 39

def visit_root(node)
  yield
rescue Sass::SyntaxError => e
  e.sass_template ||= node.template
  raise e
end