mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 16:14:10 -08:00
Adds complete enum support
This commit is contained in:
parent
f3ae632786
commit
f63d0cd8d0
|
@ -0,0 +1,68 @@
|
|||
/*
|
||||
* 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.impl;
|
||||
|
||||
import org.teavm.dependency.*;
|
||||
import org.teavm.model.ClassReader;
|
||||
import org.teavm.model.MethodDescriptor;
|
||||
import org.teavm.model.MethodReader;
|
||||
import org.teavm.model.ValueType;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Alexey Andreev
|
||||
*/
|
||||
public class EnumDependencySupport implements DependencyListener {
|
||||
private DependencyNode allEnums;
|
||||
private volatile DependencyStack enumConstantsStack;
|
||||
|
||||
@Override
|
||||
public void started(DependencyChecker dependencyChecker) {
|
||||
allEnums = dependencyChecker.createNode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void classAchieved(DependencyChecker dependencyChecker, String className) {
|
||||
ClassReader cls = dependencyChecker.getClassSource().get(className);
|
||||
if (cls == null || cls.getParent() == null || !cls.getParent().equals("java.lang.Enum")) {
|
||||
allEnums.propagate(className);
|
||||
}
|
||||
if (enumConstantsStack != null) {
|
||||
MethodReader method = cls.getMethod(new MethodDescriptor("values",
|
||||
ValueType.arrayOf(ValueType.object(cls.getName()))));
|
||||
if (method != null) {
|
||||
dependencyChecker.linkMethod(method.getReference(), enumConstantsStack).use();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void methodAchieved(DependencyChecker dependencyChecker, MethodDependency method) {
|
||||
if (method.getReference().getClassName().equals("java.lang.Class") &&
|
||||
method.getReference().getName().equals("getEnumConstantsImpl")) {
|
||||
allEnums.connect(method.getResult().getArrayItem());
|
||||
method.getResult().propagate("[java.lang.Enum");
|
||||
enumConstantsStack = method.getStack();
|
||||
for (String cls : dependencyChecker.getAchievableClasses()) {
|
||||
classAchieved(dependencyChecker, cls);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fieldAchieved(DependencyChecker dependencyChecker, FieldDependency field) {
|
||||
}
|
||||
}
|
|
@ -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.impl;
|
||||
|
||||
import org.teavm.javascript.ni.PreserveOriginalName;
|
||||
import org.teavm.model.*;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Alexey Andreev
|
||||
*/
|
||||
public class EnumTransformer implements ClassHolderTransformer {
|
||||
@Override
|
||||
public void transformClass(ClassHolder cls, ClassReaderSource innerSource) {
|
||||
if (cls.getParent() != null && !cls.getParent().equals("java.lang.Enum")) {
|
||||
return;
|
||||
}
|
||||
MethodHolder method = cls.getMethod(new MethodDescriptor("values",
|
||||
ValueType.arrayOf(ValueType.object(cls.getName()))));
|
||||
if (method == null) {
|
||||
return;
|
||||
}
|
||||
method.getAnnotations().add(new AnnotationHolder(PreserveOriginalName.class.getName()));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* 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.impl;
|
||||
|
||||
import org.teavm.javascript.JavascriptBuilderHost;
|
||||
import org.teavm.javascript.JavascriptBuilderPlugin;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Alexey Andreev
|
||||
*/
|
||||
public class JCLPlugin implements JavascriptBuilderPlugin {
|
||||
@Override
|
||||
public void install(JavascriptBuilderHost host) {
|
||||
host.add(new EnumDependencySupport());
|
||||
host.add(new EnumTransformer());
|
||||
}
|
||||
}
|
|
@ -74,6 +74,10 @@ public class ClassNativeGenerator implements Generator, Injector, DependencyPlug
|
|||
case "wrap":
|
||||
context.writeExpr(context.getArgument(0));
|
||||
break;
|
||||
case "getEnumConstantsImpl":
|
||||
context.writeExpr(context.getArgument(0));
|
||||
context.getWriter().append(".$data.values()");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -100,11 +100,12 @@ public class ObjectNativeGenerator implements Generator, Injector, DependencyPlu
|
|||
}
|
||||
|
||||
private void generateClone(GeneratorContext context, SourceWriter writer) throws IOException {
|
||||
writer.append("var copy = new ").append(context.getParameterName(0)).append(".constructor();").softNewLine();
|
||||
writer.append("for (var field in obj) {").softNewLine().indent();
|
||||
writer.append("if (!obj.hasOwnProperty(field)) {").softNewLine().indent();
|
||||
String obj = context.getParameterName(0);
|
||||
writer.append("var copy = new ").append(obj).append(".constructor();").softNewLine();
|
||||
writer.append("for (var field in " + obj + ") {").softNewLine().indent();
|
||||
writer.append("if (!" + obj + ".hasOwnProperty(field)) {").softNewLine().indent();
|
||||
writer.append("continue;").softNewLine().outdent().append("}").softNewLine();
|
||||
writer.append("copy[field] = obj[field];").softNewLine().outdent().append("}").softNewLine();
|
||||
writer.append("copy[field] = " + obj + "[field];").softNewLine().outdent().append("}").softNewLine();
|
||||
writer.append("return copy;").softNewLine();
|
||||
}
|
||||
|
||||
|
|
|
@ -18,6 +18,7 @@ package org.teavm.classlib.java.lang;
|
|||
import org.teavm.classlib.impl.unicode.UnicodeHelper;
|
||||
import org.teavm.dependency.PluggableDependency;
|
||||
import org.teavm.javascript.ni.GeneratedBy;
|
||||
import org.teavm.javascript.ni.Rename;
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -41,6 +42,20 @@ public class TCharacter extends TObject {
|
|||
return new TCharacter(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Rename("toString")
|
||||
public TString toString0() {
|
||||
return new TString(new char[] { value });
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(TObject other) {
|
||||
if (this == other) {
|
||||
return true;
|
||||
}
|
||||
return other instanceof TCharacter && ((TCharacter)other).value == value;
|
||||
}
|
||||
|
||||
@GeneratedBy(CharacterNativeGenerator.class)
|
||||
public static native char toLowerCase(char ch);
|
||||
|
||||
|
|
|
@ -27,6 +27,7 @@ public class TClass<T extends TObject> extends TObject {
|
|||
TString name;
|
||||
boolean primitive;
|
||||
boolean array;
|
||||
boolean isEnum;
|
||||
private TClass<?> componentType;
|
||||
private boolean componentTypeDirty = true;
|
||||
|
||||
|
@ -52,6 +53,10 @@ public class TClass<T extends TObject> extends TObject {
|
|||
return array;
|
||||
}
|
||||
|
||||
public boolean isEnum() {
|
||||
return isEnum;
|
||||
}
|
||||
|
||||
public TClass<?> getComponentType() {
|
||||
if (componentTypeDirty) {
|
||||
componentType = getComponentType0();
|
||||
|
@ -83,4 +88,11 @@ public class TClass<T extends TObject> extends TObject {
|
|||
@GeneratedBy(ClassNativeGenerator.class)
|
||||
@PluggableDependency(ClassNativeGenerator.class)
|
||||
public native TClass<? super T> getSuperclass();
|
||||
|
||||
public T[] getEnumConstants() {
|
||||
return isEnum ? getEnumConstantsImpl() : null;
|
||||
}
|
||||
|
||||
@InjectedBy(ClassNativeGenerator.class)
|
||||
public native T[] getEnumConstantsImpl();
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2013 Alexey Andreev.
|
||||
* 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.
|
||||
|
@ -13,18 +13,20 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.teavm.classlib.org.junit;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
package org.teavm.classlib.java.lang;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Alexey Andreev <konsoletyper@gmail.com>
|
||||
* @author Alexey Andreev
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.METHOD)
|
||||
public @interface Test {
|
||||
public class TClassCastException extends TRuntimeException {
|
||||
private static final long serialVersionUID = 5744987817019231273L;
|
||||
|
||||
public TClassCastException() {
|
||||
super();
|
||||
}
|
||||
|
||||
public TClassCastException(TString message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
|
@ -16,6 +16,7 @@
|
|||
package org.teavm.classlib.java.lang;
|
||||
|
||||
import org.teavm.javascript.ni.GeneratedBy;
|
||||
import org.teavm.javascript.ni.Rename;
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -52,6 +53,20 @@ public class TDouble extends TNumber {
|
|||
return new TDouble(d);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Rename("toString")
|
||||
public TString toString0() {
|
||||
return TString.wrap(new TStringBuilder().append(value).toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(TObject other) {
|
||||
if (this == other) {
|
||||
return true;
|
||||
}
|
||||
return other instanceof TDouble && ((TDouble)other).value == value;
|
||||
}
|
||||
|
||||
@GeneratedBy(DoubleNativeGenerator.class)
|
||||
public static native boolean isNaN(double v);
|
||||
|
||||
|
|
|
@ -62,9 +62,7 @@ public abstract class TEnum<E extends TEnum<E>> extends TObject implements TComp
|
|||
|
||||
@SuppressWarnings("unchecked")
|
||||
public final TClass<E> getDeclaringClass() {
|
||||
TClass<?> thisClass = TClass.wrap(getClass());
|
||||
TClass<?> superClass = thisClass.getSuperclass();
|
||||
return (TClass<E>)(superClass == TClass.wrap(TEnum.class) ? thisClass : superClass);
|
||||
return (TClass<E>)TClass.wrap(getClass());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -76,4 +74,19 @@ public abstract class TEnum<E extends TEnum<E>> extends TObject implements TComp
|
|||
}
|
||||
return TInteger.compare(ordinal, o.ordinal());
|
||||
}
|
||||
|
||||
public static <T extends TEnum<T>> T valueOf(TClass<T> enumType, TString name) {
|
||||
// TODO: speed-up this method, use caching
|
||||
T[] constants = enumType.getEnumConstants();
|
||||
if (constants == null) {
|
||||
throw new TIllegalArgumentException(TString.wrap("Class does not represent enum: " + enumType.getName()));
|
||||
}
|
||||
for (T constant : constants) {
|
||||
if (constant.name().equals(name)) {
|
||||
return constant;
|
||||
}
|
||||
}
|
||||
throw new TIllegalArgumentException(TString.wrap("Enum " + enumType.getName() + " does not have the " + name +
|
||||
"constant"));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,6 +15,8 @@
|
|||
*/
|
||||
package org.teavm.classlib.java.lang;
|
||||
|
||||
import org.teavm.javascript.ni.Rename;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Alexey Andreev <konsoletyper@gmail.com>
|
||||
|
@ -49,4 +51,18 @@ public class TLong extends TNumber {
|
|||
public double doubleValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Rename("toString")
|
||||
public TString toString0() {
|
||||
return TString.wrap(new TStringBuilder().append(value).toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(TObject other) {
|
||||
if (this == other) {
|
||||
return true;
|
||||
}
|
||||
return other instanceof TLong && ((TLong)other).value == value;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,87 +0,0 @@
|
|||
/*
|
||||
* Copyright 2013 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.org.junit;
|
||||
|
||||
import org.teavm.javascript.ni.GeneratedBy;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Alexey Andreev <konsoletyper@gmail.com>
|
||||
*/
|
||||
public class Assert {
|
||||
public static void assertTrue(boolean condition) {
|
||||
if (!condition) {
|
||||
fail();
|
||||
}
|
||||
}
|
||||
|
||||
public static void assertFalse(boolean condition) {
|
||||
if (condition) {
|
||||
fail();
|
||||
}
|
||||
}
|
||||
|
||||
@GeneratedBy(AssertNativeGenerator.class)
|
||||
public static native void fail();
|
||||
|
||||
public static void assertEquals(Object expected, Object actual) {
|
||||
if (expected != null ? !expected.equals(actual) : actual != null) {
|
||||
fail();
|
||||
}
|
||||
}
|
||||
|
||||
public static void assertNotEquals(Object expected, Object actual) {
|
||||
if (expected != null ? expected.equals(actual) : actual == null) {
|
||||
fail();
|
||||
}
|
||||
}
|
||||
|
||||
public static void assertEquals(long expected, long actual) {
|
||||
if (expected != actual) {
|
||||
fail();
|
||||
}
|
||||
}
|
||||
|
||||
public static void assertNotEquals(long expected, long actual) {
|
||||
if (expected == actual) {
|
||||
fail();
|
||||
}
|
||||
}
|
||||
|
||||
public static void assertNotNull(Object object) {
|
||||
if (object == null) {
|
||||
fail();
|
||||
}
|
||||
}
|
||||
|
||||
public static void assertNull(Object object) {
|
||||
if (object != null) {
|
||||
fail();
|
||||
}
|
||||
}
|
||||
|
||||
public static void assertSame(Object expected, Object actual) {
|
||||
if (expected != actual) {
|
||||
fail();
|
||||
}
|
||||
}
|
||||
|
||||
public static void assertNotSame(Object expected, Object actual) {
|
||||
if (expected == actual) {
|
||||
fail();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,42 +0,0 @@
|
|||
/*
|
||||
* Copyright 2013 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.org.junit;
|
||||
|
||||
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 AssertNativeGenerator implements Generator {
|
||||
@Override
|
||||
public void generate(GeneratorContext context, SourceWriter writer, MethodReference methodRef)
|
||||
throws IOException {
|
||||
switch (methodRef.getDescriptor().getName()) {
|
||||
case "fail":
|
||||
generateFail(writer);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void generateFail(SourceWriter writer) throws IOException {
|
||||
writer.append("throw new Error();").newLine();
|
||||
}
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
org.teavm.classlib.impl.JCLPlugin
|
|
@ -12,5 +12,4 @@
|
|||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
packagePrefix.java=org.teavm.classlib
|
||||
classPrefix.java=T
|
||||
packagePrefix.org.junit=org.teavm.classlib
|
||||
classPrefix.java=T
|
|
@ -0,0 +1,73 @@
|
|||
/*
|
||||
* 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 static org.junit.Assert.*;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Alexey Andreev
|
||||
*/
|
||||
public class EnumTest {
|
||||
private static enum Foo {
|
||||
A, B, C
|
||||
}
|
||||
|
||||
private static enum Bar {
|
||||
D, E
|
||||
}
|
||||
|
||||
@Test
|
||||
public void sameConstantsAreEqual() {
|
||||
assertEquals(Foo.A, Foo.A);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void differentConstansAreNotEqual() {
|
||||
assertNotEquals(Foo.A, Foo.B);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void constantsOfDifferentEnumsAreNotEqual() {
|
||||
assertNotEquals(Foo.A, Bar.D);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void declaringClassComputed() {
|
||||
assertEquals(Foo.class, Foo.A.getDeclaringClass());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void comparisonGivesZeroForSameConstants() {
|
||||
assertEquals(0, Foo.A.compareTo(Foo.A));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void comparisonGivesPositiveForLaterConstant() {
|
||||
assertTrue(Foo.B.compareTo(Foo.A) > 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void comparisonGivesNegativeForEarlierConstant() {
|
||||
assertTrue(Foo.A.compareTo(Foo.B) < 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void valueOfReturnsConstant() {
|
||||
assertEquals("A", Enum.valueOf(Foo.class, "A").name());
|
||||
}
|
||||
}
|
|
@ -231,9 +231,13 @@ public class Decompiler {
|
|||
Set<NodeModifier> result = EnumSet.noneOf(NodeModifier.class);
|
||||
if (modifiers.contains(ElementModifier.STATIC)) {
|
||||
result.add(NodeModifier.STATIC);
|
||||
} else if (modifiers.contains(ElementModifier.INTERFACE)) {
|
||||
}
|
||||
if (modifiers.contains(ElementModifier.INTERFACE)) {
|
||||
result.add(NodeModifier.INTERFACE);
|
||||
}
|
||||
if (modifiers.contains(ElementModifier.ENUM)) {
|
||||
result.add(NodeModifier.ENUM);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
@ -135,6 +135,11 @@ public class JavascriptBuilder implements JavascriptBuilderHost {
|
|||
ValueType.object("java.lang.Class"))), DependencyStack.ROOT).use();
|
||||
dependencyChecker.linkMethod(new MethodReference("java.lang.String", new MethodDescriptor("<init>",
|
||||
ValueType.arrayOf(ValueType.CHARACTER), ValueType.VOID)), DependencyStack.ROOT).use();
|
||||
dependencyChecker.linkMethod(new MethodReference("java.lang.String", new MethodDescriptor("getChars",
|
||||
ValueType.INTEGER, ValueType.INTEGER, ValueType.arrayOf(ValueType.CHARACTER), ValueType.INTEGER,
|
||||
ValueType.VOID)), DependencyStack.ROOT).use();
|
||||
dependencyChecker.linkMethod(new MethodReference("java.lang.Object", new MethodDescriptor("clone",
|
||||
ValueType.object("java.lang.Object"))), DependencyStack.ROOT).use();
|
||||
executor.complete();
|
||||
if (hasMissingItems()) {
|
||||
return;
|
||||
|
|
|
@ -77,6 +77,7 @@ public class Renderer implements ExprVisitor, StatementVisitor {
|
|||
try {
|
||||
renderRuntimeCls();
|
||||
renderRuntimeString();
|
||||
renderRuntimeUnwrapString();
|
||||
renderRuntimeObjcls();
|
||||
} catch (NamingException e) {
|
||||
throw new RenderingException("Error rendering runtime methods. See a cause for details", e);
|
||||
|
@ -110,6 +111,11 @@ public class Renderer implements ExprVisitor, StatementVisitor {
|
|||
.append("=").ws().append("clsProto.$meta.item").ws().append("?").ws()
|
||||
.append("1").ws().append(":").ws().append("0;").softNewLine();
|
||||
}
|
||||
if (classSource.get(classClass).getField("isEnum") != null) {
|
||||
writer.append("cls.").appendField(new FieldReference(classClass, "isEnum")).ws()
|
||||
.append("=").ws().append("clsProto.$meta.enum").ws().append("?").ws()
|
||||
.append("1").ws().append(":").ws().append("0;").softNewLine();
|
||||
}
|
||||
writer.append("clsProto.classObject").ws().append("=").ws().append("cls;").softNewLine();
|
||||
writer.outdent().append("}").softNewLine();
|
||||
writer.append("return cls;").softNewLine();
|
||||
|
@ -131,6 +137,25 @@ public class Renderer implements ExprVisitor, StatementVisitor {
|
|||
writer.outdent().append("}").newLine();
|
||||
}
|
||||
|
||||
private void renderRuntimeUnwrapString() throws IOException {
|
||||
String stringClass = "java.lang.String";
|
||||
MethodReference stringLen = new MethodReference(stringClass, new MethodDescriptor(
|
||||
"length", ValueType.INTEGER));
|
||||
MethodReference getChars = new MethodReference(stringClass, new MethodDescriptor(
|
||||
"getChars", ValueType.INTEGER, ValueType.INTEGER, ValueType.arrayOf(ValueType.CHARACTER),
|
||||
ValueType.INTEGER, ValueType.VOID));
|
||||
writer.append("$rt_ustr = function(str) {").indent().softNewLine();
|
||||
writer.append("var result = \"\";").softNewLine();
|
||||
writer.append("var sz = ").appendMethodBody(stringLen).append("(str);").softNewLine();
|
||||
writer.append("var array = $rt_createCharArray(sz);");
|
||||
writer.appendMethodBody(getChars).append("(str, 0, sz, array, 0);");
|
||||
writer.append("for (var i = 0; i < sz; i = (i + 1) | 0) {").indent().softNewLine();
|
||||
writer.append("result += String.fromCharCode(array.data[i]);").softNewLine();
|
||||
writer.outdent().append("}").softNewLine();
|
||||
writer.append("return result;").softNewLine();
|
||||
writer.outdent().append("}").newLine();
|
||||
}
|
||||
|
||||
private void renderRuntimeObjcls() throws IOException {
|
||||
writer.append("$rt_objcls = function() { return ").appendClass("java.lang.Object").append("; }").newLine();
|
||||
}
|
||||
|
@ -174,7 +199,9 @@ public class Renderer implements ExprVisitor, StatementVisitor {
|
|||
}
|
||||
writer.appendClass(cls.getName()).append(".$meta").ws().append("=").ws().append("{").ws();
|
||||
writer.append("name").ws().append(":").ws().append("\"").append(cls.getName()).append("\",").ws();
|
||||
writer.append("primitive").ws().append(":").ws().append("false,").ws();
|
||||
if (cls.getModifiers().contains(NodeModifier.ENUM)) {
|
||||
writer.append("enum").ws().append(":").ws().append("true,").ws();
|
||||
}
|
||||
writer.append("supertypes").ws().append(":").ws().append("[");
|
||||
boolean first = true;
|
||||
if (cls.getParentName() != null) {
|
||||
|
@ -195,7 +222,10 @@ public class Renderer implements ExprVisitor, StatementVisitor {
|
|||
}
|
||||
writer.ws().append("};").softNewLine();
|
||||
if (!cls.getModifiers().contains(NodeModifier.INTERFACE)) {
|
||||
writer.appendClass(cls.getName()).append("_$clinit").ws().append("=").ws().append("function()").ws()
|
||||
writer.appendClass(cls.getName()).append(".$clinit").ws().append("=").ws()
|
||||
.append("function()").ws().append("{").ws()
|
||||
.appendClass(cls.getName()).append("_$clinit();").ws().append("}").newLine();
|
||||
writer.append("function ").appendClass(cls.getName()).append("_$clinit()").ws()
|
||||
.append("{").softNewLine().indent();
|
||||
writer.appendClass(cls.getName()).append("_$clinit").ws().append("=").ws()
|
||||
.append("function(){};").newLine();
|
||||
|
@ -213,7 +243,7 @@ public class Renderer implements ExprVisitor, StatementVisitor {
|
|||
writer.outdent().append("}").newLine();
|
||||
for (MethodNode method : cls.getMethods()) {
|
||||
cls.getMethods();
|
||||
if (!method.getModifiers().contains(NodeModifier.STATIC)) {
|
||||
if (!method.getModifiers().contains(NodeModifier.STATIC) || method.isOriginalNamePreserved()) {
|
||||
renderDeclaration(method);
|
||||
}
|
||||
}
|
||||
|
@ -287,30 +317,10 @@ public class Renderer implements ExprVisitor, StatementVisitor {
|
|||
|
||||
public void renderDeclaration(MethodNode method) throws RenderingException, IOException {
|
||||
try {
|
||||
MethodReference ref = method.getReference();
|
||||
if (ref.getDescriptor().getName().equals("<init>")) {
|
||||
renderInitializer(method);
|
||||
}
|
||||
writer.appendClass(ref.getClassName()).append(".prototype.").appendMethod(ref)
|
||||
.ws().append("=").ws().append("function(");
|
||||
for (int i = 1; i <= ref.parameterCount(); ++i) {
|
||||
if (i > 1) {
|
||||
writer.append(", ");
|
||||
}
|
||||
writer.append(variableName(i));
|
||||
}
|
||||
writer.append(")").ws().append("{").softNewLine().indent();
|
||||
writer.append("return ").appendMethodBody(ref).append("(");
|
||||
writer.append("this");
|
||||
for (int i = 1; i <= ref.parameterCount(); ++i) {
|
||||
writer.append(",").ws().append(variableName(i));
|
||||
}
|
||||
writer.append(");").softNewLine();
|
||||
writer.outdent().append("}").newLine();
|
||||
if (method.isOriginalNamePreserved()) {
|
||||
writer.appendClass(ref.getClassName()).append(".prototype.").append(ref.getName()).ws().append("=")
|
||||
.ws().appendClass(ref.getClassName()).append(".prototype.").appendMethod(ref)
|
||||
.append(';').newLine();
|
||||
if (method.getModifiers().contains(NodeModifier.STATIC)) {
|
||||
renderStaticDeclaration(method);
|
||||
} else {
|
||||
renderVirtualDeclaration(method);
|
||||
}
|
||||
} catch (NamingException e) {
|
||||
throw new RenderingException("Error rendering method " + method.getReference() + ". " +
|
||||
|
@ -318,6 +328,59 @@ public class Renderer implements ExprVisitor, StatementVisitor {
|
|||
}
|
||||
}
|
||||
|
||||
private void renderVirtualDeclaration(MethodNode method) throws NamingException, IOException {
|
||||
MethodReference ref = method.getReference();
|
||||
if (ref.getDescriptor().getName().equals("<init>")) {
|
||||
renderInitializer(method);
|
||||
}
|
||||
writer.appendClass(ref.getClassName()).append(".prototype.").appendMethod(ref)
|
||||
.ws().append("=").ws().append("function(");
|
||||
for (int i = 1; i <= ref.parameterCount(); ++i) {
|
||||
if (i > 1) {
|
||||
writer.append(", ");
|
||||
}
|
||||
writer.append(variableName(i));
|
||||
}
|
||||
writer.append(")").ws().append("{").softNewLine().indent();
|
||||
writer.append("return ").appendMethodBody(ref).append("(");
|
||||
writer.append("this");
|
||||
for (int i = 1; i <= ref.parameterCount(); ++i) {
|
||||
writer.append(",").ws().append(variableName(i));
|
||||
}
|
||||
writer.append(");").softNewLine();
|
||||
writer.outdent().append("}").newLine();
|
||||
if (method.isOriginalNamePreserved()) {
|
||||
writer.appendClass(ref.getClassName()).append(".prototype.").append(ref.getName()).ws().append("=")
|
||||
.ws().appendClass(ref.getClassName()).append(".prototype.").appendMethod(ref)
|
||||
.append(';').newLine();
|
||||
}
|
||||
}
|
||||
|
||||
private void renderStaticDeclaration(MethodNode method) throws NamingException, IOException {
|
||||
MethodReference ref = method.getReference();
|
||||
if (ref.getDescriptor().getName().equals("<init>")) {
|
||||
renderInitializer(method);
|
||||
}
|
||||
writer.appendClass(ref.getClassName()).append(".").appendMethod(ref).ws().append("=").ws().append("function(");
|
||||
for (int i = 0; i < ref.parameterCount(); ++i) {
|
||||
if (i > 0) {
|
||||
writer.append(", ");
|
||||
}
|
||||
writer.append(variableName(i + 1));
|
||||
}
|
||||
writer.append(")").ws().append("{").softNewLine().indent();
|
||||
writer.append("return ").appendMethodBody(ref).append("(");
|
||||
for (int i = 0; i < ref.parameterCount(); ++i) {
|
||||
writer.append(",").ws().append(variableName(i + 1));
|
||||
}
|
||||
writer.append(");").softNewLine();
|
||||
writer.outdent().append("}").newLine();
|
||||
if (method.isOriginalNamePreserved()) {
|
||||
writer.appendClass(ref.getClassName()).append(".").append(ref.getName()).ws().append("=")
|
||||
.ws().appendClass(ref.getClassName()).append(".").appendMethod(ref).append(';').newLine();
|
||||
}
|
||||
}
|
||||
|
||||
public void renderBody(MethodNode method) throws IOException {
|
||||
MethodReference ref = method.getReference();
|
||||
writer.appendMethodBody(ref).ws().append("=").ws().append("function(");
|
||||
|
@ -1190,12 +1253,13 @@ public class Renderer implements ExprVisitor, StatementVisitor {
|
|||
InjectorHolder holder = injectorMap.get(ref);
|
||||
if (holder == null) {
|
||||
MethodHolder method = classSource.get(ref.getClassName()).getMethod(ref.getDescriptor());
|
||||
AnnotationHolder injectedByAnnot = method.getAnnotations().get(InjectedBy.class.getName());
|
||||
if (injectedByAnnot != null) {
|
||||
ValueType type = injectedByAnnot.getValues().get("value").getJavaClass();
|
||||
holder = new InjectorHolder(instantiateInjector(((ValueType.Object)type).getClassName()));
|
||||
} else {
|
||||
holder = new InjectorHolder(null);
|
||||
holder = new InjectorHolder(null);
|
||||
if (method != null) {
|
||||
AnnotationHolder injectedByAnnot = method.getAnnotations().get(InjectedBy.class.getName());
|
||||
if (injectedByAnnot != null) {
|
||||
ValueType type = injectedByAnnot.getValues().get("value").getJavaClass();
|
||||
holder = new InjectorHolder(instantiateInjector(((ValueType.Object)type).getClassName()));
|
||||
}
|
||||
}
|
||||
injectorMap.put(ref, holder);
|
||||
}
|
||||
|
|
|
@ -21,5 +21,6 @@ package org.teavm.javascript.ast;
|
|||
*/
|
||||
public enum NodeModifier {
|
||||
STATIC,
|
||||
INTERFACE
|
||||
INTERFACE,
|
||||
ENUM
|
||||
}
|
||||
|
|
|
@ -84,9 +84,9 @@
|
|||
<scanDependencies>true</scanDependencies>
|
||||
<outputDir>${project.build.directory}/javascript-tck</outputDir>
|
||||
<adapterClass>org.teavm.html4j.testing.KOTestAdapter</adapterClass>
|
||||
<!-- <wildcards>
|
||||
<wildcards>
|
||||
<param>net.java.html.js.tests.*Test</param>
|
||||
</wildcards> -->
|
||||
</wildcards>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
|
|
Loading…
Reference in New Issue
Block a user