module SyntaxTree

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.

Constants

DEFAULT_INDENTATION

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

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.

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.

HANDLERS

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

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.

VERSION

Public Class Methods

format( source, maxwidth = DEFAULT_PRINT_WIDTH, base_indentation = DEFAULT_INDENTATION, options: Formatter::Options.new ) click to toggle source

Parses the given source and returns the formatted source.

# 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 ) click to toggle source

Parses the given file and returns the formatted source.

# 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 ) click to toggle source

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

# 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) click to toggle source

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.

# File lib/syntax_tree.rb, line 103
def self.index(source)
  Index.index(source)
end
index_file(filepath) click to toggle source

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.

# File lib/syntax_tree.rb, line 110
def self.index_file(filepath)
  Index.index_file(filepath)
end
mutation() { |visitor| ... } click to toggle source

A convenience method for creating a new mutation visitor.

# File lib/syntax_tree.rb, line 115
def self.mutation
  visitor = MutationVisitor.new
  yield visitor
  visitor
end
parse(source) click to toggle source

Parses the given source and returns the syntax tree.

# 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) click to toggle source

Parses the given file and returns the syntax tree.

# File lib/syntax_tree.rb, line 129
def self.parse_file(filepath)
  parse(read(filepath))
end
read(filepath) click to toggle source

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

# 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) click to toggle source

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

# File lib/syntax_tree.rb, line 150
def self.register_handler(extension, handler)
  HANDLERS[extension] = handler
end
search_file(filepath, query, &block) click to toggle source

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

# File lib/syntax_tree.rb, line 165
def self.search_file(filepath, query, &block)
  search(read(filepath), query, &block)
end