class SyntaxSuggest::CodeLine
Repräsentiert eine einzelne Codezeile einer gegebenen Quelldatei
Dieses Objekt enthält Metadaten zur Zeile, wie z. B. die Einrückungsmenge, ob sie leer ist oder nicht, und lexikalische Daten, wie z. B. ob sie ein „end“ oder ein Schlüsselwort enthält.
Die Sichtbarkeit von Zeilen kann ausgeschaltet werden. Das Markieren einer Zeile als unsichtbar bedeutet, dass sie nicht für Syntaxprüfungen verwendet werden sollte. Es ist funktional dasselbe, als würde man sie auskommentieren.
Beispiel
line = CodeLine.from_source("def foo\n").first line.number => 1 line.empty? # => false line.visible? # => true line.mark_invisible line.visible? # => false
Constants
- TRAILING_SLASH
Attribute
Wenn die Codezeile als unsichtbar markiert ist, behalten wir den ursprünglichen Wert ihrer Zeile bei. Dies ist nützlich für das Debugging und zur Anzeige zusätzlichen Kontexts.
DisplayCodeWithLineNumbers rendert alle an sie übergebenen Zeilen, nicht nur sichtbare Zeilen. Sie verwendet die Methode original, um diese abzurufen.
Öffentliche Klassenmethoden
Source
# File lib/syntax_suggest/code_line.rb, line 29 def self.from_source(source, lines: nil) lines ||= source.lines lex_array_for_line = LexAll.new(source: source, source_lines: lines).each_with_object(Hash.new { |h, k| h[k] = [] }) { |lex, hash| hash[lex.line] << lex } lines.map.with_index do |line, index| CodeLine.new( line: line, index: index, lex: lex_array_for_line[index + 1] ) end end
Gibt ein Array von CodeLine Objekten aus dem Quelltext zurück.
Source
# File lib/syntax_suggest/code_line.rb, line 42 def initialize(line:, index:, lex:) @lex = lex @line = line @index = index @original = line @line_number = @index + 1 strip_line = line.dup strip_line.lstrip! @indent = if (@empty = strip_line.empty?) line.length - 1 # Newline removed from strip_line is not "whitespace" else line.length - strip_line.length end set_kw_end end
Öffentliche Instanzmethoden
Source
# File lib/syntax_suggest/code_line.rb, line 150 def <=>(other) index <=> other.index end
Vergleichsoperator, benötigt für Gleichheit und Sortierung
Source
# File lib/syntax_suggest/code_line.rb, line 115 def empty? @empty end
Eine „leere?“ Zeile ist eine, die ursprünglich im Quellcode leer gelassen wurde, während eine „versteckte“ Zeile eine ist, die wir seitdem als „unsichtbar“ markiert haben.
Source
# File lib/syntax_suggest/code_line.rb, line 172 def ignore_newline_not_beg? @ignore_newline_not_beg end
- Keine stabile API
-
Zeilen, die einen Token vom Typ „on_ignored_nl“ und NICHT vom Typ „BEG“ haben, scheinen ein guter Indikator dafür zu sein, ob mehrere Zeilen zu einer zusammengefügt werden können.
Diese Prädikatmethode wird verwendet, um zu bestimmen, wann diese beiden Kriterien erfüllt sind.
Der einzige bekannte Fall, den dies nicht behandelt, ist
Ripper.lex <<~EOM a && b || c EOM
Aus irgendeinem Grund führt dies zu „on_ignore_newline“, aber mit dem Typ BEG
Source
# File lib/syntax_suggest/code_line.rb, line 72 def indent_index @indent_index ||= [indent, index] end
Wird für stabile Sortierung über die Einrückungsebene verwendet
Rubys Sortierung ist nicht „stabil“, was bedeutet, dass, wenn mehrere Elemente denselben Wert haben, nicht garantiert ist, dass sie in derselben Reihenfolge zurückkehren, in der sie eingefügt wurden.
Wenn also mehrere Codezeilen die gleiche Einrückungsebene haben, werden sie nach ihrem Indexwert sortiert, der eindeutig und konsistent ist.
Dies ist hauptsächlich für die Konsistenz der Testsuite erforderlich
Source
# File lib/syntax_suggest/code_line.rb, line 87 def is_end? @is_end end
Gibt true zurück, wenn die Codezeile als eine ‚end‘-Anweisung enthält bestimmt wird
Source
# File lib/syntax_suggest/code_line.rb, line 81 def is_kw? @is_kw end
Gibt true zurück, wenn die Codezeile als ein Schlüsselwort bestimmt wird, das mit einem ‚end‘ übereinstimmt
Zum Beispiel: ‚def`, `do`, `begin`, `ensure`, etc.
Source
# File lib/syntax_suggest/code_line.rb, line 96 def mark_invisible @line = "" end
Wird verwendet, um Zeilen zu verbergen
Der Suchalgorithmus gruppiert Zeilen in Blöcke, und wenn diese Blöcke als gültiger Code bestimmt werden, werden sie verborgen.
Source
# File lib/syntax_suggest/code_line.rb, line 120 def not_empty? !empty? end
Gegenteil von ‚empty?` (Hinweis: anders als `visible?`)
Source
# File lib/syntax_suggest/code_line.rb, line 133 def to_s line end
Rendert die gegebene Zeile
Ermöglicht uns auch, Quellcode als Array von Codezeilen darzustellen.
Wenn wir ein Array von Codezeilenelementen haben und auf dem Array ‚join` aufrufen, wird für jedes Element ‚to_s` aufgerufen, was es im Wesentlichen zurück in seinen ursprünglichen Quelltext umwandelt.
Source
# File lib/syntax_suggest/code_line.rb, line 184 def trailing_slash? last = @lex.last last&.type == :on_tstring_end end
Source
# File lib/syntax_suggest/code_line.rb, line 103 def visible? !line.empty? end
Bedeutet, dass die Zeile als „unsichtbar“ markiert wurde. Verwirrenderweise sind „leere“ Zeilen sichtbar… sie enthalten nur keinen Quellcode außer einem Zeilenumbruch („n“).
Private Instanzmethoden
Source
# File lib/syntax_suggest/code_line.rb, line 206 def set_kw_end oneliner_count = 0 in_oneliner_def = nil kw_count = 0 end_count = 0 @ignore_newline_not_beg = false @lex.each do |lex| kw_count += 1 if lex.is_kw? end_count += 1 if lex.is_end? if lex.type == :on_ignored_nl @ignore_newline_not_beg = !lex.expr_beg? end if in_oneliner_def.nil? in_oneliner_def = :ENDFN if lex.state.allbits?(Ripper::EXPR_ENDFN) elsif lex.state.allbits?(Ripper::EXPR_ENDFN) # Continue elsif lex.state.allbits?(Ripper::EXPR_BEG) in_oneliner_def = :BODY if lex.token == "=" elsif lex.state.allbits?(Ripper::EXPR_END) # We found an endless method, count it oneliner_count += 1 if in_oneliner_def == :BODY in_oneliner_def = nil else in_oneliner_def = nil end end kw_count -= oneliner_count @is_kw = (kw_count - end_count) > 0 @is_end = (end_count - kw_count) > 0 end
Erkennung von endlosen Anweisungen
Von github.com/ruby/irb/commit/826ae909c9c93a2ddca6f9cfcd9c94dbf53d44ab Die Erkennung eines „Oneliners“ scheint eine Zustandsmaschine zu erfordern. Dies kann durch die Betrachtung des „Zustands“ (letzter Wert) erfolgen.
ENDFN -> BEG (token = '=' ) -> END