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:in
visitNewlineNode'
from NewlineNode.java:65:in accept' from ReWriteVisitor.java:247:in
visitNode'
from ReWriteVisitor.java:942:in printShortIfStatement' from ReWriteVisitor.java:968:in
visitIfNode'
from IfNode.java:61:in accept' from ReWriteVisitor.java:247:in
visitNode'
from ReWriteVisitor.java:1146:in visitNewlineNode' from NewlineNode.java:65:in
accept'
from ReWriteVisitor.java:247:in visitNode' from ReWriteVisitor.java:1569:in
visitNodeInIndentation'
from ReWriteVisitor.java:1579:in visitWhenNode' from WhenNode.java:59:in
accept'
from ReWriteVisitor.java:247:in visitNode' from ReWriteVisitor.java:1581:in
visitWhenNode'
from WhenNode.java:59:in accept' from ReWriteVisitor.java:247:in
visitNode'
from ReWriteVisitor.java:1581:in visitWhenNode' from WhenNode.java:59:in
accept'
from ReWriteVisitor.java:247:in visitNode' from ReWriteVisitor.java:334:in
visitAndPrintWithSeparator'
from ReWriteVisitor.java:420:in visitArrayNode' from ArrayNode.java:59:in
accept'
from ReWriteVisitor.java:247:in visitNode' from ReWriteVisitor.java:596:in
visitCaseNode'
from CaseNode.java:74:in accept' from ReWriteVisitor.java:247:in
visitNode'
from ReWriteVisitor.java:1602:in visitNewlineInParentheses' from ReWriteVisitor.java:900:in
printAsgnNode'
from ReWriteVisitor.java:1075:in visitLocalAsgnNode' from LocalAsgnNode.java:62:in
accept'
from ReWriteVisitor.java:247:in visitNode' from ReWriteVisitor.java:1146:in
visitNewlineNode'
from NewlineNode.java:65:in accept' from ReWriteVisitor.java:247:in
visitNode'
from ReWriteVisitor.java:255:in visitIter' from ReWriteVisitor.java:457:in
visitBlockNode'
from BlockNode.java:54:in accept' from ReWriteVisitor.java:247:in
visitNode'
from ReWriteVisitor.java:758:in printDefNode' from ReWriteVisitor.java:767:in
visitDefnNode'
from DefnNode.java:52:in accept' from ReWriteVisitor.java:247:in
visitNode'
from ReWriteVisitor.java:1146:in visitNewlineNode' from NewlineNode.java:65:in
accept'
from ReWriteVisitor.java:247:in visitNode' from ReWriteVisitor.java:1569:in
visitNodeInIndentation'
from ClassBodyWriter.java:28:in write' from null:-1:in
invoke'
from DelegatingMethodAccessorImpl.java:43:in invoke' from Method.java:601:in
invoke'
from JavaMethod.java:440:in invokeDirectWithExceptionHandling' from JavaMethod.java:304:in
invokeDirect'
from InstanceMethodInvoker.java:52:in call' from CachingCallSite.java:134:in
call'
from models_redundancy_calc.rb:43:in block_5$RUBY$model_handler' from models_redundancy_calc$block_5$RUBY$model_handler:-1:in
call'
from CompiledBlock19.java:163:in yield' from CompiledBlock19.java:91:in
call'
from Block.java:89:in call' from RubyProc.java:261:in
call'
from RubyProc.java:249:in call19' from RubyProc$INVOKER$i$0$0$call19.gen:-1:in
call'
from DynamicMethod.java:209:in call' from DynamicMethod.java:205:in
call'
from CachingCallSite.java:168:in call' from models_redundancy_calc.rb:55:in
block_6$RUBY$model_handler'
from models_redundancy_calc$block_6$RUBY$model_handler:-1:in call' from CompiledBlock19.java:139:in
yield'
from Block.java:130:in yield' from RubyArray.java:1606:in
eachCommon'
from RubyArray.java:1613:in each' from RubyArray$INVOKER$i$0$0$each.gen:-1:in
call'
from CachingCallSite.java:143:in callBlock' from CachingCallSite.java:154:in
callIter'
from models_redundancy_calc.rb:49:in block_1$RUBY$model_handler' from models_redundancy_calc$block_1$RUBY$model_handler:-1:in
call'
from CompiledBlock19.java:163:in yield' from CompiledBlock19.java:91:in
call'
from Block.java:89:in call' from RubyProc.java:261:in
call'
from RubyProc.java:249:in call19' from RubyProc$INVOKER$i$0$0$call19.gen:-1:in
call'
from DynamicMethod.java:217:in call' from DynamicMethod.java:213:in
call'
from CachingCallSite.java:202:in call' from CallTwoArgNode.java:59:in
interpret'
from NewlineNode.java:105:in interpret' from BlockNode.java:71:in
interpret'
from IfNode.java:118:in interpret' from NewlineNode.java:105:in
interpret'
from BlockNode.java:71:in interpret' from ASTInterpreter.java:75:in
INTERPRET_METHOD'
from InterpretedMethod.java:290:in call' from DefaultMethod.java:228:in
call'
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.