gems.scss-lint-0.34.0.lib.scss_lint.control_comment_processor.rb Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of sass-maven-plugin Show documentation
Show all versions of sass-maven-plugin Show documentation
A Maven Plugin that compiles Sass files.
require 'set'
module SCSSLint
# Tracks which lines have been disabled for a given linter.
class ControlCommentProcessor
def initialize(linter)
@disable_stack = []
@disabled_lines = Set.new
@linter = linter
end
# Filter lints given the comments that were processed in the document.
#
# @param lints [Array]
def filter_lints(lints)
lints.reject { |lint| @disabled_lines.include?(lint.location.line) }
end
# Executed before a node has been visited.
#
# @param node [Sass::Tree::Node]
def before_node_visit(node)
return unless command = extract_command(node)
linters = command[:linters]
return unless linters.include?('all') || linters.include?(@linter.name)
process_command(command[:action], node)
# Is the control comment the only thing on this line?
return if node.is_a?(Sass::Tree::RuleNode) ||
%r{^\s*(//|/\*)}.match(@linter.engine.lines[node.line - 1])
# Otherwise, pop since we only want comment to apply to the single line
pop_control_comment_stack(node)
end
# Executed after a node has been visited.
#
# @param node [Sass::Tree::Node]
def after_node_visit(node)
while @disable_stack.any? && @disable_stack.last.node_parent == node
pop_control_comment_stack(node)
end
end
private
def extract_command(node)
comment =
case node
when Sass::Tree::CommentNode
node.value.first
when Sass::Tree::RuleNode
node.rule.select { |chunk| chunk.is_a?(String) }.join
end
return unless match = %r{
(/|\*)\s* # Comment start marker
scss-lint:
(?disable|enable)\s+
(?.*?)
\s*(?:\*/|\n) # Comment end marker or end of line
}x.match(comment)
{
action: match[:action],
linters: match[:linters].split(/\s*,\s*|\s+/),
}
end
def process_command(command, node)
case command
when 'disable'
@disable_stack << node
when 'enable'
pop_control_comment_stack(node)
end
end
def pop_control_comment_stack(node)
return unless comment_node = @disable_stack.pop
start_line = comment_node.line
# Find the deepest child that has a line number to which a lint might
# apply (if it is a control comment enable node, it will be the line of
# the comment itself).
child = node
prev_child = node
while (child = last_child(child)) != prev_child
prev_child = child
end
end_line = child.line
@disabled_lines.merge(start_line..end_line)
end
# Gets the child of the node that resides on the lowest line in the file.
#
# This is necessary due to the fact that our monkey patching of the parse
# tree's {#children} method does not return nodes sorted by their line
# number.
#
# @param node [Sass::Tree::Node, Sass::Script::Tree::Node]
# @return [Sass::Tree::Node, Sass::Script::Tree::Node]
def last_child(node)
node.children.inject(node) do |lowest, child|
return lowest unless child.respond_to?(:line)
lowest.line < child.line ? child : lowest
end
end
end
end
© 2015 - 2025 Weber Informatics LLC | Privacy Policy