Class: Parser::Source::TreeRewriter

Inherits:
Object
  • Object
show all
Extended by:
Deprecation
Defined in:
sorbet/rbi/parser@3.3.7.4.rbi

Overview

TreeRewriter performs the heavy lifting in the source rewriting process. It schedules code updates to be performed in the correct order.

For simple cases, the resulting source will be obvious.

Examples for more complex cases follow. Assume these examples are acting on the source 'puts(:hello, :world). The methods #wrap, #remove, etc. receive a Range as first argument; for clarity, examples below use english sentences and a string of raw code instead.

Overlapping ranges:

Any two rewriting actions on overlapping ranges will fail and raise a ClobberingError, unless they are both deletions (covered next).

  • wrap ':hello, ' with '(' and ')'
  • wrap ', :world' with '(' and ')' => CloberringError

Overlapping deletions:

  • remove ':hello, '
  • remove ', :world'

The overlapping ranges are merged and ':hello, :world' will be removed. This policy can be changed. :crossing_deletions defaults to :accept but can be set to :warn or :raise.

Multiple actions at the same end points:

Results will always be independent on the order they were given. Exception: rewriting actions done on exactly the same range (covered next).

Example:

  • replace ', ' by ' => '
  • wrap ':hello, :world' with 'and ''
  • replace ':world' with ':everybody'
  • wrap ':world' with '[', ']'

The resulting string will be 'puts({:hello => [:everybody]})' and this result is independent on the order the instructions were given in.

Note that if the two "replace" were given as a single replacement of ', :world' for ' => :everybody', the result would be a ClobberingError because of the wrap in square brackets.

Multiple wraps on same range:

  • wrap ':hello' with '(' and ')'
  • wrap ':hello' with '[' and ']'

The wraps are combined in order given and results would be 'puts([(:hello)], :world)'.

Multiple replacements on same range:

  • replace ':hello' by ':hi', then
  • replace ':hello' by ':hey'

The replacements are made in the order given, so the latter replacement supersedes the former and ':hello' will be replaced by ':hey'.

This policy can be changed. :different_replacements defaults to :accept but can be set to :warn or :raise.

Swallowed insertions:

wrap 'world' by '', '' replace ':hello, :world' with ':hi'

A containing replacement will swallow the contained rewriting actions and ':hello, :world' will be replaced by ':hi'.

This policy can be changed for swallowed insertions. :swallowed_insertions defaults to :accept but can be set to :warn or :raise

Implementation

The updates are organized in a tree, according to the ranges they act on (where children are strictly contained by their parent), hence the name.

source://parser//lib/parser/source/tree_rewriter.rb#91

Defined Under Namespace

Classes: Action

Constant Summary collapse

ACTIONS =

source://parser//lib/parser/source/tree_rewriter.rb#391

T.let(T.unsafe(nil), Array)
DEPRECATION_WARNING =

source://parser//lib/parser/source/tree_rewriter.rb#356

T.let(T.unsafe(nil), String)
POLICY_TO_LEVEL =

source://parser//lib/parser/source/tree_rewriter.rb#417

T.let(T.unsafe(nil), Hash)

Instance Method Summary collapse

Methods included from Deprecation

warn_of_deprecation, warned_of_deprecation=

Constructor Details

#initialize(source_buffer, crossing_deletions: T.unsafe(nil), different_replacements: T.unsafe(nil), swallowed_insertions: T.unsafe(nil)) ⇒ TreeRewriter

source://parser//lib/parser/source/tree_rewriter.rb#98

Parameters:



6706
# File 'sorbet/rbi/parser@3.3.7.4.rbi', line 6706

def initialize(source_buffer, crossing_deletions: T.unsafe(nil), different_replacements: T.unsafe(nil), swallowed_insertions: T.unsafe(nil)); end

Instance Method Details

#as_nested_actionsArray<(Symbol, Range, String{, String})>

Returns a representation of the rewriter as nested insertions (:wrap) and replacements.

rewriter.as_actions # =>[ [:wrap, 1...10, '(', ')'],
                          [:wrap, 2...6, '', '!'],  # aka "insert_after"
                          [:replace, 2...4, 'foo'],
                          [:replace, 5...6, ''],  # aka "removal"
                        ],

Contrary to as_replacements, this representation is sufficient to recreate exactly the rewriter.

source://parser//lib/parser/source/tree_rewriter.rb#299

Returns:



6723
# File 'sorbet/rbi/parser@3.3.7.4.rbi', line 6723

def as_nested_actions; end

#as_replacementsArray<Range, String>

Returns a representation of the rewriter as an ordered list of replacements.

rewriter.as_replacements # => [ [1...1, '('],
                                [2...4, 'foo'],
                                [5...6, ''],
                                [6...6, '!'],
                                [10...10, ')'],
                              ]

This representation is sufficient to recreate the result of process but it is not sufficient to recreate completely the rewriter for further merging/actions. See as_nested_actions

source://parser//lib/parser/source/tree_rewriter.rb#281

Returns:



6742
# File 'sorbet/rbi/parser@3.3.7.4.rbi', line 6742

def as_replacements; end

#diagnosticsDiagnostic::Engine

source://parser//lib/parser/source/tree_rewriter.rb#93

Returns:



6748
# File 'sorbet/rbi/parser@3.3.7.4.rbi', line 6748

def diagnostics; end

#empty?Boolean

Returns true iff no (non trivial) update has been recorded

source://parser//lib/parser/source/tree_rewriter.rb#125

Returns:

  • (Boolean)


6756
# File 'sorbet/rbi/parser@3.3.7.4.rbi', line 6756

def empty?; end

#import!(foreign_rewriter, offset: T.unsafe(nil)) ⇒ Rewriter

For special cases where one needs to merge a rewriter attached to a different source_buffer or that needs to be offset. Policies of the receiver are used.

source://parser//lib/parser/source/tree_rewriter.rb#168

Parameters:

  • rewriter (TreeRewriter)

    from different source_buffer

  • offset (Integer) (defaults to: T.unsafe(nil))

Returns:

Raises:

  • (IndexError)

    if action ranges (once offset) don't fit the current buffer



6768
# File 'sorbet/rbi/parser@3.3.7.4.rbi', line 6768

def import!(foreign_rewriter, offset: T.unsafe(nil)); end

#in_transaction?Boolean

source://parser//lib/parser/source/tree_rewriter.rb#329

Returns:

  • (Boolean)


6774
# File 'sorbet/rbi/parser@3.3.7.4.rbi', line 6774

def in_transaction?; end

#insert_after(range, content) ⇒ Rewriter

Shortcut for wrap(range, nil, content)

source://parser//lib/parser/source/tree_rewriter.rb#242

Parameters:

Returns:

Raises:



6785
# File 'sorbet/rbi/parser@3.3.7.4.rbi', line 6785

def insert_after(range, content); end

#insert_after_multi(range, text) ⇒ Object

This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.

Deprecated.

Use insert_after or wrap

source://parser//lib/parser/source/tree_rewriter.rb#351



6791
# File 'sorbet/rbi/parser@3.3.7.4.rbi', line 6791

def insert_after_multi(range, text); end

#insert_before(range, content) ⇒ Rewriter

Shortcut for wrap(range, content, nil)

source://parser//lib/parser/source/tree_rewriter.rb#230

Parameters:

Returns:

Raises:



6802
# File 'sorbet/rbi/parser@3.3.7.4.rbi', line 6802

def insert_before(range, content); end

#insert_before_multi(range, text) ⇒ Object

This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.

Deprecated.

Use insert_after or wrap

source://parser//lib/parser/source/tree_rewriter.rb#342



6808
# File 'sorbet/rbi/parser@3.3.7.4.rbi', line 6808

def insert_before_multi(range, text); end

#merge(with) ⇒ Rewriter

Returns a new rewriter that consists of the updates of the received and the given argument. Policies of the receiver are used.

source://parser//lib/parser/source/tree_rewriter.rb#155

Parameters:

Returns:

  • (Rewriter)

    merge of receiver and argument

Raises:



6824
# File 'sorbet/rbi/parser@3.3.7.4.rbi', line 6824

def merge(with); end

#merge!(with) ⇒ Rewriter

Merges the updates of argument with the receiver. Policies of the receiver are used. This action is atomic in that it won't change the receiver unless it succeeds.

source://parser//lib/parser/source/tree_rewriter.rb#139

Parameters:

Returns:

Raises:



6837
# File 'sorbet/rbi/parser@3.3.7.4.rbi', line 6837

def merge!(with); end

#processString

Applies all scheduled changes to the source_buffer and returns modified source as a new string.

source://parser//lib/parser/source/tree_rewriter.rb#252

Returns:



6846
# File 'sorbet/rbi/parser@3.3.7.4.rbi', line 6846

def process; end

#remove(range) ⇒ Rewriter

Shortcut for replace(range, '')

source://parser//lib/parser/source/tree_rewriter.rb#217

Parameters:

Returns:

Raises:



6856
# File 'sorbet/rbi/parser@3.3.7.4.rbi', line 6856

def remove(range); end

#replace(range, content) ⇒ Rewriter

Replaces the code of the source range range with content.

source://parser//lib/parser/source/tree_rewriter.rb#193

Parameters:

Returns:

Raises:



6867
# File 'sorbet/rbi/parser@3.3.7.4.rbi', line 6867

def replace(range, content); end

#source_bufferSource::Buffer

source://parser//lib/parser/source/tree_rewriter.rb#92

Returns:



6873
# File 'sorbet/rbi/parser@3.3.7.4.rbi', line 6873

def source_buffer; end

#transactionObject

Provides a protected block where a sequence of multiple rewrite actions are handled atomically. If any of the actions failed by clobbering, all the actions are rolled back. Transactions can be nested.

source://parser//lib/parser/source/tree_rewriter.rb#310

Raises:

  • (RuntimeError)

    when no block is passed



6883
# File 'sorbet/rbi/parser@3.3.7.4.rbi', line 6883

def transaction; end

#wrap(range, insert_before, insert_after) ⇒ Rewriter

Inserts the given strings before and after the given range.

source://parser//lib/parser/source/tree_rewriter.rb#206

Parameters:

Returns:

Raises:



6895
# File 'sorbet/rbi/parser@3.3.7.4.rbi', line 6895

def wrap(range, insert_before, insert_after); end