mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2025-01-09 00:14:10 -08:00
Continues implementation of metadata providers
This commit is contained in:
parent
c23f62ced7
commit
10a8e0261a
|
@ -31,10 +31,13 @@ public class SourceWriter implements Appendable {
|
||||||
private NamingStrategy naming;
|
private NamingStrategy naming;
|
||||||
private boolean lineStart;
|
private boolean lineStart;
|
||||||
private boolean minified;
|
private boolean minified;
|
||||||
|
private int lineWidth;
|
||||||
|
private int pos;
|
||||||
|
|
||||||
SourceWriter(NamingStrategy naming, Appendable innerWriter) {
|
SourceWriter(NamingStrategy naming, Appendable innerWriter, int lineWidth) {
|
||||||
this.naming = naming;
|
this.naming = naming;
|
||||||
this.innerWriter = innerWriter;
|
this.innerWriter = innerWriter;
|
||||||
|
this.lineWidth = lineWidth;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setMinified(boolean minified) {
|
void setMinified(boolean minified) {
|
||||||
|
@ -42,8 +45,7 @@ public class SourceWriter implements Appendable {
|
||||||
}
|
}
|
||||||
|
|
||||||
public SourceWriter append(String value) throws IOException {
|
public SourceWriter append(String value) throws IOException {
|
||||||
appendIndent();
|
append((CharSequence)value);
|
||||||
innerWriter.append(value);
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -59,23 +61,43 @@ public class SourceWriter implements Appendable {
|
||||||
public SourceWriter append(char value) throws IOException {
|
public SourceWriter append(char value) throws IOException {
|
||||||
appendIndent();
|
appendIndent();
|
||||||
innerWriter.append(value);
|
innerWriter.append(value);
|
||||||
|
if (value == '\n') {
|
||||||
|
newLine();
|
||||||
|
} else {
|
||||||
|
pos++;
|
||||||
|
}
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SourceWriter append(CharSequence csq) throws IOException {
|
public SourceWriter append(CharSequence csq) throws IOException {
|
||||||
appendIndent();
|
append(csq, 0, csq.length());
|
||||||
innerWriter.append(csq);
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SourceWriter append(CharSequence csq, int start, int end) throws IOException {
|
public SourceWriter append(CharSequence csq, int start, int end) throws IOException {
|
||||||
appendIndent();
|
int last = start;
|
||||||
innerWriter.append(csq, start, end);
|
for (int i = start; i < end; ++i) {
|
||||||
|
if (csq.charAt(i) == '\n') {
|
||||||
|
appendSingleLine(csq, last, i);
|
||||||
|
newLine();
|
||||||
|
last = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
appendSingleLine(csq, last, end);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void appendSingleLine(CharSequence csq, int start, int end) throws IOException {
|
||||||
|
if (start == end) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
appendIndent();
|
||||||
|
pos += end - start;
|
||||||
|
innerWriter.append(csq, start, end);
|
||||||
|
}
|
||||||
|
|
||||||
public SourceWriter appendClass(String cls) throws NamingException, IOException {
|
public SourceWriter appendClass(String cls) throws NamingException, IOException {
|
||||||
return append(naming.getNameFor(cls));
|
return append(naming.getNameFor(cls));
|
||||||
}
|
}
|
||||||
|
@ -109,6 +131,7 @@ public class SourceWriter implements Appendable {
|
||||||
if (lineStart) {
|
if (lineStart) {
|
||||||
for (int i = 0; i < indentSize; ++i) {
|
for (int i = 0; i < indentSize; ++i) {
|
||||||
innerWriter.append(" ");
|
innerWriter.append(" ");
|
||||||
|
pos += 4;
|
||||||
}
|
}
|
||||||
lineStart = false;
|
lineStart = false;
|
||||||
}
|
}
|
||||||
|
@ -116,13 +139,26 @@ public class SourceWriter implements Appendable {
|
||||||
|
|
||||||
public SourceWriter newLine() throws IOException{
|
public SourceWriter newLine() throws IOException{
|
||||||
innerWriter.append('\n');
|
innerWriter.append('\n');
|
||||||
|
pos = 0;
|
||||||
lineStart = true;
|
lineStart = true;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public SourceWriter ws() throws IOException{
|
public SourceWriter ws() throws IOException {
|
||||||
if (!minified) {
|
if (pos >= lineWidth) {
|
||||||
innerWriter.append(' ');
|
newLine();
|
||||||
|
} else {
|
||||||
|
if (!minified) {
|
||||||
|
innerWriter.append(' ');
|
||||||
|
pos++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SourceWriter tokenBoundary() throws IOException {
|
||||||
|
if (pos >= lineWidth) {
|
||||||
|
newLine();
|
||||||
}
|
}
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
@ -130,6 +166,7 @@ public class SourceWriter implements Appendable {
|
||||||
public SourceWriter softNewLine() throws IOException{
|
public SourceWriter softNewLine() throws IOException{
|
||||||
if (!minified) {
|
if (!minified) {
|
||||||
innerWriter.append('\n');
|
innerWriter.append('\n');
|
||||||
|
pos = 0;
|
||||||
lineStart = true;
|
lineStart = true;
|
||||||
}
|
}
|
||||||
return this;
|
return this;
|
||||||
|
|
|
@ -22,6 +22,7 @@ package org.teavm.codegen;
|
||||||
public class SourceWriterBuilder {
|
public class SourceWriterBuilder {
|
||||||
private NamingStrategy naming;
|
private NamingStrategy naming;
|
||||||
private boolean minified;
|
private boolean minified;
|
||||||
|
private int lineWidth = 512;
|
||||||
|
|
||||||
public SourceWriterBuilder(NamingStrategy naming) {
|
public SourceWriterBuilder(NamingStrategy naming) {
|
||||||
this.naming = naming;
|
this.naming = naming;
|
||||||
|
@ -35,8 +36,12 @@ public class SourceWriterBuilder {
|
||||||
this.minified = minified;
|
this.minified = minified;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setLineWidth(int lineWidth) {
|
||||||
|
this.lineWidth = lineWidth;
|
||||||
|
}
|
||||||
|
|
||||||
public SourceWriter build(Appendable innerWriter) {
|
public SourceWriter build(Appendable innerWriter) {
|
||||||
SourceWriter writer = new SourceWriter(naming, innerWriter);
|
SourceWriter writer = new SourceWriter(naming, innerWriter, lineWidth);
|
||||||
writer.setMinified(minified);
|
writer.setMinified(minified);
|
||||||
return writer;
|
return writer;
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,6 +43,7 @@ public class Renderer implements ExprVisitor, StatementVisitor, RenderingContext
|
||||||
private ClassLoader classLoader;
|
private ClassLoader classLoader;
|
||||||
private boolean minifying;
|
private boolean minifying;
|
||||||
private Map<MethodReference, InjectorHolder> injectorMap = new HashMap<>();
|
private Map<MethodReference, InjectorHolder> injectorMap = new HashMap<>();
|
||||||
|
private Properties properties = new Properties();
|
||||||
|
|
||||||
private static class InjectorHolder {
|
private static class InjectorHolder {
|
||||||
public final Injector injector;
|
public final Injector injector;
|
||||||
|
@ -88,6 +89,16 @@ public class Renderer implements ExprVisitor, StatementVisitor, RenderingContext
|
||||||
return classLoader;
|
return classLoader;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Properties getProperties() {
|
||||||
|
return new Properties(properties);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setProperties(Properties properties) {
|
||||||
|
this.properties.clear();
|
||||||
|
this.properties.putAll(properties);
|
||||||
|
}
|
||||||
|
|
||||||
public void renderRuntime() throws RenderingException {
|
public void renderRuntime() throws RenderingException {
|
||||||
try {
|
try {
|
||||||
renderRuntimeCls();
|
renderRuntimeCls();
|
||||||
|
@ -483,6 +494,16 @@ public class Renderer implements ExprVisitor, StatementVisitor, RenderingContext
|
||||||
public ListableClassReaderSource getClassSource() {
|
public ListableClassReaderSource getClassSource() {
|
||||||
return classSource;
|
return classSource;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ClassLoader getClassLoader() {
|
||||||
|
return classLoader;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Properties getProperties() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
*/
|
*/
|
||||||
package org.teavm.javascript;
|
package org.teavm.javascript;
|
||||||
|
|
||||||
|
import java.util.Properties;
|
||||||
import org.teavm.codegen.NamingStrategy;
|
import org.teavm.codegen.NamingStrategy;
|
||||||
import org.teavm.codegen.SourceWriter;
|
import org.teavm.codegen.SourceWriter;
|
||||||
import org.teavm.model.ListableClassReaderSource;
|
import org.teavm.model.ListableClassReaderSource;
|
||||||
|
@ -33,4 +34,6 @@ public interface RenderingContext {
|
||||||
ListableClassReaderSource getClassSource();
|
ListableClassReaderSource getClassSource();
|
||||||
|
|
||||||
ClassLoader getClassLoader();
|
ClassLoader getClassLoader();
|
||||||
|
|
||||||
|
Properties getProperties();
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
*/
|
*/
|
||||||
package org.teavm.javascript.ni;
|
package org.teavm.javascript.ni;
|
||||||
|
|
||||||
|
import java.util.Properties;
|
||||||
import org.teavm.model.ListableClassReaderSource;
|
import org.teavm.model.ListableClassReaderSource;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -25,4 +26,8 @@ public interface GeneratorContext {
|
||||||
String getParameterName(int index);
|
String getParameterName(int index);
|
||||||
|
|
||||||
ListableClassReaderSource getClassSource();
|
ListableClassReaderSource getClassSource();
|
||||||
|
|
||||||
|
ClassLoader getClassLoader();
|
||||||
|
|
||||||
|
Properties getProperties();
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,15 +15,17 @@
|
||||||
*/
|
*/
|
||||||
package org.teavm.platform.plugin;
|
package org.teavm.platform.plugin;
|
||||||
|
|
||||||
|
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.platform.metadata.ResourceArray;
|
import org.teavm.platform.metadata.ResourceArray;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author Alexey Andreev
|
* @author Alexey Andreev
|
||||||
*/
|
*/
|
||||||
class BuildTimeResourceArray<T> implements ResourceArray<T> {
|
class BuildTimeResourceArray<T> implements ResourceArray<T>, ResourceWriter {
|
||||||
private List<T> data = new ArrayList<>();
|
private List<T> data = new ArrayList<>();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -40,4 +42,16 @@ class BuildTimeResourceArray<T> implements ResourceArray<T> {
|
||||||
public void add(T elem) {
|
public void add(T elem) {
|
||||||
data.add(elem);
|
data.add(elem);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void write(SourceWriter writer) throws IOException {
|
||||||
|
writer.append('[').tokenBoundary();
|
||||||
|
for (int i = 0; i < data.size(); ++i) {
|
||||||
|
if (i > 0) {
|
||||||
|
writer.append(',').ws();
|
||||||
|
}
|
||||||
|
ResourceWriterHelper.write(writer, data.get(i));
|
||||||
|
}
|
||||||
|
writer.append(']').tokenBoundary();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,15 +15,17 @@
|
||||||
*/
|
*/
|
||||||
package org.teavm.platform.plugin;
|
package org.teavm.platform.plugin;
|
||||||
|
|
||||||
|
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.platform.metadata.ResourceMap;
|
import org.teavm.platform.metadata.ResourceMap;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author Alexey Andreev
|
* @author Alexey Andreev
|
||||||
*/
|
*/
|
||||||
class BuildTimeResourceMap<T> implements ResourceMap<T> {
|
class BuildTimeResourceMap<T> implements ResourceMap<T>, ResourceWriter {
|
||||||
private Map<String, T> data = new HashMap<>();
|
private Map<String, T> data = new HashMap<>();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -40,4 +42,20 @@ class BuildTimeResourceMap<T> implements ResourceMap<T> {
|
||||||
public void put(String key, T value) {
|
public void put(String key, T value) {
|
||||||
data.put(key, value);
|
data.put(key, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void write(SourceWriter writer) throws IOException {
|
||||||
|
writer.append('{');
|
||||||
|
boolean first = true;
|
||||||
|
for (Map.Entry<String, T> entry : data.entrySet()) {
|
||||||
|
if (!first) {
|
||||||
|
writer.append(",").ws();
|
||||||
|
}
|
||||||
|
first = false;
|
||||||
|
ResourceWriterHelper.writeString(writer, entry.getKey());
|
||||||
|
writer.ws().append(':').ws();
|
||||||
|
ResourceWriterHelper.write(writer, entry.getValue());
|
||||||
|
}
|
||||||
|
writer.append('}').tokenBoundary();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,6 +31,16 @@ class BuildTimeResourceProxyBuilder {
|
||||||
boolean.class, Boolean.class, byte.class, Byte.class, short.class, Short.class,
|
boolean.class, Boolean.class, byte.class, Byte.class, short.class, Short.class,
|
||||||
int.class, Integer.class, float.class, Float.class, double.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<>();
|
||||||
|
|
||||||
|
static {
|
||||||
|
defaultValues.put(boolean.class, false);
|
||||||
|
defaultValues.put(byte.class, (byte)0);
|
||||||
|
defaultValues.put(short.class, (short)0);
|
||||||
|
defaultValues.put(int.class, 0);
|
||||||
|
defaultValues.put(float.class, 0F);
|
||||||
|
defaultValues.put(double.class, 0.0);
|
||||||
|
}
|
||||||
|
|
||||||
public BuildTimeResourceProxy buildProxy(Class<?> iface) {
|
public BuildTimeResourceProxy buildProxy(Class<?> iface) {
|
||||||
BuildTimeResourceProxyFactory factory = factories.get(iface);
|
BuildTimeResourceProxyFactory factory = factories.get(iface);
|
||||||
|
@ -50,8 +60,8 @@ class BuildTimeResourceProxyBuilder {
|
||||||
Map<String, Class<?>> getters = new HashMap<>();
|
Map<String, Class<?>> getters = new HashMap<>();
|
||||||
Map<String, Class<?>> setters = new HashMap<>();
|
Map<String, Class<?>> setters = new HashMap<>();
|
||||||
Map<Method, BuildTimeResourceMethod> methods = new HashMap<>();
|
Map<Method, BuildTimeResourceMethod> methods = new HashMap<>();
|
||||||
private List<Object> initialData = new ArrayList<>();
|
|
||||||
private Map<String, Integer> propertyIndexes = new HashMap<>();
|
private Map<String, Integer> propertyIndexes = new HashMap<>();
|
||||||
|
private Object[] initialData;
|
||||||
|
|
||||||
public ProxyFactoryCreation(Class<?> iface) {
|
public ProxyFactoryCreation(Class<?> iface) {
|
||||||
this.rootIface = iface;
|
this.rootIface = iface;
|
||||||
|
@ -63,7 +73,7 @@ class BuildTimeResourceProxyBuilder {
|
||||||
" that is not an interface");
|
" that is not an interface");
|
||||||
}
|
}
|
||||||
scanIface(rootIface);
|
scanIface(rootIface);
|
||||||
return new BuildTimeResourceProxyFactory(methods, initialData.toArray(new Object[initialData.size()]));
|
return new BuildTimeResourceProxyFactory(methods, initialData);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void scanIface(Class<?> iface) {
|
private void scanIface(Class<?> iface) {
|
||||||
|
@ -109,18 +119,18 @@ class BuildTimeResourceProxyBuilder {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify types of properties and fill default values
|
// Verify types of properties and fill default values
|
||||||
|
initialData = new Object[propertyIndexes.size()];
|
||||||
for (Map.Entry<String, Class<?>> property : getters.entrySet()) {
|
for (Map.Entry<String, Class<?>> property : getters.entrySet()) {
|
||||||
String propertyName = property.getKey();
|
String propertyName = property.getKey();
|
||||||
Class<?> propertyType = property.getValue();
|
Class<?> propertyType = property.getValue();
|
||||||
if (allowedPropertyTypes.contains(propertyType)) {
|
if (!allowedPropertyTypes.contains(propertyType)) {
|
||||||
continue;
|
if (!propertyType.isInterface() || !propertyType.isAnnotationPresent(Resource.class)) {
|
||||||
}
|
throw new IllegalArgumentException("Property " + iface.getName() + "." + propertyName +
|
||||||
if (!propertyType.isInterface() || !propertyType.isAnnotationPresent(Resource.class)) {
|
" has an illegal type " + propertyType.getName());
|
||||||
throw new IllegalArgumentException("Property " + iface.getName() + "." + propertyName +
|
}
|
||||||
" has an illegal type " + propertyType.getName());
|
|
||||||
}
|
}
|
||||||
|
initialData[propertyIndexes.get(propertyName)] = defaultValues.get(propertyType);
|
||||||
}
|
}
|
||||||
// TODO: fill default values
|
|
||||||
|
|
||||||
// Scan superinterfaces
|
// Scan superinterfaces
|
||||||
for (Class<?> superIface : iface.getInterfaces()) {
|
for (Class<?> superIface : iface.getInterfaces()) {
|
||||||
|
|
|
@ -0,0 +1,46 @@
|
||||||
|
/*
|
||||||
|
* 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.plugin;
|
||||||
|
|
||||||
|
import org.teavm.codegen.SourceWriter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Alexey Andreev
|
||||||
|
*/
|
||||||
|
class BuildTimeResourceWriterMethod implements BuildTimeResourceMethod {
|
||||||
|
private String[] propertyNames;
|
||||||
|
|
||||||
|
public BuildTimeResourceWriterMethod(String[] propertyNames) {
|
||||||
|
this.propertyNames = propertyNames;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object invoke(BuildTimeResourceProxy proxy, Object[] args) throws Throwable {
|
||||||
|
SourceWriter writer = (SourceWriter)args[0];
|
||||||
|
writer.append('{');
|
||||||
|
for (int i = 0; i < propertyNames.length; ++i) {
|
||||||
|
if (i > 0) {
|
||||||
|
writer.append(',').ws();
|
||||||
|
}
|
||||||
|
ResourceWriterHelper.writeString(writer, propertyNames[i]);
|
||||||
|
writer.ws().append(':').ws();
|
||||||
|
ResourceWriterHelper.write(writer, proxy.data[i]);
|
||||||
|
}
|
||||||
|
writer.append('}').tokenBoundary();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
|
@ -32,7 +32,7 @@ class DefaultMetadataGeneratorContext implements MetadataGeneratorContext {
|
||||||
private Properties properties;
|
private Properties properties;
|
||||||
private BuildTimeResourceProxyBuilder proxyBuilder = new BuildTimeResourceProxyBuilder();
|
private BuildTimeResourceProxyBuilder proxyBuilder = new BuildTimeResourceProxyBuilder();
|
||||||
|
|
||||||
private DefaultMetadataGeneratorContext(ListableClassReaderSource classSource, ClassLoader classLoader,
|
public DefaultMetadataGeneratorContext(ListableClassReaderSource classSource, ClassLoader classLoader,
|
||||||
Properties properties) {
|
Properties properties) {
|
||||||
this.classSource = classSource;
|
this.classSource = classSource;
|
||||||
this.classLoader = classLoader;
|
this.classLoader = classLoader;
|
||||||
|
@ -56,7 +56,8 @@ class DefaultMetadataGeneratorContext implements MetadataGeneratorContext {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <T> T createResource(Class<T> resourceType) {
|
public <T> T createResource(Class<T> resourceType) {
|
||||||
return resourceType.cast(Proxy.newProxyInstance(classLoader, new Class<?>[] { resourceType },
|
return resourceType.cast(Proxy.newProxyInstance(classLoader,
|
||||||
|
new Class<?>[] { resourceType, ResourceWriter.class },
|
||||||
proxyBuilder.buildProxy(resourceType)));
|
proxyBuilder.buildProxy(resourceType)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,19 +16,23 @@
|
||||||
package org.teavm.platform.plugin;
|
package org.teavm.platform.plugin;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.lang.reflect.Constructor;
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
import org.teavm.codegen.SourceWriter;
|
import org.teavm.codegen.SourceWriter;
|
||||||
import org.teavm.javascript.ni.Generator;
|
import org.teavm.javascript.ni.Generator;
|
||||||
import org.teavm.javascript.ni.GeneratorContext;
|
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.MetadataProvider;
|
import org.teavm.platform.metadata.MetadataProvider;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author Alexey Andreev
|
* @author Alexey Andreev
|
||||||
*/
|
*/
|
||||||
class MetadataProviderNativeGenerator implements Generator {
|
public class MetadataProviderNativeGenerator implements Generator {
|
||||||
@Override
|
@Override
|
||||||
public void generate(GeneratorContext context, SourceWriter writer, MethodReference methodRef) throws IOException {
|
public void generate(GeneratorContext context, SourceWriter writer, MethodReference methodRef) throws IOException {
|
||||||
|
// Validate method
|
||||||
ClassReader cls = context.getClassSource().get(methodRef.getClassName());
|
ClassReader cls = context.getClassSource().get(methodRef.getClassName());
|
||||||
MethodReader method = cls.getMethod(methodRef.getDescriptor());
|
MethodReader method = cls.getMethod(methodRef.getDescriptor());
|
||||||
AnnotationReader providerAnnot = method.getAnnotations().get(MetadataProvider.class.getName());
|
AnnotationReader providerAnnot = method.getAnnotations().get(MetadataProvider.class.getName());
|
||||||
|
@ -39,5 +43,43 @@ class MetadataProviderNativeGenerator implements Generator {
|
||||||
throw new IllegalStateException("Method " + method.getReference() + " was marked with " +
|
throw new IllegalStateException("Method " + method.getReference() + " was marked with " +
|
||||||
MetadataProvider.class.getName() + " but it is not native");
|
MetadataProvider.class.getName() + " but it is not native");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Find and instantiate metadata generator
|
||||||
|
ValueType generatorType = providerAnnot.getValue("value").getJavaClass();
|
||||||
|
String generatorClassName = ((ValueType.Object)generatorType).getClassName();
|
||||||
|
Class<?> generatorClass;
|
||||||
|
try {
|
||||||
|
generatorClass = Class.forName(generatorClassName, true, context.getClassLoader());
|
||||||
|
} catch (ClassNotFoundException e) {
|
||||||
|
throw new RuntimeException("Can't find metadata generator class: " + generatorClassName, e);
|
||||||
|
}
|
||||||
|
Constructor<?> cons;
|
||||||
|
try {
|
||||||
|
cons = generatorClass.getConstructor();
|
||||||
|
} catch (NoSuchMethodException e) {
|
||||||
|
throw new RuntimeException("Metadata generator " + generatorClassName + " does not have a public " +
|
||||||
|
"no-arg constructor", e);
|
||||||
|
}
|
||||||
|
MetadataGenerator generator;
|
||||||
|
try {
|
||||||
|
generator = (MetadataGenerator)cons.newInstance();
|
||||||
|
} catch (IllegalAccessException | InstantiationException e) {
|
||||||
|
throw new RuntimeException("Error instantiating metadata generator " + generatorClassName, e);
|
||||||
|
} catch (InvocationTargetException e) {
|
||||||
|
throw new RuntimeException("Error instantiating metadata generator " + generatorClassName,
|
||||||
|
e.getTargetException());
|
||||||
|
}
|
||||||
|
DefaultMetadataGeneratorContext metadataContext = new DefaultMetadataGeneratorContext(context.getClassSource(),
|
||||||
|
context.getClassLoader(), context.getProperties());
|
||||||
|
|
||||||
|
// Generate resource loader
|
||||||
|
Object resource = generator.generateMetadata(metadataContext, methodRef);
|
||||||
|
writer.append("if (!").appendMethodBody(methodRef).append("$$resource === undefined").append(") {")
|
||||||
|
.indent().softNewLine();
|
||||||
|
writer.appendMethodBody(methodRef).append("$$resource = ");
|
||||||
|
ResourceWriterHelper.write(writer, resource);
|
||||||
|
writer.append(';').softNewLine();
|
||||||
|
writer.outdent().append('}').softNewLine();
|
||||||
|
writer.append("return ").appendMethodBody(methodRef).append("$$resource;").softNewLine();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,27 @@
|
||||||
|
/*
|
||||||
|
* 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.plugin;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import org.teavm.codegen.SourceWriter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Alexey Andreev
|
||||||
|
*/
|
||||||
|
interface ResourceWriter {
|
||||||
|
void write(SourceWriter writer) throws IOException;
|
||||||
|
}
|
|
@ -0,0 +1,74 @@
|
||||||
|
/*
|
||||||
|
* 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.plugin;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import org.teavm.codegen.SourceWriter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Alexey Andreev
|
||||||
|
*/
|
||||||
|
final class ResourceWriterHelper {
|
||||||
|
public static void write(SourceWriter writer, Object resource) throws IOException {
|
||||||
|
if (resource == null) {
|
||||||
|
writer.append("null");
|
||||||
|
} else {
|
||||||
|
if (resource instanceof ResourceWriter) {
|
||||||
|
((ResourceWriter)resource).write(writer);
|
||||||
|
} else if (resource instanceof Number) {
|
||||||
|
writer.append(resource);
|
||||||
|
} else if (resource instanceof Boolean) {
|
||||||
|
writer.append(resource == Boolean.TRUE ? "true" : "false");
|
||||||
|
} else if (resource instanceof String) {
|
||||||
|
writeString(writer, (String)resource);
|
||||||
|
} else {
|
||||||
|
throw new RuntimeException("Error compiling resources. Value of illegal type found: " +
|
||||||
|
resource.getClass());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void writeString(SourceWriter writer, String s) throws IOException {
|
||||||
|
writer.append('"');
|
||||||
|
for (int i = 0; i < s.length(); ++i) {
|
||||||
|
char c = s.charAt(i);
|
||||||
|
switch (c) {
|
||||||
|
case '\0':
|
||||||
|
writer.append("\\0");
|
||||||
|
break;
|
||||||
|
case '\n':
|
||||||
|
writer.append("\\n");
|
||||||
|
break;
|
||||||
|
case '\r':
|
||||||
|
writer.append("\\r");
|
||||||
|
break;
|
||||||
|
case '\t':
|
||||||
|
writer.append("\\t");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
if (c < 32) {
|
||||||
|
writer.append("\\u00").append(Character.forDigit(c / 16, 16))
|
||||||
|
.append(Character.forDigit(c % 16, 16));
|
||||||
|
} else {
|
||||||
|
writer.append(c);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
writer.append('"');
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user