Class: Hone::Patterns::RegexpMatch

Inherits:
Base
  • Object
show all
Defined in:
lib/hone/patterns/regexp_match.rb

Overview

Pattern: str =~ /pattern/ or /pattern/.match(str) for boolean -> str.match?(/pattern/)

When the result of =~ or .match is only used for truthiness (in if/unless/ternary), using .match? avoids creating a MatchData object.

Example:

# Bad - creates MatchData object
if str =~ /pattern/
if /pattern/.match(str)

# Good - returns boolean without allocation
if str.match?(/pattern/)

Instance Attribute Summary

Attributes inherited from Base

#findings

Instance Method Summary collapse

Methods inherited from Base

#add_finding, inherited, scan_file

Constructor Details

#initialize(file_path) ⇒ RegexpMatch

Returns a new instance of RegexpMatch.



21
22
23
24
# File 'lib/hone/patterns/regexp_match.rb', line 21

def initialize(file_path)
  super
  @in_boolean_context = false
end

Instance Method Details

#visit_and_node(node) ⇒ Object

Track boolean contexts: && and || operators



60
61
62
63
# File 'lib/hone/patterns/regexp_match.rb', line 60

def visit_and_node(node)
  visit_in_boolean_context(node.left)
  visit_in_boolean_context(node.right)
end

#visit_call_node(node) ⇒ Object



70
71
72
73
74
75
76
# File 'lib/hone/patterns/regexp_match.rb', line 70

def visit_call_node(node)
  super

  if @in_boolean_context
    check_regexp_match(node)
  end
end

#visit_if_node(node) ⇒ Object

Track boolean contexts: if conditions



27
28
29
30
31
# File 'lib/hone/patterns/regexp_match.rb', line 27

def visit_if_node(node)
  visit_in_boolean_context(node.predicate)
  node.statements&.accept(self)
  node.subsequent&.accept(self)
end

#visit_match_last_line_node(node) ⇒ Object

Detect =~ operator (str =~ /pattern/ or /pattern/ =~ str)



79
80
81
82
83
# File 'lib/hone/patterns/regexp_match.rb', line 79

def visit_match_last_line_node(node)
  return unless @in_boolean_context

  add_regexp_finding(node)
end

#visit_match_write_node(node) ⇒ Object



85
86
87
88
89
# File 'lib/hone/patterns/regexp_match.rb', line 85

def visit_match_write_node(node)
  return unless @in_boolean_context

  add_regexp_finding(node)
end

#visit_or_node(node) ⇒ Object



65
66
67
68
# File 'lib/hone/patterns/regexp_match.rb', line 65

def visit_or_node(node)
  visit_in_boolean_context(node.left)
  visit_in_boolean_context(node.right)
end

#visit_ternary_node(node) ⇒ Object

Track boolean contexts: ternary operator condition



53
54
55
56
57
# File 'lib/hone/patterns/regexp_match.rb', line 53

def visit_ternary_node(node)
  visit_in_boolean_context(node.predicate)
  node.true_expression&.accept(self)
  node.false_expression&.accept(self)
end

#visit_unless_node(node) ⇒ Object

Track boolean contexts: unless conditions



34
35
36
37
38
# File 'lib/hone/patterns/regexp_match.rb', line 34

def visit_unless_node(node)
  visit_in_boolean_context(node.predicate)
  node.statements&.accept(self)
  node.else_clause&.accept(self)
end

#visit_until_node(node) ⇒ Object

Track boolean contexts: until conditions



47
48
49
50
# File 'lib/hone/patterns/regexp_match.rb', line 47

def visit_until_node(node)
  visit_in_boolean_context(node.predicate)
  node.statements&.accept(self)
end

#visit_while_node(node) ⇒ Object

Track boolean contexts: while conditions



41
42
43
44
# File 'lib/hone/patterns/regexp_match.rb', line 41

def visit_while_node(node)
  visit_in_boolean_context(node.predicate)
  node.statements&.accept(self)
end