mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 16:14:10 -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.Collection;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
|
@ -621,16 +622,16 @@ public class Renderer implements RenderingManager {
|
||||||
}
|
}
|
||||||
writer.append(',').ws();
|
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()) {
|
for (PreparedMethod method : cls.getMethods()) {
|
||||||
if (!method.methodHolder.getModifiers().contains(ElementModifier.STATIC)
|
if (!method.methodHolder.getModifiers().contains(ElementModifier.STATIC)
|
||||||
&& method.methodHolder.getLevel() != AccessLevel.PRIVATE) {
|
&& 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);
|
debugEmitter.emitClass(null);
|
||||||
}
|
}
|
||||||
writer.append("]);").newLine();
|
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<>();
|
Set<MethodDescriptor> implementedMethods = new HashSet<>();
|
||||||
ClassReader superclass = cls;
|
ClassReader superclass = cls;
|
||||||
while (superclass != null) {
|
while (superclass != null) {
|
||||||
|
@ -717,35 +718,40 @@ public class Renderer implements RenderingManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
Set<String> visitedClasses = new HashSet<>();
|
Set<String> visitedClasses = new HashSet<>();
|
||||||
for (String ifaceName : cls.getInterfaces()) {
|
superclass = cls;
|
||||||
|
while (superclass != null) {
|
||||||
|
for (String ifaceName : superclass.getInterfaces()) {
|
||||||
ClassReader iface = classSource.get(ifaceName);
|
ClassReader iface = classSource.get(ifaceName);
|
||||||
if (iface != null) {
|
if (iface != null) {
|
||||||
collectMethodsToCopyFromInterfacesImpl(iface, targetList, implementedMethods, visitedClasses);
|
collectMethodsToCopyFromInterfacesImpl(iface, target, implementedMethods, visitedClasses);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
superclass = superclass.getParent() != null ? classSource.get(superclass.getParent()) : null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void collectMethodsToCopyFromInterfacesImpl(ClassReader cls, List<MethodReference> targetList,
|
private void collectMethodsToCopyFromInterfacesImpl(ClassReader cls, Map<MethodDescriptor, MethodReference> target,
|
||||||
Set<MethodDescriptor> visited, Set<String> visitedClasses) {
|
Set<MethodDescriptor> implementedMethods, Set<String> visitedClasses) {
|
||||||
if (!visitedClasses.add(cls.getName())) {
|
if (!visitedClasses.add(cls.getName())) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (String ifaceName : cls.getInterfaces()) {
|
||||||
|
ClassReader iface = classSource.get(ifaceName);
|
||||||
|
if (iface != null) {
|
||||||
|
collectMethodsToCopyFromInterfacesImpl(iface, target, implementedMethods, visitedClasses);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (MethodReader method : cls.getMethods()) {
|
for (MethodReader method : cls.getMethods()) {
|
||||||
if (!method.hasModifier(ElementModifier.STATIC)
|
if (!method.hasModifier(ElementModifier.STATIC)
|
||||||
&& !method.hasModifier(ElementModifier.ABSTRACT)) {
|
&& !method.hasModifier(ElementModifier.ABSTRACT)) {
|
||||||
if (visited.add(method.getDescriptor())) {
|
MethodDescriptor descriptor = method.getDescriptor();
|
||||||
targetList.add(method.getReference());
|
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) {
|
private static Object getDefaultValue(ValueType type) {
|
||||||
|
|
|
@ -491,8 +491,20 @@ public class VMTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void indirectDefaultMethod() {
|
public void indirectDefaultMethod() {
|
||||||
PathJoint o = new PathJoint();
|
StringBuilder sb = new StringBuilder();
|
||||||
assertEquals("SecondPath.foo", o.foo());
|
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 {
|
interface FirstPath {
|
||||||
|
@ -511,6 +523,13 @@ public class VMTest {
|
||||||
class PathJoint implements FirstPath, SecondPath {
|
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
|
@Test
|
||||||
public void cloneArray() {
|
public void cloneArray() {
|
||||||
String[] a = new String[] { "foo" };
|
String[] a = new String[] { "foo" };
|
||||||
|
|
Loading…
Reference in New Issue
Block a user