Class: DeadEnd::CodeBlock

Inherits:
Object
  • Object
show all
Defined in:
lib/dead_end/code_block.rb

Overview

Multiple lines form a singular CodeBlock

Source code is made of multiple CodeBlocks.

Example:

code_block.to_s # =>
  #   def foo
  #     puts "foo"
  #   end

code_block.valid? # => true
code_block.in_valid? # => false

Constant Summary collapse

UNSET =
Object.new.freeze

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(lines: []) ⇒ CodeBlock

Returns a new instance of CodeBlock.



23
24
25
26
# File 'lib/dead_end/code_block.rb', line 23

def initialize(lines: [])
  @lines = Array(lines)
  @valid = UNSET
end

Instance Attribute Details

#linesObject (readonly)

Returns the value of attribute lines.



21
22
23
# File 'lib/dead_end/code_block.rb', line 21

def lines
  @lines
end

Instance Method Details

#<=>(other) ⇒ Object

This is used for frontier ordering, we are searching from the largest indentation to the smallest. This allows us to populate an array with multiple code blocks then call sort! on it without having to specify the sorting criteria



56
57
58
59
60
61
62
# File 'lib/dead_end/code_block.rb', line 56

def <=>(other)
  out = current_indent <=> other.current_indent
  return out if out != 0

  # Stable sort
  starts_at <=> other.starts_at
end

#current_indentObject



64
65
66
# File 'lib/dead_end/code_block.rb', line 64

def current_indent
  @current_indent ||= lines.select(&:not_empty?).map(&:indent).min || 0
end

#ends_atObject



48
49
50
# File 'lib/dead_end/code_block.rb', line 48

def ends_at
  @ends_at ||= @lines.last&.line_number
end

#hidden?Boolean

Returns:

  • (Boolean)


40
41
42
# File 'lib/dead_end/code_block.rb', line 40

def hidden?
  @lines.all?(&:hidden?)
end

#invalid?Boolean

Returns:

  • (Boolean)


68
69
70
# File 'lib/dead_end/code_block.rb', line 68

def invalid?
  !valid?
end

#is_end?Boolean

Returns:

  • (Boolean)


36
37
38
# File 'lib/dead_end/code_block.rb', line 36

def is_end?
  to_s.strip == "end"
end

#mark_invisibleObject



32
33
34
# File 'lib/dead_end/code_block.rb', line 32

def mark_invisible
  @lines.map(&:mark_invisible)
end

#starts_atObject



44
45
46
# File 'lib/dead_end/code_block.rb', line 44

def starts_at
  @starts_at ||= @lines.first&.line_number
end

#to_sObject



93
94
95
# File 'lib/dead_end/code_block.rb', line 93

def to_s
  @lines.join
end

#valid?Boolean

Returns:

  • (Boolean)


72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
# File 'lib/dead_end/code_block.rb', line 72

def valid?
  if @valid == UNSET
    # Performance optimization
    #
    # If all the lines were previously hidden
    # and we expand to capture additional empty
    # lines then the result cannot be invalid
    #
    # That means there's no reason to re-check all
    # lines with ripper (which is expensive).
    # Benchmark in commit message
    @valid = if lines.all? { |l| l.hidden? || l.empty? }
      true
    else
      DeadEnd.valid?(lines.map(&:original).join)
    end
  else
    @valid
  end
end

#visible_linesObject



28
29
30
# File 'lib/dead_end/code_block.rb', line 28

def visible_lines
  @lines.select(&:visible?).select(&:not_empty?)
end