mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-31 12:24:10 -08:00
Copy default methods from interfaces to implementing classes
This commit is contained in:
parent
d8913f85d1
commit
ba7f07de4b
|
@ -21,6 +21,7 @@ import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
import org.teavm.ast.AsyncMethodNode;
|
import org.teavm.ast.AsyncMethodNode;
|
||||||
import org.teavm.ast.AsyncMethodPart;
|
import org.teavm.ast.AsyncMethodPart;
|
||||||
import org.teavm.ast.ClassNode;
|
import org.teavm.ast.ClassNode;
|
||||||
|
@ -39,6 +40,7 @@ import org.teavm.common.ServiceRepository;
|
||||||
import org.teavm.debugging.information.DebugInformationEmitter;
|
import org.teavm.debugging.information.DebugInformationEmitter;
|
||||||
import org.teavm.debugging.information.DummyDebugInformationEmitter;
|
import org.teavm.debugging.information.DummyDebugInformationEmitter;
|
||||||
import org.teavm.diagnostics.Diagnostics;
|
import org.teavm.diagnostics.Diagnostics;
|
||||||
|
import org.teavm.model.ClassReader;
|
||||||
import org.teavm.model.ElementModifier;
|
import org.teavm.model.ElementModifier;
|
||||||
import org.teavm.model.FieldReference;
|
import org.teavm.model.FieldReference;
|
||||||
import org.teavm.model.ListableClassReaderSource;
|
import org.teavm.model.ListableClassReaderSource;
|
||||||
|
@ -281,8 +283,6 @@ public class Renderer implements RenderingManager {
|
||||||
}
|
}
|
||||||
for (ClassNode cls : classes) {
|
for (ClassNode cls : classes) {
|
||||||
renderDeclaration(cls);
|
renderDeclaration(cls);
|
||||||
}
|
|
||||||
for (ClassNode cls : classes) {
|
|
||||||
renderMethodBodies(cls);
|
renderMethodBodies(cls);
|
||||||
}
|
}
|
||||||
renderClassMetadata(classes);
|
renderClassMetadata(classes);
|
||||||
|
@ -481,12 +481,13 @@ public class Renderer implements RenderingManager {
|
||||||
}
|
}
|
||||||
writer.append(',').ws();
|
writer.append(',').ws();
|
||||||
|
|
||||||
List<MethodNode> virtualMethods = new ArrayList<>();
|
List<MethodReference> virtualMethods = new ArrayList<>();
|
||||||
for (MethodNode method : cls.getMethods()) {
|
for (MethodNode method : cls.getMethods()) {
|
||||||
if (!method.getModifiers().contains(ElementModifier.STATIC)) {
|
if (!method.getModifiers().contains(ElementModifier.STATIC)) {
|
||||||
virtualMethods.add(method);
|
virtualMethods.add(method.getReference());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
collectMethodsToCopyFromInterfaces(classSource.get(cls.getName()), virtualMethods);
|
||||||
|
|
||||||
renderVirtualDeclarations(virtualMethods);
|
renderVirtualDeclarations(virtualMethods);
|
||||||
}
|
}
|
||||||
|
@ -498,6 +499,43 @@ public class Renderer implements RenderingManager {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void collectMethodsToCopyFromInterfaces(ClassReader cls, List<MethodReference> targetList) {
|
||||||
|
Set<MethodDescriptor> implementedMethods = new HashSet<>();
|
||||||
|
implementedMethods.addAll(targetList.stream().map(method -> method.getDescriptor())
|
||||||
|
.collect(Collectors.toList()));
|
||||||
|
|
||||||
|
Set<String> visitedClasses = new HashSet<>();
|
||||||
|
for (String ifaceName : cls.getInterfaces()) {
|
||||||
|
ClassReader iface = classSource.get(ifaceName);
|
||||||
|
if (iface != null) {
|
||||||
|
collectMethodsToCopyFromInterfacesImpl(iface, targetList, implementedMethods, visitedClasses);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void collectMethodsToCopyFromInterfacesImpl(ClassReader cls, List<MethodReference> targetList,
|
||||||
|
Set<MethodDescriptor> visited, Set<String> visitedClasses) {
|
||||||
|
if (!visitedClasses.add(cls.getName())) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (MethodReader method : cls.getMethods()) {
|
||||||
|
if (!method.hasModifier(ElementModifier.STATIC)
|
||||||
|
&& !method.hasModifier(ElementModifier.ABSTRACT)) {
|
||||||
|
if (visited.add(method.getDescriptor())) {
|
||||||
|
targetList.add(method.getReference());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (String ifaceName : cls.getInterfaces()) {
|
||||||
|
ClassReader iface = classSource.get(ifaceName);
|
||||||
|
if (iface != null) {
|
||||||
|
collectMethodsToCopyFromInterfacesImpl(iface, targetList, visited, visitedClasses);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static Object getDefaultValue(ValueType type) {
|
private static Object getDefaultValue(ValueType type) {
|
||||||
if (type instanceof ValueType.Primitive) {
|
if (type instanceof ValueType.Primitive) {
|
||||||
ValueType.Primitive primitive = (ValueType.Primitive) type;
|
ValueType.Primitive primitive = (ValueType.Primitive) type;
|
||||||
|
@ -551,17 +589,16 @@ public class Renderer implements RenderingManager {
|
||||||
return minifying ? RenderingUtil.indexToId(index) : "var_" + index;
|
return minifying ? RenderingUtil.indexToId(index) : "var_" + index;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void renderVirtualDeclarations(List<MethodNode> methods) throws NamingException, IOException {
|
private void renderVirtualDeclarations(Iterable<MethodReference> methods) throws NamingException, IOException {
|
||||||
writer.append("[");
|
writer.append("[");
|
||||||
boolean first = true;
|
boolean first = true;
|
||||||
for (MethodNode method : methods) {
|
for (MethodReference method : methods) {
|
||||||
debugEmitter.emitMethod(method.getReference().getDescriptor());
|
debugEmitter.emitMethod(method.getDescriptor());
|
||||||
MethodReference ref = method.getReference();
|
|
||||||
if (!first) {
|
if (!first) {
|
||||||
writer.append(",").ws();
|
writer.append(",").ws();
|
||||||
}
|
}
|
||||||
first = false;
|
first = false;
|
||||||
emitVirtualDeclaration(ref);
|
emitVirtualDeclaration(method);
|
||||||
debugEmitter.emitMethod(null);
|
debugEmitter.emitMethod(null);
|
||||||
}
|
}
|
||||||
writer.append("]");
|
writer.append("]");
|
||||||
|
|
|
@ -225,6 +225,52 @@ public class VMTest {
|
||||||
callback.complete(value);
|
callback.complete(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void defaultMethodsSupported() {
|
||||||
|
WithDefaultMethod[] instances = { new WithDefaultMethodDerivedA(), new WithDefaultMethodDerivedB(),
|
||||||
|
new WithDefaultMethodDerivedC() };
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
for (WithDefaultMethod instance : instances) {
|
||||||
|
sb.append(instance.foo() + "," + instance.bar() + ";");
|
||||||
|
}
|
||||||
|
|
||||||
|
assertEquals("default,A;default,B;overridden,C;", sb.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
interface WithDefaultMethod {
|
||||||
|
default String foo() {
|
||||||
|
return "default";
|
||||||
|
}
|
||||||
|
|
||||||
|
String bar();
|
||||||
|
}
|
||||||
|
|
||||||
|
class WithDefaultMethodDerivedA implements WithDefaultMethod {
|
||||||
|
@Override
|
||||||
|
public String bar() {
|
||||||
|
return "A";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class WithDefaultMethodDerivedB implements WithDefaultMethod {
|
||||||
|
@Override
|
||||||
|
public String bar() {
|
||||||
|
return "B";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
class WithDefaultMethodDerivedC implements WithDefaultMethod {
|
||||||
|
@Override
|
||||||
|
public String foo() {
|
||||||
|
return "overridden";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String bar() {
|
||||||
|
return "C";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@JSBody(script = "return [1, 2]")
|
@JSBody(script = "return [1, 2]")
|
||||||
private static native int[] createArray();
|
private static native int[] createArray();
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user