Skip to content

Commit

Permalink
Finish documenting all public API (closes #73, #104).
Browse files Browse the repository at this point in the history
  • Loading branch information
whitequark committed Oct 5, 2013
1 parent 1393804 commit a75d390
Show file tree
Hide file tree
Showing 5 changed files with 75 additions and 9 deletions.
2 changes: 1 addition & 1 deletion lib/parser/base.rb
Expand Up @@ -218,7 +218,7 @@ def tokenize(source_buffer)

##
# @api private
# @return [TrueClass|FalseClass]
# @return [Boolean]
#
def in_def?
@def_level > 0
Expand Down
2 changes: 1 addition & 1 deletion lib/parser/builders/default.rb
Expand Up @@ -17,7 +17,7 @@ class Builders::Default
#
# Source maps are identical in both cases.
#
# @return [TrueClass|FalseClass]
# @return [Boolean]
attr_accessor :emit_file_line_as_literals

##
Expand Down
8 changes: 4 additions & 4 deletions lib/parser/diagnostic/engine.rb
Expand Up @@ -25,11 +25,11 @@ module Parser
# @!attribute [rw] all_errors_are_fatal
# When set to `true` any error that is encountered will result in
# {Parser::SyntaxError} being raised.
# @return [TrueClass|FalseClass]
# @return [Boolean]
#
# @!attribute [rw] ignore_warnings
# When set to `true` warnings will be ignored.
# @return [TrueClass|FalseClass]
# @return [Boolean]
#
class Diagnostic::Engine
attr_accessor :consumer
Expand Down Expand Up @@ -79,7 +79,7 @@ def process(diagnostic)
# Checks whether `diagnostic` should be ignored.
#
# @param [Parser::Diagnostic] diagnostic
# @return [TrueClass|FalseClass]
# @return [Boolean]
#
def ignore?(diagnostic)
@ignore_warnings &&
Expand All @@ -90,7 +90,7 @@ def ignore?(diagnostic)
# Checks whether `diagnostic` should be raised as an exception.
#
# @param [Parser::Diagnostic] diagnostic
# @return [TrueClass|FalseClass]
# @return [Boolean]
#
def raise?(diagnostic)
(@all_errors_are_fatal &&
Expand Down
9 changes: 8 additions & 1 deletion lib/parser/rewriter.rb
@@ -1,4 +1,5 @@
module Parser

##
# {Parser::Rewriter} offers a basic API that makes it easy to rewrite
# existing ASTs. It's built on top of {Parser::AST::Processor} and
Expand All @@ -7,6 +8,8 @@ module Parser
# For example, assume you want to remove `do` tokens from a while statement.
# You can do this as following:
#
# require 'parser/current'
#
# class RemoveDo < Parser::Rewriter
# def on_while(node)
# # Check if the statement starts with "do"
Expand Down Expand Up @@ -40,6 +43,9 @@ module Parser
# Keep in mind that {Parser::Rewriter} does not take care of indentation when
# inserting/replacing code so you'll have to do this yourself.
#
# See also [a blog entry](http://whitequark.org/blog/2013/04/26/lets-play-with-ruby-code/)
# describing rewriters in greater detail.
#
# @api public
#
class Rewriter < Parser::AST::Processor
Expand All @@ -64,7 +70,7 @@ def rewrite(source_buffer, ast)
# otherwise.
#
# @param [Parser::AST::Node] node
# @return [TrueClass|FalseClass]
# @return [Boolean]
#
def assignment?(node)
[:lvasgn, :ivasgn, :gvasgn, :cvasgn, :casgn].include?(node.type)
Expand Down Expand Up @@ -109,4 +115,5 @@ def replace(range, content)
@source_rewriter.replace(range, content)
end
end

end
63 changes: 61 additions & 2 deletions lib/parser/source/rewriter.rb
Expand Up @@ -2,12 +2,32 @@ module Parser
module Source

##
# {Rewriter} performs the heavy lifting in the source rewriting process.
# It schedules code updates to be performed in the correct order and
# verifies that no two updates _clobber_ each other, that is, attempt to
# modify the same part of code.
#
# If it is detected that one update clobbers another one, an `:error` and
# a `:note` diagnostics describing both updates are generated and passed to
# the diagnostic engine. After that, an exception is raised.
#
# The default diagnostic engine consumer simply prints the diagnostics to `stderr`.
#
# @!attribute [r] source_buffer
# @return [Source::Buffer]
#
# @!attribute [r] diagnostics
# @return [Diagnostic::Engine]
#
# @api public
#
class Rewriter
attr_reader :source_buffer
attr_reader :diagnostics

##
# @param [Source::Buffer] source_buffer
#
def initialize(source_buffer)
@diagnostics = Diagnostic::Engine.new
@diagnostics.consumer = lambda do |diag|
Expand All @@ -19,28 +39,67 @@ def initialize(source_buffer)
@clobber = 0
end

##
# Removes the source range.
#
# @param [Range] range
# @return [Rewriter] self
# @raise [RuntimeError] when clobbering is detected
#
def remove(range)
append Rewriter::Action.new(range, '')
end

##
# Inserts new code before the given source range.
#
# @param [Range] range
# @param [String] content
# @return [Rewriter] self
# @raise [RuntimeError] when clobbering is detected
#
def insert_before(range, content)
append Rewriter::Action.new(range.begin, content)
end

##
# Inserts new code after the given source range.
#
# @param [Range] range
# @param [String] content
# @return [Rewriter] self
# @raise [RuntimeError] when clobbering is detected
#
def insert_after(range, content)
append Rewriter::Action.new(range.end, content)
end

##
# Replaces the code of the source range `range` with `content`.
#
# @param [Range] range
# @param [String] content
# @return [Rewriter] self
# @raise [RuntimeError] when clobbering is detected
#
def replace(range, content)
append Rewriter::Action.new(range, content)
end

##
# Applies all scheduled changes to the `source_buffer` and returns
# modified source as a new string.
#
# @return [String]
#
def process
adjustment = 0
source = @source_buffer.source.dup
adjustment = 0
source = @source_buffer.source.dup

sorted_queue = @queue.sort_by.with_index do |action, index|
[action.range.begin_pos, index]
end

sorted_queue.each do |action|
begin_pos = action.range.begin_pos + adjustment
end_pos = begin_pos + action.range.length
Expand Down

0 comments on commit a75d390

Please sign in to comment.