Class: HamlLint::RubyExtractor
- Inherits:
-
Object
- Object
- HamlLint::RubyExtractor
- Includes:
- HamlVisitor
- Defined in:
- lib/haml_lint/ruby_extractor.rb
Overview
Utility class for extracting Ruby script from a HAML file that can then be linted with a Ruby linter (i.e. is “legal” Ruby). The goal is to turn this:
- if signed_in?(viewer)
%span Stuff
= link_to 'Sign Out', sign_out_path
- else
.some-class{ class: my_method }= my_method
= link_to 'Sign In', sign_in_path
into this:
if signed_in?(viewer)
link_to 'Sign Out', sign_out_path
else
{ class: my_method }
my_method
link_to 'Sign In', sign_in_path
end
The translation won’t be perfect, and won’t make any real sense, but the relationship between variable declarations/uses and the flow control graph will remain intact.
Defined Under Namespace
Classes: RubySource
Instance Method Summary collapse
- #after_visit_tag(node) ⇒ Object
-
#extract(document) ⇒ HamlLint::RubyExtractor::RubySource
Extracts Ruby code from Sexp representing a Slim document.
- #visit_filter(node) ⇒ Object
- #visit_haml_comment(node) ⇒ Object
- #visit_plain(node) ⇒ Object
- #visit_root(_node) ⇒ Object
- #visit_script(node) ⇒ Object
- #visit_silent_script(node, &block) ⇒ Object
- #visit_tag(node) ⇒ Object
Methods included from HamlVisitor
Instance Method Details
#after_visit_tag(node) ⇒ Object
90 91 92 93 |
# File 'lib/haml_lint/ruby_extractor.rb', line 90 def after_visit_tag(node) # We add a dummy puts statement for closing tag. add_dummy_puts(node, "#{node.tag_name}/") end |
#extract(document) ⇒ HamlLint::RubyExtractor::RubySource
Extracts Ruby code from Sexp representing a Slim document.
42 43 44 45 |
# File 'lib/haml_lint/ruby_extractor.rb', line 42 def extract(document) visit(document.tree) RubySource.new(@source_lines.join("\n"), @source_map) end |
#visit_filter(node) ⇒ Object
127 128 129 130 131 132 133 134 135 136 137 138 |
# File 'lib/haml_lint/ruby_extractor.rb', line 127 def visit_filter(node) if node.filter_type == 'ruby' node.text.split("\n").each_with_index do |line, index| add_line(line, node.line + index + 1, false) end else add_dummy_puts(node, ":#{node.filter_type}") HamlLint::Utils.extract_interpolated_values(node.text) do |interpolated_code, line| add_line(interpolated_code, node.line + line) end end end |
#visit_haml_comment(node) ⇒ Object
113 114 115 116 117 118 119 120 121 |
# File 'lib/haml_lint/ruby_extractor.rb', line 113 def visit_haml_comment(node) # We want to preseve leading whitespace if it exists, but include leading # whitespace if it doesn't exist so that RuboCop's LeadingCommentSpace # doesn't complain comment = node.text .gsub(/\n(\S)/, "\n# \\1") .gsub(/\n(\s)/, "\n#\\1") add_line("##{comment}", node) end |
#visit_plain(node) ⇒ Object
57 58 59 60 61 62 |
# File 'lib/haml_lint/ruby_extractor.rb', line 57 def visit_plain(node) # Don't output the text, as we don't want to have to deal with any RuboCop # cops regarding StringQuotes or AsciiComments, and it's not important to # overall document anyway. add_dummy_puts(node) end |
#visit_root(_node) ⇒ Object
47 48 49 50 51 52 53 54 55 |
# File 'lib/haml_lint/ruby_extractor.rb', line 47 def visit_root(_node) @source_lines = [] @source_map = {} @line_count = 0 @indent_level = 0 @output_count = 0 yield # Collect lines of code from children end |
#visit_script(node) ⇒ Object
95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 |
# File 'lib/haml_lint/ruby_extractor.rb', line 95 def visit_script(node) code = node.text add_line(code.strip, node) start_block = anonymous_block?(code) || start_block_keyword?(code) if start_block @indent_level += 1 end yield # Continue extracting code from children if start_block @indent_level -= 1 add_line('end', node) end end |
#visit_silent_script(node, &block) ⇒ Object
123 124 125 |
# File 'lib/haml_lint/ruby_extractor.rb', line 123 def visit_silent_script(node, &block) visit_script(node, &block) end |
#visit_tag(node) ⇒ Object
64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 |
# File 'lib/haml_lint/ruby_extractor.rb', line 64 def visit_tag(node) additional_attributes = node.dynamic_attributes_sources # Include dummy references to code executed in attributes list # (this forces a "use" of a variable to prevent "assigned but unused # variable" lints) additional_attributes.each do |attributes_code| # Normalize by removing excess whitespace to avoid format lints attributes_code = attributes_code.gsub(/\s*\n\s*/, ' ').strip # Attributes can either be a method call or a literal hash, so wrap it # in a method call itself in order to avoid having to differentiate the # two. add_line("{}.merge(#{attributes_code.strip})", node) end check_tag_static_hash_source(node) # We add a dummy puts statement to represent the tag name being output. # This prevents some erroneous RuboCop warnings. add_dummy_puts(node, node.tag_name) code = node.script.strip add_line(code, node) unless code.empty? end |