Skip to content

Commit 98d3a98

Browse files
committed
Merge branch 'master' into release
2 parents 733bfa5 + 0c94f8f commit 98d3a98

File tree

79 files changed

+8528
-1118
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

79 files changed

+8528
-1118
lines changed

README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,11 @@ The repo is structured in the following projects (ordered by dependencies):
1818
* **build/project-template** - this is an empty placeholder Android Application project, used by the [NativeScript CLI](https://github.com/NativeScript/nativescript-cli) when building an Android project.
1919

2020
# Build Prerequisites
21-
The source in this repo is organized in Android Studio projects.
21+
Following are the minimal prerequisites to build the runtime package.
2222

2323
* Install the latest [Android Studio ](https://developer.android.com/studio/index.html).
24-
* Install Android API Level 22 from Android Studio -> Tools -> Android -> SDK Manager
25-
* Install the Android NDK from Android Studio -> Tools -> Android -> SDK Manager
24+
* Install Android API Level 22, 23, 24, 25 from Android Studio -> Tools -> Android -> SDK Manager
25+
* Android NDK 12b - [NDK Archives](https://developer.android.com/ndk/downloads/older_releases.html)
2626
* Download Android Support Repository through the Android SDK Manager
2727
* Download Build Tools 25.0.2 through the Android SDK Manager.
2828

android-static-binding-generator/project/build.gradle

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,9 @@ task runAstParser(type: RunAstParserTask) {
170170
// 2. all subdirectories that do not have a package.json containing a "nativescript" key are skipped
171171
task traverseJsFiles () {
172172
doFirst {
173+
// invalidate previously generated bindings.txt file
174+
// todo: remove when removing previously generated bindings is implemented
175+
new File(bindingsFileP).delete()
173176
traverseDirectory(jsCodeAbsolutePath, false)
174177
}
175178
}

android-static-binding-generator/project/staticbindinggenerator/src/main/java/org/nativescript/staticbindinggenerator/Generator.java

Lines changed: 71 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,16 @@
77
import java.io.IOException;
88
import java.io.InputStreamReader;
99
import java.io.PrintStream;
10+
import java.nio.file.Files;
11+
import java.nio.file.Paths;
1012
import java.util.ArrayDeque;
1113
import java.util.ArrayList;
1214
import java.util.Arrays;
1315
import java.util.HashMap;
1416
import java.util.HashSet;
1517
import java.util.List;
1618
import java.util.Map;
19+
import java.util.Objects;
1720
import java.util.Queue;
1821
import java.util.Set;
1922
import java.util.jar.JarInputStream;
@@ -24,6 +27,8 @@
2427
import org.apache.bcel.classfile.Method;
2528
import org.apache.bcel.generic.Type;
2629

30+
import javafx.util.Pair;
31+
2732
public class Generator {
2833
private static final String JAVA_EXT = ".java";
2934

@@ -45,18 +50,23 @@ public Generator(String outputDir, String[] libs, boolean throwOnError) throws I
4550
this.classes = readClasses(libs, throwOnError);
4651
}
4752

48-
4953
public void writeBindings(String filename) throws IOException, ClassNotFoundException {
5054
Binding[] bindings = generateBindings(filename);
51-
List<File> writenFiles = new ArrayList<File>();
55+
Set<File> writtenFiles = new HashSet<File>();
5256
for (Binding b : bindings) {
53-
if (!writenFiles.contains(b.getFile())) {
54-
writenFiles.add(b.getFile());
57+
if (writtenFiles.add(b.getFile())) {
5558
try (PrintStream ps = new PrintStream(b.getFile())) {
5659
ps.append(b.getContent());
5760
}
61+
// A file with that name has already been written
5862
} else {
59-
throw new IOException("File already exists. This may lead to undesired behavior.\nPlease change the name of one of the extended classes.\n" + b.getFile());
63+
// Compare text contents for equality
64+
String content = new String(Files.readAllBytes(Paths.get(b.getFile().toString())));
65+
if (content.equals(b.getContent())) {
66+
System.out.println("Warning: File already exists. This could mean the same code has been parsed more than once from two or more different files. \nFile:" + b.getFile());
67+
} else {
68+
throw new IOException("File already exists. This may lead to undesired behavior.\nPlease change the name of one of the extended classes.\nFile:" + b.getFile() + " Class: " + b.getClassname());
69+
}
6070
}
6171
}
6272
}
@@ -187,51 +197,32 @@ private String getNormalizedName(String filename) {
187197
return sb.toString();
188198
}
189199

190-
private Map<String, List<Method>> getPublicApi(JavaClass clazz) throws ClassNotFoundException {
191-
Map<String, List<Method>> api = new HashMap<String, List<Method>>();
200+
private Map<String, MethodGroup> getPublicApi(JavaClass clazz) throws ClassNotFoundException {
201+
Map<String, MethodGroup> api = new HashMap<>();
192202
JavaClass currentClass = clazz;
193203
String clazzName = clazz.getClassName();
194204
while (true) {
195205
String currentClassname = currentClass.getClassName();
196206

197-
boolean shouldCollectMethods = !(!clazzName.equals(currentClassname) && currentClass.isAbstract());
198-
199-
if (shouldCollectMethods || currentClass.isInterface()) {
200-
// Don't include abstract parent class's methods to avoid compilation issues
201-
// where a child class has 2 methods, of the same type, with just a
202-
// return type/parameter type that differs by being of a superclass of the class being extended.
203-
// see Test testCanCompileBindingClassExtendingAnExtendedClassWithMethodsWithTheSameSignature
204-
List<Method> methods = new ArrayList<Method>();
205-
for (Method m : currentClass.getMethods()) {
206-
methods.add(m);
207-
}
208-
209-
// System.out.println("SBG: getPublicApi:collectInterfaceMethods classname: " + currentClassname);
207+
List<Method> methods = new ArrayList<Method>();
208+
for (Method m : currentClass.getMethods()) {
209+
methods.add(m);
210+
}
210211

211-
collectInterfaceMethods(clazz, methods);
212-
for (Method m : methods) {
213-
if (!m.isSynthetic() && (m.isPublic() || m.isProtected()) && !m.isStatic()) {
214-
String name = m.getName();
212+
collectInterfaceMethods(clazz, methods);
213+
for (Method m : methods) {
214+
if (!m.isSynthetic() && (m.isPublic() || m.isProtected()) && !m.isStatic()) {
215+
String name = m.getName();
215216

216-
List<Method> methodGroup;
217-
if (api.containsKey(name)) {
218-
methodGroup = api.get(name);
219-
} else {
220-
methodGroup = new ArrayList<Method>();
221-
api.put(name, methodGroup);
222-
}
223-
boolean found = false;
224-
String methodSig = m.getSignature();
225-
for (Method m1 : methodGroup) {
226-
found = methodSig.equals(m1.getSignature());
227-
if (found) {
228-
break;
229-
}
230-
}
231-
if (!found) {
232-
methodGroup.add(m);
233-
}
217+
MethodGroup methodGroup;
218+
if (api.containsKey(name)) {
219+
methodGroup = api.get(name);
220+
} else {
221+
methodGroup = new MethodGroup(currentClassname);
222+
api.put(name, methodGroup);
234223
}
224+
225+
methodGroup.add(currentClassname, m);
235226
}
236227
}
237228

@@ -332,7 +323,7 @@ private void writeBinding(Writer w, DataRow dataRow, JavaClass clazz, String pac
332323
String[] implInterfaces = dataRow.getInterfaces();
333324
collectImplementedInterfaces(implInterfaces, clazz);
334325

335-
Map<String, List<Method>> api = getPublicApi(clazz);
326+
Map<String, MethodGroup> api = getPublicApi(clazz);
336327

337328
w.writeln("package " + packageName + ";");
338329
w.writeln();
@@ -439,7 +430,7 @@ private void writeBinding(Writer w, DataRow dataRow, JavaClass clazz, String pac
439430
collectInterfaceMethods(clazz, interfaceMethods);
440431
for (String methodName : dataRow.getMethods()) {
441432
if (api.containsKey(methodName)) {
442-
List<Method> methodGroup = api.get(methodName);
433+
List<Method> methodGroup = api.get(methodName).getList();
443434
for (Method m : methodGroup) {
444435
boolean isInterfaceMethod = false;
445436
if (interfaceMethods.contains(m)) {
@@ -720,4 +711,40 @@ private JavaClass getClass(String className) throws ClassNotFoundException {
720711

721712
return clazz;
722713
}
714+
715+
private class MethodGroup {
716+
private List<Method> methods;
717+
private String latestInheritorClassName;
718+
719+
public MethodGroup(String forClass) {
720+
this.methods = new ArrayList<>();
721+
this.latestInheritorClassName = forClass;
722+
}
723+
724+
public void add(String methodClassname, Method m) {
725+
boolean found = false;
726+
727+
String methodSig = m.getSignature();
728+
for (Method m1 : this.methods) {
729+
found = methodSig.equals(m1.getSignature());
730+
if (found) {
731+
break;
732+
}
733+
}
734+
735+
if (!found) {
736+
// Only add method to API if method hasn't already been added by an inheritor of
737+
// the current class
738+
if (!methodClassname.equals(this.latestInheritorClassName)) {
739+
return;
740+
}
741+
742+
this.methods.add(m);
743+
}
744+
}
745+
746+
public List<Method> getList() {
747+
return this.methods;
748+
}
749+
}
723750
}

android-static-binding-generator/project/staticbindinggenerator/src/test/java/com/example/ListView.java

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,5 @@
11
package com.example;
22

3-
/**
4-
* Created by pkanev on 4/27/2017.
5-
*/
6-
73
public class ListView extends View {
84
public ListView createView() {
95
return new ListView();
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package com.example;
2+
3+
public abstract class MyAbstractClass {
4+
String className;
5+
6+
public MyAbstractClass(String name) {
7+
this.className = name;
8+
}
9+
10+
public abstract void abstractMethod();
11+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package com.example;
2+
3+
public abstract class MyAbstractClass2 extends MyAbstractClass {
4+
public MyAbstractClass2() {
5+
super("MyNotSoAbstractClass");
6+
}
7+
}
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,4 @@
11
package com.example;
22

3-
/**
4-
* Created by slavchev on 7/6/2016.
5-
*/
63
public class MyClass {
74
}

android-static-binding-generator/project/staticbindinggenerator/src/test/java/com/example/View.java

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,5 @@
11
package com.example;
22

3-
/**
4-
* Created by pkanev on 4/27/2017.
5-
*/
6-
73
public abstract class View {
84
public View createView() {
95
return null;

android-static-binding-generator/project/staticbindinggenerator/src/test/java/org/nativescript/staticbindinggenerator/test/GeneratorTest.java

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package org.nativescript.staticbindinggenerator.test;
22

33
import com.example.ListView;
4+
import com.example.MyAbstractClass2;
45
import com.example.MyInterface;
56

67
import org.apache.commons.io.IOUtils;
@@ -129,4 +130,29 @@ public void testCanCompileBindingClassExtendingAnExtendedClassWithMethodsWithThe
129130
Assert.assertNotNull(ComplexClass);
130131
Assert.assertEquals(4, ComplexClass.getDeclaredMethods().length); // 1 + constructor + (equals + hashcode)
131132
}
133+
134+
@Test
135+
public void testCanCompileBindingClassExtendingAnAbstractClassThatExtendsAbstractClass() throws Exception {
136+
URL u = MyAbstractClass2.class.getResource('/' + MyAbstractClass2.class.getName().replace('.', '/') + ".class");
137+
File f = new File(u.toURI()).getParentFile().getParentFile().getParentFile();
138+
139+
String dataRowString = "com.example.MyAbstractClass2*_fapp_l9_c29__*abstractMethod*com.example.com.example.MyExtendedClass**";
140+
DataRow dataRow = new DataRow(dataRowString);
141+
142+
System.out.println(dataRowString);
143+
144+
String outputDir = null;
145+
String[] libs = {runtimePath, f.getAbsolutePath()};
146+
Generator generator = new Generator(outputDir, libs);
147+
Binding binding = generator.generateBinding(dataRow);
148+
149+
StringBuffer sourceCode = new StringBuffer();
150+
sourceCode.append(binding.getContent());
151+
152+
Iterable<String> options = new ArrayList<String>(Arrays.asList("-cp", dependenciesDir));
153+
Class<?> ComplexClass = InMemoryJavaCompiler.compile(binding.getClassname(), sourceCode.toString(), options);
154+
155+
// class compiles, meaning abstract method of super-super class is extended properly
156+
Assert.assertNotNull(ComplexClass);
157+
}
132158
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
com.example.MyAbstractClass2*_fapp_l9_c29__*abstractMethod*com.example.com.example.MyExtendedClass**

0 commit comments

Comments
 (0)