Package looksee

Source Code of looksee.JRubyAdapter

package looksee;

import java.lang.reflect.Field;
import java.util.Map;
import org.jruby.MetaClass;
import org.jruby.Ruby;
import org.jruby.RubyArray;
import org.jruby.RubyClass;
import org.jruby.RubyFixnum;
import org.jruby.RubyMethod;
import org.jruby.RubyModule;
import org.jruby.RubyObject;
import org.jruby.RubyProc;
import org.jruby.RubyString;
import org.jruby.RubyUnboundMethod;
import org.jruby.IncludedModuleWrapper;
import org.jruby.anno.JRubyClass;
import org.jruby.anno.JRubyMethod;
import org.jruby.internal.runtime.methods.AliasMethod;
import org.jruby.internal.runtime.methods.DynamicMethod;
import org.jruby.internal.runtime.methods.MethodMethod;
import org.jruby.internal.runtime.methods.ProcMethod;
import org.jruby.internal.runtime.methods.WrapperMethod;
import org.jruby.lexer.yacc.ISourcePosition;
import org.jruby.runtime.PositionAware;
import org.jruby.runtime.ThreadContext;
import org.jruby.runtime.Visibility;
import org.jruby.runtime.builtin.IRubyObject;

@JRubyClass(name = "Looksee::Adapter::JRuby")
public class JRubyAdapter extends RubyObject {
  public JRubyAdapter(Ruby runtime, RubyClass klass) {
    super(runtime, klass);
  }

  @JRubyMethod(name = "internal_superclass")
  public static IRubyObject internalSuperclass(ThreadContext context, IRubyObject self, IRubyObject internalClass) {
    return ((RubyModule)internalClass).getSuperClass();
  }

  @JRubyMethod(name = "internal_class")
  public static IRubyObject internalClass(ThreadContext context, IRubyObject self, IRubyObject object) {
    return object.getMetaClass();
  }

  @JRubyMethod(name = "internal_public_instance_methods")
  public static IRubyObject internalPublicInstanceMethods(ThreadContext context, IRubyObject self, IRubyObject module) {
    return findMethodsByVisibility(context.getRuntime(), module, Visibility.PUBLIC);
  }

  @JRubyMethod(name = "internal_protected_instance_methods")
  public static IRubyObject internalProtectedInstanceMethods(ThreadContext context, IRubyObject self, IRubyObject module) {
    return findMethodsByVisibility(context.getRuntime(), module, Visibility.PROTECTED);
  }

  @JRubyMethod(name = "internal_private_instance_methods")
  public static IRubyObject internalPrivateInstanceMethods(ThreadContext context, IRubyObject self, IRubyObject module) {
    return findMethodsByVisibility(context.getRuntime(), module, Visibility.PRIVATE);
  }

  private static RubyArray findMethodsByVisibility(Ruby runtime, IRubyObject module, Visibility visibility) {
    RubyArray result = runtime.newArray();
    for (Map.Entry<String, DynamicMethod> entry : ((RubyModule)module).getMethods().entrySet()) {
      if (entry.getValue().getVisibility() == visibility)
        result.add(runtime.newSymbol(entry.getKey()));
    }
    return result;
  }

  @JRubyMethod(name = "internal_undefined_instance_methods")
  public static RubyArray internalUndefinedInstanceMethods(ThreadContext context, IRubyObject self, IRubyObject module) {
    Ruby runtime = context.getRuntime();
    RubyArray result = runtime.newArray();
    for (Map.Entry<String, DynamicMethod> entry : ((RubyModule)module).getMethods().entrySet()) {
      if (entry.getValue().isUndefined())
        result.add(runtime.newSymbol(entry.getKey()));
    }
    return result;
  }

  @JRubyMethod(name = "included_class?")
  public static IRubyObject isIncludedClass(ThreadContext context, IRubyObject self, IRubyObject object) {
    Ruby runtime = context.getRuntime();
    return runtime.newBoolean(object instanceof IncludedModuleWrapper);
  }

  @JRubyMethod(name = "singleton_class?")
  public static IRubyObject isSingletonClass(ThreadContext context, IRubyObject self, IRubyObject object) {
    Ruby runtime = context.getRuntime();
    return runtime.newBoolean(object instanceof MetaClass);
  }

  @JRubyMethod(name = "singleton_instance")
  public static IRubyObject singletonInstance(ThreadContext context, IRubyObject self, IRubyObject singleton_class) {
    Ruby runtime = context.getRuntime();
    if (singleton_class instanceof MetaClass)
      return ((MetaClass)singleton_class).getAttached();
    else
      throw runtime.newTypeError("expected singleton class, got " + singleton_class.getMetaClass().getName());
  }

  @JRubyMethod(name = "real_module")
  public static IRubyObject realModule(ThreadContext context, IRubyObject self, IRubyObject module) {
    Ruby runtime = context.getRuntime();
    if (module instanceof IncludedModuleWrapper)
      return ((IncludedModuleWrapper)module).getNonIncludedClass();
    else
      return module;
  }

  @JRubyMethod(name = "module_name")
  public static IRubyObject moduleName(ThreadContext context, IRubyObject self, IRubyObject module) {
    Ruby runtime = context.getRuntime();
    if (module instanceof IncludedModuleWrapper)
      return ((IncludedModuleWrapper)module).getNonIncludedClass().name();
    if (module instanceof RubyModule)
      return ((RubyModule)module).name();
    else
      throw runtime.newTypeError("expected Module, got " + module.getMetaClass().getName());
  }

  @JRubyMethod(name = "source_location")
  public static IRubyObject sourceLocation(ThreadContext context, IRubyObject self, IRubyObject arg) {
    Ruby runtime = context.getRuntime();
    if (!(arg instanceof RubyUnboundMethod))
      throw runtime.newTypeError("expected UnboundMethod, got " + arg.getMetaClass().getName());

    IRubyObject sourceLocation = ((RubyUnboundMethod)arg).source_location(context);
    if (!sourceLocation.isNil())
      return sourceLocation;

    // source_location doesn't always work. If it returns nil, try a little harder.
    DynamicMethod method = (DynamicMethod)getPrivateField(runtime, RubyMethod.class, "method", arg);
    return methodSourceLocation(runtime, method);
  }

  public static IRubyObject methodSourceLocation(Ruby runtime, DynamicMethod method) {
    if (method instanceof PositionAware) {
      PositionAware positionAware = (PositionAware)method;
      return runtime.newArray(runtime.newString(positionAware.getFile()),
                              runtime.newFixnum(positionAware.getLine() + 1));
    } else if (method instanceof ProcMethod) {
      RubyProc proc = (RubyProc)getPrivateField(runtime, ProcMethod.class, "proc", method);
      String file = (String)getPrivateField(runtime, RubyProc.class, "file", proc);
      int line = getPrivateIntField(runtime, RubyProc.class, "line", proc);
      RubyString rubyFile = runtime.newString(file);
      RubyFixnum rubyLine = runtime.newFixnum(line + 1);
      return runtime.newArray(rubyFile, rubyLine);
    } else if (method instanceof AliasMethod) {
      method = method.getRealMethod();
      return methodSourceLocation(runtime, method);
    } else if (method instanceof MethodMethod) {
      // MethodMethod.getRealMethod and RubyMethod.getMethod are JRuby >= 1.6 only.
      RubyUnboundMethod unboundMethod = (RubyUnboundMethod)getPrivateField(runtime, MethodMethod.class, "method", method);
      DynamicMethod realMethod = (DynamicMethod)getPrivateField(runtime, RubyMethod.class, "method", unboundMethod);
      return methodSourceLocation(runtime, realMethod);
    } else if (method instanceof WrapperMethod) {
      method = (DynamicMethod)getPrivateField(runtime, WrapperMethod.class, "method", method);
      return methodSourceLocation(runtime, method);
    }
    return runtime.getNil();
  }

  // Yes, we are evil.
  private static Object getPrivateField(Ruby runtime, Class klass, String name, Object receiver) {
    try {
      Field field = klass.getDeclaredField(name);
      field.setAccessible(true);
      return field.get(receiver);
    } catch (IllegalAccessException e) {
      throw runtime.newTypeError("[LOOKSEE BUG] unexpected exception: " + e.getClass().getName() + ": " + e.getMessage() + " (klass = " + klass.getName() + ")");
    } catch (NoSuchFieldException e) {
      throw runtime.newTypeError("[LOOKSEE BUG] unexpected exception: " + e.getClass().getName() + ": " + e.getMessage() + " (klass = " + klass.getName() + ")");
    }
  }

  private static int getPrivateIntField(Ruby runtime, Class klass, String name, Object receiver) {
    try {
      Field field = klass.getDeclaredField(name);
      field.setAccessible(true);
      return field.getInt(receiver);
    } catch (IllegalAccessException e) {
      throw runtime.newTypeError("[LOOKSEE BUG] unexpected exception: " + e.getClass().getName() + ": " + e.getMessage() + " (klass = " + klass.getName() + ")");
    } catch (NoSuchFieldException e) {
      throw runtime.newTypeError("[LOOKSEE BUG] unexpected exception: " + e.getClass().getName() + ": " + e.getMessage() + " (klass = " + klass.getName() + ")");
    }
  }
}
TOP

Related Classes of looksee.JRubyAdapter

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.