Skip to content

Commit

Permalink
set the anonymous (generated) class name instead of an empty string o…
Browse files Browse the repository at this point in the history
…n proxy class
  • Loading branch information
kares committed Feb 6, 2015
1 parent 45598f3 commit 2c50057
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 36 deletions.
79 changes: 50 additions & 29 deletions core/src/main/java/org/jruby/javasupport/JavaClass.java
Expand Up @@ -757,18 +757,40 @@ public IRubyObject call(ThreadContext context, IRubyObject self, RubyModule claz
proxy.setJavaProxy(true);
proxy.getSingletonClass().setJavaProxy(true);

// set the Java class name and package
proxy.setBaseName(javaClass.getSimpleName());

// set parent to either package module or outer class
RubyModule parent;
if (javaClass.getEnclosingClass() != null) {
parent = Java.getProxyClass(getRuntime(), javaClass.getEnclosingClass());
final RubyModule parent;
final Class<?> enclosingClass = javaClass.getEnclosingClass();
if ( enclosingClass != null ) {
parent = Java.getProxyClass(getRuntime(), enclosingClass);
} else {
parent = Java.getJavaPackageModule(getRuntime(), javaClass.getPackage());
}
proxy.setParent(parent);

// set the Java class name and package
if ( javaClass.isAnonymousClass() ) {
String baseName = ""; // javaClass.getSimpleName() returns "" for anonymous
if ( enclosingClass != null ) {
// instead of an empty name anonymous classes will have a "conforming"
// although not valid (by Ruby semantics) RubyClass name e.g. :
// 'Java::JavaUtilConcurrent::TimeUnit::1' for $1 anonymous enum class
// NOTE: if this turns out suitable shall do the same for method etc.
final String className = javaClass.getName();
final int length = className.length();
final int offset = enclosingClass.getName().length();
if ( length > offset && className.charAt(offset) != '$' ) {
baseName = className.substring( offset );
}
else if ( length > offset + 1 ) { // skip '$'
baseName = className.substring( offset + 1 );
}
}
proxy.setBaseName( baseName );
}
else {
proxy.setBaseName( javaClass.getSimpleName() );
}

// FIXME: bit of a kludge here (non-interface classes assigned to both
// class and module fields). simplifies proxy extender code, will go away
// when JI is overhauled (and proxy extenders are deprecated).
Expand Down Expand Up @@ -976,37 +998,36 @@ private void setupClassFields(Class<?> javaClass, InitializerState state) {
}
}

private static String fixScalaNames(String name) {
private static String fixScalaNames(final String name) {
String s = name;
for (Map.Entry<String, String> entry : SCALA_OPERATORS.entrySet()) {
s = s.replaceAll(entry.getKey(), entry.getValue());
}

return s;
}

private static final Map<String, String> SCALA_OPERATORS;
static {
Map<String, String> tmp = new HashMap();
tmp.put("\\$plus", "+");
tmp.put("\\$minus", "-");
tmp.put("\\$colon", ":");
tmp.put("\\$div", "/");
tmp.put("\\$eq", "=");
tmp.put("\\$less", "<");
tmp.put("\\$greater", ">");
tmp.put("\\$bslash", "\\\\");
tmp.put("\\$hash", "#");
tmp.put("\\$times", "*");
tmp.put("\\$bang", "!");
tmp.put("\\$at", "@");
tmp.put("\\$percent", "%");
tmp.put("\\$up", "^");
tmp.put("\\$amp", "&");
tmp.put("\\$tilde", "~");
tmp.put("\\$qmark", "?");
tmp.put("\\$bar", "|");
SCALA_OPERATORS = Collections.unmodifiableMap(tmp);
HashMap<String, String> scalaOperators = new HashMap<String, String>();
scalaOperators.put("\\$plus", "+");
scalaOperators.put("\\$minus", "-");
scalaOperators.put("\\$colon", ":");
scalaOperators.put("\\$div", "/");
scalaOperators.put("\\$eq", "=");
scalaOperators.put("\\$less", "<");
scalaOperators.put("\\$greater", ">");
scalaOperators.put("\\$bslash", "\\\\");
scalaOperators.put("\\$hash", "#");
scalaOperators.put("\\$times", "*");
scalaOperators.put("\\$bang", "!");
scalaOperators.put("\\$at", "@");
scalaOperators.put("\\$percent", "%");
scalaOperators.put("\\$up", "^");
scalaOperators.put("\\$amp", "&");
scalaOperators.put("\\$tilde", "~");
scalaOperators.put("\\$qmark", "?");
scalaOperators.put("\\$bar", "|");
SCALA_OPERATORS = Collections.unmodifiableMap(scalaOperators);
}

private void setupClassMethods(Class<?> javaClass, InitializerState state) {
Expand Down Expand Up @@ -1295,7 +1316,7 @@ public static RubyClass createJavaClassClass(Ruby runtime, RubyModule javaModule

public static synchronized JavaClass forNameVerbose(Ruby runtime, String className) {
Class <?> klass = null;
if (className.indexOf(".") == -1 && Character.isLowerCase(className.charAt(0))) {
if (className.indexOf('.') == -1 && Character.isLowerCase(className.charAt(0))) {
// one word type name that starts lower-case...it may be a primitive type
klass = PRIMITIVE_TO_CLASS.get(className);
}
Expand Down
20 changes: 13 additions & 7 deletions test/test_java_extension.rb
Expand Up @@ -2,8 +2,6 @@
require 'test/unit'

class TestJavaExtension < Test::Unit::TestCase
import org.jruby.test.Worker
import org.jruby.test.Abstract

class TestParent < org.jruby.test.Parent
attr_accessor :result
Expand All @@ -12,6 +10,8 @@ def run(a)
end
end

java_import org.jruby.test.Worker

def test_overriding_method_in_java_superclass
w = Worker.new
p = TestParent.new
Expand All @@ -22,24 +22,24 @@ def test_overriding_method_in_java_superclass
import java.util.HashMap
import java.util.ArrayList
import java.util.HashSet
import java.lang.Short

def test_set
set = HashSet.new
set.add(1)
set.add(2)

newSet = []
set.each {|x| newSet << x }
set.each { |x| newSet << x }

assert newSet.include?(1)
assert newSet.include?(2)
end

def test_comparable
one = Short.new(1)
two = Short.new(2)
three = Short.new(3)
short = Java::JavaLang::Short
one = short.new(1)
two = short.new(2)
three = short.new(3)
list = [three, two, one]
list = list.sort
assert_equal([one, two, three], list)
Expand Down Expand Up @@ -156,6 +156,12 @@ def test_java_class_name
assert_equal 'java.lang.Runnable', Java::JavaLang::Runnable.java_class.name

assert_equal 'Java::JavaLang::String', JString.name

assert_equal 'Java::JavaLang::Thread::State', Java::java.lang.Thread::State.name
# an enum class with custom code for each constant :
assert_equal 'Java::JavaUtilConcurrent::TimeUnit::1', java.util.concurrent.TimeUnit::NANOSECONDS.class.name
assert_equal 'Java::JavaUtilConcurrent::TimeUnit::2', java.util.concurrent.TimeUnit::MICROSECONDS.class.name
assert java.util.concurrent.TimeUnit::MICROSECONDS.is_a?(java.util.concurrent.TimeUnit)
end

include_package 'org.jruby.javasupport.test'
Expand Down

0 comments on commit 2c50057

Please sign in to comment.