class ERBLint::Linters::RequireInputAutocomplete

Constants

FORM_HELPERS_REQUIRING_AUTOCOMPLETE
HTML_INPUT_TYPES_REQUIRING_AUTOCOMPLETE

Public Instance Methods

run(processed_source) click to toggle source
# File lib/erb_lint/linters/require_input_autocomplete.rb, line 44
def run(processed_source)
  parser = processed_source.parser

  find_html_input_tags(parser)
  find_rails_helper_input_tags(parser)
end

Private Instance Methods

autocomplete_present?(autocomplete_attribute) click to toggle source
# File lib/erb_lint/linters/require_input_autocomplete.rb, line 72
def autocomplete_present?(autocomplete_attribute)
  autocomplete_attribute.present? && autocomplete_attribute.value_node.present?
end
code_comment?(indicator_node) click to toggle source
# File lib/erb_lint/linters/require_input_autocomplete.rb, line 110
def code_comment?(indicator_node)
  indicator_node&.loc&.source == "#"
end
extract_ruby_node(source) click to toggle source
# File lib/erb_lint/linters/require_input_autocomplete.rb, line 114
def extract_ruby_node(source)
  BetterHtml::TestHelper::RubyNode.parse(source)
rescue ::Parser::SyntaxError
  nil
end
find_html_input_tags(parser) click to toggle source
# File lib/erb_lint/linters/require_input_autocomplete.rb, line 53
def find_html_input_tags(parser)
  parser.nodes_with_type(:tag).each do |tag_node|
    tag = BetterHtml::Tree::Tag.from_node(tag_node)

    autocomplete_attribute = tag.attributes["autocomplete"]
    type_attribute = tag.attributes["type"]

    next if !html_input_tag?(tag) || autocomplete_present?(autocomplete_attribute)
    next unless html_type_requires_autocomplete_attribute?(type_attribute)

    add_offense(
      tag_node.to_a[1].loc,
      "Input tag is missing an autocomplete attribute. If no "\
      "autocomplete behaviour is desired, use the value `off` or `nope`.",
      [autocomplete_attribute]
    )
  end
end
find_rails_helper_input_tags(parser) click to toggle source
# File lib/erb_lint/linters/require_input_autocomplete.rb, line 85
def find_rails_helper_input_tags(parser)
  parser.ast.descendants(:erb).each do |erb_node|
    indicator_node, _, code_node, _ = *erb_node
    source = code_node.loc.source
    ruby_node = extract_ruby_node(source)
    send_node = ruby_node&.descendants(:send)&.first

    next if code_comment?(indicator_node) ||
      !ruby_node ||
      !input_helper?(send_node) ||
      source.include?("autocomplete")

    add_offense(
      erb_node.loc,
      "Input field helper is missing an autocomplete attribute. If no "\
      "autocomplete behaviour is desired, use the value `off` or `nope`.",
      [erb_node, send_node]
    )
  end
end
html_input_tag?(tag) click to toggle source
# File lib/erb_lint/linters/require_input_autocomplete.rb, line 76
def html_input_tag?(tag)
  !tag.closing? && tag.name == "input"
end
html_type_requires_autocomplete_attribute?(type_attribute) click to toggle source
# File lib/erb_lint/linters/require_input_autocomplete.rb, line 80
def html_type_requires_autocomplete_attribute?(type_attribute)
  type_present = type_attribute.present? && type_attribute.value_node.present?
  type_present && HTML_INPUT_TYPES_REQUIRING_AUTOCOMPLETE.include?(type_attribute.value)
end
input_helper?(send_node) click to toggle source
# File lib/erb_lint/linters/require_input_autocomplete.rb, line 106
def input_helper?(send_node)
  FORM_HELPERS_REQUIRING_AUTOCOMPLETE.include?(send_node&.method_name)
end