Module: SyntaxTree

Defined in:
lib/syntax_tree.rb,
lib/syntax_tree/cli.rb,
lib/syntax_tree/dsl.rb,
lib/syntax_tree/node.rb,
lib/syntax_tree/yarv.rb,
lib/syntax_tree/index.rb,
lib/syntax_tree/parser.rb,
lib/syntax_tree/search.rb,
lib/syntax_tree/mermaid.rb,
lib/syntax_tree/pattern.rb,
lib/syntax_tree/version.rb,
lib/syntax_tree/visitor.rb,
lib/syntax_tree/yarv/bf.rb,
lib/syntax_tree/yarv/vm.rb,
lib/syntax_tree/database.rb,
lib/syntax_tree/formatter.rb,
lib/syntax_tree/rake/task.rb,
lib/syntax_tree/reflection.rb,
lib/syntax_tree/with_scope.rb,
lib/syntax_tree/translation.rb,
lib/syntax_tree/yarv/legacy.rb,
lib/syntax_tree/json_visitor.rb,
lib/syntax_tree/basic_visitor.rb,
lib/syntax_tree/field_visitor.rb,
lib/syntax_tree/match_visitor.rb,
lib/syntax_tree/yarv/calldata.rb,
lib/syntax_tree/yarv/compiler.rb,
lib/syntax_tree/yarv/assembler.rb,
lib/syntax_tree/language_server.rb,
lib/syntax_tree/mermaid_visitor.rb,
lib/syntax_tree/rake/check_task.rb,
lib/syntax_tree/rake/write_task.rb,
lib/syntax_tree/yarv/decompiler.rb,
lib/syntax_tree/mutation_visitor.rb,
lib/syntax_tree/yarv/basic_block.rb,
lib/syntax_tree/yarv/local_table.rb,
lib/syntax_tree/yarv/disassembler.rb,
lib/syntax_tree/yarv/instructions.rb,
lib/syntax_tree/yarv/sea_of_nodes.rb,
lib/syntax_tree/translation/parser.rb,
lib/syntax_tree/plugin/single_quotes.rb,
lib/syntax_tree/pretty_print_visitor.rb,
lib/syntax_tree/yarv/data_flow_graph.rb,
lib/syntax_tree/plugin/trailing_comma.rb,
lib/syntax_tree/translation/rubocop_ast.rb,
lib/syntax_tree/yarv/control_flow_graph.rb,
lib/syntax_tree/yarv/instruction_sequence.rb,
lib/syntax_tree/plugin/disable_auto_ternary.rb

Overview

Syntax Tree is a suite of tools built on top of the internal CRuby parser. It provides the ability to generate a syntax tree from source, as well as the tools necessary to inspect and manipulate that syntax tree. It can be used to build formatters, linters, language servers, and more.

Defined Under Namespace

Modules: ArrayMatch, AssignFormatting, CLI, ContainsAssignment, DSL, Database, HashKeyFormatter, Index, Mermaid, Parentheses, Quotes, Rake, Reflection, Ternaryable, Translation, WithScope, YARV Classes: ARef, ARefField, AliasNode, ArgBlock, ArgParen, ArgStar, Args, ArgsForward, ArrayLiteral, AryPtn, Assign, Assoc, AssocSplat, BEGINBlock, Backref, Backtick, BareAssocHash, BasicVisitor, Begin, Binary, BlockArg, BlockNode, BlockVar, BodyStmt, Break, CHAR, CVar, CallChainFormatter, CallNode, CallOperatorFormatter, Case, ClassDeclaration, Comma, Command, CommandCall, Comment, ConditionalFormatter, Const, ConstPathField, ConstPathRef, ConstRef, DefNode, Defined, DynaSymbol, ENDBlock, Else, Elsif, EmbDoc, EmbExprBeg, EmbExprEnd, EmbVar, EndContent, Ensure, ExcessedComma, Field, FieldVisitor, FloatLiteral, FlowControlFormatter, FndPtn, For, Formatter, GVar, HashLiteral, Heredoc, HeredocBeg, HeredocEnd, HshPtn, IVar, Ident, IfNode, IfOp, Imaginary, In, Int, JSONVisitor, Kw, KwRestParam, LBrace, LBracket, LParen, Label, LabelEnd, Lambda, LambdaVar, LanguageServer, Location, LoopFormatter, MAssign, MLHS, MLHSParen, MRHS, MatchVisitor, MermaidVisitor, MethodAddBlock, ModuleDeclaration, MutationVisitor, Next, Node, Not, Op, OpAssign, Params, Paren, Parser, Pattern, Period, PinnedBegin, PinnedVarRef, PrettyPrintVisitor, Program, QSymbols, QSymbolsBeg, QWords, QWordsBeg, RAssign, RBrace, RBracket, RParen, RangeNode, RationalLiteral, Redo, RegexpBeg, RegexpContent, RegexpEnd, RegexpLiteral, Rescue, RescueEx, RescueMod, RestParam, Retry, ReturnNode, SClass, Search, Statements, StringConcat, StringContent, StringDVar, StringEmbExpr, StringLiteral, Super, SymBeg, SymbolContent, SymbolLiteral, Symbols, SymbolsBeg, TLamBeg, TLambda, TStringBeg, TStringContent, TStringEnd, TopConstField, TopConstRef, Unary, Undef, UnlessNode, UntilNode, VCall, VarField, VarRef, Visitor, VoidStmt, When, WhileNode, Word, Words, WordsBeg, XString, XStringLiteral, YieldNode, ZSuper

Constant Summary collapse

HANDLERS =

This holds references to objects that respond to both #parse and #format so that we can use them in the CLI.

{}
DEFAULT_PRINT_WIDTH =

This is the default print width when formatting. It can be overridden in the CLI by passing the –print-width option or here in the API by passing the optional second argument to ::format.

80
DEFAULT_RUBY_VERSION =

This is the default ruby version that we’re going to target for formatting. It shouldn’t really be changed except in very niche circumstances.

Formatter::SemanticVersion.new(RUBY_VERSION).freeze
DEFAULT_INDENTATION =

The default indentation level for formatting. We allow changing this so that Syntax Tree can format arbitrary parts of a document.

0
PATTERNS =

The list of nodes that represent patterns inside of pattern matching so that when a pattern is being printed it knows if it’s nested.

[AryPtn, Binary, FndPtn, HshPtn, RAssign].freeze
VERSION =
"6.2.0"

Class Method Summary collapse

Class Method Details

.format(source, maxwidth = DEFAULT_PRINT_WIDTH, base_indentation = DEFAULT_INDENTATION, options: Formatter::Options.new) ⇒ Object

Parses the given source and returns the formatted source.



60
61
62
63
64
65
66
67
68
69
70
71
72
73
# File 'lib/syntax_tree.rb', line 60

def self.format(
  source,
  maxwidth = DEFAULT_PRINT_WIDTH,
  base_indentation = DEFAULT_INDENTATION,
  options: Formatter::Options.new
)
  format_node(
    source,
    parse(source),
    maxwidth,
    base_indentation,
    options: options
  )
end

.format_file(filepath, maxwidth = DEFAULT_PRINT_WIDTH, base_indentation = DEFAULT_INDENTATION, options: Formatter::Options.new) ⇒ Object

Parses the given file and returns the formatted source.



76
77
78
79
80
81
82
83
# File 'lib/syntax_tree.rb', line 76

def self.format_file(
  filepath,
  maxwidth = DEFAULT_PRINT_WIDTH,
  base_indentation = DEFAULT_INDENTATION,
  options: Formatter::Options.new
)
  format(read(filepath), maxwidth, base_indentation, options: options)
end

.format_node(source, node, maxwidth = DEFAULT_PRINT_WIDTH, base_indentation = DEFAULT_INDENTATION, options: Formatter::Options.new) ⇒ Object

Accepts a node in the tree and returns the formatted source.



86
87
88
89
90
91
92
93
94
95
96
97
98
# File 'lib/syntax_tree.rb', line 86

def self.format_node(
  source,
  node,
  maxwidth = DEFAULT_PRINT_WIDTH,
  base_indentation = DEFAULT_INDENTATION,
  options: Formatter::Options.new
)
  formatter = Formatter.new(source, [], maxwidth, options: options)
  node.format(formatter)

  formatter.flush(base_indentation)
  formatter.output.join
end

.index(source) ⇒ Object

Indexes the given source code to return a list of all class, module, and method definitions. Used to quickly provide indexing capability for IDEs or documentation generation.



103
104
105
# File 'lib/syntax_tree.rb', line 103

def self.index(source)
  Index.index(source)
end

.index_file(filepath) ⇒ Object

Indexes the given file to return a list of all class, module, and method definitions. Used to quickly provide indexing capability for IDEs or documentation generation.



110
111
112
# File 'lib/syntax_tree.rb', line 110

def self.index_file(filepath)
  Index.index_file(filepath)
end

.mutation {|visitor| ... } ⇒ Object

A convenience method for creating a new mutation visitor.

Yields:

  • (visitor)


115
116
117
118
119
# File 'lib/syntax_tree.rb', line 115

def self.mutation
  visitor = MutationVisitor.new
  yield visitor
  visitor
end

.parse(source) ⇒ Object

Parses the given source and returns the syntax tree.



122
123
124
125
126
# File 'lib/syntax_tree.rb', line 122

def self.parse(source)
  parser = Parser.new(source)
  response = parser.parse
  response unless parser.error?
end

.parse_file(filepath) ⇒ Object

Parses the given file and returns the syntax tree.



129
130
131
# File 'lib/syntax_tree.rb', line 129

def self.parse_file(filepath)
  parse(read(filepath))
end

.read(filepath) ⇒ Object

Returns the source from the given filepath taking into account any potential magic encoding comments.



135
136
137
138
139
140
141
142
143
144
145
146
# File 'lib/syntax_tree.rb', line 135

def self.read(filepath)
  encoding =
    File.open(filepath, "r") do |file|
      break Encoding.default_external if file.eof?

      header = file.readline
      header += file.readline if !file.eof? && header.start_with?("#!")
      Ripper.new(header).tap(&:parse).encoding
    end

  File.read(filepath, encoding: encoding)
end

.register_handler(extension, handler) ⇒ Object

This is a hook provided so that plugins can register themselves as the handler for a particular file type.



150
151
152
# File 'lib/syntax_tree.rb', line 150

def self.register_handler(extension, handler)
  HANDLERS[extension] = handler
end

.search(source, query, &block) ⇒ Object

Searches through the given source using the given pattern and yields each node in the tree that matches the pattern to the given block.



156
157
158
159
160
161
# File 'lib/syntax_tree.rb', line 156

def self.search(source, query, &block)
  pattern = Pattern.new(query).compile
  program = parse(source)

  Search.new(pattern).scan(program, &block)
end

.search_file(filepath, query, &block) ⇒ Object

Searches through the given file using the given pattern and yields each node in the tree that matches the pattern to the given block.



165
166
167
# File 'lib/syntax_tree.rb', line 165

def self.search_file(filepath, query, &block)
  search(read(filepath), query, &block)
end