Removes primitive wrappers support from metadata providers

This commit is contained in:
konsoletyper 2014-06-09 17:08:49 +04:00
parent a5f9e4a0b4
commit 0ee5ba52c4
25 changed files with 235 additions and 324 deletions

View File

@ -19,8 +19,7 @@ package org.teavm.platform.metadata;
* *
* @author Alexey Andreev * @author Alexey Andreev
*/ */
@Resource public interface DependentTestResource extends Resource {
public interface DependentTestResource {
String getBar(); String getBar();
void setBar(String bar); void setBar(String bar);

View File

@ -32,11 +32,11 @@ public class MetadataGeneratorTest {
} }
@MetadataProvider(TestResourceGenerator.class) @MetadataProvider(TestResourceGenerator.class)
private native int getInt(); private native IntResource getInt();
@Test @Test
public void intExposed() { public void intExposed() {
assertEquals(23, getInt()); assertEquals(23, getInt().getValue());
} }
@MetadataProvider(TestResourceGenerator.class) @MetadataProvider(TestResourceGenerator.class)
@ -52,20 +52,13 @@ public class MetadataGeneratorTest {
assertEquals(3.14, res.getF(), 0.001); assertEquals(3.14, res.getF(), 0.001);
assertEquals(2.72, res.getG(), 0.001); assertEquals(2.72, res.getG(), 0.001);
assertEquals(Integer.valueOf(26), res.getH());
assertNull(res.getI());
assertEquals(Byte.valueOf((byte)27), res.getJ());
assertEquals(Short.valueOf((short)28), res.getK());
assertEquals(100, res.getL().floatValue(), 0.1);
assertEquals(200, res.getM().doubleValue(), 0.1);
assertEquals("qwe", res.getFoo()); assertEquals("qwe", res.getFoo());
assertEquals(2, res.getArrayA().size()); assertEquals(2, res.getArrayA().size());
assertEquals(Integer.valueOf(2), res.getArrayA().get(0)); assertEquals(2, res.getArrayA().get(0).getValue());
assertEquals(Integer.valueOf(3), res.getArrayA().get(1)); assertEquals(3, res.getArrayA().get(1).getValue());
assertEquals(1, res.getArrayB().size()); assertEquals(1, res.getArrayB().size());
assertEquals("baz", res.getArrayB().get(0)); assertEquals("baz", res.getArrayB().get(0).getBar());
assertNull(res.getArrayC()); assertNull(res.getArrayC());
} }
} }

View File

@ -19,8 +19,7 @@ package org.teavm.platform.metadata;
* *
* @author Alexey Andreev * @author Alexey Andreev
*/ */
@Resource public interface TestResource extends Resource {
public interface TestResource {
int getA(); int getA();
void setA(int a); void setA(int a);
@ -45,55 +44,31 @@ public interface TestResource {
void setG(double g); void setG(double g);
Integer getH();
void setH(Integer a);
Boolean getI();
void setI(Boolean i);
Byte getJ();
void setJ(Byte d);
Short getK();
void setK(Short k);
Float getL();
void setL(Float l);
Double getM();
void setM(Double g);
String getFoo(); String getFoo();
void setFoo(String foo); void setFoo(String foo);
ResourceArray<Integer> getArrayA(); ResourceArray<IntResource> getArrayA();
void setArrayA(ResourceArray<Integer> arrayA); void setArrayA(ResourceArray<IntResource> arrayA);
ResourceArray<DependentTestResource> getArrayB(); ResourceArray<DependentTestResource> getArrayB();
void setArrayB(ResourceArray<DependentTestResource> arrayB); void setArrayB(ResourceArray<DependentTestResource> arrayB);
ResourceArray<ResourceArray<String>> getArrayC(); ResourceArray<ResourceArray<StringResource>> getArrayC();
void setArrayC(ResourceArray<ResourceArray<String>> arrayC); void setArrayC(ResourceArray<ResourceArray<StringResource>> arrayC);
ResourceMap<Integer> getMapA(); ResourceMap<IntResource> getMapA();
void setMapA(ResourceMap<Integer> mapA); void setMapA(ResourceMap<IntResource> mapA);
ResourceMap<DependentTestResource> getMapB(); ResourceMap<DependentTestResource> getMapB();
void setMapB(ResourceMap<DependentTestResource> mapB); void setMapB(ResourceMap<DependentTestResource> mapB);
ResourceMap<ResourceArray<String>> getMapC(); ResourceMap<ResourceArray<StringResource>> getMapC();
void setMapC(ResourceMap<ResourceArray<String>> mapC); void setMapC(ResourceMap<ResourceArray<StringResource>> mapC);
} }

View File

@ -23,12 +23,12 @@ import org.teavm.model.MethodReference;
*/ */
public class TestResourceGenerator implements MetadataGenerator { public class TestResourceGenerator implements MetadataGenerator {
@Override @Override
public Object generateMetadata(MetadataGeneratorContext context, MethodReference method) { public Resource generateMetadata(MetadataGeneratorContext context, MethodReference method) {
switch (method.getName()) { switch (method.getName()) {
case "getNull": case "getNull":
return null; return null;
case "getInt": case "getInt":
return 23; return createInt(context, 23);
case "getResource": case "getResource":
return getResource(context); return getResource(context);
default: default:
@ -36,7 +36,7 @@ public class TestResourceGenerator implements MetadataGenerator {
} }
} }
private Object getResource(MetadataGeneratorContext context) { private Resource getResource(MetadataGeneratorContext context) {
TestResource resource = context.createResource(TestResource.class); TestResource resource = context.createResource(TestResource.class);
resource.setA(23); resource.setA(23);
resource.setB(false); resource.setB(false);
@ -44,17 +44,11 @@ public class TestResourceGenerator implements MetadataGenerator {
resource.setE((short)25); resource.setE((short)25);
resource.setF(3.14f); resource.setF(3.14f);
resource.setG(2.72); resource.setG(2.72);
resource.setH(26);
resource.setI(null);
resource.setJ((byte)27);
resource.setK((short)28);
resource.setL(100f);
resource.setM(200.0);
resource.setFoo("qwe"); resource.setFoo("qwe");
ResourceArray<Integer> array = context.createResourceArray(); ResourceArray<IntResource> array = context.createResourceArray();
array.add(2); array.add(createInt(context, 2));
array.add(3); array.add(createInt(context, 3));
resource.setArrayA(array); resource.setArrayA(array);
DependentTestResource dep = context.createResource(DependentTestResource.class); DependentTestResource dep = context.createResource(DependentTestResource.class);
dep.setBar("baz"); dep.setBar("baz");
@ -63,4 +57,10 @@ public class TestResourceGenerator implements MetadataGenerator {
resource.setArrayB(resArray); resource.setArrayB(resArray);
return resource; return resource;
} }
private IntResource createInt(MetadataGeneratorContext context, int value) {
IntResource res = context.createResource(IntResource.class);
res.setValue(value);
return res;
}
} }

View File

@ -0,0 +1,26 @@
/*
* 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.platform.metadata;
/**
*
* @author Alexey Andreev
*/
public interface BooleanResource extends Resource {
boolean getValue();
void setValue(boolean value);
}

View File

@ -0,0 +1,26 @@
/*
* 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.platform.metadata;
/**
*
* @author Alexey Andreev
*/
public interface ByteResource extends Resource {
byte getValue();
void setValue(byte value);
}

View File

@ -0,0 +1,26 @@
/*
* 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.platform.metadata;
/**
*
* @author Alexey Andreev
*/
public interface DoubleResource extends Resource {
double getValue();
void setValue(double value);
}

View File

@ -0,0 +1,26 @@
/*
* 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.platform.metadata;
/**
*
* @author Alexey Andreev
*/
public interface FloatResource extends Resource {
float getValue();
void setValue(float value);
}

View File

@ -0,0 +1,26 @@
/*
* 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.platform.metadata;
/**
*
* @author Alexey Andreev
*/
public interface IntResource extends Resource {
int getValue();
void setValue(int value);
}

View File

@ -41,12 +41,10 @@ import org.teavm.model.MethodReference;
* <p>The valid resource types are the following:</p> * <p>The valid resource types are the following:</p>
* *
* <ul> * <ul>
* <li>Valid interfaces, marked with the {@link Resource} annotation. Read the description of this annotation * <li>Valid interfaces, extending the {@link Resource} annotation. Read the description of this interface
* for detailed description about valid resources interfaces.</li> * for detailed description about valid resources interfaces.</li>
* <li>{@link ResourceArray} of valid resources.</li> * <li>{@link ResourceArray} of valid resources.</li>
* <li>{@link ResourceMap} of valid resources.</li> * <li>{@link ResourceMap} of valid resources.</li>
* <li>{@link String}, {@link Integer}, {@link Byte}, {@link Short}, {@link Float}, {@link Double},
* {@link Boolean}.</li>
* <li>The <code>null</code> value.</li> * <li>The <code>null</code> value.</li>
* </ul> * </ul>
* *
@ -61,5 +59,5 @@ public interface MetadataGenerator {
* @param context context that contains useful compile-time information. * @param context context that contains useful compile-time information.
* @param method method which will be used to access the generated resources at run time. * @param method method which will be used to access the generated resources at run time.
*/ */
Object generateMetadata(MetadataGeneratorContext context, MethodReference method); Resource generateMetadata(MetadataGeneratorContext context, MethodReference method);
} }

View File

@ -45,15 +45,15 @@ public interface MetadataGeneratorContext {
* Creates a new resource of the given type. The description of valid resources * Creates a new resource of the given type. The description of valid resources
* is available in documentation for {@link Resource}. * is available in documentation for {@link Resource}.
*/ */
<T> T createResource(Class<T> resourceType); <T extends Resource> T createResource(Class<T> resourceType);
/** /**
* Creates a new resource array. * Creates a new resource array.
*/ */
<T> ResourceArray<T> createResourceArray(); <T extends Resource> ResourceArray<T> createResourceArray();
/** /**
* Creates a new resource map. * Creates a new resource map.
*/ */
<T> ResourceMap<T> createResourceMap(); <T extends Resource> ResourceMap<T> createResourceMap();
} }

View File

@ -15,8 +15,6 @@
*/ */
package org.teavm.platform.metadata; package org.teavm.platform.metadata;
import java.lang.annotation.*;
/** /**
* <p>Marks a valid <b>resource interface</b>. Resource interface is an interface, that has get* and set* methods, * <p>Marks a valid <b>resource interface</b>. Resource interface is an interface, that has get* and set* methods,
* according the default convention for JavaBeans. Each property must have both getter and setter. * according the default convention for JavaBeans. Each property must have both getter and setter.
@ -28,9 +26,5 @@ import java.lang.annotation.*;
* *
* @author Alexey Andreev <konsoletyper@gmail.com> * @author Alexey Andreev <konsoletyper@gmail.com>
*/ */
@Retention(RetentionPolicy.RUNTIME) public interface Resource {
@Target(ElementType.TYPE)
@Inherited
@Documented
public @interface Resource {
} }

View File

@ -19,7 +19,7 @@ package org.teavm.platform.metadata;
* *
* @author Alexey Andreev <konsoletyper@gmail.com> * @author Alexey Andreev <konsoletyper@gmail.com>
*/ */
public interface ResourceArray<T> { public interface ResourceArray<T extends Resource> extends Resource {
int size(); int size();
T get(int i); T get(int i);

View File

@ -19,7 +19,7 @@ package org.teavm.platform.metadata;
* *
* @author Alexey Andreev <konsoletyper@gmail.com> * @author Alexey Andreev <konsoletyper@gmail.com>
*/ */
public interface ResourceMap<T> { public interface ResourceMap<T extends Resource> extends Resource {
boolean has(String key); boolean has(String key);
T get(String key); T get(String key);

View File

@ -0,0 +1,26 @@
/*
* 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.platform.metadata;
/**
*
* @author Alexey Andreev
*/
public interface ShortResource extends Resource {
short getValue();
void setValue(short value);
}

View File

@ -0,0 +1,26 @@
/*
* 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.platform.metadata;
/**
*
* @author Alexey Andreev
*/
public interface StringResource extends Resource {
String getValue();
void setValue(String value);
}

View File

@ -19,13 +19,14 @@ import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import org.teavm.codegen.SourceWriter; import org.teavm.codegen.SourceWriter;
import org.teavm.platform.metadata.Resource;
import org.teavm.platform.metadata.ResourceArray; import org.teavm.platform.metadata.ResourceArray;
/** /**
* *
* @author Alexey Andreev * @author Alexey Andreev
*/ */
class BuildTimeResourceArray<T> implements ResourceArray<T>, ResourceWriter { class BuildTimeResourceArray<T extends Resource> implements ResourceArray<T>, ResourceWriter {
private List<T> data = new ArrayList<>(); private List<T> data = new ArrayList<>();
@Override @Override

View File

@ -19,13 +19,14 @@ import java.io.IOException;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import org.teavm.codegen.SourceWriter; import org.teavm.codegen.SourceWriter;
import org.teavm.platform.metadata.Resource;
import org.teavm.platform.metadata.ResourceMap; import org.teavm.platform.metadata.ResourceMap;
/** /**
* *
* @author Alexey Andreev * @author Alexey Andreev
*/ */
class BuildTimeResourceMap<T> implements ResourceMap<T>, ResourceWriter { class BuildTimeResourceMap<T extends Resource> implements ResourceMap<T>, ResourceWriter {
private Map<String, T> data = new HashMap<>(); private Map<String, T> data = new HashMap<>();
@Override @Override

View File

@ -29,8 +29,7 @@ import org.teavm.platform.metadata.ResourceMap;
class BuildTimeResourceProxyBuilder { class BuildTimeResourceProxyBuilder {
private Map<Class<?>, BuildTimeResourceProxyFactory> factories = new HashMap<>(); private Map<Class<?>, BuildTimeResourceProxyFactory> factories = new HashMap<>();
private static Set<Class<?>> allowedPropertyTypes = new HashSet<>(Arrays.<Class<?>>asList( private static Set<Class<?>> allowedPropertyTypes = new HashSet<>(Arrays.<Class<?>>asList(
boolean.class, Boolean.class, byte.class, Byte.class, short.class, Short.class, boolean.class, byte.class, short.class, int.class, float.class, double.class,
int.class, Integer.class, float.class, Float.class, double.class, Double.class,
String.class, ResourceArray.class, ResourceMap.class)); String.class, ResourceArray.class, ResourceMap.class));
private static Map<Class<?>, Object> defaultValues = new HashMap<>(); private static Map<Class<?>, Object> defaultValues = new HashMap<>();
@ -89,9 +88,9 @@ class BuildTimeResourceProxyBuilder {
} }
private void scanIface(Class<?> iface) { private void scanIface(Class<?> iface) {
if (!iface.isAnnotationPresent(Resource.class)) { if (!Resource.class.isAssignableFrom(iface)) {
throw new IllegalArgumentException("Error creating a new resource of type " + iface.getName() + throw new IllegalArgumentException("Error creating a new resource of type " + iface.getName() +
". This type is not marked with the " + Resource.class.getName() + " annotation"); ". This type does not implement the " + Resource.class.getName() + " interface");
} }
// Scan methods // Scan methods
@ -136,7 +135,7 @@ class BuildTimeResourceProxyBuilder {
String propertyName = property.getKey(); String propertyName = property.getKey();
Class<?> propertyType = property.getValue(); Class<?> propertyType = property.getValue();
if (!allowedPropertyTypes.contains(propertyType)) { if (!allowedPropertyTypes.contains(propertyType)) {
if (!propertyType.isInterface() || !propertyType.isAnnotationPresent(Resource.class)) { if (!propertyType.isInterface() || !Resource.class.isAssignableFrom(propertyType)) {
throw new IllegalArgumentException("Property " + iface.getName() + "." + propertyName + throw new IllegalArgumentException("Property " + iface.getName() + "." + propertyName +
" has an illegal type " + propertyType.getName()); " has an illegal type " + propertyType.getName());
} }

View File

@ -19,6 +19,7 @@ import java.lang.reflect.Proxy;
import java.util.Properties; import java.util.Properties;
import org.teavm.model.ListableClassReaderSource; import org.teavm.model.ListableClassReaderSource;
import org.teavm.platform.metadata.MetadataGeneratorContext; import org.teavm.platform.metadata.MetadataGeneratorContext;
import org.teavm.platform.metadata.Resource;
import org.teavm.platform.metadata.ResourceArray; import org.teavm.platform.metadata.ResourceArray;
import org.teavm.platform.metadata.ResourceMap; import org.teavm.platform.metadata.ResourceMap;
@ -55,19 +56,19 @@ class DefaultMetadataGeneratorContext implements MetadataGeneratorContext {
} }
@Override @Override
public <T> T createResource(Class<T> resourceType) { public <T extends Resource> T createResource(Class<T> resourceType) {
return resourceType.cast(Proxy.newProxyInstance(classLoader, return resourceType.cast(Proxy.newProxyInstance(classLoader,
new Class<?>[] { resourceType, ResourceWriter.class }, new Class<?>[] { resourceType, ResourceWriter.class },
proxyBuilder.buildProxy(resourceType))); proxyBuilder.buildProxy(resourceType)));
} }
@Override @Override
public <T> ResourceArray<T> createResourceArray() { public <T extends Resource> ResourceArray<T> createResourceArray() {
return new BuildTimeResourceArray<>(); return new BuildTimeResourceArray<>();
} }
@Override @Override
public <T> ResourceMap<T> createResourceMap() { public <T extends Resource> ResourceMap<T> createResourceMap() {
return new BuildTimeResourceMap<>(); return new BuildTimeResourceMap<>();
} }
} }

View File

@ -24,6 +24,7 @@ import org.teavm.javascript.ni.GeneratorContext;
import org.teavm.model.*; import org.teavm.model.*;
import org.teavm.platform.metadata.MetadataGenerator; import org.teavm.platform.metadata.MetadataGenerator;
import org.teavm.platform.metadata.MetadataProvider; import org.teavm.platform.metadata.MetadataProvider;
import org.teavm.platform.metadata.Resource;
/** /**
* *
@ -73,7 +74,7 @@ public class MetadataProviderNativeGenerator implements Generator {
context.getClassLoader(), context.getProperties()); context.getClassLoader(), context.getProperties());
// Generate resource loader // Generate resource loader
Object resource = generator.generateMetadata(metadataContext, methodRef); Resource resource = generator.generateMetadata(metadataContext, methodRef);
writer.append("if (!window.hasOwnProperty(\"").appendMethodBody(methodRef).append("$$resource\")) {") writer.append("if (!window.hasOwnProperty(\"").appendMethodBody(methodRef).append("$$resource\")) {")
.indent().softNewLine(); .indent().softNewLine();
writer.appendMethodBody(methodRef).append("$$resource = "); writer.appendMethodBody(methodRef).append("$$resource = ");

View File

@ -15,6 +15,8 @@
*/ */
package org.teavm.platform.plugin; package org.teavm.platform.plugin;
import org.teavm.platform.metadata.Resource;
/** /**
* *
* @author Alexey Andreev * @author Alexey Andreev
@ -24,9 +26,9 @@ final class ResourceAccessor {
public static native void put(Object obj, String propertyName, Object elem); public static native void put(Object obj, String propertyName, Object elem);
public static native Object get(Object obj, int index); public static native Resource get(Object obj, int index);
public static native void add(Object obj, Object elem); public static native void add(Object obj, Resource elem);
public static native boolean has(Object obj, String key); public static native boolean has(Object obj, String key);
@ -34,53 +36,29 @@ final class ResourceAccessor {
public static native int castToInt(Object obj); public static native int castToInt(Object obj);
public static native Integer castToIntWrapper(Object obj);
public static native short castToShort(Object obj); public static native short castToShort(Object obj);
public static native Short castToShortWrapper(Object obj);
public static native byte castToByte(Object obj); public static native byte castToByte(Object obj);
public static native Byte castToByteWrapper(Object obj);
public static native boolean castToBoolean(Object obj); public static native boolean castToBoolean(Object obj);
public static native Boolean castToBooleanWrapper(Object obj);
public static native float castToFloat(Object obj); public static native float castToFloat(Object obj);
public static native Float castToFloatWrapper(Object obj);
public static native double castToDouble(Object obj); public static native double castToDouble(Object obj);
public static native Double castToDoubleWrapper(Object obj);
public static native String castToString(Object obj); public static native String castToString(Object obj);
public static native Object castFromInt(int value); public static native Object castFromInt(int value);
public static native Object castFromIntWrapper(Integer value);
public static native Object castFromShort(short value); public static native Object castFromShort(short value);
public static native Object castFromShortWrapper(Short value);
public static native Object castFromByte(byte value); public static native Object castFromByte(byte value);
public static native Object castFromByteWrapper(Byte value);
public static native Object castFromBoolean(boolean value); public static native Object castFromBoolean(boolean value);
public static native Object castFromBooleanWrapper(Boolean value);
public static native Object castFromFloat(float value); public static native Object castFromFloat(float value);
public static native Object castFromFloatWrapper(Float value);
public static native Object castFromDouble(double value); public static native Object castFromDouble(double value);
public static native Object castFromDoubleWrapper(Double value);
public static native Object castFromString(String value); public static native Object castFromString(String value);
} }

View File

@ -19,7 +19,6 @@ import org.teavm.dependency.DependencyAgent;
import org.teavm.dependency.DependencyListener; import org.teavm.dependency.DependencyListener;
import org.teavm.dependency.FieldDependency; import org.teavm.dependency.FieldDependency;
import org.teavm.dependency.MethodDependency; import org.teavm.dependency.MethodDependency;
import org.teavm.model.MethodReference;
/** /**
* *
@ -37,58 +36,12 @@ class ResourceAccessorDependencyListener implements DependencyListener {
@Override @Override
public void methodAchieved(DependencyAgent agent, MethodDependency method) { public void methodAchieved(DependencyAgent agent, MethodDependency method) {
switch (method.getReference().getName()) { switch (method.getReference().getName()) {
case "castToIntWrapper":
castToWrapper(agent, method, Integer.class, int.class);
break;
case "castToShortWrapper":
castToWrapper(agent, method, Short.class, short.class);
break;
case "castToByteWrapper":
castToWrapper(agent, method, Byte.class, byte.class);
break;
case "castToBooleanWrapper":
castToWrapper(agent, method, Boolean.class, boolean.class);
break;
case "castToFloatWrapper":
castToWrapper(agent, method, Float.class, float.class);
break;
case "castToDoubleWrapper":
castToWrapper(agent, method, Double.class, double.class);
break;
case "castFromIntegerWrapper":
castFromWrapper(agent, method, Integer.class, int.class);
break;
case "castFromShortWrapper":
castFromWrapper(agent, method, Short.class, short.class);
break;
case "castFromByteWrapper":
castFromWrapper(agent, method, Byte.class, byte.class);
break;
case "castFromBooleanWrapper":
castFromWrapper(agent, method, Boolean.class, boolean.class);
break;
case "castFromFloatWrapper":
castFromWrapper(agent, method, Float.class, float.class);
break;
case "castFromDoubleWrapper":
castFromWrapper(agent, method, Double.class, double.class);
break;
case "castToString": case "castToString":
method.getResult().propagate("java.lang.String"); method.getResult().propagate("java.lang.String");
break; break;
} }
} }
private void castToWrapper(DependencyAgent agent, MethodDependency method, Class<?> wrapper, Class<?> primitive) {
method.getResult().propagate(wrapper.getName());
agent.linkMethod(new MethodReference(wrapper, "valueOf", primitive, wrapper), method.getStack()).use();
}
private void castFromWrapper(DependencyAgent agent, MethodDependency method, Class<?> wrapper, Class<?> primitive) {
String primitiveName = primitive.getName();
agent.linkMethod(new MethodReference(wrapper, primitiveName + "Value", primitive), method.getStack()).use();
}
@Override @Override
public void fieldAchieved(DependencyAgent agent, FieldDependency field) { public void fieldAchieved(DependencyAgent agent, FieldDependency field) {
} }

View File

@ -86,42 +86,6 @@ class ResourceAccessorGenerator implements Injector {
case "castFromDouble": case "castFromDouble":
context.writeExpr(context.getArgument(0)); context.writeExpr(context.getArgument(0));
break; break;
case "castToIntWrapper":
castToWrapper(context, Integer.class, int.class);
break;
case "castToShortWrapper":
castToWrapper(context, Short.class, short.class);
break;
case "castToByteWrapper":
castToWrapper(context, Byte.class, byte.class);
break;
case "castToBooleanWrapper":
castToWrapper(context, Boolean.class, boolean.class);
break;
case "castToFloatWrapper":
castToWrapper(context, Float.class, float.class);
break;
case "castToDoubleWrapper":
castToWrapper(context, Double.class, double.class);
break;
case "castFromIntWrapper":
castFromWrapper(context, Integer.class, int.class);
break;
case "castFromShortWrapper":
castFromWrapper(context, Short.class, short.class);
break;
case "castFromByteWrapper":
castFromWrapper(context, Byte.class, byte.class);
break;
case "castFromBooleanWrapper":
castFromWrapper(context, Boolean.class, boolean.class);
break;
case "castFromFloatWrapper":
castFromWrapper(context, Float.class, float.class);
break;
case "castFromDoubleWrapper":
castFromWrapper(context, Double.class, double.class);
break;
case "castToString": case "castToString":
context.getWriter().append("$rt_str("); context.getWriter().append("$rt_str(");
context.writeExpr(context.getArgument(0)); context.writeExpr(context.getArgument(0));
@ -135,28 +99,6 @@ class ResourceAccessorGenerator implements Injector {
} }
} }
private void castToWrapper(InjectorContext context, Class<?> wrapper, Class<?> primitive) throws IOException {
context.getWriter().append('(');
context.writeExpr(context.getArgument(0));
context.getWriter().ws().append("==").ws().append("null").ws().append('?').ws().append("null")
.ws().append(':').ws();
context.getWriter().appendMethodBody(new MethodReference(wrapper, "valueOf", primitive, wrapper)).append('(');
context.writeExpr(context.getArgument(0));
context.getWriter().append("))");
}
private void castFromWrapper(InjectorContext context, Class<?> wrapper, Class<?> primitive) throws IOException {
context.getWriter().append('(');
context.writeExpr(context.getArgument(0));
context.getWriter().ws().append("==").ws().append("null").ws().append('?').ws().append("null")
.ws().append(':').ws();
String primitiveName = primitive.getName();
context.getWriter().appendMethodBody(new MethodReference(wrapper, primitiveName + "Value", primitive))
.append('(');
context.writeExpr(context.getArgument(0));
context.getWriter().append("))");
}
private void writePropertyAccessor(InjectorContext context, Expr property) throws IOException { private void writePropertyAccessor(InjectorContext context, Expr property) throws IOException {
if (property instanceof ConstantExpr) { if (property instanceof ConstantExpr) {
String str = (String)((ConstantExpr)property).getValue(); String str = (String)((ConstantExpr)property).getValue();

View File

@ -14,7 +14,6 @@ import org.teavm.platform.metadata.ResourceMap;
class ResourceProgramTransformer { class ResourceProgramTransformer {
private ClassReaderSource innerSource; private ClassReaderSource innerSource;
private Program program; private Program program;
private Set<Variable> arrayItemsVars = new HashSet<>();
public ResourceProgramTransformer(ClassReaderSource innerSource, Program program) { public ResourceProgramTransformer(ClassReaderSource innerSource, Program program) {
this.innerSource = innerSource; this.innerSource = innerSource;
@ -25,11 +24,6 @@ class ResourceProgramTransformer {
for (int i = 0; i < program.basicBlockCount(); ++i) { for (int i = 0; i < program.basicBlockCount(); ++i) {
transformBasicBlock(program.basicBlockAt(i)); transformBasicBlock(program.basicBlockAt(i));
} }
if (!arrayItemsVars.isEmpty()) {
for (int i = 0; i < program.basicBlockCount(); ++i) {
postProcessBasicBlock(program.basicBlockAt(i));
}
}
} }
private void transformBasicBlock(BasicBlock block) { private void transformBasicBlock(BasicBlock block) {
@ -48,56 +42,6 @@ class ResourceProgramTransformer {
} }
} }
private void postProcessBasicBlock(BasicBlock block) {
List<Instruction> instructions = block.getInstructions();
for (int i = 0; i < instructions.size(); ++i) {
Instruction insn = instructions.get(i);
if (!(insn instanceof CastInstruction)) {
continue;
}
CastInstruction cast = (CastInstruction)insn;
if (!arrayItemsVars.contains(cast.getReceiver())) {
continue;
}
if (!(cast.getTargetType() instanceof ValueType.Object)) {
continue;
}
String targetTypeName = ((ValueType.Object)cast.getTargetType()).getClassName();
Variable var = cast.getValue();
Variable recv = cast.getReceiver();
switch (targetTypeName) {
case "java.lang.Integer":
instructions.set(i, castToWrapper(var, recv, int.class, Integer.class));
break;
case "java.lang.Boolean":
instructions.set(i, castToWrapper(var, recv, boolean.class, Boolean.class));
break;
case "java.lang.Byte":
instructions.set(i, castToWrapper(var, recv, byte.class, Byte.class));
break;
case "java.lang.Short":
instructions.set(i, castToWrapper(var, recv, short.class, Short.class));
break;
case "java.lang.Float":
instructions.set(i, castToWrapper(var, recv, float.class, Float.class));
break;
case "java.lang.Double":
instructions.set(i, castToWrapper(var, recv, double.class, Double.class));
break;
case "java.lang.String": {
InvokeInstruction castInvoke = new InvokeInstruction();
castInvoke.setType(InvocationType.SPECIAL);
castInvoke.setMethod(new MethodReference(ResourceAccessor.class, "castToString",
Object.class, String.class));
castInvoke.getArguments().add(var);
castInvoke.setReceiver(recv);
instructions.set(i, castInvoke);
break;
}
}
}
}
private List<Instruction> transformInvoke(InvokeInstruction insn) { private List<Instruction> transformInvoke(InvokeInstruction insn) {
if (insn.getType() != InvocationType.VIRTUAL) { if (insn.getType() != InvocationType.VIRTUAL) {
return null; return null;
@ -105,9 +49,6 @@ class ResourceProgramTransformer {
MethodReference method = insn.getMethod(); MethodReference method = insn.getMethod();
if (method.getClassName().equals(ResourceArray.class.getName()) || if (method.getClassName().equals(ResourceArray.class.getName()) ||
method.getClassName().equals(ResourceMap.class.getName())) { method.getClassName().equals(ResourceMap.class.getName())) {
if (method.getName().equals("get")) {
arrayItemsVars.add(insn.getReceiver());
}
InvokeInstruction accessInsn = new InvokeInstruction(); InvokeInstruction accessInsn = new InvokeInstruction();
accessInsn.setType(InvocationType.SPECIAL); accessInsn.setType(InvocationType.SPECIAL);
ValueType[] types = new ValueType[method.getDescriptor().parameterCount() + 2]; ValueType[] types = new ValueType[method.getDescriptor().parameterCount() + 2];
@ -172,24 +113,6 @@ class ResourceProgramTransformer {
} }
} else if (type instanceof ValueType.Object) { } else if (type instanceof ValueType.Object) {
switch (((ValueType.Object)type).getClassName()) { switch (((ValueType.Object)type).getClassName()) {
case "java.lang.Boolean":
getAndCastPropertyToWrapper(insn, property, instructions, boolean.class, Boolean.class);
return instructions;
case "java.lang.Byte":
getAndCastPropertyToWrapper(insn, property, instructions, byte.class, Byte.class);
return instructions;
case "java.lang.Short":
getAndCastPropertyToWrapper(insn, property, instructions, short.class, Short.class);
return instructions;
case "java.lang.Integer":
getAndCastPropertyToWrapper(insn, property, instructions, int.class, Integer.class);
return instructions;
case "java.lang.Float":
getAndCastPropertyToWrapper(insn, property, instructions, float.class, Float.class);
return instructions;
case "java.lang.Double":
getAndCastPropertyToWrapper(insn, property, instructions, double.class, Double.class);
return instructions;
case "java.lang.String": { case "java.lang.String": {
Variable resultVar = insn.getProgram().createVariable(); Variable resultVar = insn.getProgram().createVariable();
getProperty(insn, property, instructions, resultVar); getProperty(insn, property, instructions, resultVar);
@ -250,35 +173,6 @@ class ResourceProgramTransformer {
instructions.add(castInvoke); instructions.add(castInvoke);
} }
private Instruction castToWrapper(Variable var, Variable receiver, Class<?> primitive, Class<?> wrapper) {
InvokeInstruction castInvoke = new InvokeInstruction();
castInvoke.setType(InvocationType.SPECIAL);
String primitiveCapitalized = primitive.getName();
primitiveCapitalized = Character.toUpperCase(primitiveCapitalized.charAt(0)) +
primitiveCapitalized.substring(1);
castInvoke.setMethod(new MethodReference(ResourceAccessor.class, "castTo" + primitiveCapitalized + "Wrapper",
Object.class, wrapper));
castInvoke.getArguments().add(var);
castInvoke.setReceiver(receiver);
return castInvoke;
}
private void getAndCastPropertyToWrapper(InvokeInstruction insn, String property, List<Instruction> instructions,
Class<?> primitive, Class<?> wrapper) {
Variable resultVar = program.createVariable();
getProperty(insn, property, instructions, resultVar);
InvokeInstruction castInvoke = new InvokeInstruction();
castInvoke.setType(InvocationType.SPECIAL);
String primitiveCapitalized = primitive.getName();
primitiveCapitalized = Character.toUpperCase(primitiveCapitalized.charAt(0)) +
primitiveCapitalized.substring(1);
castInvoke.setMethod(new MethodReference(ResourceAccessor.class, "castTo" + primitiveCapitalized + "Wrapper",
Object.class, wrapper));
castInvoke.getArguments().add(resultVar);
castInvoke.setReceiver(insn.getReceiver());
instructions.add(castInvoke);
}
private List<Instruction> transformSetterInvocation(InvokeInstruction insn, String property) { private List<Instruction> transformSetterInvocation(InvokeInstruction insn, String property) {
return null; return null;
} }