Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Syntax Tree (RubyConf Mini)

Kevin Newton
November 16, 2022
99

Syntax Tree (RubyConf Mini)

Syntax Tree is a new toolkit for interacting with the Ruby parse tree. It can be used to analyze, inspect, debug, and format your Ruby code. In this talk we'll walk through how it works, how to use it in your own applications, and the exciting future possibilities enabled by Syntax Tree.

Kevin Newton

November 16, 2022
Tweet

Transcript

  1. Grammar Parser · Syntax tree · Visitor verb-phrase : VERB

    ADJECTIVE 
 subject-phrase : NOUN verb-phrase
  2. Parser · Syntax tree · Visitor Matz is nice subject

    phrase subject phrase verb phrase we verb phrase are nice
  3. Parser · Syntax tree · Visitor Matz is nice so

    subject phrase subject phrase verb phrase we verb phrase are nice
  4. Grammar Parser · Syntax tree · Visitor verb-phrase : VERB

    ADJECTIVE 
 subject-phrase : NOUN verb-phrase
  5. Grammar Parser · Syntax tree · Visitor verb-phrase : VERB

    ADJECTIVE 
 subject-phrase : NOUN verb-phrase subordinating-conjunction : 
 subject-phrase CONJUNCTION subject-phrase
  6. Parser · Syntax tree · Visitor Matz is nice so

    subject phrase subject phrase verb phrase we verb phrase are nice
  7. Parser · Syntax tree · Visitor Matz is nice so

    subord. conjunction subject phrase subject phrase verb phrase we verb phrase are nice
  8. Parser · Syntax tree · Visitor Matz is nice so

    . subord. conjunction subject phrase subject phrase verb phrase we verb phrase are nice
  9. verb-phrase : VERB ADJECTIVE 
 subject-phrase : NOUN verb-phrase 


    subordinating-conjunction : 
 subject-phrase CONJUNCTION subject-phrase Grammar Parser · Syntax tree · Visitor
  10. verb-phrase : VERB ADJECTIVE 
 subject-phrase : NOUN verb-phrase 


    subordinating-conjunction : 
 subject-phrase CONJUNCTION subject-phrase 
 sentence : subordinating-conjunction PERIOD Grammar Parser · Syntax tree · Visitor
  11. Parser · Syntax tree · Visitor Matz is nice so

    . subord. conjunction subject phrase subject phrase verb phrase we verb phrase are nice
  12. Parser · Syntax tree · Visitor Matz is nice so

    . sentence subord. conjunction subject phrase subject phrase verb phrase we verb phrase are nice
  13. verb-phrase : VERB ADJECTIVE 
 subject-phrase : NOUN verb-phrase 


    subordinating-conjunction : 
 subject-phrase CONJUNCTION subject-phrase 
 sentence : subordinating-conjunction PERIOD Grammar Parser · Syntax tree · Visitor
  14. verb-phrase : VERB ADJECTIVE 
 subject-phrase : NOUN verb-phrase 


    subordinating-conjunction : 
 subject-phrase CONJUNCTION subject-phrase 
 sentence : subordinating-conjunction PERIOD Grammar Parser · Syntax tree · Visitor
  15. Parser · Syntax tree · Visitor verb-phrase : VERB ADJECTIVE

    subject-phrase : NOUN verb-phrase subordinating-conjunction : 
 subject-phrase CONJUNCTION subject-phrase sentence : subordinating-conjunction PERIOD
  16. Parser · Syntax tree · Visitor class VerbPhrase attr_reader :verb,

    :adjective def initialize(verb:, adjective:) @verb = verb @adjective = adjective end end verb-phrase : VERB ADJECTIVE subject-phrase : NOUN verb-phrase subordinating-conjunction : 
 subject-phrase CONJUNCTION subject-phrase sentence : subordinating-conjunction PERIOD
  17. Parser · Syntax tree · Visitor verb-phrase : VERB ADJECTIVE

    subject-phrase : NOUN verb-phrase subordinating-conjunction : 
 subject-phrase CONJUNCTION subject-phrase sentence : subordinating-conjunction PERIOD class VerbPhrase attr_reader :verb, :adjective def initialize(verb:, adjective:) @verb = verb @adjective = adjective end end
  18. Parser · Syntax tree · Visitor class SubjectPhrase attr_reader :noun,

    :verb_phrase def initialize(noun:, verb_phrase:) @noun = noun @verb_phrase = verb_phrase end end verb-phrase : VERB ADJECTIVE subject-phrase : NOUN verb-phrase subordinating-conjunction : 
 subject-phrase CONJUNCTION subject-phrase sentence : subordinating-conjunction PERIOD class VerbPhrase attr_reader :verb, :adjective def initialize(verb:, adjective:) @verb = verb @adjective = adjective end end
  19. Parser · Syntax tree · Visitor verb-phrase : VERB ADJECTIVE

    subject-phrase : NOUN verb-phrase subordinating-conjunction : 
 subject-phrase CONJUNCTION subject-phrase sentence : subordinating-conjunction PERIOD class SubjectPhrase attr_reader :noun, :verb_phrase def initialize(noun:, verb_phrase:) @noun = noun @verb_phrase = verb_phrase end end class VerbPhrase attr_reader :verb, :adjective def initialize(verb:, adjective:) @verb = verb @adjective = adjective end end
  20. Parser · Syntax tree · Visitor verb-phrase : VERB ADJECTIVE

    subject-phrase : NOUN verb-phrase subordinating-conjunction : 
 subject-phrase CONJUNCTION subject-phrase sentence : subordinating-conjunction PERIOD class SubordinatingConjunction attr_reader :left, :conjunction, :right def initialize(left:, conjunction:, right:) @left = left @conjunction = conjunction @right = right end end class SubjectPhrase attr_reader :noun, :verb_phrase def initialize(noun:, verb_phrase:) @noun = noun @verb_phrase = verb_phrase end end class VerbPhrase attr_reader :verb, :adjective def initialize(verb:, adjective:) @verb = verb @adjective = adjective end end
  21. Parser · Syntax tree · Visitor class SubjectPhrase attr_reader :noun,

    :verb_phrase def initialize(noun:, verb_phrase:) @noun = noun @verb_phrase = verb_phrase end end verb-phrase : VERB ADJECTIVE subject-phrase : NOUN verb-phrase subordinating-conjunction : 
 subject-phrase CONJUNCTION subject-phrase sentence : subordinating-conjunction PERIOD class VerbPhrase attr_reader :verb, :adjective def initialize(verb:, adjective:) @verb = verb @adjective = adjective end end class SubordinatingConjunction attr_reader :left, :conjunction, :right def initialize(left:, conjunction:, right:) @left = left @conjunction = conjunction @right = right end end
  22. Parser · Syntax tree · Visitor class SubjectPhrase attr_reader :noun,

    :verb_phrase def initialize(noun:, verb_phrase:) @noun = noun @verb_phrase = verb_phrase end end verb-phrase : VERB ADJECTIVE subject-phrase : NOUN verb-phrase subordinating-conjunction : 
 subject-phrase CONJUNCTION subject-phrase sentence : subordinating-conjunction PERIOD class VerbPhrase attr_reader :verb, :adjective def initialize(verb:, adjective:) @verb = verb @adjective = adjective end end class SubordinatingConjunction attr_reader :left, :conjunction, :right def initialize(left:, conjunction:, right:) @left = left @conjunction = conjunction @right = right end end class Sentence attr_reader :phrase, :punctuation def initialize(phrase:, punctuation:) @phrase = phrase @punctuation = punctuation end end
  23. Parser · Syntax tree · Visitor class SubjectPhrase attr_reader :noun,

    :verb_phrase def initialize(noun:, verb_phrase:) @noun = noun @verb_phrase = verb_phrase end end verb-phrase : VERB ADJECTIVE subject-phrase : NOUN verb-phrase subordinating-conjunction : 
 subject-phrase CONJUNCTION subject-phrase sentence : subordinating-conjunction PERIOD class VerbPhrase attr_reader :verb, :adjective def initialize(verb:, adjective:) @verb = verb @adjective = adjective end end class SubordinatingConjunction attr_reader :left, :conjunction, :right def initialize(left:, conjunction:, right:) @left = left @conjunction = conjunction @right = right end end class Sentence attr_reader :phrase, :punctuation def initialize(phrase:, punctuation:) @phrase = phrase @punctuation = punctuation end end
  24. Parser · Syntax tree · Visitor class SubjectPhrase attr_reader :noun,

    :verb_phrase def initialize(noun:, verb_phrase:) @noun = noun @verb_phrase = verb_phrase end end verb-phrase : VERB ADJECTIVE subject-phrase : NOUN verb-phrase subordinating-conjunction : 
 subject-phrase CONJUNCTION subject-phrase sentence : subordinating-conjunction PERIOD class VerbPhrase attr_reader :verb, :adjective def initialize(verb:, adjective:) @verb = verb @adjective = adjective end end class SubordinatingConjunction attr_reader :left, :conjunction, :right def initialize(left:, conjunction:, right:) @left = left @conjunction = conjunction @right = right end end class Sentence attr_reader :phrase, :punctuation def initialize(phrase:, punctuation:) @phrase = phrase @punctuation = punctuation end end class Verb attr_reader :value def initialize(value:) @value = value end end
  25. Parser · Syntax tree · Visitor class SubjectPhrase attr_reader :noun,

    :verb_phrase def initialize(noun:, verb_phrase:) @noun = noun @verb_phrase = verb_phrase end end verb-phrase : VERB ADJECTIVE subject-phrase : NOUN verb-phrase subordinating-conjunction : 
 subject-phrase CONJUNCTION subject-phrase sentence : subordinating-conjunction PERIOD class VerbPhrase attr_reader :verb, :adjective def initialize(verb:, adjective:) @verb = verb @adjective = adjective end end class SubordinatingConjunction attr_reader :left, :conjunction, :right def initialize(left:, conjunction:, right:) @left = left @conjunction = conjunction @right = right end end class Sentence attr_reader :phrase, :punctuation def initialize(phrase:, punctuation:) @phrase = phrase @punctuation = punctuation end end class Verb attr_reader :value def initialize(value:) @value = value end end
  26. Parser · Syntax tree · Visitor class SubjectPhrase attr_reader :noun,

    :verb_phrase def initialize(noun:, verb_phrase:) @noun = noun @verb_phrase = verb_phrase end end verb-phrase : VERB ADJECTIVE subject-phrase : NOUN verb-phrase subordinating-conjunction : 
 subject-phrase CONJUNCTION subject-phrase sentence : subordinating-conjunction PERIOD class VerbPhrase attr_reader :verb, :adjective def initialize(verb:, adjective:) @verb = verb @adjective = adjective end end class SubordinatingConjunction attr_reader :left, :conjunction, :right def initialize(left:, conjunction:, right:) @left = left @conjunction = conjunction @right = right end end class Sentence attr_reader :phrase, :punctuation def initialize(phrase:, punctuation:) @phrase = phrase @punctuation = punctuation end end class Verb attr_reader :value def initialize(value:) @value = value end end class Adjective attr_reader :value def initialize(value:) @value = value end end
  27. Parser · Syntax tree · Visitor class SubjectPhrase attr_reader :noun,

    :verb_phrase def initialize(noun:, verb_phrase:) @noun = noun @verb_phrase = verb_phrase end end verb-phrase : VERB ADJECTIVE subject-phrase : NOUN verb-phrase subordinating-conjunction : 
 subject-phrase CONJUNCTION subject-phrase sentence : subordinating-conjunction PERIOD class VerbPhrase attr_reader :verb, :adjective def initialize(verb:, adjective:) @verb = verb @adjective = adjective end end class SubordinatingConjunction attr_reader :left, :conjunction, :right def initialize(left:, conjunction:, right:) @left = left @conjunction = conjunction @right = right end end class Sentence attr_reader :phrase, :punctuation def initialize(phrase:, punctuation:) @phrase = phrase @punctuation = punctuation end end class Verb attr_reader :value def initialize(value:) @value = value end end class Adjective attr_reader :value def initialize(value:) @value = value end end
  28. Parser · Syntax tree · Visitor class SubjectPhrase attr_reader :noun,

    :verb_phrase def initialize(noun:, verb_phrase:) @noun = noun @verb_phrase = verb_phrase end end verb-phrase : VERB ADJECTIVE subject-phrase : NOUN verb-phrase subordinating-conjunction : 
 subject-phrase CONJUNCTION subject-phrase sentence : subordinating-conjunction PERIOD class VerbPhrase attr_reader :verb, :adjective def initialize(verb:, adjective:) @verb = verb @adjective = adjective end end class SubordinatingConjunction attr_reader :left, :conjunction, :right def initialize(left:, conjunction:, right:) @left = left @conjunction = conjunction @right = right end end class Sentence attr_reader :phrase, :punctuation def initialize(phrase:, punctuation:) @phrase = phrase @punctuation = punctuation end end class Verb attr_reader :value def initialize(value:) @value = value end end class Adjective attr_reader :value def initialize(value:) @value = value end end class Noun attr_reader :value def initialize(value:) @value = value end end
  29. Parser · Syntax tree · Visitor class SubjectPhrase attr_reader :noun,

    :verb_phrase def initialize(noun:, verb_phrase:) @noun = noun @verb_phrase = verb_phrase end end verb-phrase : VERB ADJECTIVE subject-phrase : NOUN verb-phrase subordinating-conjunction : 
 subject-phrase CONJUNCTION subject-phrase sentence : subordinating-conjunction PERIOD class VerbPhrase attr_reader :verb, :adjective def initialize(verb:, adjective:) @verb = verb @adjective = adjective end end class SubordinatingConjunction attr_reader :left, :conjunction, :right def initialize(left:, conjunction:, right:) @left = left @conjunction = conjunction @right = right end end class Sentence attr_reader :phrase, :punctuation def initialize(phrase:, punctuation:) @phrase = phrase @punctuation = punctuation end end class Verb attr_reader :value def initialize(value:) @value = value end end class Adjective attr_reader :value def initialize(value:) @value = value end end class Noun attr_reader :value def initialize(value:) @value = value end end
  30. Parser · Syntax tree · Visitor class SubjectPhrase attr_reader :noun,

    :verb_phrase def initialize(noun:, verb_phrase:) @noun = noun @verb_phrase = verb_phrase end end verb-phrase : VERB ADJECTIVE subject-phrase : NOUN verb-phrase subordinating-conjunction : 
 subject-phrase CONJUNCTION subject-phrase sentence : subordinating-conjunction PERIOD class VerbPhrase attr_reader :verb, :adjective def initialize(verb:, adjective:) @verb = verb @adjective = adjective end end class SubordinatingConjunction attr_reader :left, :conjunction, :right def initialize(left:, conjunction:, right:) @left = left @conjunction = conjunction @right = right end end class Sentence attr_reader :phrase, :punctuation def initialize(phrase:, punctuation:) @phrase = phrase @punctuation = punctuation end end class Verb attr_reader :value def initialize(value:) @value = value end end class Adjective attr_reader :value def initialize(value:) @value = value end end class Noun attr_reader :value def initialize(value:) @value = value end end class Conjunction attr_reader :value def initialize(value:) @value = value end end
  31. Parser · Syntax tree · Visitor class SubjectPhrase attr_reader :noun,

    :verb_phrase def initialize(noun:, verb_phrase:) @noun = noun @verb_phrase = verb_phrase end end verb-phrase : VERB ADJECTIVE subject-phrase : NOUN verb-phrase subordinating-conjunction : 
 subject-phrase CONJUNCTION subject-phrase sentence : subordinating-conjunction PERIOD class VerbPhrase attr_reader :verb, :adjective def initialize(verb:, adjective:) @verb = verb @adjective = adjective end end class SubordinatingConjunction attr_reader :left, :conjunction, :right def initialize(left:, conjunction:, right:) @left = left @conjunction = conjunction @right = right end end class Sentence attr_reader :phrase, :punctuation def initialize(phrase:, punctuation:) @phrase = phrase @punctuation = punctuation end end class Verb attr_reader :value def initialize(value:) @value = value end end class Adjective attr_reader :value def initialize(value:) @value = value end end class Noun attr_reader :value def initialize(value:) @value = value end end class Conjunction attr_reader :value def initialize(value:) @value = value end end
  32. Parser · Syntax tree · Visitor class SubjectPhrase attr_reader :noun,

    :verb_phrase def initialize(noun:, verb_phrase:) @noun = noun @verb_phrase = verb_phrase end end verb-phrase : VERB ADJECTIVE subject-phrase : NOUN verb-phrase subordinating-conjunction : 
 subject-phrase CONJUNCTION subject-phrase sentence : subordinating-conjunction PERIOD class VerbPhrase attr_reader :verb, :adjective def initialize(verb:, adjective:) @verb = verb @adjective = adjective end end class SubordinatingConjunction attr_reader :left, :conjunction, :right def initialize(left:, conjunction:, right:) @left = left @conjunction = conjunction @right = right end end class Sentence attr_reader :phrase, :punctuation def initialize(phrase:, punctuation:) @phrase = phrase @punctuation = punctuation end end class Verb attr_reader :value def initialize(value:) @value = value end end class Adjective attr_reader :value def initialize(value:) @value = value end end class Noun attr_reader :value def initialize(value:) @value = value end end class Conjunction attr_reader :value def initialize(value:) @value = value end end class Period attr_reader :value def initialize(value:) @value = value end end
  33. Parser · Syntax tree · Visitor class SubjectPhrase attr_reader :noun,

    :verb_phrase def initialize(noun:, verb_phrase:) @noun = noun @verb_phrase = verb_phrase end end verb-phrase : VERB ADJECTIVE subject-phrase : NOUN verb-phrase subordinating-conjunction : 
 subject-phrase CONJUNCTION subject-phrase sentence : subordinating-conjunction PERIOD class VerbPhrase attr_reader :verb, :adjective def initialize(verb:, adjective:) @verb = verb @adjective = adjective end end class SubordinatingConjunction attr_reader :left, :conjunction, :right def initialize(left:, conjunction:, right:) @left = left @conjunction = conjunction @right = right end end class Sentence attr_reader :phrase, :punctuation def initialize(phrase:, punctuation:) @phrase = phrase @punctuation = punctuation end end class Verb attr_reader :value def initialize(value:) @value = value end end class Adjective attr_reader :value def initialize(value:) @value = value end end class Noun attr_reader :value def initialize(value:) @value = value end end class Conjunction attr_reader :value def initialize(value:) @value = value end end class Period attr_reader :value def initialize(value:) @value = value end end
  34. Parser · Syntax tree · Visitor class SubjectPhrase attr_reader :noun,

    :verb_phrase def initialize(noun:, verb_phrase:) @noun = noun @verb_phrase = verb_phrase end end class VerbPhrase attr_reader :verb, :adjective def initialize(verb:, adjective:) @verb = verb @adjective = adjective end end class SubordinatingConjunction attr_reader :left, :conjunction, :right def initialize(left:, conjunction:, right:) @left = left @conjunction = conjunction @right = right end end class Sentence attr_reader :phrase, :punctuation def initialize(phrase:, punctuation:) @phrase = phrase @punctuation = punctuation end end class Verb attr_reader :value def initialize(value:) @value = value end end class Adjective attr_reader :value def initialize(value:) @value = value end end class Noun attr_reader :value def initialize(value:) @value = value end end class Conjunction attr_reader :value def initialize(value:) @value = value end end class Period attr_reader :value def initialize(value:) @value = value end end
  35. class SubjectPhrase attr_reader :noun, :verb_phrase def initialize(noun:, verb_phrase:) @noun =

    noun @verb_phrase = verb_phrase end end class VerbPhrase attr_reader :verb, :adjective def initialize(verb:, adjective:) @verb = verb @adjective = adjective end end class SubordinatingConjunction attr_reader :left, :conjunction, :right def initialize(left:, conjunction:, right:) @left = left @conjunction = conjunction @right = right end end class Sentence attr_reader :phrase, :punctuation def initialize(phrase:, punctuation:) @phrase = phrase @punctuation = punctuation end end class Verb attr_reader :value def initialize(value:) @value = value end end class Adjective attr_reader :value def initialize(value:) @value = value end end class Noun attr_reader :value def initialize(value:) @value = value end end class Conjunction attr_reader :value def initialize(value:) @value = value end end class Period attr_reader :value def initialize(value:) @value = value end end Parser · Syntax tree · Visitor
  36. class VerbPhrase attr_reader :verb, :adjective def initialize(verb:, adjective:) @verb =

    verb @adjective = adjective end end Parser · Syntax tree · Visitor
  37. Parser · Syntax tree · Visitor class VerbPhrase attr_reader :verb,

    :adjective def initialize(verb:, adjective:) @verb = verb @adjective = adjective end def deconstruct_keys(keys) { verb: verb, adjective: adjective } end def ==(other) other in VerbPhrase[ verb: ^(verb), adjective: ^(adjective) ] end end
  38. class VerbPhrase attr_reader :verb, :adjective def initialize(verb:, adjective:) @verb =

    verb @adjective = adjective end end Parser · Syntax tree · Visitor
  39. Parser · Syntax tree · Visitor class VerbPhrase attr_reader :verb,

    :adjective def initialize(verb:, adjective:) @verb = verb @adjective = adjective end def copy(verb: self.verb, adjective: self.adjective) VerbPhrase.new(verb: verb, adjective: adjective) end end
  40. class VerbPhrase attr_reader :verb, :adjective def initialize(verb:, adjective:) @verb =

    verb @adjective = adjective end end Parser · Syntax tree · Visitor
  41. Parser · Syntax tree · Visitor class VerbPhrase attr_reader :verb,

    :adjective def initialize(verb:, adjective:) @verb = verb @adjective = adjective end def accept(visitor) visitor.visit_verb_phrase(self) end def child_nodes [verb, adjective] end end
  42. Parser · Syntax tree · Visitor class VerbPhrase attr_reader :verb,

    :adjective def initialize(verb:, adjective:) @verb = verb @adjective = adjective end def accept(visitor) visitor.visit_verb_phrase(self) end def child_nodes [verb, adjective] end end
  43. class VerbPhrase attr_reader :verb, :adjective def initialize(verb:, adjective:) @verb =

    verb @adjective = adjective end def accept(visitor) visitor.visit_verb_phrase(self) end def child_nodes [verb, adjective] end end Parser · Syntax tree · Visitor
  44. class VerbPhrase def accept(visitor) visitor.visit_verb_phrase(self) end end 
 class Visitor

    def visit_verb_phrase(node) # ... end end node.accept(Visitor.new) Parser · Syntax tree · Visitor
  45. class VerbPhrase def accept(visitor) visitor.visit_verb_phrase(self) end end 
 class Visitor

    def visit_adjective(node) end def visit_conjunction(node) end def visit_noun(node) end def visit_verb(node) end def visit_punctuation(node) end def visit_sentence(node) end def visit_subordinating_conjunction(node) end def visit_subject_phrase(node) end def visit_verb_phrase(node) # ... end end node.accept(Visitor.new) Parser · Syntax tree · Visitor
  46. class Visitor def visit_adjective(node) end def visit_conjunction(node) end def visit_noun(node)

    end def visit_verb(node) end def visit_punctuation(node) end def visit_sentence(node) end def visit_subordinating_conjunction(node) end def visit_subject_phrase(node) end def visit_verb_phrase(node) # ... end end node.accept(Visitor.new) Parser · Syntax tree · Visitor
  47. class Visitor def visit(node) node.accept(self) end def visit_adjective(node) end def

    visit_conjunction(node) end def visit_noun(node) end def visit_verb(node) end def visit_punctuation(node) end def visit_sentence(node) end def visit_subordinating_conjunction(node) end def visit_subject_phrase(node) end def visit_verb_phrase(node) # ... end end node.accept(Visitor.new) Parser · Syntax tree · Visitor
  48. Parser · Syntax tree · Visitor class Visitor def visit(node)

    node.accept(self) end def visit_adjective(node) end def visit_conjunction(node) end def visit_noun(node) end def visit_verb(node) end def visit_punctuation(node) end def visit_sentence(node) end def visit_subordinating_conjunction(node) end def visit_subject_phrase(node) end def visit_verb_phrase(node) node.child_nodes.each { |node| visit(node) } end end node.accept(Visitor.new)
  49. Parser · Syntax tree · Visitor class Visitor def visit(node)

    node.accept(self) end def visit_adjective(node) end def visit_conjunction(node) end def visit_noun(node) end def visit_verb(node) end def visit_punctuation(node) end def visit_sentence(node) end def visit_subordinating_conjunction(node) end def visit_subject_phrase(node) end def visit_verb_phrase(node) node.child_nodes.each { |node| visit(node) } end end
  50. Parser · Syntax tree · Visitor class Visitor def visit(node)

    node.accept(self) end def visit_child_nodes(node) node.child_nodes.each { |node| visit(node) } end def visit_adjective(node) end def visit_conjunction(node) end def visit_noun(node) end def visit_verb(node) end def visit_punctuation(node) end def visit_sentence(node) end def visit_subordinating_conjunction(node) end def visit_subject_phrase(node) end def visit_verb_phrase(node) visit_child_nodes(node) end end
  51. Parser · Syntax tree · Visitor class Visitor def visit(node)

    node.accept(self) end def visit_child_nodes(node) node.child_nodes.each { |node| visit(node) } end def visit_adjective(node) end def visit_conjunction(node) end def visit_noun(node) end def visit_verb(node) end def visit_punctuation(node) end def visit_sentence(node) end def visit_subordinating_conjunction(node) end def visit_subject_phrase(node) end alias visit_verb_phrase visit_child_nodes end
  52. Parser · Syntax tree · Visitor class Visitor def visit(node)

    node.accept(self) end def visit_child_nodes(node) node.child_nodes.each { |node| visit(node) } end alias visit_adjective visit_child_nodes alias visit_conjunction visit_child_nodes alias visit_noun visit_child_nodes alias visit_verb visit_child_nodes alias visit_punctuation visit_child_nodes alias visit_sentence visit_child_nodes alias visit_subordinating_conjunction 
 visit_child_nodes alias visit_subject_phrase visit_child_nodes alias visit_verb_phrase visit_child_nodes end
  53. Parser · Syntax tree · Visitor class SentenceCountVisitor < Visitor

    attr_reader :count def initialize @count = 0 end def visit_sentence(node) @count += 1 super end end visitor = SentenceCountVisitor.new node.accept(visitor) puts visitor.count
  54. Parser · Syntax tree · Visitor class PrettyPrintVisitor < Visitor

    attr_reader :q def initialize @q = PP.new(+"") end def visit_sentence(node) q.group(2, "sentence(", ")") do visit(node.phrase) visit(node.punctuation) end end end visitor = PrettyPrintVisitor.new node.accept(visitor) visitor.q.flush puts visitor.q.output
  55. Parser · Syntax tree · Visitor class FormatterVisitor < Visitor

    attr_reader :q def initialize @q = PP.new(+"") end def visit_sentence(node) q.group do q.format(node.phrase) q.format(node.punctuation) end end end visitor = FormatterVisitor.new node.accept(visitor) visitor.q.flush puts visitor.q.output
  56. Object layer representing the result of parsing Ruby Tools to

    interact with and manipulate that layer Syntax Tree
  57. Build a syntax tree Format the syntax tree Create a

    CLI Create a language server (LSP) Syntax Tree
  58. Build a syntax tree Format the syntax tree Create a

    CLI Create a language server (LSP) Translate the syntax tree Syntax Tree
  59. Build · Format · CLI · LSP · Translate class

    VCall < Node attr_reader :value, :location, :comments def initialize(value:, location:, comments: []) @value = value @location = location @comments = comments end def accept(visitor) visitor.visit_vcall(self) end def child_nodes [value] end alias deconstruct child_nodes def deconstruct_keys(keys) { value: value, location: location, comments: comments } end end
  60. Build · Format · CLI · LSP · Translate class

    VCall < Node attr_reader :value, :location, :comments def initialize(value:, location:, comments: []) @value = value @location = location @comments = comments end def accept(visitor) visitor.visit_vcall(self) end def child_nodes [value] end alias deconstruct child_nodes def deconstruct_keys(keys) { value: value, location: location, comments: comments } end end Named fields
  61. Build · Format · CLI · LSP · Translate class

    VCall < Node attr_reader :value, :location, :comments def initialize(value:, location:, comments: []) @value = value @location = location @comments = comments end def accept(visitor) visitor.visit_vcall(self) end def child_nodes [value] end alias deconstruct child_nodes def deconstruct_keys(keys) { value: value, location: location, comments: comments } end end Named fields #location/#comments
  62. Build · Format · CLI · LSP · Translate class

    VCall < Node attr_reader :value, :location, :comments def initialize(value:, location:, comments: []) @value = value @location = location @comments = comments end def accept(visitor) visitor.visit_vcall(self) end def child_nodes [value] end alias deconstruct child_nodes def deconstruct_keys(keys) { value: value, location: location, comments: comments } end end Named fields #location/#comments #accept/#child_nodes
  63. Build · Format · CLI · LSP · Translate class

    VCall < Node attr_reader :value, :location, :comments def initialize(value:, location:, comments: []) @value = value @location = location @comments = comments end def accept(visitor) visitor.visit_vcall(self) end def child_nodes [value] end alias deconstruct child_nodes def deconstruct_keys(keys) { value: value, location: location, comments: comments } end end Named fields #location/#comments #accept/#child_nodes #deconstruct/ 
 #deconstruct_keys
  64. Build · Format · CLI · LSP · Translate class

    VCall < Node attr_reader :value, :location, :comments def initialize(value:, location:, comments: []) @value = value @location = location @comments = comments end def accept(visitor) visitor.visit_vcall(self) end def child_nodes [value] end alias deconstruct child_nodes def deconstruct_keys(keys) { value: value, location: location, comments: comments } end end Named fields #location/#comments #accept/#child_nodes #deconstruct/ 
 #deconstruct_keys Immutable
  65. Ripper::EVENTS.count # => 190 SyntaxTree::Node.descendants.count 
 # => 162 qwords_new/qwords_add

    -> SyntaxTree::QWords Define each node Build · Format · CLI · LSP · Translate
  66. var_ref : user_variable { /*%%%*/ if (!($$ = gettable(p, $1,

    &@$))) $$ = NEW_BEGIN(0, &@$); /*% if (id_is_var(p, get_id($1))) { $$ = dispatch1(var_ref, $1); } else { $$ = dispatch1(vcall, $1); } %*/ } | keyword_variable { /*%%%*/ if (!($$ = gettable(p, $1, &@$))) $$ = NEW_BEGIN(0, &@$); /*% %*/ /*% ripper: var_ref!($1) %*/ } ; Build · Format · CLI · LSP · Translate
  67. var_ref : user_variable { /*%%%*/ if (!($$ = gettable(p, $1,

    &@$))) $$ = NEW_BEGIN(0, &@$); /*% if (id_is_var(p, get_id($1))) { $$ = dispatch1(var_ref, $1); } else { $$ = dispatch1(vcall, $1); } %*/ } | keyword_variable { /*%%%*/ if (!($$ = gettable(p, $1, &@$))) $$ = NEW_BEGIN(0, &@$); /*% %*/ /*% ripper: var_ref!($1) %*/ } ; Build · Format · CLI · LSP · Translate
  68. class Foo def bar baz end end Build · Format

    · CLI · LSP · Translate class Parser < Ripper def on_const(value) = [:@const, value] def on_ident(value) = [:@ident, value] def on_const_ref(const) = [:const_ref, const] def on_vcall(ident) = [:vcall, ident] def on_class(const, superclass, bodystmt) [:class, [const, superclass, bodystmt]] end def on_def(name, params, bodystmt) [:def, [name, params, bodystmt]] end end
  69. class Foo def bar baz end end Build · Format

    · CLI · LSP · Translate class Parser < Ripper def on_const(value) = [:@const, value] def on_ident(value) = [:@ident, value] def on_const_ref(const) = [:const_ref, const] def on_vcall(ident) = [:vcall, ident] def on_class(const, superclass, bodystmt) [:class, [const, superclass, bodystmt]] end def on_def(name, params, bodystmt) [:def, [name, params, bodystmt]] end end
  70. class Foo def bar baz end end Build · Format

    · CLI · LSP · Translate class Parser < Ripper def on_const(value) = [:@const, value] def on_ident(value) = [:@ident, value] def on_const_ref(const) = [:const_ref, const] def on_vcall(ident) = [:vcall, ident] def on_class(const, superclass, bodystmt) [:class, [const, superclass, bodystmt]] end def on_def(name, params, bodystmt) [:def, [name, params, bodystmt]] end end
  71. class Foo def bar baz end end Build · Format

    · CLI · LSP · Translate class Parser < Ripper def on_const(value) = [:@const, value] def on_ident(value) = [:@ident, value] def on_const_ref(const) = [:const_ref, const] def on_vcall(ident) = [:vcall, ident] def on_class(const, superclass, bodystmt) [:class, [const, superclass, bodystmt]] end def on_def(name, params, bodystmt) [:def, [name, params, bodystmt]] end end
  72. class Foo def bar baz end end Build · Format

    · CLI · LSP · Translate class Parser < Ripper def on_const(value) = [:@const, value] def on_ident(value) = [:@ident, value] def on_const_ref(const) = [:const_ref, const] def on_vcall(ident) = [:vcall, ident] def on_class(const, superclass, bodystmt) [:class, [const, superclass, bodystmt]] end def on_def(name, params, bodystmt) [:def, [name, params, bodystmt]] end end
  73. class Foo def bar baz end end Build · Format

    · CLI · LSP · Translate class Parser < Ripper def on_const(value) = [:@const, value] def on_ident(value) = [:@ident, value] def on_const_ref(const) = [:const_ref, const] def on_vcall(ident) = [:vcall, ident] def on_class(const, superclass, bodystmt) [:class, [const, superclass, bodystmt]] end def on_def(name, params, bodystmt) [:def, [name, params, bodystmt]] end end
  74. class Foo def bar baz end end Build · Format

    · CLI · LSP · Translate class Parser < Ripper def on_const(value) = [:@const, value] def on_ident(value) = [:@ident, value] def on_const_ref(const) = [:const_ref, const] def on_vcall(ident) = [:vcall, ident] def on_class(const, superclass, bodystmt) [:class, [const, superclass, bodystmt]] end def on_def(name, params, bodystmt) [:def, [name, params, bodystmt]] end end
  75. class Foo def bar baz end end Build · Format

    · CLI · LSP · Translate class Parser < Ripper def on_const(value) = [:@const, value] def on_ident(value) = [:@ident, value] def on_const_ref(const) = [:const_ref, const] def on_vcall(ident) = [:vcall, ident] def on_class(const, superclass, bodystmt) [:class, [const, superclass, bodystmt]] end def on_def(name, params, bodystmt) [:def, [name, params, bodystmt]] end end
  76. Build · Format · CLI · LSP · Translate class

    Parser < Ripper def on_const(value) = [:@const, value] def on_ident(value) = [:@ident, value] def on_const_ref(const) = [:const_ref, const] def on_vcall(ident) = [:vcall, ident] def on_class(const, superclass, bodystmt) [:class, [const, superclass, bodystmt]] end def on_def(name, params, bodystmt) [:def, [name, params, bodystmt]] end end
  77. Build · Format · CLI · LSP · Translate class

    Parser < Ripper def on_const(value) = [:@const, value] def on_ident(value) = [:@ident, value] def on_kw(value) = @stack << [:@kw, value] def on_const_ref(const) = [:const_ref, const] def on_vcall(ident) = [:vcall, ident] def on_class(const, superclass, bodystmt) kw = @stack.rfind { |token| token in [:@kw, "class"] } [:class, [@stack.delete(kw), const, superclass, bodystmt]] end def on_def(name, params, bodystmt) kw = @stack.rfind { |token| token in [:@kw, "def"] } [:def, [@stack.delete(kw), name, params, bodystmt]] end end
  78. Build · Format · CLI · LSP · Translate class

    Parser < Ripper def on_const(value) = [:@const, value] def on_ident(value) = [:@ident, value] def on_kw(value) = @stack << [:@kw, value] def on_const_ref(const) = [:const_ref, const] def on_vcall(ident) = [:vcall, ident] def on_class(const, superclass, bodystmt) kw = @stack.rfind { |token| token in [:@kw, "class"] } [:class, [@stack.delete(kw), const, superclass, bodystmt]] end def on_def(name, params, bodystmt) kw = @stack.rfind { |token| token in [:@kw, "def"] } [:def, [@stack.delete(kw), name, params, bodystmt]] end end
  79. Build · Format · CLI · LSP · Translate ->

    (positional; local1, local2) {}
  80. Build · Format · CLI · LSP · Translate ->

    (positional; local1, local2) {} range = (location.start_char + 1)...location.end_char locals = lambda_locals(source[range]) Paren.new( lparen: params.lparen, contents: LambdaVar.new( params: params.contents, locals: locals, location: location ), location: params.location, comments: params.comments )
  81. Build · Format · CLI · LSP · Translate class

    Foo # comment def bar baz end end
  82. Build · Format · CLI · LSP · Translate class

    Foo def bar # comment baz end end
  83. Build · Format · CLI · LSP · Translate class

    Foo def bar baz # comment end end
  84. Build · Format · CLI · LSP · Translate #

    comment class Foo def bar baz end end
  85. Build · Format · CLI · LSP · Translate class

    Foo # comment def bar baz end end
  86. Build · Format · CLI · LSP · Translate #

    comment1 class Foo # comment2 # comment3 def bar # comment4 baz # comment5 end end
  87. Build · Format · CLI · LSP · Translate #

    comment1 class Foo # comment2 # comment3 def bar # comment4 baz # comment5 end end [ ]
  88. Build · Format · CLI · LSP · Translate #

    comment1 class Foo # comment2 # comment3 def bar # comment4 baz # comment5 end end [ # comment1, ]
  89. Build · Format · CLI · LSP · Translate #

    comment1 class Foo # comment2 # comment3 def bar # comment4 baz # comment5 end end [ # comment1, # comment2, ]
  90. Build · Format · CLI · LSP · Translate #

    comment1 class Foo # comment2 # comment3 def bar # comment4 baz # comment5 end end [ # comment1, # comment2, # comment3, ]
  91. Build · Format · CLI · LSP · Translate #

    comment1 class Foo # comment2 # comment3 def bar # comment4 baz # comment5 end end [ # comment1, # comment2, # comment3, # comment4, ]
  92. Build · Format · CLI · LSP · Translate #

    comment1 class Foo # comment2 # comment3 def bar # comment4 baz # comment5 end end [ # comment1, # comment2, # comment3, # comment4, # comment5 ]
  93. Build · Format · CLI · LSP · Translate [

    # comment1, # comment2, # comment3, # comment4, # comment5 ] (program (statements ((class (const_ref (const "Foo")) (bodystmt (statements ((void_stmt), (def (ident "bar") (params) (bodystmt (statements ((vcall (ident "baz")))))))))))))
  94. Build · Format · CLI · LSP · Translate (program

    (statements ((comment "# comment1"), (class (const_ref (const "Foo") ((comment "# comment2"))) (bodystmt (statements ((void_stmt), (comment "# comment3"), (def (ident "bar") (params ((comment "# comment4"))) (bodystmt (statements ((vcall (ident "baz") ((comment "# comment5"))))))))))))))
  95. Build · Format · CLI · LSP · Translate class

    Visitor def visit(node) node&.accept(self) end def visit_child_nodes(node) node.child_nodes.map do |node| visit(node) end end end
  96. Build · Format · CLI · LSP · Translate class

    VCall < Node def accept(visitor) visitor.visit_vcall(self) end end class Visitor def visit(node) node&.accept(self) end def visit_child_nodes(node) node.child_nodes.map do |node| visit(node) end end end
  97. Build · Format · CLI · LSP · Translate class

    VCall < Node def accept(visitor) visitor.visit_vcall(self) end end # Visit an ARef node. alias visit_aref visit_child_nodes # Visit an ARefField node. alias visit_aref_field visit_child_nodes # Visit an Alias node. alias visit_alias visit_child_nodes # Visit an ArgBlock node. alias visit_arg_block visit_child_nodes # Visit an ArgParen node. alias visit_arg_paren visit_child_nodes # Visit an ArgStar node. alias visit_arg_star visit_child_nodes # Visit an Args node. alias visit_args visit_child_nodes # Visit an ArgsForward node. alias visit_args_forward visit_child_nodes # Visit an ArrayLiteral node. alias visit_array visit_child_nodes # Visit an AryPtn node. alias visit_aryptn visit_child_nodes # Visit an Assign node. alias visit_assign visit_child_nodes # Visit an Assoc node. alias visit_assoc visit_child_nodes # Visit an AssocSplat node. alias visit_assoc_splat visit_child_nodes # Visit a Backref node. alias visit_backref visit_child_nodes class Visitor def visit(node) node&.accept(self) end def visit_child_nodes(node) node.child_nodes.map do |node| visit(node) end end end
  98. Build · Format · CLI · LSP · Translate class

    VCall < Node def accept(visitor) visitor.visit_vcall(self) end end alias visit_vcall visit_child_nodes # Visit a VoidStmt node. alias visit_void_stmt visit_child_nodes # Visit a When node. alias visit_when visit_child_nodes # Visit a While node. alias visit_while visit_child_nodes # Visit a WhileMod node. alias visit_while_mod visit_child_nodes # Visit a Word node. alias visit_word visit_child_nodes # Visit a Words node. alias visit_words visit_child_nodes # Visit a WordsBeg node. alias visit_words_beg visit_child_nodes # Visit a XString node. alias visit_xstring visit_child_nodes # Visit a XStringLiteral node. alias visit_xstring_literal visit_child_nodes # Visit a Yield node. alias visit_yield visit_child_nodes # Visit a Yield0 node. alias visit_yield0 visit_child_nodes # Visit a ZSuper node. alias visit_zsuper visit_child_nodes # Visit an EndContent node. alias visit___end__ visit_child_nodes class Visitor def visit(node) node&.accept(self) end def visit_child_nodes(node) node.child_nodes.map do |node| visit(node) end end end
  99. Build · Format · CLI · LSP · Translate class

    RegexpVisitor < Visitor def visit_regexp_literal(node) # do something with regexp literal node here node.options # call super to continue walking the tree super end end
  100. Build · Format · CLI · LSP · Translate class

    JSONVisitor < Visitor def visit_aref(node) node(node, "aref") do field("collection", node.collection) field("index", node.index) comments(node) end end def visit_aref_field(node) node(node, "aref_field") do field("collection", node.collection) field("index", node.index) comments(node) end end def visit_alias(node) node(node, "alias") do field("left", node.left) field("right", node.right) comments(node) end end
  101. prettyprint Build group, text, breakable to layout content Break outermost

    groups to fit to print width Algorithm Build · Format · CLI · LSP · Translate
  102. Build · Format · CLI · LSP · Translate [foo1,

    foo2, [bar1, bar2, bar3, bar4], foo3, foo4, [baz1, baz2]]
  103. Build · Format · CLI · LSP · Translate [foo1,

    foo2, [bar1, bar2, bar3, bar4], foo3, foo4, [baz1, baz2]]
  104. Build · Format · CLI · LSP · Translate [foo1,

    foo2, [bar1, bar2, bar3, bar4], foo3, foo4, [baz1, baz2]]
  105. Build · Format · CLI · LSP · Translate [

    foo1, foo2, [bar1, bar2, bar3, bar4], foo3, foo4, [baz1, baz2] ]
  106. Build · Format · CLI · LSP · Translate [

    foo1, foo2, [bar1, bar2, bar3, bar4], foo3, foo4, [baz1, baz2] ]
  107. Build · Format · CLI · LSP · Translate [

    foo1, foo2, [ bar1, bar2, bar3, bar4 ], foo3, foo4, [baz1, baz2] ]
  108. breakGroup([group([text(["["]), indent([breakable, text(["foo1", ","]), breakable, text(["foo2", ","]), breakable, group([text(["["]), indent([breakable,

    text(["bar1", ","]), breakable, text(["bar2", ","]), breakable, text(["bar3", ","]), breakable, text(["bar4"])]), breakable, text(["]"])]), text([","]), breakable, text(["foo3", ","]), breakable, text(["foo4", ","]), breakable, ... Build · Format · CLI · LSP · Translate
  109. breakGroup([group([text(["["]), indent([breakable, text(["foo1", ","]), breakable, text(["foo2", ","]), breakable, group([text(["["]), indent([breakable,

    text(["bar1", ","]), breakable, text(["bar2", ","]), breakable, text(["bar3", ","]), breakable, text(["bar4"])]), breakable, text(["]"])]), text([","]), breakable, text(["foo3", ","]), breakable, text(["foo4", ","]), breakable, ... Build · Format · CLI · LSP · Translate
  110. breakGroup([group([text(["["]), indent([breakable, text(["foo1", ","]), breakable, text(["foo2", ","]), breakable, group([text(["["]), indent([breakable,

    text(["bar1", ","]), breakable, text(["bar2", ","]), breakable, text(["bar3", ","]), breakable, text(["bar4"])]), breakable, text(["]"])]), text([","]), breakable, text(["foo3", ","]), breakable, text(["foo4", ","]), breakable, ... Build · Format · CLI · LSP · Translate
  111. breakGroup([group([text(["["]), indent([breakable, text(["foo1", ","]), breakable, text(["foo2", ","]), breakable, group([text(["["]), indent([breakable,

    text(["bar1", ","]), breakable, text(["bar2", ","]), breakable, text(["bar3", ","]), breakable, text(["bar4"])]), breakable, text(["]"])]), text([","]), breakable, text(["foo3", ","]), breakable, text(["foo4", ","]), breakable, ... Build · Format · CLI · LSP · Translate
  112. breakGroup([group([text(["["]), indent([breakable, text(["foo1", ","]), breakable, text(["foo2", ","]), breakable, group([text(["["]), indent([breakable,

    text(["bar1", ","]), breakable, text(["bar2", ","]), breakable, text(["bar3", ","]), breakable, text(["bar4"])]), breakable, text(["]"])]), text([","]), breakable, text(["foo3", ","]), breakable, text(["foo4", ","]), breakable, ... Build · Format · CLI · LSP · Translate
  113. I made too many additions to prettyprint Build · Format

    · CLI · LSP · Translate 😅😅😅
  114. Build · Format · CLI · LSP · Translate here_is_a_method_call(1,

    2, <<~HEREDOC this is the content of the heredoc HEREDOC )
  115. Build · Format · CLI · LSP · Translate here_is_a_method_call(1,

    2, <<~HEREDOC this is the content of the heredoc HEREDOC )
  116. Build · Format · CLI · LSP · Translate here_is_a_method_call(1,

    2, <<~HEREDOC) this is the content of the heredoc HEREDOC
  117. Build · Format · CLI · LSP · Translate def

    foo return [1, 2, 3].map { |element| element * 2 } # comment end
  118. Build · Format · CLI · LSP · Translate def

    foo return [1, 2, 3].map { |element| element * 2 } # comment end
  119. Build · Format · CLI · LSP · Translate def

    foo return( [1, 2, 3].map do |element| element * 2 end ) # comment end
  120. Build · Format · CLI · LSP · Translate class

    If < Node def format(q) if node.consequent || node.statements.empty? q.group { format_break(q, force: true) } else q.group do q .if_break { format_break(q, force: false) } .if_flat do Parentheses.flat(q) do q.format(node.statements) q.text(" if ") q.format(node.predicate) end end end end end end
  121. Build · Format · CLI · LSP · Translate class

    If < Node def format(q) if node.consequent || node.statements.empty? q.group { format_break(q, force: true) } else q.group do q .if_break { format_break(q, force: false) } .if_flat do Parentheses.flat(q) do q.format(node.statements) q.text(" if ") q.format(node.predicate) end end end end end end
  122. Build · Format · CLI · LSP · Translate stree

    ast [--plugins=...] [--print-width=NUMBER] [-e SCRIPT] FILE Print out the AST corresponding to the given files stree check [--plugins=...] [--print-width=NUMBER] [-e SCRIPT] FILE Check that the given files are formatted as syntax tree would format them stree debug [--plugins=...] [--print-width=NUMBER] [-e SCRIPT] FILE Check that the given files can be formatted idempotently stree doc [--plugins=...] [-e SCRIPT] FILE Print out the doc tree that would be used to format the given files stree expr [-e SCRIPT] FILE Print out a pattern-matching Ruby expression that would match the first expression of the given files stree format [--plugins=...] [--print-width=NUMBER] [-e SCRIPT] FILE Print out the formatted version of the given files stree json [--plugins=...] [-e SCRIPT] FILE Print out the JSON representation of the given files stree match [--plugins=...] [-e SCRIPT] FILE Print out a pattern-matching Ruby expression that would match the given files stree help Display this help message stree lsp [--plugins=...] [--print-width=NUMBER] Run syntax tree in language server mode stree search PATTERN [-e SCRIPT] FILE Search for the given pattern in the given files stree version Output the current version of syntax tree stree write [--plugins=...] [--print-width=NUMBER] [-e SCRIPT] FILE Read, format, and write back the source of the given files --plugins=... A comma-separated list of plugins to load. --print-width=NUMBER The maximum line width to use when formatting. -e SCRIPT Parse an inline Ruby string.
  123. Build · Format · CLI · LSP · Translate stree

    ast [--plugins=...] [--print-width=NUMBER] [-e SCRIPT] FILE Print out the AST corresponding to the given files stree format [--plugins=...] [--print-width=NUMBER] [-e SCRIPT] FILE Print out the formatted version of the given files stree match [--plugins=...] [-e SCRIPT] FILE Print out a pattern-matching Ruby expression that would match the given files stree lsp [--plugins=...] [--print-width=NUMBER] Run syntax tree in language server mode stree search PATTERN [-e SCRIPT] FILE Search for the given pattern in the given files
  124. Build · Format · CLI · LSP · Translate stree

    ast [--plugins=...] [--print-width=NUMBER] [-e SCRIPT] FILE Print out the AST corresponding to the given files stree format [--plugins=...] [--print-width=NUMBER] [-e SCRIPT] FILE Print out the formatted version of the given files stree match [--plugins=...] [-e SCRIPT] FILE Print out a pattern-matching Ruby expression that would match the given files stree lsp [--plugins=...] [--print-width=NUMBER] Run syntax tree in language server mode stree search PATTERN [-e SCRIPT] FILE Search for the given pattern in the given files
  125. Build · Format · CLI · LSP · Translate $

    stree ast -e '1+2' (program (statements ((binary (int "1") + (int "2")))))
  126. Build · Format · CLI · LSP · Translate stree

    ast [--plugins=...] [--print-width=NUMBER] [-e SCRIPT] FILE Print out the AST corresponding to the given files stree format [--plugins=...] [--print-width=NUMBER] [-e SCRIPT] FILE Print out the formatted version of the given files stree match [--plugins=...] [-e SCRIPT] FILE Print out a pattern-matching Ruby expression that would match the given files stree lsp [--plugins=...] [--print-width=NUMBER] Run syntax tree in language server mode stree search PATTERN [-e SCRIPT] FILE Search for the given pattern in the given files
  127. Build · Format · CLI · LSP · Translate stree

    ast [--plugins=...] [--print-width=NUMBER] [-e SCRIPT] FILE Print out the AST corresponding to the given files stree format [--plugins=...] [--print-width=NUMBER] [-e SCRIPT] FILE Print out the formatted version of the given files stree match [--plugins=...] [-e SCRIPT] FILE Print out a pattern-matching Ruby expression that would match the given files stree lsp [--plugins=...] [--print-width=NUMBER] Run syntax tree in language server mode stree search PATTERN [-e SCRIPT] FILE Search for the given pattern in the given files
  128. Build · Format · CLI · LSP · Translate $

    stree format -e '1+2' 1 + 2
  129. Build · Format · CLI · LSP · Translate stree

    ast [--plugins=...] [--print-width=NUMBER] [-e SCRIPT] FILE Print out the AST corresponding to the given files stree format [--plugins=...] [--print-width=NUMBER] [-e SCRIPT] FILE Print out the formatted version of the given files stree match [--plugins=...] [-e SCRIPT] FILE Print out a pattern-matching Ruby expression that would match the given files stree lsp [--plugins=...] [--print-width=NUMBER] Run syntax tree in language server mode stree search PATTERN [-e SCRIPT] FILE Search for the given pattern in the given files
  130. Build · Format · CLI · LSP · Translate stree

    ast [--plugins=...] [--print-width=NUMBER] [-e SCRIPT] FILE Print out the AST corresponding to the given files stree format [--plugins=...] [--print-width=NUMBER] [-e SCRIPT] FILE Print out the formatted version of the given files stree match [--plugins=...] [-e SCRIPT] FILE Print out a pattern-matching Ruby expression that would match the given files stree lsp [--plugins=...] [--print-width=NUMBER] Run syntax tree in language server mode stree search PATTERN [-e SCRIPT] FILE Search for the given pattern in the given files
  131. Build · Format · CLI · LSP · Translate $

    stree match -e '1+2' SyntaxTree::Program[ statements: SyntaxTree::Statements[ body: [ SyntaxTree::Binary[ left: SyntaxTree::Int[value: "1"], operator: :+, right: SyntaxTree::Int[value: "2"] ] ] ] ]
  132. Build · Format · CLI · LSP · Translate stree

    ast [--plugins=...] [--print-width=NUMBER] [-e SCRIPT] FILE Print out the AST corresponding to the given files stree format [--plugins=...] [--print-width=NUMBER] [-e SCRIPT] FILE Print out the formatted version of the given files stree match [--plugins=...] [-e SCRIPT] FILE Print out a pattern-matching Ruby expression that would match the given files stree lsp [--plugins=...] [--print-width=NUMBER] Run syntax tree in language server mode stree search PATTERN [-e SCRIPT] FILE Search for the given pattern in the given files
  133. Build · Format · CLI · LSP · Translate stree

    ast [--plugins=...] [--print-width=NUMBER] [-e SCRIPT] FILE Print out the AST corresponding to the given files stree format [--plugins=...] [--print-width=NUMBER] [-e SCRIPT] FILE Print out the formatted version of the given files stree match [--plugins=...] [-e SCRIPT] FILE Print out a pattern-matching Ruby expression that would match the given files stree lsp [--plugins=...] [--print-width=NUMBER] Run syntax tree in language server mode stree search PATTERN [-e SCRIPT] FILE Search for the given pattern in the given files
  134. Build · Format · CLI · LSP · Translate $

    stree search Int -e '1+2' script:1:0: 1+2 script:1:2: 1+2
  135. Build · Format · CLI · LSP · Translate $

    stree search 'Int[value: "2"]' -e '1+2'
  136. Build · Format · CLI · LSP · Translate $

    stree search 'Int[value: "2"]' -e '1+2' 
 
 script:1:2: 1+2
  137. Build · Format · CLI · LSP · Translate $

    stree search <(stree match -e '1+2') \ 
 -e '1+2'
  138. Build · Format · CLI · LSP · Translate $

    stree search <(stree match -e '1+2') \ 
 -e '1+2' 
 
 script:1:0: 1+2
  139. Build · Format · CLI · LSP · Translate stree

    ast [--plugins=...] [--print-width=NUMBER] [-e SCRIPT] FILE Print out the AST corresponding to the given files stree format [--plugins=...] [--print-width=NUMBER] [-e SCRIPT] FILE Print out the formatted version of the given files stree match [--plugins=...] [-e SCRIPT] FILE Print out a pattern-matching Ruby expression that would match the given files stree lsp [--plugins=...] [--print-width=NUMBER] Run syntax tree in language server mode stree search PATTERN [-e SCRIPT] FILE Search for the given pattern in the given files stree write [--plugins=...] [--print-width=NUMBER] [-e SCRIPT] FILE Read, format, and write back the source of the given files
  140. Build · Format · CLI · LSP · Translate stree

    ast [--plugins=...] [--print-width=NUMBER] [-e SCRIPT] FILE Print out the AST corresponding to the given files stree format [--plugins=...] [--print-width=NUMBER] [-e SCRIPT] FILE Print out the formatted version of the given files stree match [--plugins=...] [-e SCRIPT] FILE Print out a pattern-matching Ruby expression that would match the given files stree lsp [--plugins=...] [--print-width=NUMBER] Run syntax tree in language server mode stree search PATTERN [-e SCRIPT] FILE Search for the given pattern in the given files stree write [--plugins=...] [--print-width=NUMBER] [-e SCRIPT] FILE Read, format, and write back the source of the given files
  141. Language server protocol Runs a JSON RPC server behind an

    editor Build · Format · CLI · LSP · Translate
  142. Language server protocol Runs a JSON RPC server behind an

    editor textDocument/didChange textDocument/didOpen textDocument/didClose Build · Format · CLI · LSP · Translate
  143. Language server protocol Runs a JSON RPC server behind an

    editor textDocument/didChange textDocument/didOpen textDocument/didClose textDocument/formatting Build · Format · CLI · LSP · Translate
  144. Language server protocol Runs a JSON RPC server behind an

    editor textDocument/didChange textDocument/didOpen textDocument/didClose textDocument/formatting textDocument/inlayHint Build · Format · CLI · LSP · Translate
  145. Shopify/ruby-lsp Document highlight Document symbols Folding ranges Formatting Selection ranges

    Semantic highlighting Build · Format · CLI · LSP · Translate
  146. Build · Format · CLI · LSP · Translate class

    RubyParserVisitor < Visitor def visit_binary(node) left = visit(node.left) right = visit(node.right) case node in { operator: :and } s(:and, left, right) in { operator: :!~ } s(:not, s(:call, left, :=~, right)) else s(:call, left, node.operator, right) end end # ... end
  147. Build · Format · CLI · LSP · Translate class

    ParserVisitor < Visitor def visit_binary(node) left = visit(node.left) right = visit(node.right) case node in { operator: :and } s(:and, [left, right]) in { operator: :or } s(:or, [left, right]) else s(:send, [left, node.operator, right]) end end # ... end
  148. Build · Format · CLI · LSP · Translate class

    YARVVisitor < Visitor def visit_binary(node) case node.operator when :"&&" # ... when :"||" # ... else visit(node.left) visit(node.right) builder.send( node.operator, 1, VM_CALL_ARGS_SIMPLE ) end end # ... end
  149. Build · Format · CLI · LSP · Translate class

    MutationVisitor < Visitor def visit_binary(node) node.copy( left: visit(node.left), right: visit(node.right) ) end end
  150. Build · Format · CLI · LSP · Translate mutator

    = SyntaxTree.mutation do |mutator| query = <<~RUBY IfNode[predicate: Assign | OpAssign] | UnlessNode[predicate: Assign | OpAssign] RUBY mutator.mutate(query) do |node| node.copy(predicate: SyntaxTree::Paren.new( lparen: SyntaxTree::LParen.default, contents: node.predicate, location: node.predicate.location )) end end mutated = node.accept(mutator)
  151. Syntax Tree Build a syntax tree Format the syntax tree

    Create a CLI Create a language server (LSP)
  152. Syntax Tree Build a syntax tree Format the syntax tree

    Create a CLI Create a language server (LSP) Translate the syntax tree