Refactoring JSO implementation

This commit is contained in:
Alexey Andreev 2015-09-26 23:44:59 +03:00
parent bae388a778
commit 6986f1c02a
23 changed files with 84 additions and 77 deletions

View File

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.teavm.jso.plugin;
package org.teavm.jso.impl;
import java.io.IOException;
import java.util.Collections;

View File

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.teavm.jso.plugin;
package org.teavm.jso.impl;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;

View File

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.teavm.jso.plugin;
package org.teavm.jso.impl;
import java.lang.reflect.Array;
import java.util.function.Function;

View File

@ -13,13 +13,13 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.teavm.jso.plugin;
package org.teavm.jso.impl;
import java.io.IOException;
import java.util.Map;
import org.teavm.codegen.SourceWriter;
import org.teavm.javascript.RenderingContext;
import org.teavm.jso.plugin.JSODependencyListener.ExposedClass;
import org.teavm.jso.impl.JSDependencyListener.ExposedClass;
import org.teavm.model.MethodDescriptor;
import org.teavm.vm.BuildTarget;
import org.teavm.vm.spi.RendererListener;
@ -28,12 +28,12 @@ import org.teavm.vm.spi.RendererListener;
*
* @author Alexey Andreev
*/
class JSOAliasRenderer implements RendererListener {
class JSAliasRenderer implements RendererListener {
private static String variableChars = "abcdefghijklmnopqrstuvwxyz";
private JSODependencyListener dependencyListener;
private JSDependencyListener dependencyListener;
private SourceWriter writer;
public JSOAliasRenderer(JSODependencyListener dependencyListener) {
public JSAliasRenderer(JSDependencyListener dependencyListener) {
this.dependencyListener = dependencyListener;
}

View File

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.teavm.jso.plugin;
package org.teavm.jso.impl;
import java.io.IOException;
import org.mozilla.javascript.ast.AstNode;

View File

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.teavm.jso.plugin;
package org.teavm.jso.impl;
import java.io.IOException;
import org.teavm.codegen.SourceWriter;

View File

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.teavm.jso.plugin;
package org.teavm.jso.impl;
import java.io.IOException;
import org.teavm.codegen.SourceWriter;

View File

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.teavm.jso.plugin;
package org.teavm.jso.impl;
import java.io.IOException;
import org.teavm.codegen.SourceWriter;

View File

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.teavm.jso.plugin;
package org.teavm.jso.impl;
import java.util.HashMap;
import java.util.Map;

View File

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.teavm.jso.plugin;
package org.teavm.jso.impl;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;

View File

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.teavm.jso.plugin;
package org.teavm.jso.impl;
import java.util.HashMap;
import java.util.HashSet;

View File

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.teavm.jso.plugin;
package org.teavm.jso.impl;
import java.io.IOException;
import java.io.StringReader;
@ -78,18 +78,18 @@ import org.teavm.model.util.ProgramUtils;
*
* @author Alexey Andreev
*/
class JavascriptNativeProcessor {
class JSClassProcessor {
private ClassReaderSource classSource;
private Program program;
private List<Instruction> replacement = new ArrayList<>();
private NativeJavascriptClassRepository nativeRepos;
private JSTypeHelper typeHelper;
private Diagnostics diagnostics;
private int methodIndexGenerator;
private Map<MethodReference, MethodReader> overridenMethodCache = new HashMap<>();
public JavascriptNativeProcessor(ClassReaderSource classSource) {
public JSClassProcessor(ClassReaderSource classSource) {
this.classSource = classSource;
nativeRepos = new NativeJavascriptClassRepository(classSource);
typeHelper = new JSTypeHelper(classSource);
}
public ClassReaderSource getClassSource() {
@ -97,11 +97,11 @@ class JavascriptNativeProcessor {
}
public boolean isNative(String className) {
return nativeRepos.isJavaScriptClass(className);
return typeHelper.isJavaScriptClass(className);
}
public boolean isNativeImplementation(String className) {
return nativeRepos.isJavaScriptImplementation(className);
return typeHelper.isJavaScriptImplementation(className);
}
public void setDiagnostics(Diagnostics diagnostics) {
@ -109,7 +109,7 @@ class JavascriptNativeProcessor {
}
public MethodReference isFunctor(String className) {
if (!nativeRepos.isJavaScriptImplementation(className)) {
if (!typeHelper.isJavaScriptImplementation(className)) {
return null;
}
ClassReader cls = classSource.get(className);
@ -138,7 +138,7 @@ class JavascriptNativeProcessor {
public void processClass(ClassHolder cls) {
Set<MethodDescriptor> preservedMethods = new HashSet<>();
for (String iface : cls.getInterfaces()) {
if (nativeRepos.isJavaScriptClass(iface)) {
if (typeHelper.isJavaScriptClass(iface)) {
addPreservedMethods(iface, preservedMethods);
}
}
@ -314,7 +314,7 @@ class JavascriptNativeProcessor {
return processJSBodyInvocation(repository, method, callLocation, invoke);
}
if (!nativeRepos.isJavaScriptClass(invoke.getMethod().getClassName())) {
if (!typeHelper.isJavaScriptClass(invoke.getMethod().getClassName())) {
return false;
}
@ -452,14 +452,14 @@ class JavascriptNativeProcessor {
name = redefinedMethodName.getString();
}
}
if (method.getResultType() != ValueType.VOID && !isSupportedType(method.getResultType())) {
if (method.getResultType() != ValueType.VOID && !typeHelper.isSupportedType(method.getResultType())) {
diagnostics.error(callLocation, "Method {{m0}} is not a proper native JavaScript method "
+ "declaration", invoke.getMethod());
return false;
}
for (ValueType arg : method.getParameterTypes()) {
if (!isSupportedType(arg)) {
if (!typeHelper.isSupportedType(arg)) {
diagnostics.error(callLocation, "Method {{m0}} is not a proper native JavaScript method "
+ "or constructor declaration", invoke.getMethod());
return false;
@ -521,12 +521,13 @@ class JavascriptNativeProcessor {
if (!isStatic) {
ValueType paramType = ValueType.object(methodToProcess.getOwnerName());
paramTypes[offset++] = paramType;
if (!isSupportedType(paramType)) {
if (!typeHelper.isSupportedType(paramType)) {
diagnostics.error(location, "Non-static JSBody method {{m0}} is owned by non-JS class {{c1}}",
methodToProcess.getReference(), methodToProcess.getOwnerName());
}
}
if (methodToProcess.getResultType() != ValueType.VOID && !isSupportedType(methodToProcess.getResultType())) {
if (methodToProcess.getResultType() != ValueType.VOID
&& !typeHelper.isSupportedType(methodToProcess.getResultType())) {
diagnostics.error(location, "JSBody method {{m0}} returns unsupported type {{t1}}",
methodToProcess.getReference(), methodToProcess.getResultType());
}
@ -579,8 +580,9 @@ class JavascriptNativeProcessor {
} else {
expr = rootNode;
}
JavaInvocationValidator javaValidator = new JavaInvocationValidator(classSource, diagnostics);
javaValidator.validate(location, expr);
JavaInvocationProcessor javaInvocationProcessor = new JavaInvocationProcessor(typeHelper,
classSource, diagnostics);
javaInvocationProcessor.validate(location, expr);
repository.emitters.put(proxyMethod, new JSBodyAstEmitter(isStatic, expr, parameterNames));
}
repository.methodMap.put(methodToProcess.getReference(), proxyMethod);
@ -1078,7 +1080,7 @@ class JavascriptNativeProcessor {
}
private boolean isProperGetter(MethodDescriptor desc) {
if (desc.parameterCount() > 0 || !isSupportedType(desc.getResultType())) {
if (desc.parameterCount() > 0 || !typeHelper.isSupportedType(desc.getResultType())) {
return false;
}
if (desc.getResultType().equals(ValueType.BOOLEAN)) {
@ -1090,7 +1092,7 @@ class JavascriptNativeProcessor {
}
private boolean isProperSetter(MethodDescriptor desc) {
if (desc.parameterCount() != 1 || !isSupportedType(desc.parameterType(0))
if (desc.parameterCount() != 1 || !typeHelper.isSupportedType(desc.parameterType(0))
|| desc.getResultType() != ValueType.VOID) {
return false;
}
@ -1106,13 +1108,13 @@ class JavascriptNativeProcessor {
}
private boolean isProperGetIndexer(MethodDescriptor desc) {
return desc.parameterCount() == 1 && isSupportedType(desc.parameterType(0))
&& isSupportedType(desc.getResultType());
return desc.parameterCount() == 1 && typeHelper.isSupportedType(desc.parameterType(0))
&& typeHelper.isSupportedType(desc.getResultType());
}
private boolean isProperSetIndexer(MethodDescriptor desc) {
return desc.parameterCount() == 2 && isSupportedType(desc.parameterType(0))
&& isSupportedType(desc.parameterType(0)) && desc.getResultType() == ValueType.VOID;
return desc.parameterCount() == 2 && typeHelper.isSupportedType(desc.parameterType(0))
&& typeHelper.isSupportedType(desc.parameterType(0)) && desc.getResultType() == ValueType.VOID;
}
private String cutPrefix(String name, int prefixLength) {
@ -1125,25 +1127,4 @@ class JavascriptNativeProcessor {
}
return Character.toLowerCase(name.charAt(prefixLength)) + name.substring(prefixLength + 1);
}
private boolean isSupportedType(ValueType type) {
if (type == ValueType.VOID) {
return false;
}
if (type instanceof ValueType.Primitive) {
switch (((ValueType.Primitive) type).getKind()) {
case LONG:
return false;
default:
return true;
}
} else if (type instanceof ValueType.Array) {
return isSupportedType(((ValueType.Array) type).getItemType());
} else if (type instanceof ValueType.Object) {
String typeName = ((ValueType.Object) type).getClassName();
return typeName.equals("java.lang.String") || nativeRepos.isJavaScriptClass(typeName);
} else {
return false;
}
}
}

View File

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.teavm.jso.plugin;
package org.teavm.jso.impl;
import java.util.HashMap;
import java.util.HashSet;
@ -38,7 +38,7 @@ import org.teavm.model.MethodReader;
*
* @author Alexey Andreev
*/
class JSODependencyListener extends AbstractDependencyListener {
class JSDependencyListener extends AbstractDependencyListener {
private Map<String, ExposedClass> exposedClasses = new HashMap<>();
private ClassReaderSource classSource;
private DependencyAgent agent;

View File

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.teavm.jso.plugin;
package org.teavm.jso.impl;
import java.io.IOException;
import org.teavm.codegen.SourceWriter;

View File

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.teavm.jso.plugin;
package org.teavm.jso.impl;
import org.teavm.vm.spi.TeaVMHost;
import org.teavm.vm.spi.TeaVMPlugin;
@ -28,8 +28,8 @@ public class JSOPlugin implements TeaVMPlugin {
JSBodyRepository repository = new JSBodyRepository();
host.registerService(JSBodyRepository.class, repository);
host.add(new JSObjectClassTransformer(repository));
JSODependencyListener dependencyListener = new JSODependencyListener();
JSOAliasRenderer aliasRenderer = new JSOAliasRenderer(dependencyListener);
JSDependencyListener dependencyListener = new JSDependencyListener();
JSAliasRenderer aliasRenderer = new JSAliasRenderer(dependencyListener);
host.add(dependencyListener);
host.add(aliasRenderer);
}

View File

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.teavm.jso.plugin;
package org.teavm.jso.impl;
import org.teavm.diagnostics.Diagnostics;
import org.teavm.model.ClassHolder;
@ -27,7 +27,7 @@ import org.teavm.model.MethodReference;
* @author Alexey Andreev
*/
public class JSObjectClassTransformer implements ClassHolderTransformer {
private JavascriptNativeProcessor processor;
private JSClassProcessor processor;
private JSBodyRepository repository;
public JSObjectClassTransformer(JSBodyRepository repository) {
@ -37,7 +37,7 @@ public class JSObjectClassTransformer implements ClassHolderTransformer {
@Override
public void transformClass(ClassHolder cls, ClassReaderSource innerSource, Diagnostics diagnostics) {
if (processor == null || processor.getClassSource() != innerSource) {
processor = new JavascriptNativeProcessor(innerSource);
processor = new JSClassProcessor(innerSource);
}
processor.setDiagnostics(diagnostics);
processor.processClass(cls);

View File

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.teavm.jso.plugin;
package org.teavm.jso.impl;
import org.mozilla.javascript.CompilerEnvirons;
import org.mozilla.javascript.ErrorReporter;

View File

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.teavm.jso.plugin;
package org.teavm.jso.impl;
import java.util.HashMap;
import java.util.Map;
@ -21,17 +21,18 @@ import org.teavm.jso.JSObject;
import org.teavm.model.ClassReader;
import org.teavm.model.ClassReaderSource;
import org.teavm.model.ElementModifier;
import org.teavm.model.ValueType;
/**
*
* @author Alexey Andreev
*/
class NativeJavascriptClassRepository {
class JSTypeHelper {
private ClassReaderSource classSource;
private Map<String, Boolean> knownJavaScriptClasses = new HashMap<>();
private Map<String, Boolean> knownJavaScriptImplementations = new HashMap<>();
public NativeJavascriptClassRepository(ClassReaderSource classSource) {
public JSTypeHelper(ClassReaderSource classSource) {
this.classSource = classSource;
knownJavaScriptClasses.put(JSObject.class.getName(), true);
}
@ -82,4 +83,25 @@ class NativeJavascriptClassRepository {
}
return cls.getInterfaces().stream().anyMatch(iface -> isJavaScriptClass(iface));
}
public boolean isSupportedType(ValueType type) {
if (type == ValueType.VOID) {
return false;
}
if (type instanceof ValueType.Primitive) {
switch (((ValueType.Primitive) type).getKind()) {
case LONG:
return false;
default:
return true;
}
} else if (type instanceof ValueType.Array) {
return isSupportedType(((ValueType.Array) type).getItemType());
} else if (type instanceof ValueType.Object) {
String typeName = ((ValueType.Object) type).getClassName();
return typeName.equals("java.lang.String") || isJavaScriptClass(typeName);
} else {
return false;
}
}
}

View File

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.teavm.jso.plugin;
package org.teavm.jso.impl;
import org.mozilla.javascript.Token;
import org.mozilla.javascript.ast.AstNode;
@ -34,12 +34,14 @@ import org.teavm.model.MethodReference;
*
* @author Alexey Andreev
*/
class JavaInvocationValidator implements NodeVisitor {
class JavaInvocationProcessor implements NodeVisitor {
private ClassReaderSource classSource;
private JSTypeHelper typeHelper;
private Diagnostics diagnostics;
private CallLocation location;
public JavaInvocationValidator(ClassReaderSource classSource, Diagnostics diagnostics) {
public JavaInvocationProcessor(JSTypeHelper typeHelper, ClassReaderSource classSource, Diagnostics diagnostics) {
this.typeHelper = typeHelper;
this.classSource = classSource;
this.diagnostics = diagnostics;
}

View File

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.teavm.jso.plugin;
package org.teavm.jso.impl;
import java.io.IOException;

View File

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.teavm.jso.plugin;
package org.teavm.jso.impl;
import org.mozilla.javascript.ErrorReporter;
import org.mozilla.javascript.EvaluatorException;

View File

@ -1 +1 @@
org.teavm.jso.plugin.JSOPlugin
org.teavm.jso.impl.JSOPlugin

View File

@ -25,6 +25,8 @@ import org.mozilla.javascript.Context;
import org.mozilla.javascript.ast.AstRoot;
import org.teavm.codegen.SourceWriter;
import org.teavm.codegen.SourceWriterBuilder;
import org.teavm.jso.impl.AstWriter;
import org.teavm.jso.impl.JSParser;
/**
*