Class: SyntaxSuggest::BlockExpand
- Inherits:
-
Object
- Object
- SyntaxSuggest::BlockExpand
- Defined in:
- lib/syntax_suggest/block_expand.rb
Overview
This class is responsible for taking a code block that exists at a far indentaion and then iteratively increasing the block so that it captures everything within the same indentation block.
def dog
puts "bow"
puts "wow"
end
block = BlockExpand.new(code_lines: code_lines)
.call(CodeBlock.new(lines: code_lines[1]))
puts block.to_s # => puts “bow”
puts "wow"
Once a code block has captured everything at a given indentation level then it will expand to capture surrounding indentation.
block = BlockExpand.new(code_lines: code_lines)
.call(block)
block.to_s # => def dog
puts "bow"
puts "wow"
end
Instance Method Summary collapse
-
#call(block) ⇒ Object
Main interface.
-
#expand_indent(block) ⇒ Object
Expands code to the next lowest indentation.
-
#expand_neighbors(block) ⇒ Object
A neighbor is code that is at or above the current indent line.
-
#initialize(code_lines:) ⇒ BlockExpand
constructor
A new instance of BlockExpand.
-
#inspect ⇒ Object
Manageable rspec errors.
Constructor Details
#initialize(code_lines:) ⇒ BlockExpand
Returns a new instance of BlockExpand.
34 35 36 |
# File 'lib/syntax_suggest/block_expand.rb', line 34 def initialize(code_lines:) @code_lines = code_lines end |
Instance Method Details
#call(block) ⇒ Object
Main interface. Expand current indentation, before expanding to a lower indentation
40 41 42 43 44 45 46 |
# File 'lib/syntax_suggest/block_expand.rb', line 40 def call(block) if (next_block = (block)) next_block else (block) end end |
#expand_indent(block) ⇒ Object
Expands code to the next lowest indentation
For example:
1 def dog
2 print "dog"
3 end
If a block starts on line 2 then it has captured all it’s “neighbors” (code at the same indentation or higher). To continue expanding, this block must capture lines one and three which are at a different indentation level.
This method allows fully expanded blocks to decrease their indentation level (so they can expand to capture more code up and down). It does this conservatively as there’s no undo (currently).
63 64 65 66 67 68 69 70 71 72 |
# File 'lib/syntax_suggest/block_expand.rb', line 63 def (block) now = AroundBlockScan.new(code_lines: @code_lines, block: block) .force_add_hidden .stop_after_kw .scan_adjacent_indent now.lookahead_balance_one_line now.code_block end |
#expand_neighbors(block) ⇒ Object
A neighbor is code that is at or above the current indent line.
First we build a block with all neighbors. If we can’t go further then we decrease the indentation threshold and expand via indentation i.e. ‘expand_indent`
Handles two general cases.
## Case #1: Check code inside of methods/classes/etc.
It’s important to note, that not everything in a given indentation level can be parsed as valid code even if it’s part of valid code. For example:
1 hash = {
2 name: "richard",
3 dog: "cinco",
4 }
In this case lines 2 and 3 will be neighbors, but they’re invalid until ‘expand_indent` is called on them.
When we are adding code within a method or class (at the same indentation level), use the empty lines to denote the programmer intended logical chunks. Stop and check each one. For example:
1 def dog
2 print "dog"
3
4 hash = {
5 end
If we did not stop parsing at empty newlines then the block might mistakenly grab all the contents (lines 2, 3, and 4) and report them as being problems, instead of only line 4.
## Case #2: Expand/grab other logical blocks
Once the search algorithm has converted all lines into blocks at a given indentation it will then ‘expand_indent`. Once the blocks that generates are expanded as neighbors we then begin seeing neighbors being other logical blocks i.e. a block’s neighbors may be another method or class (something with keywords/ends).
For example:
1 def bark
2
3 end
4
5 def sit
6 end
In this case if lines 4, 5, and 6 are in a block when it tries to expand neighbors it will expand up. If it stops after line 2 or 3 it may cause problems since there’s a valid kw/end pair, but the block will be checked without it.
We try to resolve this edge case with ‘lookahead_balance_one_line` below.
130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 |
# File 'lib/syntax_suggest/block_expand.rb', line 130 def (block) now = AroundBlockScan.new(code_lines: @code_lines, block: block) # Initial scan now .force_add_hidden .stop_after_kw .scan_neighbors_not_empty # Slurp up empties now .scan_while { |line| line.empty? } # If next line is kw and it will balance us, take it = now .lookahead_balance_one_line .lines # Don't allocate a block if it won't be used # # If nothing was taken, return nil to indicate that status # used in `def call` to determine if # we need to expand up/out (`expand_indent`) if block.lines == nil else CodeBlock.new(lines: ) end end |
#inspect ⇒ Object
Manageable rspec errors
161 162 163 |
# File 'lib/syntax_suggest/block_expand.rb', line 161 def inspect "#<SyntaxSuggest::CodeBlock:0x0000123843lol >" end |