Class: Hone::Patterns::StringConcatInLoop

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

Overview

Pattern: String concatenation (+=) inside a loop -> use << or array join

Each string += operation creates a new string object, copying all previous content. In a loop, this leads to O(n^2) memory allocations and copies. Using << mutates the string in place, avoiding allocations.

Example:

# Bad - O(n^2) allocations
items.each { |item| result += item.to_s }

# Good - O(n) with in-place mutation
items.each { |item| result << item.to_s }

# Good - collect and join once
result = items.map(&:to_s).join

Impact: Significant in tight loops, avoids O(n^2) string copying

Constant Summary collapse

LOOP_METHODS =
i[each each_with_index each_with_object map collect
times upto downto step loop].freeze

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) ⇒ StringConcatInLoop

Returns a new instance of StringConcatInLoop.



29
30
31
32
# File 'lib/hone/patterns/string_concat_in_loop.rb', line 29

def initialize(file_path)
  super
  @in_loop = false
end

Instance Method Details

#visit_call_node(node) ⇒ Object

Handle block-based loops (.each, .times, .map, loop, etc.)



50
51
52
53
54
55
56
# File 'lib/hone/patterns/string_concat_in_loop.rb', line 50

def visit_call_node(node)
  if loop_method?(node) && node.block
    with_context(:@in_loop, true) { super }
  else
    super
  end
end

#visit_class_variable_operator_write_node(node) ⇒ Object

Detect class variable += (e.g., @@str += "x")



71
72
73
74
# File 'lib/hone/patterns/string_concat_in_loop.rb', line 71

def visit_class_variable_operator_write_node(node)
  check_string_concat(node)
  super
end

#visit_for_node(node) ⇒ Object

Track when we enter/exit for loops



45
46
47
# File 'lib/hone/patterns/string_concat_in_loop.rb', line 45

def visit_for_node(node)
  with_context(:@in_loop, true) { super }
end

#visit_global_variable_operator_write_node(node) ⇒ Object

Detect global variable += (e.g., $str += "x")



77
78
79
80
# File 'lib/hone/patterns/string_concat_in_loop.rb', line 77

def visit_global_variable_operator_write_node(node)
  check_string_concat(node)
  super
end

#visit_instance_variable_operator_write_node(node) ⇒ Object

Detect instance variable += (e.g., @str += "x")



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

def visit_instance_variable_operator_write_node(node)
  check_string_concat(node)
  super
end

#visit_local_variable_operator_write_node(node) ⇒ Object

Detect local variable += (e.g., str += "x")



59
60
61
62
# File 'lib/hone/patterns/string_concat_in_loop.rb', line 59

def visit_local_variable_operator_write_node(node)
  check_string_concat(node)
  super
end

#visit_until_node(node) ⇒ Object

Track when we enter/exit until loops



40
41
42
# File 'lib/hone/patterns/string_concat_in_loop.rb', line 40

def visit_until_node(node)
  with_context(:@in_loop, true) { super }
end

#visit_while_node(node) ⇒ Object

Track when we enter/exit while loops



35
36
37
# File 'lib/hone/patterns/string_concat_in_loop.rb', line 35

def visit_while_node(node)
  with_context(:@in_loop, true) { super }
end