mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 16:14:10 -08:00
Fix bugs in method resolution in html4j
This commit is contained in:
parent
c54b2b9e9e
commit
680f0dabb5
|
@ -140,21 +140,101 @@ public class JavaScriptBodyDependency extends AbstractDependencyListener {
|
||||||
agent.linkMethod(JavaScriptConvGenerator.valueOfLongMethod, location).use();
|
agent.linkMethod(JavaScriptConvGenerator.valueOfLongMethod, location).use();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static MethodReader findMethod(ClassReaderSource classSource, String clsName, MethodDescriptor desc) {
|
class GeneratorJsCallback extends JsCallback {
|
||||||
while (clsName != null) {
|
private DependencyAgent agent;
|
||||||
ClassReader cls = classSource.get(clsName);
|
private MethodDependency caller;
|
||||||
if (cls == null) {
|
private CallLocation location;
|
||||||
return null;
|
|
||||||
}
|
GeneratorJsCallback(DependencyAgent agent, MethodDependency caller, CallLocation location) {
|
||||||
for (MethodReader method : cls.getMethods()) {
|
this.agent = agent;
|
||||||
if (method.getName().equals(desc.getName()) && sameParams(method.getDescriptor(), desc)) {
|
this.caller = caller;
|
||||||
return method;
|
this.location = location;
|
||||||
}
|
|
||||||
}
|
|
||||||
clsName = cls.getParent();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected CharSequence callMethod(String ident, String fqn, String method, String params) {
|
||||||
|
MethodDescriptor desc = MethodDescriptor.parse(method + params + "V");
|
||||||
|
MethodReference methodRef = new MethodReference(fqn, desc);
|
||||||
|
|
||||||
|
MethodReader reader = findMethod(agent.getClassSource(), fqn, desc);
|
||||||
|
if (reader == null) {
|
||||||
|
agent.getDiagnostics().error(location, "Can't resolve method {{m0}}", methodRef);
|
||||||
|
}
|
||||||
|
|
||||||
|
methodRef = reader.getReference();
|
||||||
|
MethodDependency methodDep = agent.linkMethod(methodRef, location);
|
||||||
|
if (ident == null) {
|
||||||
|
reachedMethods.get(caller.getReference()).add(methodRef);
|
||||||
|
methodDep.use();
|
||||||
|
for (int i = 0; i < methodDep.getParameterCount(); ++i) {
|
||||||
|
allClassesNode.connect(methodDep.getVariable(i));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
allClassesNode.addConsumer(new VirtualCallbackConsumer(agent, methodRef, location));
|
||||||
|
}
|
||||||
|
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class VirtualCallbackConsumer implements DependencyConsumer {
|
||||||
|
private DependencyAgent agent;
|
||||||
|
private MethodReference superMethod;
|
||||||
|
private CallLocation location;
|
||||||
|
|
||||||
|
VirtualCallbackConsumer(DependencyAgent agent, MethodReference superMethod, CallLocation location) {
|
||||||
|
this.agent = agent;
|
||||||
|
this.superMethod = superMethod;
|
||||||
|
this.location = location;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void consume(DependencyType type) {
|
||||||
|
if (!agent.getClassSource().isSuperType(superMethod.getClassName(), type.getName()).orElse(false)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
MethodReader method = agent.getClassSource().resolveImplementation(new MethodReference(
|
||||||
|
type.getName(), superMethod.getDescriptor()));
|
||||||
|
if (method == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
MethodDependency methodDep = agent.linkMethod(method.getReference(), location);
|
||||||
|
methodDep.use();
|
||||||
|
for (int i = 0; i < methodDep.getParameterCount(); ++i) {
|
||||||
|
allClassesNode.connect(methodDep.getVariable(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static MethodReader findMethod(ClassReaderSource classSource, String clsName, MethodDescriptor desc) {
|
||||||
|
ClassReader cls = classSource.get(clsName);
|
||||||
|
if (cls == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (MethodReader method : cls.getMethods()) {
|
||||||
|
if (method.getName().equals(desc.getName()) && sameParams(method.getDescriptor(), desc)) {
|
||||||
|
return method;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cls.getParent() != null) {
|
||||||
|
MethodReader result = findMethod(classSource, cls.getParent(), desc);
|
||||||
|
if (result != null) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (String iface : cls.getInterfaces()) {
|
||||||
|
MethodReader result = findMethod(classSource, iface, desc);
|
||||||
|
if (result != null) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean sameParams(MethodDescriptor a, MethodDescriptor b) {
|
private static boolean sameParams(MethodDescriptor a, MethodDescriptor b) {
|
||||||
if (a.parameterCount() != b.parameterCount()) {
|
if (a.parameterCount() != b.parameterCount()) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -166,57 +246,4 @@ public class JavaScriptBodyDependency extends AbstractDependencyListener {
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
class GeneratorJsCallback extends JsCallback {
|
|
||||||
private DependencyAgent agent;
|
|
||||||
private MethodDependency caller;
|
|
||||||
private CallLocation location;
|
|
||||||
GeneratorJsCallback(DependencyAgent agent, MethodDependency caller, CallLocation location) {
|
|
||||||
this.agent = agent;
|
|
||||||
this.caller = caller;
|
|
||||||
this.location = location;
|
|
||||||
}
|
|
||||||
@Override protected CharSequence callMethod(String ident, String fqn, String method, String params) {
|
|
||||||
MethodDescriptor desc = MethodDescriptor.parse(method + params + "V");
|
|
||||||
MethodReader reader = findMethod(agent.getClassSource(), fqn, desc);
|
|
||||||
MethodReference ref = reader != null ? reader.getReference() : new MethodReference(fqn, desc);
|
|
||||||
MethodDependency methodDep = agent.linkMethod(ref, location);
|
|
||||||
reachedMethods.get(caller.getReference()).add(ref);
|
|
||||||
if (!methodDep.isMissing()) {
|
|
||||||
if (reader.hasModifier(ElementModifier.STATIC) || reader.hasModifier(ElementModifier.FINAL)) {
|
|
||||||
methodDep.use();
|
|
||||||
for (int i = 0; i < methodDep.getParameterCount(); ++i) {
|
|
||||||
allClassesNode.connect(methodDep.getVariable(i));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
allClassesNode.addConsumer(new VirtualCallbackConsumer(agent, reader, caller));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class VirtualCallbackConsumer implements DependencyConsumer {
|
|
||||||
private DependencyAgent agent;
|
|
||||||
private MethodReader superMethod;
|
|
||||||
private ClassReader superClass;
|
|
||||||
private MethodDependency caller;
|
|
||||||
VirtualCallbackConsumer(DependencyAgent agent, MethodReader superMethod, MethodDependency caller) {
|
|
||||||
this.agent = agent;
|
|
||||||
this.superMethod = superMethod;
|
|
||||||
this.caller = caller;
|
|
||||||
this.superClass = agent.getClassSource().get(superMethod.getOwnerName());
|
|
||||||
}
|
|
||||||
@Override public void consume(DependencyType type) {
|
|
||||||
if (!agent.getClassSource().isSuperType(superClass.getName(), type.getName()).orElse(false)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
MethodReference methodRef = new MethodReference(type.getName(), superMethod.getDescriptor());
|
|
||||||
MethodDependency method = agent.linkMethod(methodRef, new CallLocation(caller.getReference()));
|
|
||||||
method.use();
|
|
||||||
for (int i = 0; i < method.getParameterCount(); ++i) {
|
|
||||||
allClassesNode.connect(method.getVariable(i));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,7 +24,6 @@ import org.teavm.backend.javascript.spi.Generator;
|
||||||
import org.teavm.backend.javascript.spi.GeneratorContext;
|
import org.teavm.backend.javascript.spi.GeneratorContext;
|
||||||
import org.teavm.model.AnnotationReader;
|
import org.teavm.model.AnnotationReader;
|
||||||
import org.teavm.model.AnnotationValue;
|
import org.teavm.model.AnnotationValue;
|
||||||
import org.teavm.model.ClassReader;
|
|
||||||
import org.teavm.model.ClassReaderSource;
|
import org.teavm.model.ClassReaderSource;
|
||||||
import org.teavm.model.ElementModifier;
|
import org.teavm.model.ElementModifier;
|
||||||
import org.teavm.model.MethodDescriptor;
|
import org.teavm.model.MethodDescriptor;
|
||||||
|
@ -63,7 +62,7 @@ public class JavaScriptBodyGenerator implements Generator {
|
||||||
}
|
}
|
||||||
writer.append(");").softNewLine();
|
writer.append(");").softNewLine();
|
||||||
writer.append("return ");
|
writer.append("return ");
|
||||||
unwrapValue(context, writer, method.getResultType(), "result");
|
unwrapValue(context, writer, method.getResultType());
|
||||||
writer.append(";").softNewLine();
|
writer.append(";").softNewLine();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -72,10 +71,10 @@ public class JavaScriptBodyGenerator implements Generator {
|
||||||
writer.append("(").append(param).append(")");
|
writer.append("(").append(param).append(")");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void unwrapValue(GeneratorContext context, SourceWriter writer, ValueType type, String param)
|
private void unwrapValue(GeneratorContext context, SourceWriter writer, ValueType type)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
writer.appendMethodBody(JavaScriptConvGenerator.fromJsMethod);
|
writer.appendMethodBody(JavaScriptConvGenerator.fromJsMethod);
|
||||||
writer.append("(").append(param).append(",").ws().append(context.typeToClassString(type))
|
writer.append("(").append("result").append(",").ws().append(context.typeToClassString(type))
|
||||||
.append(")");
|
.append(")");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -83,20 +82,28 @@ public class JavaScriptBodyGenerator implements Generator {
|
||||||
private GeneratorContext context;
|
private GeneratorContext context;
|
||||||
private ClassReaderSource classSource;
|
private ClassReaderSource classSource;
|
||||||
private NamingStrategy naming;
|
private NamingStrategy naming;
|
||||||
public GeneratorJsCallback(GeneratorContext context, ClassReaderSource classSource, NamingStrategy naming) {
|
|
||||||
|
GeneratorJsCallback(GeneratorContext context, ClassReaderSource classSource, NamingStrategy naming) {
|
||||||
this.context = context;
|
this.context = context;
|
||||||
this.classSource = classSource;
|
this.classSource = classSource;
|
||||||
this.naming = naming;
|
this.naming = naming;
|
||||||
}
|
}
|
||||||
@Override protected CharSequence callMethod(String ident, String fqn, String method, String params) {
|
|
||||||
|
@Override
|
||||||
|
protected CharSequence callMethod(String ident, String fqn, String method, String params) {
|
||||||
MethodDescriptor desc = MethodDescriptor.parse(method + params + "V");
|
MethodDescriptor desc = MethodDescriptor.parse(method + params + "V");
|
||||||
MethodReader reader = findMethod(fqn, desc);
|
MethodReader reader = JavaScriptBodyDependency.findMethod(classSource, fqn, desc);
|
||||||
|
if (reader == null) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
desc = reader.getDescriptor();
|
||||||
|
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
sb.append("(function(");
|
sb.append("(function(");
|
||||||
if (ident != null) {
|
if (ident != null) {
|
||||||
sb.append("$this");
|
sb.append("$this");
|
||||||
}
|
}
|
||||||
for (int i = 0; i < reader.parameterCount(); ++i) {
|
for (int i = 0; i < desc.parameterCount(); ++i) {
|
||||||
if (ident != null || i > 0) {
|
if (ident != null || i > 0) {
|
||||||
sb.append(", ");
|
sb.append(", ");
|
||||||
}
|
}
|
||||||
|
@ -106,14 +113,14 @@ public class JavaScriptBodyGenerator implements Generator {
|
||||||
if (ident == null) {
|
if (ident == null) {
|
||||||
sb.append(naming.getFullNameFor(reader.getReference()));
|
sb.append(naming.getFullNameFor(reader.getReference()));
|
||||||
} else {
|
} else {
|
||||||
sb.append("$this.").append(naming.getNameFor(reader.getDescriptor()));
|
sb.append("$this.").append(naming.getNameFor(desc));
|
||||||
}
|
}
|
||||||
sb.append("(");
|
sb.append("(");
|
||||||
for (int i = 0; i < reader.parameterCount(); ++i) {
|
for (int i = 0; i < desc.parameterCount(); ++i) {
|
||||||
if (i > 0) {
|
if (i > 0) {
|
||||||
sb.append(", ");
|
sb.append(", ");
|
||||||
}
|
}
|
||||||
ValueType paramType = simplifyParamType(reader.parameterType(i));
|
ValueType paramType = simplifyParamType(desc.parameterType(i));
|
||||||
sb.append(naming.getFullNameFor(JavaScriptConvGenerator.fromJsMethod)).append("(p").append(i)
|
sb.append(naming.getFullNameFor(JavaScriptConvGenerator.fromJsMethod)).append("(p").append(i)
|
||||||
.append(", ")
|
.append(", ")
|
||||||
.append(context.typeToClassString(paramType)).append(")");
|
.append(context.typeToClassString(paramType)).append(")");
|
||||||
|
@ -124,6 +131,7 @@ public class JavaScriptBodyGenerator implements Generator {
|
||||||
}
|
}
|
||||||
return sb.toString();
|
return sb.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
private ValueType simplifyParamType(ValueType type) {
|
private ValueType simplifyParamType(ValueType type) {
|
||||||
if (type instanceof ValueType.Object) {
|
if (type instanceof ValueType.Object) {
|
||||||
return ValueType.object("java.lang.Object");
|
return ValueType.object("java.lang.Object");
|
||||||
|
@ -134,28 +142,5 @@ public class JavaScriptBodyGenerator implements Generator {
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
private MethodReader findMethod(String clsName, MethodDescriptor desc) {
|
|
||||||
while (clsName != null) {
|
|
||||||
ClassReader cls = classSource.get(clsName);
|
|
||||||
for (MethodReader method : cls.getMethods()) {
|
|
||||||
if (method.getName().equals(desc.getName()) && sameParams(method.getDescriptor(), desc)) {
|
|
||||||
return method;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
clsName = cls.getParent();
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
private boolean sameParams(MethodDescriptor a, MethodDescriptor b) {
|
|
||||||
if (a.parameterCount() != b.parameterCount()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
for (int i = 0; i < a.parameterCount(); ++i) {
|
|
||||||
if (!a.parameterType(i).equals(b.parameterType(i))) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,7 +21,6 @@ import java.io.BufferedReader;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.InputStreamReader;
|
import java.io.InputStreamReader;
|
||||||
import java.util.Calendar;
|
|
||||||
import net.java.html.js.JavaScriptBody;
|
import net.java.html.js.JavaScriptBody;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
|
@ -79,12 +78,9 @@ public class JavaScriptBodyTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void unusedArgumentIgnored() {
|
public void unusedArgumentIgnored() {
|
||||||
final int[] array = new int[1];
|
int[] array = new int[1];
|
||||||
invokeCallback(new Callback() {
|
invokeCallback(input -> {
|
||||||
@Override
|
array[0] = 23;
|
||||||
public void exec(Calendar input) {
|
|
||||||
array[0] = 23;
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
assertEquals(23, array[0]);
|
assertEquals(23, array[0]);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user