Method: SyntaxSuggest::BlockExpand#expand_neighbors

Defined in:
lib/syntax_suggest/block_expand.rb

#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 expand_neighbors(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
  expanded_lines = 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 == expanded_lines
    nil
  else
    CodeBlock.new(lines: expanded_lines)
  end
end