Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: jruby/jruby
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: d45a1c896819
Choose a base ref
...
head repository: jruby/jruby
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 4c2d934d7dcb
Choose a head ref
  • 2 commits
  • 2 files changed
  • 1 contributor

Commits on Mar 11, 2015

  1. Copy the full SHA
    13ab4a3 View commit details
  2. Copy the full SHA
    4c2d934 View commit details
Showing with 155 additions and 0 deletions.
  1. +90 −0 core/src/main/java/org/jruby/java/proxies/ArrayJavaProxy.java
  2. +65 −0 test/test_higher_javasupport.rb
90 changes: 90 additions & 0 deletions core/src/main/java/org/jruby/java/proxies/ArrayJavaProxy.java
Original file line number Diff line number Diff line change
@@ -4,6 +4,7 @@
import java.util.Arrays;
import org.jruby.Ruby;
import org.jruby.RubyArray;
import org.jruby.RubyBoolean;
import org.jruby.RubyClass;
import org.jruby.RubyFixnum;
import org.jruby.RubyInteger;
@@ -186,6 +187,95 @@ public IRubyObject inspect(ThreadContext context) {
return context.runtime.newString(buffer.toString());
}

@JRubyMethod(name = "==")
@Override
public RubyBoolean op_eqq(ThreadContext context, IRubyObject other) {
return eql_p(context, other);
}

@JRubyMethod(name = "eql?")
public RubyBoolean eql_p(ThreadContext context, IRubyObject obj) {
boolean equals = false;
if ( obj instanceof ArrayJavaProxy ) {
final ArrayJavaProxy that = (ArrayJavaProxy) obj;
equals = arraysEquals(this.getObject(), that.getObject());
}
if ( obj.getClass().isArray() ) {
equals = arraysEquals(getObject(), obj);
}
return context.runtime.newBoolean(equals);
}

@Override
public boolean equals(Object obj) {
if ( obj instanceof ArrayJavaProxy ) {
final ArrayJavaProxy that = (ArrayJavaProxy) obj;
final Object thisArray = this.getObject();
final Object thatArray = that.getObject();
return arraysEquals(thisArray, thatArray);
}
return false;
}

private static boolean arraysEquals(final Object thisArray, final Object thatArray) {
final Class<?> componentType = thisArray.getClass().getComponentType();
if ( ! componentType.equals(thatArray.getClass().getComponentType()) ) {
return false;
}
if ( componentType.isPrimitive() ) {
switch ( componentType.getName().charAt(0) ) {
case 'b':
if (componentType == byte.class) return Arrays.equals((byte[]) thisArray, (byte[]) thatArray);
if (componentType == boolean.class) return Arrays.equals((boolean[]) thisArray, (boolean[]) thatArray);
case 's':
if (componentType == short.class) return Arrays.equals((short[]) thisArray, (short[]) thatArray);
case 'c':
if (componentType == char.class) return Arrays.equals((char[]) thisArray, (char[]) thatArray);
case 'i':
if (componentType == int.class) return Arrays.equals((int[]) thisArray, (int[]) thatArray);
case 'l':
if (componentType == long.class) return Arrays.equals((long[]) thisArray, (long[]) thatArray);
case 'f':
if (componentType == float.class) return Arrays.equals((float[]) thisArray, (float[]) thatArray);
case 'd':
if (componentType == double.class) return Arrays.equals((double[]) thisArray, (double[]) thatArray);
}
}
return Arrays.equals((Object[]) thisArray, (Object[]) thatArray);
}

@JRubyMethod
@Override
public RubyFixnum hash() {
return getRuntime().newFixnum( hashCode() );
}

@Override
public int hashCode() {
final Object array = getObject();
final Class<?> componentType = array.getClass().getComponentType();
if ( componentType.isPrimitive() ) {
switch ( componentType.getName().charAt(0) ) {
case 'b':
if (componentType == byte.class) return 11 * Arrays.hashCode((byte[]) array);
if (componentType == boolean.class) return 11 * Arrays.hashCode((boolean[]) array);
case 's':
if (componentType == short.class) return 11 * Arrays.hashCode((short[]) array);
case 'c':
if (componentType == char.class) return 11 * Arrays.hashCode((char[]) array);
case 'i':
if (componentType == int.class) return 11 * Arrays.hashCode((int[]) array);
case 'l':
if (componentType == long.class) return 11 * Arrays.hashCode((long[]) array);
case 'f':
if (componentType == float.class) return 11 * Arrays.hashCode((float[]) array);
case 'd':
if (componentType == double.class) return 11 * Arrays.hashCode((double[]) array);
}
}
return 11 * Arrays.hashCode((Object[]) array);
}

public IRubyObject getRange(ThreadContext context, IRubyObject[] args) {
if (args.length == 1) {
return getRange(context, args[0]);
65 changes: 65 additions & 0 deletions test/test_higher_javasupport.rb
Original file line number Diff line number Diff line change
@@ -138,6 +138,71 @@ def test_array_with_non_ruby_integer_indexes
assert_equal 41, array.at( -1.to_java(:int) )
end

def test_array_eql_and_hash
array1 = java.lang.Long[4].new
array2 = java.lang.Long[4].new

do_test_eql_arrays(array1, array2)

array1 = Java::long[5].new
array2 = Java::long[5].new

do_test_eql_arrays(array1, array2)

array1 = Java::long[4].new
array2 = Java::long[5].new
assert_equal false, array1 == array2
end

def do_test_eql_arrays(array1, array2)
assert_equal(array1, array2)
assert array1.eql?(array2)

array1[0] = 1
assert_equal false, array1.eql?(array2)

array2[0] = 1
array2[1] = 2
array2[2] = 3
array1[1] = 2
array1[2] = 3

assert_equal(array2, array1)
assert_equal(array2.hash, array1.hash)
assert array2.eql?(array1)
assert_equal true, array1 == array2

assert ! array2.equal?(array1)
assert array2.equal?(array2)
end
private :do_test_eql_arrays

def test_bare_eql_and_hash
l1 = java.lang.Long.valueOf 100_000_000
l2 = java.lang.Long.valueOf 100_000_000
assert l1.eql? l2
assert l1 == l2

s1 = Java::JavaLang::String.new 'a-string'
s2 = 'a-string'.to_java
assert ! s1.equal?(s2)
assert s1.eql? s2
assert s1 == s2

a1 = java.util.Arrays.asList(1, 2, 3)
a2 = java.util.ArrayList.new
a2 << 0; a2 << 2; a2 << 3
assert_equal false, a1.eql?(a2)
assert_equal false, a2 == a1
assert_not_equal a1.hash, a2.hash
a2[0] = 1
assert_equal true, a2.eql?(a1)
assert_equal true, a1 == a2
assert_equal true, a2 == a1
assert_equal a1.hash, a2.hash
assert_equal false, a2.equal?(a1)
end

Pipe = java.nio.channels.Pipe
def test_inner_classes
assert_equal("java.nio.channels.Pipe$SinkChannel",