jruby / jruby-parser

JRuby's parser customized for IDE usage

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

IndexOutOfBoundsException while rewriting

ftomassetti opened this issue · comments

I parsed this method and I was trying to regenerate the code with this code:

            sw = java.io.StringWriter.new
            rwv = org.jrubyparser.rewriter.ReWriteVisitor.new(sw,'')
            cbw = org.jrubyparser.rewriter.ClassBodyWriter.new(rwv,corr_node)
            cbw.write
            sw.to_string

This code works for thousand of methods but fail on a few.

The methods parsed and failed 1/2:

     def index
          @question = params[:q] || ""
          @question.strip!
          @all_words = params[:all_words] ? params[:all_words].present? : true
          @titles_only = params[:titles_only] ? params[:titles_only].present? : false

          projects_to_search =
            case params[:scope]
            when 'all'
              nil
            when 'my_projects'
              User.current.memberships.collect(&:project)
            when 'subprojects'
              @project ? (@project.self_and_descendants.active.all) : nil
            else
              @project
            end

          offset = nil
          begin; offset = params[:offset].to_time if params[:offset]; rescue; end

          # quick jump to an issue
          if (m = @question.match(/^#?(\d+)$/)) && (issue = Issue.visible.find_by_id(m[1].to_i))
            redirect_to issue_path(issue)
            return
          end

          @object_types = Redmine::Search.available_search_types.dup
          if projects_to_search.is_a? Project
            # don't search projects
            @object_types.delete('projects')
            # only show what the user is allowed to view
            @object_types = @object_types.select {|o| User.current.allowed_to?("view_#{o}".to_sym, projects_to_search)}
          end

          @scope = @object_types.select {|t| params[t]}
          @scope = @object_types if @scope.empty?

          # extract tokens from the question
          # eg. hello "bye bye" => ["hello", "bye bye"]
          @tokens = @question.scan(%r{((\s|^)"[\s\w]+"(\s|$)|\S+)}).collect {|m| m.first.gsub(%r{(^\s*"\s*|\s*"\s*$)}, '')}
          # tokens must be at least 2 characters long
          @tokens = @tokens.uniq.select {|w| w.length > 1 }

          if !@tokens.empty?
            # no more than 5 tokens to search for
            @tokens.slice! 5..-1 if @tokens.size > 5

            @results = []
            @results_by_type = Hash.new {|h,k| h[k] = 0}

            limit = 10
            @scope.each do |s|
              r, c = s.singularize.camelcase.constantize.search(@tokens, projects_to_search,
                :all_words => @all_words,
                :titles_only => @titles_only,
                :limit => (limit+1),
                :offset => offset,
                :before => params[:previous].nil?)
              @results += r
              @results_by_type[s] += c
            end
            @results = @results.sort {|a,b| b.event_datetime <=> a.event_datetime}
            if params[:previous].nil?
              @pagination_previous_date = @results[0].event_datetime if offset && @results[0]
              if @results.size > limit
                @pagination_next_date = @results[limit-1].event_datetime
                @results = @results[0, limit]
              end
            else
              @pagination_next_date = @results[-1].event_datetime if offset && @results[-1]
              if @results.size > limit
                @pagination_previous_date = @results[-(limit)].event_datetime
                @results = @results[-(limit), limit]
              end
            end
          else
            @question = ""
          end
          render :layout => false if request.xhr?
        end

methods 2/2:

  def pretty_title
        WikiPage.pretty_title(title)
  end

This is the exception I get:

String.java:695:in charAt': java.lang.StringIndexOutOfBoundsException: String index out of range: 1344 from ShortIfNodeReWriteVisitor.java:47:invisitNewlineNode'
from NewlineNode.java:65:in accept' from ReWriteVisitor.java:247:invisitNode'
from ReWriteVisitor.java:942:in printShortIfStatement' from ReWriteVisitor.java:968:invisitIfNode'
from IfNode.java:61:in accept' from ReWriteVisitor.java:247:invisitNode'
from ReWriteVisitor.java:1146:in visitNewlineNode' from NewlineNode.java:65:inaccept'
from ReWriteVisitor.java:247:in visitNode' from ReWriteVisitor.java:1569:invisitNodeInIndentation'
from ReWriteVisitor.java:1579:in visitWhenNode' from WhenNode.java:59:inaccept'
from ReWriteVisitor.java:247:in visitNode' from ReWriteVisitor.java:1581:invisitWhenNode'
from WhenNode.java:59:in accept' from ReWriteVisitor.java:247:invisitNode'
from ReWriteVisitor.java:1581:in visitWhenNode' from WhenNode.java:59:inaccept'
from ReWriteVisitor.java:247:in visitNode' from ReWriteVisitor.java:334:invisitAndPrintWithSeparator'
from ReWriteVisitor.java:420:in visitArrayNode' from ArrayNode.java:59:inaccept'
from ReWriteVisitor.java:247:in visitNode' from ReWriteVisitor.java:596:invisitCaseNode'
from CaseNode.java:74:in accept' from ReWriteVisitor.java:247:invisitNode'
from ReWriteVisitor.java:1602:in visitNewlineInParentheses' from ReWriteVisitor.java:900:inprintAsgnNode'
from ReWriteVisitor.java:1075:in visitLocalAsgnNode' from LocalAsgnNode.java:62:inaccept'
from ReWriteVisitor.java:247:in visitNode' from ReWriteVisitor.java:1146:invisitNewlineNode'
from NewlineNode.java:65:in accept' from ReWriteVisitor.java:247:invisitNode'
from ReWriteVisitor.java:255:in visitIter' from ReWriteVisitor.java:457:invisitBlockNode'
from BlockNode.java:54:in accept' from ReWriteVisitor.java:247:invisitNode'
from ReWriteVisitor.java:758:in printDefNode' from ReWriteVisitor.java:767:invisitDefnNode'
from DefnNode.java:52:in accept' from ReWriteVisitor.java:247:invisitNode'
from ReWriteVisitor.java:1146:in visitNewlineNode' from NewlineNode.java:65:inaccept'
from ReWriteVisitor.java:247:in visitNode' from ReWriteVisitor.java:1569:invisitNodeInIndentation'
from ClassBodyWriter.java:28:in write' from null:-1:ininvoke'
from DelegatingMethodAccessorImpl.java:43:in invoke' from Method.java:601:ininvoke'
from JavaMethod.java:440:in invokeDirectWithExceptionHandling' from JavaMethod.java:304:ininvokeDirect'
from InstanceMethodInvoker.java:52:in call' from CachingCallSite.java:134:incall'
from models_redundancy_calc.rb:43:in block_5$RUBY$model_handler' from models_redundancy_calc$block_5$RUBY$model_handler:-1:incall'
from CompiledBlock19.java:163:in yield' from CompiledBlock19.java:91:incall'
from Block.java:89:in call' from RubyProc.java:261:incall'
from RubyProc.java:249:in call19' from RubyProc$INVOKER$i$0$0$call19.gen:-1:incall'
from DynamicMethod.java:209:in call' from DynamicMethod.java:205:incall'
from CachingCallSite.java:168:in call' from models_redundancy_calc.rb:55:inblock_6$RUBY$model_handler'
from models_redundancy_calc$block_6$RUBY$model_handler:-1:in call' from CompiledBlock19.java:139:inyield'
from Block.java:130:in yield' from RubyArray.java:1606:ineachCommon'
from RubyArray.java:1613:in each' from RubyArray$INVOKER$i$0$0$each.gen:-1:incall'
from CachingCallSite.java:143:in callBlock' from CachingCallSite.java:154:incallIter'
from models_redundancy_calc.rb:49:in block_1$RUBY$model_handler' from models_redundancy_calc$block_1$RUBY$model_handler:-1:incall'
from CompiledBlock19.java:163:in yield' from CompiledBlock19.java:91:incall'
from Block.java:89:in call' from RubyProc.java:261:incall'
from RubyProc.java:249:in call19' from RubyProc$INVOKER$i$0$0$call19.gen:-1:incall'
from DynamicMethod.java:217:in call' from DynamicMethod.java:213:incall'
from CachingCallSite.java:202:in call' from CallTwoArgNode.java:59:ininterpret'
from NewlineNode.java:105:in interpret' from BlockNode.java:71:ininterpret'
from IfNode.java:118:in interpret' from NewlineNode.java:105:ininterpret'
from BlockNode.java:71:in interpret' from ASTInterpreter.java:75:inINTERPRET_METHOD'
from InterpretedMethod.java:290:in call' from DefaultMethod.java:228:incall'
from CachingCallSite.java:245:in `callBlock'

So I just looked at this and the wild thing is that in order to rewrite short if's (?:) you need to pass string source or original source. That seems rather sad. You currently are passing in '' which explains why when you hit a few constructs it blows up.

I have the beginnings of an AST annotator which adds all syntactical elements to the AST. Once that is done then rewriting will become 100% lexically equivalent to the original source. Unfortunately, I have not had time to complete this. I have added commands into the tree but not all syntactical elements (like ')').

So I will leave this open to remember to ping you when I am able to make more progress on the real fix.