mirror of
https://github.com/konsoletyper/teavm.git
synced 2024-11-27 01:30:35 +08:00
JS: fix overrides with default methods
This commit is contained in:
parent
4fe012740d
commit
f97484365c
@ -22,6 +22,7 @@ import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
@ -621,16 +622,16 @@ public class Renderer implements RenderingManager {
|
||||
}
|
||||
writer.append(',').ws();
|
||||
|
||||
List<MethodReference> virtualMethods = new ArrayList<>();
|
||||
Map<MethodDescriptor, MethodReference> virtualMethods = new LinkedHashMap<>();
|
||||
collectMethodsToCopyFromInterfaces(classSource.get(cls.getName()), virtualMethods);
|
||||
for (PreparedMethod method : cls.getMethods()) {
|
||||
if (!method.methodHolder.getModifiers().contains(ElementModifier.STATIC)
|
||||
&& method.methodHolder.getLevel() != AccessLevel.PRIVATE) {
|
||||
virtualMethods.add(method.reference);
|
||||
virtualMethods.put(method.reference.getDescriptor(), method.reference);
|
||||
}
|
||||
}
|
||||
collectMethodsToCopyFromInterfaces(classSource.get(cls.getName()), virtualMethods);
|
||||
|
||||
renderVirtualDeclarations(virtualMethods);
|
||||
renderVirtualDeclarations(virtualMethods.values());
|
||||
debugEmitter.emitClass(null);
|
||||
}
|
||||
writer.append("]);").newLine();
|
||||
@ -702,7 +703,7 @@ public class Renderer implements RenderingManager {
|
||||
}
|
||||
}
|
||||
|
||||
private void collectMethodsToCopyFromInterfaces(ClassReader cls, List<MethodReference> targetList) {
|
||||
private void collectMethodsToCopyFromInterfaces(ClassReader cls, Map<MethodDescriptor, MethodReference> target) {
|
||||
Set<MethodDescriptor> implementedMethods = new HashSet<>();
|
||||
ClassReader superclass = cls;
|
||||
while (superclass != null) {
|
||||
@ -717,35 +718,40 @@ public class Renderer implements RenderingManager {
|
||||
}
|
||||
|
||||
Set<String> visitedClasses = new HashSet<>();
|
||||
for (String ifaceName : cls.getInterfaces()) {
|
||||
ClassReader iface = classSource.get(ifaceName);
|
||||
if (iface != null) {
|
||||
collectMethodsToCopyFromInterfacesImpl(iface, targetList, implementedMethods, visitedClasses);
|
||||
superclass = cls;
|
||||
while (superclass != null) {
|
||||
for (String ifaceName : superclass.getInterfaces()) {
|
||||
ClassReader iface = classSource.get(ifaceName);
|
||||
if (iface != null) {
|
||||
collectMethodsToCopyFromInterfacesImpl(iface, target, implementedMethods, visitedClasses);
|
||||
}
|
||||
}
|
||||
superclass = superclass.getParent() != null ? classSource.get(superclass.getParent()) : null;
|
||||
}
|
||||
}
|
||||
|
||||
private void collectMethodsToCopyFromInterfacesImpl(ClassReader cls, List<MethodReference> targetList,
|
||||
Set<MethodDescriptor> visited, Set<String> visitedClasses) {
|
||||
private void collectMethodsToCopyFromInterfacesImpl(ClassReader cls, Map<MethodDescriptor, MethodReference> target,
|
||||
Set<MethodDescriptor> implementedMethods, Set<String> visitedClasses) {
|
||||
if (!visitedClasses.add(cls.getName())) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (String ifaceName : cls.getInterfaces()) {
|
||||
ClassReader iface = classSource.get(ifaceName);
|
||||
if (iface != null) {
|
||||
collectMethodsToCopyFromInterfacesImpl(iface, target, implementedMethods, visitedClasses);
|
||||
}
|
||||
}
|
||||
|
||||
for (MethodReader method : cls.getMethods()) {
|
||||
if (!method.hasModifier(ElementModifier.STATIC)
|
||||
&& !method.hasModifier(ElementModifier.ABSTRACT)) {
|
||||
if (visited.add(method.getDescriptor())) {
|
||||
targetList.add(method.getReference());
|
||||
MethodDescriptor descriptor = method.getDescriptor();
|
||||
if (!implementedMethods.contains(descriptor)) {
|
||||
target.put(descriptor, 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) {
|
||||
|
@ -491,8 +491,20 @@ public class VMTest {
|
||||
|
||||
@Test
|
||||
public void indirectDefaultMethod() {
|
||||
PathJoint o = new PathJoint();
|
||||
assertEquals("SecondPath.foo", o.foo());
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (FirstPath o : new FirstPath[] { new PathJoint(), new FirstPathOptimizationPrevention() }) {
|
||||
sb.append(o.foo()).append(";");
|
||||
}
|
||||
assertEquals("SecondPath.foo;FirstPath.foo;", sb.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void indirectDefaultMethodSubclass() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (FirstPath o : new FirstPath[] { new PathJointSubclass(), new FirstPathOptimizationPrevention() }) {
|
||||
sb.append(o.foo()).append(";");
|
||||
}
|
||||
assertEquals("SecondPath.foo;FirstPath.foo;", sb.toString());
|
||||
}
|
||||
|
||||
interface FirstPath {
|
||||
@ -511,6 +523,13 @@ public class VMTest {
|
||||
class PathJoint implements FirstPath, SecondPath {
|
||||
}
|
||||
|
||||
class PathJointSubclass extends PathJoint implements FirstPath {
|
||||
}
|
||||
|
||||
class FirstPathOptimizationPrevention implements FirstPath {
|
||||
// Used to ensure that the implementation of FirstPath.foo() is not optimized away by TeaVM.
|
||||
}
|
||||
|
||||
@Test
|
||||
public void cloneArray() {
|
||||
String[] a = new String[] { "foo" };
|
||||
|
Loading…
Reference in New Issue
Block a user