Skip to content

Commit 21efa7e

Browse files
committed
Add static and default interface methods support
1 parent 5231e67 commit 21efa7e

File tree

5 files changed

+66
-39
lines changed

5 files changed

+66
-39
lines changed

test-app/build-tools/android-metadata-generator/build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ compileJava {
3636
compileJava.outputs.dir("$rootDir/dist/classes")
3737

3838
dependencies {
39-
compile 'org.apache.bcel:bcel:6.2'
39+
compile 'org.apache.bcel:bcel:6.0'
4040
compile files("./src/libs/dx.jar")
4141
}
4242

test-app/build-tools/android-metadata-generator/src/src/com/telerik/metadata/Builder.java

Lines changed: 8 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import java.util.HashSet;
1313
import java.util.List;
1414
import java.util.Map;
15+
import java.util.Set;
1516

1617
import com.telerik.metadata.TreeNode.FieldInfo;
1718
import com.telerik.metadata.TreeNode.MethodInfo;
@@ -22,6 +23,7 @@
2223
import com.telerik.metadata.desc.MethodDescriptor;
2324
import com.telerik.metadata.desc.TypeDescriptor;
2425
import com.telerik.metadata.dx.DexFile;
26+
import com.telerik.metadata.parsing.ClassParser;
2527

2628
public class Builder {
2729
private static class MethodNameComparator implements Comparator<MethodDescriptor> {
@@ -130,7 +132,7 @@ private static void setNodeMembers(ClassDescriptor clazz, TreeNode node, TreeNod
130132

131133
MethodDescriptor[] allMethods = ClassUtil.getAllMethods(clazz);
132134
MethodDescriptor[] classImplementedMethods = clazz.getMethods();
133-
MethodDescriptor[] interfaceImplementedMethods = getDefaultMethodsFromImplementedInterfaces(clazz, classImplementedMethods);
135+
MethodDescriptor[] interfaceImplementedMethods = clazz.isClass() ? getDefaultMethodsFromImplementedInterfaces(clazz, classImplementedMethods) : new MethodDescriptor[0];
134136
MethodDescriptor[] methods = concatenate(classImplementedMethods, interfaceImplementedMethods);
135137

136138
Arrays.sort(methods, methodNameComparator);
@@ -250,33 +252,14 @@ private static void getFieldsFromImplementedInterfaces(ClassDescriptor clazz, Tr
250252
}
251253

252254
private static MethodDescriptor[] getDefaultMethodsFromImplementedInterfaces(ClassDescriptor clazz, MethodDescriptor[] originalClassMethodDescriptors) {
253-
HashSet<MethodDescriptor> defaultMethods = getAllDefaultMethodsFromImplementedInterfaces(clazz);
254-
HashSet<MethodDescriptor> classMethods = new HashSet<MethodDescriptor>(Arrays.asList(originalClassMethodDescriptors));
255-
defaultMethods.removeAll(classMethods);
256-
257-
return defaultMethods.toArray(new MethodDescriptor[0]);
258-
}
259-
260-
private static HashSet<MethodDescriptor> getAllDefaultMethodsFromImplementedInterfaces(ClassDescriptor clazz) {
261-
return getAllDefaultMethodsFromImplementedInterfacesRecursively(clazz, new HashSet<MethodDescriptor>());
262-
}
263-
264-
private static HashSet<MethodDescriptor> getAllDefaultMethodsFromImplementedInterfacesRecursively(ClassDescriptor clazz, HashSet<MethodDescriptor> collectedDefaultMethods) {
265-
String[] implementedInterfacesNames = clazz.getInterfaceNames();
266-
267-
for (String implementedInterfaceName : implementedInterfacesNames) {
268-
ClassDescriptor interfaceClass = ClassRepo.findClass(implementedInterfaceName);
255+
ClassParser parser = ClassParser.forClassDescriptor(clazz);
269256

270-
for (MethodDescriptor md : interfaceClass.getMethods()) {
271-
if (!md.isStatic() && !md.isAbstract()) {
272-
collectedDefaultMethods.add(md);
273-
}
274-
}
257+
Set<MethodDescriptor> defaultMethods = parser.getAllDefaultMethodsFromImplementedInterfaces();
258+
Set<MethodDescriptor> classMethods = new HashSet<MethodDescriptor>(Arrays.asList(originalClassMethodDescriptors));
275259

276-
collectedDefaultMethods.addAll(getAllDefaultMethodsFromImplementedInterfacesRecursively(interfaceClass, new HashSet<MethodDescriptor>()));
277-
}
260+
defaultMethods.removeAll(classMethods);
278261

279-
return collectedDefaultMethods;
262+
return defaultMethods.toArray(new MethodDescriptor[0]);
280263
}
281264

282265
private static TreeNode getOrCreateNode(TreeNode root, TypeDescriptor type)
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
package com.telerik.metadata.parsing;
2+
3+
import com.telerik.metadata.ClassRepo;
4+
import com.telerik.metadata.desc.ClassDescriptor;
5+
import com.telerik.metadata.desc.MethodDescriptor;
6+
7+
import java.util.HashSet;
8+
import java.util.Set;
9+
10+
public final class ClassParser {
11+
12+
private final ClassDescriptor clazz;
13+
14+
private ClassParser(ClassDescriptor clazz) {
15+
this.clazz = clazz;
16+
}
17+
18+
public static ClassParser forClassDescriptor(ClassDescriptor clazz) {
19+
return new ClassParser(clazz);
20+
}
21+
22+
public Set<MethodDescriptor> getAllDefaultMethodsFromImplementedInterfaces() {
23+
return getAllDefaultMethodsFromImplementedInterfacesRecursively(clazz, new HashSet<MethodDescriptor>());
24+
}
25+
26+
private HashSet<MethodDescriptor> getAllDefaultMethodsFromImplementedInterfacesRecursively(ClassDescriptor clazz, HashSet<MethodDescriptor> collectedDefaultMethods) {
27+
String[] implementedInterfacesNames = clazz.getInterfaceNames();
28+
29+
for (String implementedInterfaceName : implementedInterfacesNames) {
30+
ClassDescriptor interfaceClass = ClassRepo.findClass(implementedInterfaceName);
31+
32+
for (MethodDescriptor md : interfaceClass.getMethods()) {
33+
if (!md.isStatic() && !md.isAbstract()) {
34+
collectedDefaultMethods.add(md);
35+
}
36+
}
37+
38+
collectedDefaultMethods.addAll(getAllDefaultMethodsFromImplementedInterfacesRecursively(interfaceClass, new HashSet<MethodDescriptor>()));
39+
}
40+
41+
return collectedDefaultMethods;
42+
}
43+
}

test-app/runtime/src/main/cpp/MetadataNode.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -968,6 +968,7 @@ void MetadataNode::MethodCallback(const v8::FunctionCallbackInfo<v8::Value>& inf
968968
auto e = info.Data().As<External>();
969969

970970
auto callbackData = reinterpret_cast<MethodCallbackData*>(e->Value());
971+
auto initialCallbackData = reinterpret_cast<MethodCallbackData*>(e->Value());
971972

972973
// Number of arguments the method is invoked with
973974
int argLength = info.Length();
@@ -1011,7 +1012,7 @@ void MetadataNode::MethodCallback(const v8::FunctionCallbackInfo<v8::Value>& inf
10111012
if ((argLength == 0) && (methodName == V8StringConstants::VALUE_OF)) {
10121013
info.GetReturnValue().Set(thiz);
10131014
} else {
1014-
bool isFromInterface = callbackData->node->IsNodeTypeInterface();
1015+
bool isFromInterface = initialCallbackData->node->IsNodeTypeInterface();
10151016
CallbackHandlers::CallJavaMethod(thiz, *className, methodName, entry, isFromInterface, first.isStatic, isSuper, info);
10161017
}
10171018
} catch (NativeScriptException& e) {

test-app/runtime/src/main/java/com/tns/MethodResolver.java

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ static String resolveMethodOverload(Class<?> clazz, String methodName, Object[]
114114
methodOverloadsForClass.put(c, finder);
115115
}
116116

117-
if(!finder.errorGettingMethods()) {
117+
if (!finder.errorGettingMethods()) {
118118
ArrayList<Method> matchingMethods = finder.getMatchingMethods(methodName);
119119
tryFindMatches(methodName, candidates, args, argLength, matchingMethods);
120120
if (candidates.size() > iterationIndex && candidates.get(iterationIndex).y == 0) {
@@ -123,7 +123,7 @@ static String resolveMethodOverload(Class<?> clazz, String methodName, Object[]
123123
}
124124
} else {
125125
Method method = finder.getMatchingMethodWithArguments(methodName, args);
126-
if(method != null) {
126+
if (method != null) {
127127
candidates.add(new Tuple<>(method, 0));
128128
break;
129129
}
@@ -159,8 +159,8 @@ static void tryFindMatches(String methodName, ArrayList<Tuple<Method, Integer>>
159159
for (int i = 0; i < params.length; i++) {
160160
if (args[i] != null) {
161161
Class<?> argClass = args[i] instanceof NullObject ?
162-
((NullObject)args[i]).getNullObjectClass()
163-
: args[i].getClass();
162+
((NullObject) args[i]).getNullObjectClass()
163+
: args[i].getClass();
164164

165165
Tuple<Boolean, Integer> res = isAssignableFrom(params[i], argClass);
166166
success = res.x.booleanValue();
@@ -226,8 +226,8 @@ static Constructor<?> resolveConstructor(Class<?> clazz, Object[] args) throws C
226226
for (int i = 0; i < args.length; i++) {
227227
if (args[i] != null) {
228228
Class<?> argClass = args[i] instanceof NullObject ?
229-
((NullObject)args[i]).getNullObjectClass()
230-
: args[i].getClass();
229+
((NullObject) args[i]).getNullObjectClass()
230+
: args[i].getClass();
231231

232232
Tuple<Boolean, Integer> res = isAssignableFrom(paramTypes[i], argClass);
233233
success = res.x.booleanValue();
@@ -514,7 +514,7 @@ public MethodFinder(Class<?> clazz) {
514514
errorGettingMethods = true;
515515
}
516516
}
517-
Method[] interfaceDefaultMethods = getInterfaceDefaultMethods(clazz);
517+
Method[] interfaceDefaultMethods = (!clazz.isInterface()) ? getInterfaceDefaultMethods(clazz) : new Method[0];
518518
declaredMethods = concatenate(declaredMethods, interfaceDefaultMethods);
519519
this.couldNotGetMethods = errorGettingMethods;
520520
}
@@ -531,13 +531,13 @@ private static <T> T[] concatenate(T[] a, T[] b) {
531531
return c;
532532
}
533533

534-
private Method[] getInterfaceDefaultMethods(Class<?> clazz){
534+
private Method[] getInterfaceDefaultMethods(Class<?> clazz) {
535535
List<Method> interfaceDefaultMethods = new ArrayList<>();
536536
Class<?>[] interfaces = clazz.getInterfaces();
537-
for(Class<?> interfaze: interfaces){
538-
for(Method method: interfaze.getMethods()) {
537+
for (Class<?> interfaze : interfaces) {
538+
for (Method method : interfaze.getMethods()) {
539539
int methodModifiers = method.getModifiers();
540-
if(!Modifier.isAbstract(methodModifiers) && !Modifier.isStatic(methodModifiers)){
540+
if (!Modifier.isAbstract(methodModifiers) && !Modifier.isStatic(methodModifiers)) {
541541
interfaceDefaultMethods.add(method);
542542
}
543543
}
@@ -551,7 +551,7 @@ public boolean errorGettingMethods() {
551551
}
552552

553553
public ArrayList<Method> getMatchingMethods(String methodName) {
554-
if(this.errorGettingMethods()) {
554+
if (this.errorGettingMethods()) {
555555
return null;
556556
}
557557
ArrayList<Method> matches = this.matchingMethods.get(methodName);

0 commit comments

Comments
 (0)