private static void addBackTraceElement( Ruby runtime, RubyArray backtrace, Frame frame, Frame previousFrame) { if (frame != previousFrame && // happens with native exceptions, should not filter those out frame.getLine() == previousFrame.getLine() && frame.getName() != null && frame.getName().equals(previousFrame.getName()) && frame.getFile().equals(previousFrame.getFile())) { return; } RubyString traceLine; if (previousFrame.getName() != null) { traceLine = RubyString.newString( runtime, frame.getFile() + ':' + (frame.getLine() + 1) + ":in `" + previousFrame.getName() + '\''); } else if (runtime.is1_9()) { // TODO: This probably isn't the best hack, but it works until we can have different // root frame setup for 1.9 easily. traceLine = RubyString.newString( runtime, frame.getFile() + ':' + (frame.getLine() + 1) + ":in `<main>'"); } else { traceLine = RubyString.newString(runtime, frame.getFile() + ':' + (frame.getLine() + 1)); } backtrace.append(traceLine); }
/** * Return a binding representing the previous call's state but with a specified self * * @param self the self object to use * @return the current binding, using the specified self */ public Binding previousBinding(IRubyObject self) { Frame frame = getPreviousFrame(); Frame current = getCurrentFrame(); return new Binding( self, frame, frame.getVisibility(), getPreviousRubyClass(), getCurrentScope(), current.getFile(), current.getLine()); }
private RubyStackTraceElement[] buildTrace(RubyStackTraceElement[] newTrace) { for (int i = 0; i < newTrace.length; i++) { Frame current = frameStack[i]; String klazzName = getClassNameFromFrame(current); String methodName = getMethodNameFromFrame(current); newTrace[newTrace.length - 1 - i] = new RubyStackTraceElement( klazzName, methodName, current.getFile(), current.getLine() + 1, current.isBindingFrame()); } return newTrace; }
public void setFileAndLine(Frame frame) { this.file = frame.getFile(); this.line = frame.getLine(); }
/** * Return a binding representing the previous call's state * * @return the current binding */ public Binding previousBinding() { Frame frame = getPreviousFrame(); Frame current = getCurrentFrame(); return new Binding( frame, getPreviousRubyClass(), getCurrentScope(), current.getFile(), current.getLine()); }
public static IRubyObject createRubyHybridBacktrace( Ruby runtime, RubyStackTraceElement[] backtraceFrames, RubyStackTraceElement[] stackTrace, boolean debug) { RubyArray traceArray = RubyArray.newArray(runtime); ThreadContext context = runtime.getCurrentContext(); int rubyFrameIndex = backtraceFrames.length - 1; for (int i = 0; i < stackTrace.length; i++) { RubyStackTraceElement element = stackTrace[i]; // look for mangling markers for compiled Ruby in method name int index = element.getMethodName().indexOf("$RUBY$"); if (index >= 0) { String unmangledMethod = element.getMethodName().substring(index + 6); RubyString str = RubyString.newString( runtime, element.getFileName() + ":" + element.getLineNumber() + ":in `" + unmangledMethod + "'"); traceArray.append(str); // if it's not a rescue or ensure, there's a frame associated, so decrement if (!(element.getMethodName().contains("__rescue__") || element.getMethodName().contains("__ensure__"))) { rubyFrameIndex--; } continue; } // look for __file__ method name for compiled roots if (element.getMethodName().equals("__file__")) { RubyString str = RubyString.newString( runtime, element.getFileName() + ":" + element.getLineNumber() + ": `<toplevel>'"); traceArray.append(str); rubyFrameIndex--; continue; } // look for mangling markers for bound, unframed methods in class name index = element.getClassName().indexOf("$RUBYINVOKER$"); if (index >= 0) { // unframed invokers have no Ruby frames, so pull from class name // but use current frame as file and line String unmangledMethod = element.getClassName().substring(index + 13); Frame current = context.frameStack[rubyFrameIndex]; RubyString str = RubyString.newString( runtime, current.getFile() + ":" + (current.getLine() + 1) + ":in `" + unmangledMethod + "'"); traceArray.append(str); continue; } // look for mangling markers for bound, framed methods in class name index = element.getClassName().indexOf("$RUBYFRAMEDINVOKER$"); if (index >= 0) { // framed invokers will have Ruby frames associated with them addBackTraceElement( traceArray, backtraceFrames[rubyFrameIndex], backtraceFrames[rubyFrameIndex - 1], FrameType.METHOD); rubyFrameIndex--; continue; } // try to mine out a Ruby frame using our list of interpreter entry-point markers String classMethod = element.getClassName() + "." + element.getMethodName(); FrameType frameType = INTERPRETED_FRAMES.get(classMethod); if (frameType != null) { // Frame matches one of our markers for "interpreted" calls if (rubyFrameIndex == 0) { addBackTraceElement( traceArray, backtraceFrames[rubyFrameIndex], backtraceFrames[rubyFrameIndex], frameType); } else { addBackTraceElement( traceArray, backtraceFrames[rubyFrameIndex], backtraceFrames[rubyFrameIndex - 1], frameType); rubyFrameIndex--; } continue; } else { // Frame is extraneous runtime information, skip it unless debug if (debug) { RubyString str = RubyString.newString(runtime, createRubyBacktraceString(element.getElement())); traceArray.append(str); } continue; } } return traceArray; }