unparser 0.1.6 → 0.1.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Changelog.md +4 -0
- data/lib/unparser.rb +1 -0
- data/lib/unparser/cli.rb +36 -4
- data/lib/unparser/cli/color.rb +53 -0
- data/lib/unparser/cli/differ.rb +110 -10
- data/lib/unparser/cli/preprocessor.rb +4 -3
- data/lib/unparser/cli/source.rb +61 -9
- data/lib/unparser/emitter/literal/dynamic_body.rb +2 -0
- data/lib/unparser/emitter/resbody.rb +83 -40
- data/lib/unparser/emitter/rescue.rb +47 -3
- data/lib/unparser/node_helpers.rb +2 -2
- data/spec/unit/unparser_spec.rb +24 -0
- data/unparser.gemspec +22 -20
- metadata +3 -2
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA1:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: bbd1a7e700a15704cf6045d49b60c819fa098a56
         | 
| 4 | 
            +
              data.tar.gz: c4309776665a4ee2703ff6569d57423d17b20bd7
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: 96cad113e6bd2c968267edb3f3008e64bcb7c1e217f7256b182ebb3e7412a51a8bb7675204a9b897a926da7e3cdb8ed49a9f34c2516f2db901adcef65c302c68
         | 
| 7 | 
            +
              data.tar.gz: a9a4694e7475058e25e97f107a835cf704533937ea9bfa08985593abb85dfd150daa48633497d354f1ed53ebee3c27bb8fbc04bf1833d2e096933adcad29b214
         | 
    
        data/Changelog.md
    CHANGED
    
    
    
        data/lib/unparser.rb
    CHANGED
    
    
    
        data/lib/unparser/cli.rb
    CHANGED
    
    | @@ -1,12 +1,14 @@ | |
| 1 1 | 
             
            # encoding: utf-8
         | 
| 2 2 |  | 
| 3 3 | 
             
            require 'unparser'
         | 
| 4 | 
            -
            require 'mutant'
         | 
| 5 4 | 
             
            require 'optparse'
         | 
| 5 | 
            +
            require 'diff/lcs'
         | 
| 6 | 
            +
            require 'diff/lcs/hunk'
         | 
| 6 7 |  | 
| 7 8 | 
             
            require 'unparser/cli/preprocessor'
         | 
| 8 9 | 
             
            require 'unparser/cli/source'
         | 
| 9 10 | 
             
            require 'unparser/cli/differ'
         | 
| 11 | 
            +
            require 'unparser/cli/color'
         | 
| 10 12 |  | 
| 11 13 | 
             
            module Unparser
         | 
| 12 14 | 
             
              # Unparser CLI implementation
         | 
| @@ -46,10 +48,14 @@ module Unparser | |
| 46 48 | 
             
                    add_options(builder)
         | 
| 47 49 | 
             
                  end
         | 
| 48 50 |  | 
| 49 | 
            -
                   | 
| 51 | 
            +
                  arguments = opts.parse!(arguments)
         | 
| 50 52 |  | 
| 51 | 
            -
                   | 
| 52 | 
            -
                     | 
| 53 | 
            +
                  arguments.each do |name|
         | 
| 54 | 
            +
                    if File.directory?(name)
         | 
| 55 | 
            +
                      add_directory(name)
         | 
| 56 | 
            +
                    else
         | 
| 57 | 
            +
                      add_file(name)
         | 
| 58 | 
            +
                    end
         | 
| 53 59 | 
             
                  end
         | 
| 54 60 | 
             
                end
         | 
| 55 61 |  | 
| @@ -109,5 +115,31 @@ module Unparser | |
| 109 115 | 
             
                  end
         | 
| 110 116 | 
             
                end
         | 
| 111 117 |  | 
| 118 | 
            +
                # Add file
         | 
| 119 | 
            +
                #
         | 
| 120 | 
            +
                # @param [String] file_name
         | 
| 121 | 
            +
                #
         | 
| 122 | 
            +
                # @return [undefined]
         | 
| 123 | 
            +
                #
         | 
| 124 | 
            +
                # @api private
         | 
| 125 | 
            +
                #
         | 
| 126 | 
            +
                def add_file(file_name)
         | 
| 127 | 
            +
                  @sources << Source::File.new(file_name)
         | 
| 128 | 
            +
                end
         | 
| 129 | 
            +
             | 
| 130 | 
            +
                # Add directory
         | 
| 131 | 
            +
                #
         | 
| 132 | 
            +
                # @param [String] directory_name
         | 
| 133 | 
            +
                #
         | 
| 134 | 
            +
                # @return [undefined]
         | 
| 135 | 
            +
                #
         | 
| 136 | 
            +
                # @api private
         | 
| 137 | 
            +
                #
         | 
| 138 | 
            +
                def add_directory(directory_name)
         | 
| 139 | 
            +
                  Dir.glob(File.join(directory_name, '**/*.rb')).each do |file_name|
         | 
| 140 | 
            +
                    add_file(file_name)
         | 
| 141 | 
            +
                  end
         | 
| 142 | 
            +
                end
         | 
| 143 | 
            +
             | 
| 112 144 | 
             
              end # CLI
         | 
| 113 145 | 
             
            end # Unparser
         | 
| @@ -0,0 +1,53 @@ | |
| 1 | 
            +
            # encoding: utf-8
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module Unparser
         | 
| 4 | 
            +
              # Class to colorize strings
         | 
| 5 | 
            +
              class Color
         | 
| 6 | 
            +
                include Adamantium::Flat, Concord.new(:code)
         | 
| 7 | 
            +
             | 
| 8 | 
            +
                # Format text with color
         | 
| 9 | 
            +
                #
         | 
| 10 | 
            +
                # @param [String] text
         | 
| 11 | 
            +
                #
         | 
| 12 | 
            +
                # @return [String]
         | 
| 13 | 
            +
                #
         | 
| 14 | 
            +
                # @api private
         | 
| 15 | 
            +
                #
         | 
| 16 | 
            +
                def format(text)
         | 
| 17 | 
            +
                  "\e[#{@code}m#{text}\e[0m"
         | 
| 18 | 
            +
                end
         | 
| 19 | 
            +
             | 
| 20 | 
            +
                NONE = Class.new(self) do
         | 
| 21 | 
            +
             | 
| 22 | 
            +
                  # Format null color
         | 
| 23 | 
            +
                  #
         | 
| 24 | 
            +
                  # @param [String] text
         | 
| 25 | 
            +
                  #
         | 
| 26 | 
            +
                  # @return [String]
         | 
| 27 | 
            +
                  #   the argument string
         | 
| 28 | 
            +
                  #
         | 
| 29 | 
            +
                  # @api private
         | 
| 30 | 
            +
                  #
         | 
| 31 | 
            +
                  def format(text)
         | 
| 32 | 
            +
                    text
         | 
| 33 | 
            +
                  end
         | 
| 34 | 
            +
             | 
| 35 | 
            +
                private
         | 
| 36 | 
            +
             | 
| 37 | 
            +
                  # Initialize null color
         | 
| 38 | 
            +
                  #
         | 
| 39 | 
            +
                  # @return [undefined]
         | 
| 40 | 
            +
                  #
         | 
| 41 | 
            +
                  # @api private
         | 
| 42 | 
            +
                  #
         | 
| 43 | 
            +
                  def initialize
         | 
| 44 | 
            +
                  end
         | 
| 45 | 
            +
             | 
| 46 | 
            +
                end.new
         | 
| 47 | 
            +
             | 
| 48 | 
            +
                RED   = Color.new(31)
         | 
| 49 | 
            +
                GREEN = Color.new(32)
         | 
| 50 | 
            +
                BLUE  = Color.new(34)
         | 
| 51 | 
            +
             | 
| 52 | 
            +
              end # Color
         | 
| 53 | 
            +
            end # Unparser
         | 
    
        data/lib/unparser/cli/differ.rb
    CHANGED
    
    | @@ -2,14 +2,12 @@ | |
| 2 2 |  | 
| 3 3 | 
             
            module Unparser
         | 
| 4 4 | 
             
              class CLI
         | 
| 5 | 
            -
                #  | 
| 6 | 
            -
                class Differ | 
| 7 | 
            -
                  include Procto.call(:colorized_diff)
         | 
| 5 | 
            +
                # Class to create diffs from source code
         | 
| 6 | 
            +
                class Differ
         | 
| 7 | 
            +
                  include Adamantium::Flat, Concord.new(:old, :new), Procto.call(:colorized_diff)
         | 
| 8 8 |  | 
| 9 9 | 
             
                  # Return source diff
         | 
| 10 10 | 
             
                  #
         | 
| 11 | 
            -
                  # FIXME: Multiple diffs get screwed up!
         | 
| 12 | 
            -
                  #
         | 
| 13 11 | 
             
                  # @return [String]
         | 
| 14 12 | 
             
                  #   if there is a diff
         | 
| 15 13 | 
             
                  #
         | 
| @@ -19,12 +17,114 @@ module Unparser | |
| 19 17 | 
             
                  # @api private
         | 
| 20 18 | 
             
                  #
         | 
| 21 19 | 
             
                  def diff
         | 
| 22 | 
            -
                     | 
| 23 | 
            -
             | 
| 24 | 
            -
                     | 
| 20 | 
            +
                    output = ""
         | 
| 21 | 
            +
                    lines = 5
         | 
| 22 | 
            +
                    hunk = oldhunk = nil
         | 
| 23 | 
            +
                    file_length_difference = new.length - old.length
         | 
| 24 | 
            +
                    diffs.each do |piece|
         | 
| 25 | 
            +
                      begin
         | 
| 26 | 
            +
                        hunk = Diff::LCS::Hunk.new(old, new, piece, lines, file_length_difference)
         | 
| 27 | 
            +
                        file_length_difference = hunk.file_length_difference
         | 
| 28 | 
            +
             | 
| 29 | 
            +
                        next unless oldhunk
         | 
| 30 | 
            +
                        next if (lines > 0) && hunk.merge(oldhunk)
         | 
| 31 | 
            +
             | 
| 32 | 
            +
                        output << oldhunk.diff(:unified) << "\n"
         | 
| 33 | 
            +
                      ensure
         | 
| 34 | 
            +
                        oldhunk = hunk
         | 
| 35 | 
            +
                      end
         | 
| 36 | 
            +
                    end
         | 
| 37 | 
            +
                    output << oldhunk.diff(:unified) << "\n"
         | 
| 38 | 
            +
             | 
| 39 | 
            +
                    output
         | 
| 25 40 | 
             
                  end
         | 
| 26 41 | 
             
                  memoize :diff
         | 
| 27 42 |  | 
| 28 | 
            -
             | 
| 29 | 
            -
             | 
| 43 | 
            +
                  # Return colorized source diff
         | 
| 44 | 
            +
                  #
         | 
| 45 | 
            +
                  # @return [String]
         | 
| 46 | 
            +
                  #   if there is a diff
         | 
| 47 | 
            +
                  #
         | 
| 48 | 
            +
                  # @return [nil]
         | 
| 49 | 
            +
                  #   otherwise
         | 
| 50 | 
            +
                  #
         | 
| 51 | 
            +
                  # @api private
         | 
| 52 | 
            +
                  #
         | 
| 53 | 
            +
                  def colorized_diff
         | 
| 54 | 
            +
                    diff.lines.map do |line|
         | 
| 55 | 
            +
                      self.class.colorize_line(line)
         | 
| 56 | 
            +
                    end.join
         | 
| 57 | 
            +
                  end
         | 
| 58 | 
            +
                  memoize :colorized_diff
         | 
| 59 | 
            +
             | 
| 60 | 
            +
                  # Return new object
         | 
| 61 | 
            +
                  #
         | 
| 62 | 
            +
                  # @param [String] old
         | 
| 63 | 
            +
                  # @param [String] new
         | 
| 64 | 
            +
                  #
         | 
| 65 | 
            +
                  # @return [Differ]
         | 
| 66 | 
            +
                  #
         | 
| 67 | 
            +
                  # @api private
         | 
| 68 | 
            +
                  #
         | 
| 69 | 
            +
                  def self.build(old, new)
         | 
| 70 | 
            +
                    new(lines(old), lines(new))
         | 
| 71 | 
            +
                  end
         | 
| 72 | 
            +
             | 
| 73 | 
            +
                  # Break up source into lines
         | 
| 74 | 
            +
                  #
         | 
| 75 | 
            +
                  # @param [String] source
         | 
| 76 | 
            +
                  #
         | 
| 77 | 
            +
                  # @return [Array<String>]
         | 
| 78 | 
            +
                  #
         | 
| 79 | 
            +
                  # @api private
         | 
| 80 | 
            +
                  #
         | 
| 81 | 
            +
                  def self.lines(source)
         | 
| 82 | 
            +
                    source.lines.map { |line| line.chomp }
         | 
| 83 | 
            +
                  end
         | 
| 84 | 
            +
                  private_class_method :lines
         | 
| 85 | 
            +
             | 
| 86 | 
            +
                private
         | 
| 87 | 
            +
             | 
| 88 | 
            +
                  # Return diffs
         | 
| 89 | 
            +
                  #
         | 
| 90 | 
            +
                  # @return [Array<Array>]
         | 
| 91 | 
            +
                  #
         | 
| 92 | 
            +
                  # @api private
         | 
| 93 | 
            +
                  #
         | 
| 94 | 
            +
                  def diffs
         | 
| 95 | 
            +
                    Diff::LCS.diff(old, new)
         | 
| 96 | 
            +
                  end
         | 
| 97 | 
            +
                  memoize :diffs
         | 
| 98 | 
            +
             | 
| 99 | 
            +
                  # Return max length
         | 
| 100 | 
            +
                  #
         | 
| 101 | 
            +
                  # @return [Fixnum]
         | 
| 102 | 
            +
                  #
         | 
| 103 | 
            +
                  # @api private
         | 
| 104 | 
            +
                  #
         | 
| 105 | 
            +
                  def max_length
         | 
| 106 | 
            +
                    [old, new].map(&:length).max
         | 
| 107 | 
            +
                  end
         | 
| 108 | 
            +
             | 
| 109 | 
            +
                  # Return colorized diff line
         | 
| 110 | 
            +
                  #
         | 
| 111 | 
            +
                  # @param [String] line
         | 
| 112 | 
            +
                  #
         | 
| 113 | 
            +
                  # @return [String]
         | 
| 114 | 
            +
                  #
         | 
| 115 | 
            +
                  # @api private
         | 
| 116 | 
            +
                  #
         | 
| 117 | 
            +
                  def self.colorize_line(line)
         | 
| 118 | 
            +
                    case line[0]
         | 
| 119 | 
            +
                    when '+'
         | 
| 120 | 
            +
                      Color::GREEN
         | 
| 121 | 
            +
                    when '-'
         | 
| 122 | 
            +
                      Color::RED
         | 
| 123 | 
            +
                    else
         | 
| 124 | 
            +
                      Color::NONE
         | 
| 125 | 
            +
                    end.format(line)
         | 
| 126 | 
            +
                  end
         | 
| 127 | 
            +
             | 
| 128 | 
            +
                end # CLI
         | 
| 129 | 
            +
              end # Differ
         | 
| 30 130 | 
             
            end # Unparser
         | 
| @@ -91,8 +91,9 @@ module Unparser | |
| 91 91 | 
             
                    # @api private
         | 
| 92 92 | 
             
                    #
         | 
| 93 93 | 
             
                    def result
         | 
| 94 | 
            -
                      s(node.type,  | 
| 94 | 
            +
                      s(node.type, mapped_children)
         | 
| 95 95 | 
             
                    end
         | 
| 96 | 
            +
             | 
| 96 97 | 
             
                  end # Noop
         | 
| 97 98 |  | 
| 98 99 | 
             
                  # Preprocessor for dynamic string nodes. Collapses adjacent string segments into one.
         | 
| @@ -108,7 +109,7 @@ module Unparser | |
| 108 109 | 
             
                    #
         | 
| 109 110 | 
             
                    def result
         | 
| 110 111 | 
             
                      if collapsed_children.all? { |node| node.type == :str }
         | 
| 111 | 
            -
                        s(:str, collapsed_children.map { |node| node.children.first }.join)
         | 
| 112 | 
            +
                        s(:str, [collapsed_children.map { |node| node.children.first }.join])
         | 
| 112 113 | 
             
                      else
         | 
| 113 114 | 
             
                        node.updated(nil, collapsed_children)
         | 
| 114 115 | 
             
                      end
         | 
| @@ -125,7 +126,7 @@ module Unparser | |
| 125 126 | 
             
                    def collapsed_children
         | 
| 126 127 | 
             
                      chunked_children.each_with_object([]) do |(type, nodes), aggregate|
         | 
| 127 128 | 
             
                        if type == :str
         | 
| 128 | 
            -
                          aggregate << s(:str, nodes.map { |node| node.children.first }.join)
         | 
| 129 | 
            +
                          aggregate << s(:str, [nodes.map { |node| node.children.first }.join])
         | 
| 129 130 | 
             
                        else
         | 
| 130 131 | 
             
                          aggregate.concat(nodes)
         | 
| 131 132 | 
             
                        end
         | 
    
        data/lib/unparser/cli/source.rb
    CHANGED
    
    | @@ -4,7 +4,7 @@ module Unparser | |
| 4 4 | 
             
              class CLI
         | 
| 5 5 | 
             
                # Source representation for CLI sources
         | 
| 6 6 | 
             
                class Source
         | 
| 7 | 
            -
                  include AbstractType, Adamantium::Flat
         | 
| 7 | 
            +
                  include AbstractType, Adamantium::Flat, NodeHelpers
         | 
| 8 8 |  | 
| 9 9 | 
             
                  # Test if source could be unparsed successfully
         | 
| 10 10 | 
             
                  #
         | 
| @@ -16,7 +16,7 @@ module Unparser | |
| 16 16 | 
             
                  # @api private
         | 
| 17 17 | 
             
                  #
         | 
| 18 18 | 
             
                  def success?
         | 
| 19 | 
            -
                    original_ast == generated_ast
         | 
| 19 | 
            +
                    original_ast && generated_ast && original_ast == generated_ast
         | 
| 20 20 | 
             
                  end
         | 
| 21 21 |  | 
| 22 22 | 
             
                  # Return error report
         | 
| @@ -26,14 +26,15 @@ module Unparser | |
| 26 26 | 
             
                  # @api private
         | 
| 27 27 | 
             
                  #
         | 
| 28 28 | 
             
                  def error_report
         | 
| 29 | 
            -
                     | 
| 30 | 
            -
                       | 
| 31 | 
            -
             | 
| 32 | 
            -
             | 
| 33 | 
            -
                     | 
| 29 | 
            +
                    if original_ast && generated_ast
         | 
| 30 | 
            +
                      error_report_with_ast_diff
         | 
| 31 | 
            +
                    else
         | 
| 32 | 
            +
                      error_report_with_parser_error
         | 
| 33 | 
            +
                    end
         | 
| 34 34 | 
             
                  end
         | 
| 35 35 | 
             
                  memoize :error_report
         | 
| 36 36 |  | 
| 37 | 
            +
             | 
| 37 38 | 
             
                private
         | 
| 38 39 |  | 
| 39 40 | 
             
                  # Return generated source
         | 
| @@ -47,14 +48,51 @@ module Unparser | |
| 47 48 | 
             
                  end
         | 
| 48 49 | 
             
                  memoize :generated_source
         | 
| 49 50 |  | 
| 51 | 
            +
                  # Return error report with parser error
         | 
| 52 | 
            +
                  #
         | 
| 53 | 
            +
                  # @return [String]
         | 
| 54 | 
            +
                  #
         | 
| 55 | 
            +
                  # @api private
         | 
| 56 | 
            +
                  #
         | 
| 57 | 
            +
                  def error_report_with_parser_error
         | 
| 58 | 
            +
                    unless original_ast
         | 
| 59 | 
            +
                      return "Parsing of original source failed:\n#{original_source}"
         | 
| 60 | 
            +
                    end
         | 
| 61 | 
            +
             | 
| 62 | 
            +
                    unless generated_ast
         | 
| 63 | 
            +
                      return "Parsing of generated source failed:\nOriginal-AST:#{original_ast.inspect}\nSource:\n#{generated_source}"
         | 
| 64 | 
            +
                    end
         | 
| 65 | 
            +
             | 
| 66 | 
            +
                  end
         | 
| 67 | 
            +
             | 
| 68 | 
            +
                  # Return error report with AST difference
         | 
| 69 | 
            +
                  #
         | 
| 70 | 
            +
                  # @return [String]
         | 
| 71 | 
            +
                  #
         | 
| 72 | 
            +
                  # @api private
         | 
| 73 | 
            +
                  #
         | 
| 74 | 
            +
                  def error_report_with_ast_diff
         | 
| 75 | 
            +
                    diff = Differ.call(
         | 
| 76 | 
            +
                      original_ast.inspect.lines.map(&:chomp),
         | 
| 77 | 
            +
                      generated_ast.inspect.lines.map(&:chomp)
         | 
| 78 | 
            +
                    )
         | 
| 79 | 
            +
                    "#{diff}\nOriginal:\n#{original_source}\nGenerated:\n#{generated_source}"
         | 
| 80 | 
            +
                  end
         | 
| 81 | 
            +
             | 
| 50 82 | 
             
                  # Return generated AST
         | 
| 51 83 | 
             
                  #
         | 
| 52 84 | 
             
                  # @return [Parser::AST::Node]
         | 
| 85 | 
            +
                  #   if parser was sucessful for generated ast
         | 
| 86 | 
            +
                  #
         | 
| 87 | 
            +
                  # @return [nil]
         | 
| 88 | 
            +
                  #   otherwise
         | 
| 53 89 | 
             
                  #
         | 
| 54 90 | 
             
                  # @api private
         | 
| 55 91 | 
             
                  #
         | 
| 56 92 | 
             
                  def generated_ast
         | 
| 57 | 
            -
                    Preprocessor.run( | 
| 93 | 
            +
                    Preprocessor.run(parse(generated_source)) || s(:empty)
         | 
| 94 | 
            +
                  rescue Parser::SyntaxError
         | 
| 95 | 
            +
                    nil
         | 
| 58 96 | 
             
                  end
         | 
| 59 97 | 
             
                  memoize :generated_ast
         | 
| 60 98 |  | 
| @@ -65,10 +103,24 @@ module Unparser | |
| 65 103 | 
             
                  # @api private
         | 
| 66 104 | 
             
                  #
         | 
| 67 105 | 
             
                  def original_ast
         | 
| 68 | 
            -
                    Preprocessor.run( | 
| 106 | 
            +
                    Preprocessor.run(parse(original_source)) || s(:empty)
         | 
| 107 | 
            +
                  rescue Parser::SyntaxError
         | 
| 108 | 
            +
                    nil
         | 
| 69 109 | 
             
                  end
         | 
| 70 110 | 
             
                  memoize :original_ast
         | 
| 71 111 |  | 
| 112 | 
            +
                  # Parse source with current ruby
         | 
| 113 | 
            +
                  #
         | 
| 114 | 
            +
                  # @param [String] source
         | 
| 115 | 
            +
                  #
         | 
| 116 | 
            +
                  # @return [Parser::AST::Node]
         | 
| 117 | 
            +
                  #
         | 
| 118 | 
            +
                  # @api private
         | 
| 119 | 
            +
                  #
         | 
| 120 | 
            +
                  def parse(source)
         | 
| 121 | 
            +
                    Parser::CurrentRuby.parse(source)
         | 
| 122 | 
            +
                  end
         | 
| 123 | 
            +
             | 
| 72 124 | 
             
                  # CLI source from string
         | 
| 73 125 | 
             
                  class String < self
         | 
| 74 126 | 
             
                    include Concord.new(:original_source)
         | 
| @@ -5,49 +5,92 @@ module Unparser | |
| 5 5 | 
             
                # Emitter for rescue body nodes
         | 
| 6 6 | 
             
                class Resbody < self
         | 
| 7 7 |  | 
| 8 | 
            -
             | 
| 9 | 
            -
             | 
| 10 | 
            -
                  children :exception, :assignment, :body
         | 
| 11 | 
            -
             | 
| 12 | 
            -
                private
         | 
| 13 | 
            -
             | 
| 14 | 
            -
                  # Perform dispatch
         | 
| 15 | 
            -
                  #
         | 
| 16 | 
            -
                  # @return [undefined]
         | 
| 17 | 
            -
                  #
         | 
| 18 | 
            -
                  # @api private
         | 
| 19 | 
            -
                  #
         | 
| 20 | 
            -
                  def dispatch
         | 
| 21 | 
            -
                    write(K_RESCUE)
         | 
| 22 | 
            -
                    emit_exception
         | 
| 23 | 
            -
                    emit_assignment
         | 
| 24 | 
            -
                    emit_body
         | 
| 25 | 
            -
                  end
         | 
| 8 | 
            +
                    children :exception, :assignment, :body
         | 
| 26 9 |  | 
| 27 | 
            -
                   | 
| 28 | 
            -
             | 
| 29 | 
            -
             | 
| 30 | 
            -
             | 
| 31 | 
            -
                   | 
| 32 | 
            -
             | 
| 33 | 
            -
             | 
| 34 | 
            -
                     | 
| 35 | 
            -
                     | 
| 36 | 
            -
                     | 
| 37 | 
            -
             | 
| 10 | 
            +
                  class Standalone < self
         | 
| 11 | 
            +
             | 
| 12 | 
            +
                    handle :resbody
         | 
| 13 | 
            +
             | 
| 14 | 
            +
                  private
         | 
| 15 | 
            +
             | 
| 16 | 
            +
                    # Perform dispatch
         | 
| 17 | 
            +
                    #
         | 
| 18 | 
            +
                    # @return [undefined]
         | 
| 19 | 
            +
                    #
         | 
| 20 | 
            +
                    # @api private
         | 
| 21 | 
            +
                    #
         | 
| 22 | 
            +
                    def dispatch
         | 
| 23 | 
            +
                      write(K_RESCUE)
         | 
| 24 | 
            +
                      parentheses { visit(body) }
         | 
| 25 | 
            +
                    end
         | 
| 26 | 
            +
             | 
| 27 | 
            +
                    # Emit exception
         | 
| 28 | 
            +
                    #
         | 
| 29 | 
            +
                    # @return [undefined]
         | 
| 30 | 
            +
                    #
         | 
| 31 | 
            +
                    # @api private
         | 
| 32 | 
            +
                    #
         | 
| 33 | 
            +
                    def emit_exception
         | 
| 34 | 
            +
                      return unless exception
         | 
| 35 | 
            +
                      ws
         | 
| 36 | 
            +
                      delimited(exception.children)
         | 
| 37 | 
            +
                    end
         | 
| 38 38 |  | 
| 39 | 
            -
             | 
| 40 | 
            -
             | 
| 41 | 
            -
             | 
| 42 | 
            -
             | 
| 43 | 
            -
             | 
| 44 | 
            -
             | 
| 45 | 
            -
             | 
| 46 | 
            -
             | 
| 47 | 
            -
             | 
| 48 | 
            -
             | 
| 39 | 
            +
                    # Emit assignment
         | 
| 40 | 
            +
                    #
         | 
| 41 | 
            +
                    # @return [undefined]
         | 
| 42 | 
            +
                    #
         | 
| 43 | 
            +
                    # @api private
         | 
| 44 | 
            +
                    #
         | 
| 45 | 
            +
                    def emit_assignment
         | 
| 46 | 
            +
                      return unless assignment
         | 
| 47 | 
            +
                      write(WS, T_ASR, WS)
         | 
| 48 | 
            +
                      visit(assignment)
         | 
| 49 | 
            +
                    end
         | 
| 49 50 | 
             
                  end
         | 
| 50 51 |  | 
| 51 | 
            -
             | 
| 52 | 
            +
                  class Embedded < self
         | 
| 53 | 
            +
             | 
| 54 | 
            +
                  private
         | 
| 55 | 
            +
             | 
| 56 | 
            +
                    # Perform dispatch
         | 
| 57 | 
            +
                    #
         | 
| 58 | 
            +
                    # @return [undefined]
         | 
| 59 | 
            +
                    #
         | 
| 60 | 
            +
                    # @api private
         | 
| 61 | 
            +
                    #
         | 
| 62 | 
            +
                    def dispatch
         | 
| 63 | 
            +
                      write(K_RESCUE)
         | 
| 64 | 
            +
                      emit_exception
         | 
| 65 | 
            +
                      emit_assignment
         | 
| 66 | 
            +
                      emit_body
         | 
| 67 | 
            +
                    end
         | 
| 68 | 
            +
             | 
| 69 | 
            +
                    # Emit exception
         | 
| 70 | 
            +
                    #
         | 
| 71 | 
            +
                    # @return [undefined]
         | 
| 72 | 
            +
                    #
         | 
| 73 | 
            +
                    # @api private
         | 
| 74 | 
            +
                    #
         | 
| 75 | 
            +
                    def emit_exception
         | 
| 76 | 
            +
                      return unless exception
         | 
| 77 | 
            +
                      ws
         | 
| 78 | 
            +
                      delimited(exception.children)
         | 
| 79 | 
            +
                    end
         | 
| 80 | 
            +
             | 
| 81 | 
            +
                    # Emit assignment
         | 
| 82 | 
            +
                    #
         | 
| 83 | 
            +
                    # @return [undefined]
         | 
| 84 | 
            +
                    #
         | 
| 85 | 
            +
                    # @api private
         | 
| 86 | 
            +
                    #
         | 
| 87 | 
            +
                    def emit_assignment
         | 
| 88 | 
            +
                      return unless assignment
         | 
| 89 | 
            +
                      write(WS, T_ASR, WS)
         | 
| 90 | 
            +
                      visit(assignment)
         | 
| 91 | 
            +
                    end
         | 
| 92 | 
            +
             | 
| 93 | 
            +
                  end # Resbody
         | 
| 94 | 
            +
                end
         | 
| 52 95 | 
             
              end # Emitter
         | 
| 53 96 | 
             
            end # Unparser
         | 
| @@ -7,7 +7,11 @@ module Unparser | |
| 7 7 |  | 
| 8 8 | 
             
                  handle :rescue
         | 
| 9 9 |  | 
| 10 | 
            -
                  children :body
         | 
| 10 | 
            +
                  children :body, :rescue_body
         | 
| 11 | 
            +
             | 
| 12 | 
            +
                  RESCUE_BODIES_RANGE = (1..-2).freeze
         | 
| 13 | 
            +
             | 
| 14 | 
            +
                  EMBEDDED_TYPES = [:def, :defs, :kwbegin, :ensure].to_set.freeze
         | 
| 11 15 |  | 
| 12 16 | 
             
                private
         | 
| 13 17 |  | 
| @@ -18,13 +22,53 @@ module Unparser | |
| 18 22 | 
             
                  # @api private
         | 
| 19 23 | 
             
                  #
         | 
| 20 24 | 
             
                  def dispatch
         | 
| 25 | 
            +
                    if standalone?
         | 
| 26 | 
            +
                      emit_standalone
         | 
| 27 | 
            +
                    else
         | 
| 28 | 
            +
                      emit_embedded
         | 
| 29 | 
            +
                    end
         | 
| 30 | 
            +
                  end
         | 
| 31 | 
            +
             | 
| 32 | 
            +
                  # Test if rescue node ist standalone
         | 
| 33 | 
            +
                  #
         | 
| 34 | 
            +
                  # @return [true]
         | 
| 35 | 
            +
                  #   if rescue node is standalone
         | 
| 36 | 
            +
                  #
         | 
| 37 | 
            +
                  # @return [false]
         | 
| 38 | 
            +
                  #   otherwise
         | 
| 39 | 
            +
                  #
         | 
| 40 | 
            +
                  # @api private
         | 
| 41 | 
            +
                  #
         | 
| 42 | 
            +
                  def standalone?
         | 
| 43 | 
            +
                    !EMBEDDED_TYPES.include?(parent_type) && body
         | 
| 44 | 
            +
                  end
         | 
| 45 | 
            +
             | 
| 46 | 
            +
                  # Emit standalone form
         | 
| 47 | 
            +
                  #
         | 
| 48 | 
            +
                  # @return [undefined]
         | 
| 49 | 
            +
                  #
         | 
| 50 | 
            +
                  # @api private
         | 
| 51 | 
            +
                  #
         | 
| 52 | 
            +
                  def emit_standalone
         | 
| 53 | 
            +
                    visit(body)
         | 
| 54 | 
            +
                    ws
         | 
| 55 | 
            +
                    run(Resbody::Standalone, rescue_body)
         | 
| 56 | 
            +
                  end
         | 
| 57 | 
            +
             | 
| 58 | 
            +
                  # Emit embedded form
         | 
| 59 | 
            +
                  #
         | 
| 60 | 
            +
                  # @return [undefined]
         | 
| 61 | 
            +
                  #
         | 
| 62 | 
            +
                  # @api private
         | 
| 63 | 
            +
                  #
         | 
| 64 | 
            +
                  def emit_embedded
         | 
| 21 65 | 
             
                    if body
         | 
| 22 66 | 
             
                      visit_indented(body)
         | 
| 23 67 | 
             
                    else
         | 
| 24 68 | 
             
                      nl
         | 
| 25 69 | 
             
                    end
         | 
| 26 70 | 
             
                    rescue_bodies.each do |child|
         | 
| 27 | 
            -
                       | 
| 71 | 
            +
                      run(Resbody::Embedded, child)
         | 
| 28 72 | 
             
                    end
         | 
| 29 73 | 
             
                    emit_else
         | 
| 30 74 | 
             
                  end
         | 
| @@ -36,7 +80,7 @@ module Unparser | |
| 36 80 | 
             
                  # @api private
         | 
| 37 81 | 
             
                  #
         | 
| 38 82 | 
             
                  def rescue_bodies
         | 
| 39 | 
            -
                    children[ | 
| 83 | 
            +
                    children[RESCUE_BODIES_RANGE]
         | 
| 40 84 | 
             
                  end
         | 
| 41 85 |  | 
| 42 86 | 
             
                  # Emit else
         | 
    
        data/spec/unit/unparser_spec.rb
    CHANGED
    
    | @@ -91,6 +91,8 @@ describe Unparser do | |
| 91 91 | 
             
                    assert_source %q("foo\nbar")
         | 
| 92 92 | 
             
                    assert_source %q("foo bar #{}")
         | 
| 93 93 | 
             
                    assert_source %q("foo\nbar #{}")
         | 
| 94 | 
            +
                    assert_source %q("#{}\#{}")
         | 
| 95 | 
            +
                    assert_source %q("\#{}#{}")
         | 
| 94 96 | 
             
                    # Within indentation
         | 
| 95 97 | 
             
                    assert_generates <<-'RUBY', <<-'RUBY'
         | 
| 96 98 | 
             
                      if foo
         | 
| @@ -632,6 +634,10 @@ describe Unparser do | |
| 632 634 | 
             
                      baz
         | 
| 633 635 | 
             
                    end
         | 
| 634 636 | 
             
                  RUBY
         | 
| 637 | 
            +
             | 
| 638 | 
            +
                  assert_source 'foo rescue(bar)'
         | 
| 639 | 
            +
                  assert_source 'foo rescue(return(bar))'
         | 
| 640 | 
            +
                  assert_source 'x = foo rescue(return(bar))'
         | 
| 635 641 | 
             
                end
         | 
| 636 642 |  | 
| 637 643 | 
             
                context 'super' do
         | 
| @@ -770,12 +776,30 @@ describe Unparser do | |
| 770 776 |  | 
| 771 777 | 
             
                    assert_source <<-'RUBY'
         | 
| 772 778 | 
             
                      def foo
         | 
| 779 | 
            +
                        foo
         | 
| 780 | 
            +
                      rescue
         | 
| 773 781 | 
             
                        bar
         | 
| 774 782 | 
             
                      ensure
         | 
| 775 783 | 
             
                        baz
         | 
| 776 784 | 
             
                      end
         | 
| 777 785 | 
             
                    RUBY
         | 
| 778 786 |  | 
| 787 | 
            +
                    assert_source <<-'RUBY'
         | 
| 788 | 
            +
                      def foo
         | 
| 789 | 
            +
                        bar
         | 
| 790 | 
            +
                      ensure
         | 
| 791 | 
            +
                        baz
         | 
| 792 | 
            +
                      end
         | 
| 793 | 
            +
                    RUBY
         | 
| 794 | 
            +
             | 
| 795 | 
            +
                    assert_source <<-'RUBY'
         | 
| 796 | 
            +
                      def self.foo
         | 
| 797 | 
            +
                        bar
         | 
| 798 | 
            +
                      rescue
         | 
| 799 | 
            +
                        baz
         | 
| 800 | 
            +
                      end
         | 
| 801 | 
            +
                    RUBY
         | 
| 802 | 
            +
             | 
| 779 803 | 
             
                    assert_source <<-'RUBY'
         | 
| 780 804 | 
             
                      def foo
         | 
| 781 805 | 
             
                        bar
         | 
    
        data/unparser.gemspec
    CHANGED
    
    | @@ -1,26 +1,28 @@ | |
| 1 1 | 
             
            # -*- encoding: utf-8 -*-
         | 
| 2 2 |  | 
| 3 | 
            -
            Gem::Specification.new do | | 
| 4 | 
            -
               | 
| 5 | 
            -
               | 
| 3 | 
            +
            Gem::Specification.new do |gem|
         | 
| 4 | 
            +
              gem.name     = 'unparser'
         | 
| 5 | 
            +
              gem.version  = '0.1.7'
         | 
| 6 6 |  | 
| 7 | 
            -
               | 
| 8 | 
            -
               | 
| 9 | 
            -
               | 
| 10 | 
            -
               | 
| 11 | 
            -
               | 
| 12 | 
            -
               | 
| 7 | 
            +
              gem.authors  = ['Markus Schirp']
         | 
| 8 | 
            +
              gem.email    = 'mbj@schir-dso.com'
         | 
| 9 | 
            +
              gem.summary  = 'Generate equivalent source for parser gem AST nodes'
         | 
| 10 | 
            +
              gem.description = gem.summary
         | 
| 11 | 
            +
              gem.homepage = 'http://github.com/mbj/unparser'
         | 
| 12 | 
            +
              gem.license  = 'MIT'
         | 
| 13 13 |  | 
| 14 | 
            -
               | 
| 15 | 
            -
               | 
| 16 | 
            -
               | 
| 17 | 
            -
               | 
| 18 | 
            -
               | 
| 14 | 
            +
              gem.files            = `git ls-files`.split("\n")
         | 
| 15 | 
            +
              gem.test_files       = `git ls-files -- {spec,features}/*`.split("\n")
         | 
| 16 | 
            +
              gem.require_paths    = %w(lib)
         | 
| 17 | 
            +
              gem.extra_rdoc_files = %w(README.md)
         | 
| 18 | 
            +
              gem.executables      = [ 'unparser' ]
         | 
| 19 19 |  | 
| 20 | 
            -
               | 
| 21 | 
            -
             | 
| 22 | 
            -
               | 
| 23 | 
            -
               | 
| 24 | 
            -
               | 
| 25 | 
            -
               | 
| 20 | 
            +
              gem.required_ruby_version
         | 
| 21 | 
            +
             | 
| 22 | 
            +
              gem.add_dependency('parser',        '~> 2.1.0')
         | 
| 23 | 
            +
              gem.add_dependency('procto',        '~> 0.0.2')
         | 
| 24 | 
            +
              gem.add_dependency('concord',       '~> 0.1.4')
         | 
| 25 | 
            +
              gem.add_dependency('adamantium',    '~> 0.1')
         | 
| 26 | 
            +
              gem.add_dependency('equalizer',     '~> 0.0.7')
         | 
| 27 | 
            +
              gem.add_dependency('abstract_type', '~> 0.0.7')
         | 
| 26 28 | 
             
            end
         | 
    
        metadata
    CHANGED
    
    | @@ -1,14 +1,14 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: unparser
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 0.1. | 
| 4 | 
            +
              version: 0.1.7
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - Markus Schirp
         | 
| 8 8 | 
             
            autorequire: 
         | 
| 9 9 | 
             
            bindir: bin
         | 
| 10 10 | 
             
            cert_chain: []
         | 
| 11 | 
            -
            date:  | 
| 11 | 
            +
            date: 2014-01-03 00:00:00.000000000 Z
         | 
| 12 12 | 
             
            dependencies:
         | 
| 13 13 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 14 14 | 
             
              name: parser
         | 
| @@ -125,6 +125,7 @@ files: | |
| 125 125 | 
             
            - lib/unparser.rb
         | 
| 126 126 | 
             
            - lib/unparser/buffer.rb
         | 
| 127 127 | 
             
            - lib/unparser/cli.rb
         | 
| 128 | 
            +
            - lib/unparser/cli/color.rb
         | 
| 128 129 | 
             
            - lib/unparser/cli/differ.rb
         | 
| 129 130 | 
             
            - lib/unparser/cli/preprocessor.rb
         | 
| 130 131 | 
             
            - lib/unparser/cli/source.rb
         |