Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

[2.0] Add Thread::Backtrace::Location and related methods.

* Thread#backtrace_locations
* Kernel#caller_locations
* Exception#backtrace_locations (not official, but should be soon)
  • Loading branch information...
commit 281ead709e1e855b552a42e86e48f8f91ca8ebb5 1 parent f729d8d
@headius headius authored
View
10 src/org/jruby/Ruby.java
@@ -2226,6 +2226,14 @@ public RubyHash getENV() {
public void setENV(RubyHash env) {
envObject = env;
}
+
+ public RubyClass getLocation() {
+ return locationClass;
+ }
+
+ public void setLocation(RubyClass location) {
+ this.locationClass = location;
+ }
public RubyModule getErrno() {
return errnoModule;
@@ -4455,7 +4463,7 @@ public void secure(int level) {
syntaxError, standardError, loadError, notImplementedError, securityError, noMemoryError,
regexpError, eofError, threadError, concurrencyError, systemStackError, zeroDivisionError, floatDomainError, mathDomainError,
encodingError, encodingCompatibilityError, converterNotFoundError, undefinedConversionError,
- invalidByteSequenceError, fiberError, randomClass, keyError;
+ invalidByteSequenceError, fiberError, randomClass, keyError, locationClass;
/**
* All the core modules we keep direct references to, for quick access and
View
8 src/org/jruby/RubyException.java
@@ -98,6 +98,14 @@ public IRubyObject set_backtrace(IRubyObject obj) {
}
return backtrace();
}
+
+ @JRubyMethod(compat = CompatVersion.RUBY2_0, omit = true)
+ public IRubyObject backtrace_locations(ThreadContext context) {
+ Ruby runtime = context.runtime;
+ RubyStackTraceElement[] elements = backtraceData.getBacktrace(runtime);
+
+ return RubyThread.Location.newLocationArray(runtime, elements);
+ }
@JRubyMethod(name = "exception", optional = 1, rest = true, meta = true)
public static IRubyObject exception(ThreadContext context, IRubyObject recv, IRubyObject[] args, Block block) {
View
10 src/org/jruby/RubyKernel.java
@@ -84,6 +84,7 @@
import static org.jruby.runtime.Visibility.PRIVATE;
import static org.jruby.runtime.Visibility.PROTECTED;
import static org.jruby.runtime.Visibility.PUBLIC;
+import org.jruby.runtime.backtrace.TraceType;
/**
* Note: For CVS history, see KernelModule.java.
@@ -1149,6 +1150,15 @@ public static IRubyObject caller(ThreadContext context, IRubyObject recv, IRubyO
return context.createCallerBacktrace(context.runtime, level);
}
+
+ @JRubyMethod(module = true, visibility = PRIVATE, omit = true)
+ public static IRubyObject caller_locations(ThreadContext context, IRubyObject recv) {
+ Ruby runtime = context.runtime;
+ RubyStackTraceElement[] elements =
+ TraceType.Gather.CALLER.getBacktraceData(context, Thread.currentThread().getStackTrace(), true).getBacktrace(runtime);
+
+ return RubyThread.Location.newLocationArray(runtime, elements);
+ }
@JRubyMethod(name = "catch", module = true, visibility = PRIVATE, compat = RUBY1_8)
public static IRubyObject rbCatch(ThreadContext context, IRubyObject recv, IRubyObject tag, Block block) {
View
76 src/org/jruby/RubyThread.java
@@ -76,6 +76,9 @@
import org.jruby.util.unsafe.UnsafeFactory;
import static org.jruby.CompatVersion.*;
+import org.jruby.runtime.backtrace.BacktraceData;
+import org.jruby.runtime.backtrace.RubyStackTraceElement;
+import org.jruby.runtime.backtrace.TraceType;
/**
* Implementation of Ruby's <code>Thread</code> class. Each Ruby thread is
@@ -277,8 +280,72 @@ public static RubyClass createThreadClass(Ruby runtime) {
threadClass.setMarshal(ObjectMarshal.NOT_MARSHALABLE_MARSHAL);
+ if (runtime.is2_0()) {
+ // set up Thread::Backtrace::Location class
+ RubyClass backtrace = threadClass.defineClassUnder("Backtrace", runtime.getObject(), ObjectAllocator.NOT_ALLOCATABLE_ALLOCATOR);
+ RubyClass location = backtrace.defineClassUnder("Location", runtime.getObject(), ObjectAllocator.NOT_ALLOCATABLE_ALLOCATOR);
+
+ location.defineAnnotatedMethods(Location.class);
+
+ runtime.setLocation(location);
+ }
+
return threadClass;
}
+
+ public static class Location extends RubyObject {
+ public Location(Ruby runtime, RubyClass klass, RubyStackTraceElement element) {
+ super(runtime, klass);
+ this.element = element;
+ }
+
+ @JRubyMethod
+ public IRubyObject absolute_path(ThreadContext context) {
+ return context.runtime.newString(element.getFileName());
+ }
+
+ @JRubyMethod
+ public IRubyObject base_label(ThreadContext context) {
+ return context.runtime.newString(element.getMethodName());
+ }
+
+ @JRubyMethod
+ public IRubyObject inspect(ThreadContext context) {
+ return to_s(context).inspect();
+ }
+
+ @JRubyMethod
+ public IRubyObject label(ThreadContext context) {
+ return context.runtime.newString(element.getMethodName());
+ }
+
+ @JRubyMethod
+ public IRubyObject lineno(ThreadContext context) {
+ return context.runtime.newFixnum(element.getLineNumber());
+ }
+
+ @JRubyMethod
+ public IRubyObject path(ThreadContext context) {
+ return context.runtime.newString(element.getFileName());
+ }
+
+ @JRubyMethod
+ public IRubyObject to_s(ThreadContext context) {
+ return context.runtime.newString(element.mriStyleString());
+ }
+
+ public static IRubyObject newLocationArray(Ruby runtime, RubyStackTraceElement[] elements) {
+ RubyArray ary = runtime.newArray(elements.length);
+
+ for (RubyStackTraceElement element : elements) {
+ ary.append(new RubyThread.Location(runtime, runtime.getLocation(), element));
+ }
+
+ return ary;
+ }
+
+ private final RubyStackTraceElement element;
+ }
/**
* <code>Thread.new</code>
@@ -972,6 +1039,15 @@ public IRubyObject safe_level() {
public IRubyObject backtrace(ThreadContext context) {
return getContext().createCallerBacktrace(context.runtime, 0);
}
+
+ @JRubyMethod(compat = CompatVersion.RUBY2_0, omit = true)
+ public IRubyObject backtrace_locations(ThreadContext context) {
+ Ruby runtime = context.runtime;
+ RubyStackTraceElement[] elements =
+ TraceType.Gather.CALLER.getBacktraceData(context, getNativeThread().getStackTrace(), true).getBacktrace(runtime);
+
+ return RubyThread.Location.newLocationArray(runtime, elements);
+ }
public StackTraceElement[] javaBacktrace() {
if (threadImpl instanceof NativeThread) {
View
2  src/org/jruby/runtime/ThreadContext.java
@@ -710,7 +710,7 @@ public IRubyObject setConstantInObject(String internedName, IRubyObject result)
}
private static void addBackTraceElement(Ruby runtime, RubyArray backtrace, RubyStackTraceElement element) {
- RubyString str = RubyString.newString(runtime, element.getFileName() + ":" + element.getLineNumber() + ":in `" + element.getMethodName() + "'");
+ RubyString str = RubyString.newString(runtime, element.mriStyleString());
backtrace.append(str);
}
View
4 src/org/jruby/runtime/backtrace/RubyStackTraceElement.java
@@ -55,4 +55,8 @@ public FrameType getFrameType() {
public String toString() {
return element.toString();
}
+
+ public String mriStyleString() {
+ return element.getFileName() + ":" + element.getLineNumber() + ":in `" + element.getMethodName() + "'";
+ }
}
Please sign in to comment.
Something went wrong with that request. Please try again.