class SyntaxSuggest::CaptureCodeContext
Verwandelt „ungültige(n) Block(s)“ in nützlichen Kontext
Es gibt drei Hauptphasen im Algorithmus
-
Bereinigung/Formatierung des Eingabequellcodes
-
Suche nach ungültigen Blöcken
-
Formatierung ungültiger Blöcke in etwas Sinnvolles
Diese Klasse behandelt den dritten Teil.
Der Algorithmus ist sehr gut darin, einen Syntaxfehler in einem einzigen Block unter Nummer 2 zu erfassen, jedoch können die Ergebnisse Mehrdeutigkeiten enthalten. Menschen sind gut im Mustererkennung und Filtern und können unwesentliche Daten mental entfernen, aber sie können keine zusätzlichen Daten hinzufügen, die nicht vorhanden sind.
In Fällen bekannter mehrdeutiger Fälle fügt diese Klasse Kontext zur Mehrdeutigkeit hinzu, damit der Programmierer vollständige Informationen hat.
Über die Behandlung dieser Mehrdeutigkeiten hinaus erfasst sie auch Informationen über den umliegenden Codekontext
puts block.to_s # => "def bark"
context = CaptureCodeContext.new(
blocks: block,
code_lines: code_lines
)
lines = context.call.map(&:original)
puts lines.join
# =>
class Dog
def bark
end
Attribute
Öffentliche Klassenmethoden
Source
# File lib/syntax_suggest/capture_code_context.rb, line 51 def initialize(blocks:, code_lines:) @blocks = Array(blocks) @code_lines = code_lines @visible_lines = @blocks.map(&:visible_lines).flatten @lines_to_output = @visible_lines.dup end
Öffentliche Instanzmethoden
Source
# File lib/syntax_suggest/capture_code_context.rb, line 58 def call @blocks.each do |block| capture_first_kw_end_same_indent(block) capture_last_end_same_indent(block) capture_before_after_kws(block) capture_falling_indent(block) end sorted_lines end
Source
# File lib/syntax_suggest/capture_code_context.rb, line 127 def capture_before_after_kws(block) return unless block.visible_lines.count == 1 around_lines = Capture::BeforeAfterKeywordEnds.new( code_lines: @code_lines, block: block ).call around_lines -= block.lines @lines_to_output.concat(around_lines) end
Zeigt umliegende Schlüsselwort/end-Paare an
Der Zweck der Anzeige dieser zusätzlichen Paare liegt an Fällen von Mehrdeutigkeit, wenn nur eine sichtbare Zeile übereinstimmt.
Zum Beispiel
1 class Dog 2 def bark 4 def eat 5 end 6 end
In diesem Fall fehlt entweder Zeile 2 ein 'end' oder Zeile 4 war eine zusätzliche Zeile, die versehentlich hinzugefügt wurde (es passiert).
Wenn wir das obige Problem erkennen, wird das Problem nur als auf Zeile 2 befindlich angezeigt
2 def bark
Das Anzeigen von „Nachbar“-Schlüsselwortpaaren liefert zusätzlichen Kontext
2 def bark 4 def eat 5 end
Source
# File lib/syntax_suggest/capture_code_context.rb, line 91 def capture_falling_indent(block) Capture::FallingIndentLines.new( block: block, code_lines: @code_lines ).call do |line| @lines_to_output << line end end
Zeigt den Kontext rund um Code an, der durch „fallende“ Einrückung bereitgestellt wird
Konvertiert
it "foo" do
in
class OH
def hello
it "foo" do
end
end
Source
# File lib/syntax_suggest/capture_code_context.rb, line 221 def capture_first_kw_end_same_indent(block) return if block.visible_lines.length != 1 return unless block.visible_lines.first.is_end? visible_line = block.visible_lines.first lines = @code_lines[block.lines.first.index..visible_line.index] matching_kw = lines.reverse.detect { |line| line.indent == block.current_indent && line.is_kw? } return unless matching_kw @lines_to_output << matching_kw kw_count = 0 end_count = 0 orphan_end = @code_lines[matching_kw.index..visible_line.index].detect do |line| kw_count += 1 if line.is_kw? end_count += 1 if line.is_end? end_count >= kw_count end return unless orphan_end @lines_to_output << orphan_end end
Die logische Umkehrung von 'capture_last_end_same_indent`
Wenn ein ungültiger Block mit einem 'end' fehlt, direkt nach einem anderen 'end' fehlt ein Schlüsselwort, ist unklar, welches 'end' das Schlüsselwort vermisst.
Nehmen Sie dieses Beispiel
class Dog # 1
puts "woof" # 2
end # 3
end # 4
Die Problemzeile wird identifiziert als
> end # 4
Dies geschieht, weil die Zeilen 1, 2 und 3 technisch gültiger Code sind und zuerst erweitert, als gültig erachtet und ausgeblendet werden. Wir müssen das übereinstimmende Schlüsselwort in Zeile 1 wieder einblenden. Arbeiten Sie auch rückwärts und zeigen Sie es an, wenn ein nicht übereinstimmendes 'end' vorhanden ist
Source
# File lib/syntax_suggest/capture_code_context.rb, line 161 def capture_last_end_same_indent(block) return if block.visible_lines.length != 1 return unless block.visible_lines.first.is_kw? visible_line = block.visible_lines.first lines = @code_lines[visible_line.index..block.lines.last.index] # Find first end with same indent # (this would return line 4) # # end # 4 matching_end = lines.detect { |line| line.indent == block.current_indent && line.is_end? } return unless matching_end @lines_to_output << matching_end # Work backwards from the end to # see if there are mis-matched # keyword/end pairs # # Return the first mis-matched keyword # this would find line 2 # # def bark # 2 # puts "woof" # 3 # end # 4 end_count = 0 kw_count = 0 kw_line = @code_lines[visible_line.index..matching_end.index].reverse.detect do |line| end_count += 1 if line.is_end? kw_count += 1 if line.is_kw? !kw_count.zero? && kw_count >= end_count end return unless kw_line @lines_to_output << kw_line end
Wenn ein ungültiger Block mit einem Schlüsselwort fehlt, das ein 'end' direkt vor einem anderen 'end' fehlt, ist unklar, welches Schlüsselwort das 'end' vermisst
Nehmen Sie dieses Beispiel
class Dog # 1
def bark # 2
puts "woof" # 3
end # 4
Aufgrund von github.com/ruby/syntax_suggest/issues/32 wird die Problemzeile jedoch identifiziert als
> class Dog # 1
Da die Zeilen 2, 3 und 4 technisch gültiger Code sind und zuerst erweitert, als gültig erachtet und ausgeblendet werden. Wir müssen die übereinstimmende Zeile 4 wieder einblenden. Arbeiten Sie auch rückwärts und zeigen Sie es an, wenn ein nicht übereinstimmendes Schlüsselwort vorhanden ist
Source
# File lib/syntax_suggest/capture_code_context.rb, line 69 def sorted_lines @lines_to_output.select!(&:not_empty?) @lines_to_output.uniq! @lines_to_output.sort! @lines_to_output end