Completes implementation of java.util.Arrays and java.util.Objects

This commit is contained in:
konsoletyper 2014-03-09 14:51:08 +04:00
parent 714b2e3bb3
commit 79a4983fb5
9 changed files with 1373 additions and 10 deletions

View File

@ -98,7 +98,7 @@ public class ClassNativeGenerator implements Generator, Injector, DependencyPlug
case "doubleClass": case "doubleClass":
context.getWriter().append("$rt_cls($rt_doublecls())"); context.getWriter().append("$rt_cls($rt_doublecls())");
break; break;
case "wrap": case "wrapClass":
context.writeExpr(context.getArgument(0)); context.writeExpr(context.getArgument(0));
break; break;
case "getEnumConstantsImpl": case "getEnumConstantsImpl":
@ -193,7 +193,7 @@ public class ClassNativeGenerator implements Generator, Injector, DependencyPlug
case "intClass": case "intClass":
case "floatClass": case "floatClass":
case "doubleClass": case "doubleClass":
case "wrap": case "wrapClass":
case "getSuperclass": case "getSuperclass":
case "getComponentType0": case "getComponentType0":
case "forNameImpl": case "forNameImpl":

View File

@ -0,0 +1,38 @@
/*
* Copyright 2014 Alexey Andreev.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.teavm.classlib.java.lang;
import java.io.IOException;
import org.teavm.codegen.SourceWriter;
import org.teavm.javascript.ni.Generator;
import org.teavm.javascript.ni.GeneratorContext;
import org.teavm.model.MethodReference;
/**
*
* @author Alexey Andreev <konsoletyper@gmail.com>
*/
public class LongNativeGenerator implements Generator {
@Override
public void generate(GeneratorContext context, SourceWriter writer, MethodReference methodRef) throws IOException {
switch (methodRef.getName()) {
case "compare":
writer.append("Long_compare(").append(context.getParameterName(1)).append(", ")
.append(context.getParameterName(2)).append(");").softNewLine();
break;
}
}
}

View File

@ -103,7 +103,7 @@ public class TClass<T> extends TObject {
@InjectedBy(ClassNativeGenerator.class) @InjectedBy(ClassNativeGenerator.class)
@PluggableDependency(ClassNativeGenerator.class) @PluggableDependency(ClassNativeGenerator.class)
public static native <S extends TObject> TClass<S> wrap(Class<S> cls); public static native <S extends TObject> TClass<S> wrapClass(Class<S> cls);
public boolean desiredAssertionStatus() { public boolean desiredAssertionStatus() {
return true; return true;
@ -122,9 +122,9 @@ public class TClass<T> extends TObject {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public T cast(TObject obj) { public T cast(TObject obj) {
if (obj != null && !isAssignableFrom(TClass.wrap(obj.getClass()))) { if (obj != null && !isAssignableFrom(TClass.wrapClass(obj.getClass()))) {
throw new TClassCastException(TString.wrap(new TStringBuilder() throw new TClassCastException(TString.wrap(new TStringBuilder()
.append(TClass.wrap(obj.getClass()).getName()) .append(TClass.wrapClass(obj.getClass()).getName())
.append(TString.wrap(" is not subtype of ")).append(name).toString())); .append(TString.wrap(" is not subtype of ")).append(name).toString()));
} }
return (T)obj; return (T)obj;

View File

@ -62,7 +62,7 @@ public abstract class TEnum<E extends TEnum<E>> extends TObject implements TComp
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public final TClass<E> getDeclaringClass() { public final TClass<E> getDeclaringClass() {
return (TClass<E>)TClass.wrap(getClass()); return (TClass<E>)TClass.wrapClass(getClass());
} }
@Override @Override

View File

@ -15,6 +15,7 @@
*/ */
package org.teavm.classlib.java.lang; package org.teavm.classlib.java.lang;
import org.teavm.javascript.ni.GeneratedBy;
import org.teavm.javascript.ni.Rename; import org.teavm.javascript.ni.Rename;
/** /**
@ -69,4 +70,7 @@ public class TLong extends TNumber {
} }
return other instanceof TLong && ((TLong)other).value == value; return other instanceof TLong && ((TLong)other).value == value;
} }
@GeneratedBy(LongNativeGenerator.class)
public static native int compare(long a, long b);
} }

View File

@ -55,4 +55,52 @@ public final class TObjects extends TObject {
} }
return obj; return obj;
} }
public static boolean deepEquals(Object a, Object b) {
if (a == b) {
return true;
}
if (a == null) {
return b == null;
}
if (a instanceof boolean[]) {
return b instanceof boolean[] && TArrays.equals((boolean[])a, (boolean[])b);
} else if (b instanceof boolean[]) {
return false;
} else if (a instanceof byte[]) {
return b instanceof byte[] && TArrays.equals((byte[])a, (byte[])b);
} else if (b instanceof byte[]) {
return false;
} else if (a instanceof short[]) {
return b instanceof short[] && TArrays.equals((short[])a, (short[])b);
} else if (b instanceof short[]) {
return false;
} else if (a instanceof int[]) {
return b instanceof int[] && TArrays.equals((int[])a, (int[])b);
} else if (b instanceof int[]) {
return false;
} else if (a instanceof char[]) {
return b instanceof char[] && TArrays.equals((char[])a, (char[])b);
} else if (b instanceof char[]) {
return false;
} else if (a instanceof float[]) {
return b instanceof float[] && TArrays.equals((float[])a, (float[])b);
} else if (b instanceof float[]) {
return false;
} else if (a instanceof double[]) {
return b instanceof double[] && TArrays.equals((double[])a, (double[])b);
} else if (b instanceof double[]) {
return false;
} else if (a instanceof Object[]) {
return b instanceof Object[] && TArrays.deepEquals((Object[])a, (Object[])b);
} else if (b instanceof Object[]) {
return false;
} else {
return a.equals(b);
}
}
public static int hash(Object... values) {
return TArrays.hashCode(values);
}
} }

View File

@ -60,4 +60,8 @@ public final class TServiceLoader<S> extends TObject implements TIterable<S> {
} }
private static native <T> T[] loadServices(TClass<T> serviceType); private static native <T> T[] loadServices(TClass<T> serviceType);
public void reload() {
// Do nothing, services are bound at build time
}
} }

View File

@ -37,6 +37,19 @@ public class ArraysTest {
assertEquals(Integer.valueOf(7), array[5]); assertEquals(Integer.valueOf(7), array[5]);
} }
@Test
public void binarySearchWorks() {
Integer[] array = { 2, 4, 6, 8, 10, 12, 14, 16 };
assertEquals(3, Arrays.binarySearch(array, 8));
assertEquals(7, Arrays.binarySearch(array, 16));
assertEquals(0, Arrays.binarySearch(array, 2));
assertEquals(-1, Arrays.binarySearch(array, 1));
assertEquals(-2, Arrays.binarySearch(array, 3));
assertEquals(-3, Arrays.binarySearch(array, 5));
assertEquals(-8, Arrays.binarySearch(array, 15));
assertEquals(-9, Arrays.binarySearch(array, 17));
}
@Test @Test
public void arrayExposedAsList() { public void arrayExposedAsList() {
Integer[] array = { 2, 3, 4 }; Integer[] array = { 2, 3, 4 };
@ -44,4 +57,11 @@ public class ArraysTest {
assertEquals(3, list.size()); assertEquals(3, list.size());
assertEquals(Integer.valueOf(4), list.get(2)); assertEquals(Integer.valueOf(4), list.get(2));
} }
@Test
public void arrayExposedAsString() {
Object[] array = { 1, 2, null, null, "foo" };
array[3] = array;
assertEquals("[1, 2, null, [...], foo]", Arrays.deepToString(array));
}
} }