3
3
import com .google .googlejavaformat .java .Formatter ;
4
4
import com .google .googlejavaformat .java .FormatterException ;
5
5
6
- import java .io .BufferedReader ;
7
- import java .io .File ;
8
- import java .io .FileInputStream ;
9
- import java .io .FileNotFoundException ;
10
- import java .io .IOException ;
11
- import java .io .InputStreamReader ;
12
- import java .io .PrintStream ;
13
- import java .nio .file .Files ;
14
- import java .nio .file .Paths ;
15
- import java .util .ArrayList ;
16
- import java .util .Arrays ;
17
- import java .util .HashMap ;
18
- import java .util .HashSet ;
19
- import java .util .List ;
20
- import java .util .Map ;
21
- import java .util .Set ;
22
-
23
6
import org .apache .bcel .classfile .JavaClass ;
24
7
import org .apache .bcel .classfile .Method ;
8
+ import org .apache .commons .io .FileUtils ;
25
9
import org .nativescript .staticbindinggenerator .files .FileSystemHelper ;
10
+ import org .nativescript .staticbindinggenerator .files .impl .ClassesCollection ;
26
11
import org .nativescript .staticbindinggenerator .files .impl .FileSystemHelperImpl ;
12
+ import org .nativescript .staticbindinggenerator .generating .parsing .checkers .AndroidClassChecker ;
13
+ import org .nativescript .staticbindinggenerator .generating .parsing .checkers .ImplementationObjectChecker ;
14
+ import org .nativescript .staticbindinggenerator .generating .parsing .checkers .impl .AndroidClassCheckerImpl ;
15
+ import org .nativescript .staticbindinggenerator .generating .parsing .checkers .impl .ImplementationObjectCheckerImpl ;
27
16
import org .nativescript .staticbindinggenerator .generating .parsing .classes .hierarchy .generics .GenericHierarchyView ;
17
+ import org .nativescript .staticbindinggenerator .generating .parsing .classes .hierarchy .generics .GenericParameters ;
28
18
import org .nativescript .staticbindinggenerator .generating .parsing .classes .hierarchy .generics .impl .GenericSignatureReader ;
29
19
import org .nativescript .staticbindinggenerator .generating .parsing .classes .hierarchy .generics .impl .GenericsAwareClassHierarchyParserImpl ;
30
20
import org .nativescript .staticbindinggenerator .generating .parsing .methods .InheritedMethodsCollector ;
45
35
import org .nativescript .staticbindinggenerator .generating .writing .impl .MethodsWriterImpl ;
46
36
import org .nativescript .staticbindinggenerator .generating .writing .impl .PackageNameWriterImpl ;
47
37
import org .nativescript .staticbindinggenerator .naming .BcelNamingUtil ;
48
- import org .nativescript .staticbindinggenerator .generating .parsing .checkers .AndroidClassChecker ;
49
- import org .nativescript .staticbindinggenerator .generating .parsing .checkers .ImplementationObjectChecker ;
50
- import org .nativescript .staticbindinggenerator .generating .parsing .checkers .impl .AndroidClassCheckerImpl ;
51
- import org .nativescript .staticbindinggenerator .generating .parsing .checkers .impl .ImplementationObjectCheckerImpl ;
38
+
39
+ import java .io .BufferedReader ;
40
+ import java .io .File ;
41
+ import java .io .FileInputStream ;
42
+ import java .io .FileNotFoundException ;
43
+ import java .io .IOException ;
44
+ import java .io .InputStreamReader ;
45
+ import java .io .PrintStream ;
46
+ import java .nio .charset .Charset ;
47
+ import java .nio .file .Files ;
48
+ import java .nio .file .Paths ;
49
+ import java .util .ArrayList ;
50
+ import java .util .Arrays ;
51
+ import java .util .HashMap ;
52
+ import java .util .HashSet ;
53
+ import java .util .List ;
54
+ import java .util .Map ;
55
+ import java .util .Set ;
52
56
53
57
public class Generator {
54
58
@@ -71,6 +75,7 @@ public class Generator {
71
75
private final FileSystemHelper fileSystemHelper ;
72
76
private final boolean suppressCallJSMethodExceptions ;
73
77
private final AndroidClassChecker androidClassChecker ;
78
+ private Set <String > nonPublicNestedClasses ;
74
79
75
80
public Generator (File outputDir , List <DataRow > libs ) throws IOException {
76
81
this (outputDir , libs , false , false );
@@ -80,7 +85,9 @@ public Generator(File outputDir, List<DataRow> libs, boolean suppressCallJSMetho
80
85
this .outputDir = outputDir ;
81
86
this .libs = libs ;
82
87
this .fileSystemHelper = new FileSystemHelperImpl (throwOnError );
83
- this .classes = readClasses (libs );
88
+ ClassesCollection classesCollection = readClasses (libs );
89
+ this .classes = classesCollection .getRegularClasses ();
90
+ this .nonPublicNestedClasses = classesCollection .getNonPublicNestedClasses ();
84
91
androidClassChecker = new AndroidClassCheckerImpl (classes );
85
92
this .suppressCallJSMethodExceptions = suppressCallJSMethodExceptions ;
86
93
}
@@ -122,6 +129,9 @@ public Binding[] generateBindings(String filename) throws IOException, ClassNotF
122
129
123
130
public Binding generateBinding (DataRow dataRow , HashSet <String > interfaceNames ) throws ClassNotFoundException {
124
131
JavaClass clazz = getClass (dataRow .getBaseClassname ());
132
+ if (!canClassBeExtended (clazz )) {
133
+ return null ;
134
+ }
125
135
126
136
boolean hasSpecifiedName = !dataRow .getFilename ().isEmpty ();
127
137
String packageName = hasSpecifiedName ? getBaseDir (dataRow .getFilename ()) : (DEFAULT_PACKAGE_NAME + "." + clazz .getPackageName ());
@@ -159,7 +169,6 @@ public Binding generateBinding(DataRow dataRow, HashSet<String> interfaceNames)
159
169
Writer w = new Writer ();
160
170
161
171
writeBinding (w , dataRow , clazz , packageName , name );
162
-
163
172
String classname = dataRow .getFilename ();
164
173
165
174
try {
@@ -168,8 +177,28 @@ public Binding generateBinding(DataRow dataRow, HashSet<String> interfaceNames)
168
177
} catch (FormatterException e ) {
169
178
return new Binding (new File (baseDir , normalizedName + JAVA_EXT ), w .toString (), classname );
170
179
}
180
+ }
181
+
182
+ private boolean canClassBeExtended (JavaClass javaClass ) {
183
+ if (javaClass .isInterface () && (javaClass .isProtected () || javaClass .isPublic ())) {
184
+ return true ;
185
+ }
171
186
187
+ if (javaClass .isFinal () || (!javaClass .isProtected () && !javaClass .isPublic ())) {
188
+ return false ;
189
+ }
172
190
191
+ nextMethod :
192
+ for (Method method : javaClass .getMethods ()) {
193
+ if (method .getName ().equals ("<init>" )
194
+ && !method .isStatic ()
195
+ && (method .isPublic () || method .isProtected ())) {
196
+
197
+ return true ;
198
+ }
199
+ }
200
+
201
+ return false ;
173
202
}
174
203
175
204
public Binding generateBinding (DataRow dataRow ) throws ClassNotFoundException {
@@ -223,17 +252,19 @@ private String getNormalizedName(String filename) {
223
252
return sb .toString ();
224
253
}
225
254
226
- private Map < String , JavaClass > readClasses (List <DataRow > libs ) {
255
+ private ClassesCollection readClasses (List <DataRow > libs ) {
227
256
Map <String , JavaClass > map = new HashMap <String , JavaClass >();
257
+ Set <String > nonPublicNestedClasses = new HashSet <>();
228
258
if (libs != null ) {
229
259
for (DataRow dr : libs ) {
230
260
String lib = dr .getRow ();
231
261
File f = new File (lib );
232
- Map <String , JavaClass > classes = f .isFile () ? fileSystemHelper .readClassesFromJar (lib ) : fileSystemHelper .readClassesFromDirectory (lib );
233
- map .putAll (classes );
262
+ ClassesCollection classes = f .isFile () ? fileSystemHelper .readClassesFromJar (lib ) : fileSystemHelper .readClassesFromDirectory (lib );
263
+ map .putAll (classes .getRegularClasses ());
264
+ nonPublicNestedClasses .addAll (classes .getNonPublicNestedClasses ());
234
265
}
235
266
}
236
- return map ;
267
+ return new ClassesCollection ( map , nonPublicNestedClasses ) ;
237
268
}
238
269
239
270
@@ -248,24 +279,48 @@ private String getSimpleClassname(String classname) {
248
279
}
249
280
250
281
private void writeBinding (Writer w , DataRow dataRow , JavaClass clazz , String packageName , String name ) {
282
+ GenericHierarchyView genView = new GenericsAwareClassHierarchyParserImpl (new GenericSignatureReader (), classes ).getClassHierarchy (clazz );
283
+
251
284
writePackageNameToWriter (w , packageName );
252
285
writeImportsToWriter (w , clazz , packageName );
253
- writeClassBeginningToWriter (w , clazz , dataRow .getInterfaces (), name , dataRow );
286
+ writeClassBeginningToWriter (w , clazz , dataRow .getInterfaces (), name , dataRow , genView );
254
287
writeFieldsToWriter (w , clazz );
255
-
256
- GenericHierarchyView genView = new GenericsAwareClassHierarchyParserImpl (new GenericSignatureReader (), classes ).getClassHierarchy (clazz );
257
288
writeConstructorsToWriter (w , clazz , dataRow , name , genView );
258
289
writeMethodsToWriter (w , genView , clazz , Arrays .asList (dataRow .getMethods ()), Arrays .asList (dataRow .getInterfaces ()), packageName );
259
290
writeClassEndToWriter (w );
260
291
}
261
292
262
- private void writeClassBeginningToWriter (Writer writer , JavaClass clazz , String [] implementedInterfacesNames , String generatedClassName , DataRow dataRow ) {
293
+ private void writeClassBeginningToWriter (Writer writer , JavaClass clazz , String [] implementedInterfacesNames , String generatedClassName , DataRow dataRow , GenericHierarchyView genericHierarchyView ) {
263
294
ClassWriter classWriter = new ClassWriterImpl (writer );
264
- String extendedClassName ;
265
- extendedClassName = BcelNamingUtil .resolveClassName (clazz .getClassName ());
295
+ StringBuilder extendedClassNameBuilder = new StringBuilder ();
296
+ extendedClassNameBuilder .append (BcelNamingUtil .resolveClassName (clazz .getClassName ()));
297
+
298
+ GenericParameters initialClassGenericParameters = genericHierarchyView .getInitialClassGenericParameters ();
299
+
300
+ if (initialClassGenericParameters != null ) {
301
+ Map <String , String > initialClassGenericParametersMap = initialClassGenericParameters .getGenericParameters ();
302
+ int initialClassGenericParametersMapCount = initialClassGenericParametersMap .size ();
303
+
304
+ if (initialClassGenericParametersMapCount > 0 ) {
305
+ extendedClassNameBuilder .append ('<' );
306
+ int parameterCounter = 0 ;
307
+ for (Map .Entry <String , String > genericParameter : initialClassGenericParametersMap .entrySet ()) {
308
+ String resolvedGeneriParameterValue = BcelNamingUtil .resolveClassName (genericParameter .getValue ());
309
+ extendedClassNameBuilder .append (resolvedGeneriParameterValue );
310
+
311
+ if (parameterCounter != initialClassGenericParametersMapCount - 1 ) {
312
+ extendedClassNameBuilder .append (", " );
313
+ parameterCounter += 1 ;
314
+ }
315
+ }
316
+ extendedClassNameBuilder .append ('>' );
317
+ }
318
+
319
+ }
266
320
267
321
boolean hasCustomJsName = !dataRow .getFilename ().isEmpty ();
268
322
323
+ String extendedClassName = extendedClassNameBuilder .toString ();
269
324
if (hasCustomJsName ) {
270
325
if (clazz .isInterface ()) { // extending an interface
271
326
classWriter .writeBeginningOfNamedClassImplementingSingleInterface (generatedClassName , dataRow .getJsFilename (), extendedClassName );
@@ -358,14 +413,15 @@ private void writeMethodsToWriter(Writer writer, GenericHierarchyView genericHie
358
413
for (ReifiedJavaMethod overridableMethod : inheritedMethodsView .getOverridableImplementedMethods ()) {
359
414
for (String userImplementedMethodName : userImplementedMethods ) {
360
415
if (overridableMethod .getName ().equals (userImplementedMethodName )) {
361
- writer .writeln ();
362
- writer .writeln ();
363
- methodsWriter .writeMethod (overridableMethod );
416
+ if (areAllArgumentsAndReturnTypePublic (overridableMethod )) {
417
+ writer .writeln ();
418
+ writer .writeln ();
419
+ methodsWriter .writeMethod (overridableMethod );
420
+ }
364
421
}
365
422
}
366
423
}
367
424
368
-
369
425
if (isApplicationClass ) {
370
426
String normalizedClassName = BcelNamingUtil .resolveClassName (clazz .getClassName ());
371
427
methodsWriter .writeGetInstanceMethod (normalizedClassName );
@@ -377,6 +433,36 @@ private void writeMethodsToWriter(Writer writer, GenericHierarchyView genericHie
377
433
}
378
434
}
379
435
436
+ private boolean areAllArgumentsAndReturnTypePublic (ReifiedJavaMethod method ) {
437
+ String returnType = BcelNamingUtil .resolveClassName (method .getReifiedReturnType ());
438
+ if (nonPublicNestedClasses .contains (returnType )) {
439
+ return false ;
440
+ }
441
+
442
+ JavaClass returnTypeClass = classes .get (returnType );
443
+ if (returnTypeClass != null && (!returnTypeClass .isPublic () && !returnTypeClass .isProtected ())) {
444
+ return false ;
445
+ }
446
+
447
+ List <String > argumentTypes = method .getReifiedArguments ();
448
+ for (String argumentType : argumentTypes ) {
449
+ argumentType = argumentType .trim ();
450
+ int indexOfSpace = argumentType .indexOf (' ' );
451
+ String withoutParamName = argumentType .substring (0 , indexOfSpace );
452
+ String resolvedName = BcelNamingUtil .resolveClassName (withoutParamName );
453
+ if (nonPublicNestedClasses .contains (resolvedName )) {
454
+ return false ;
455
+ }
456
+
457
+ JavaClass argumentTypeClass = classes .get (resolvedName );
458
+ if (argumentTypeClass != null && (!argumentTypeClass .isPublic () && !argumentTypeClass .isProtected ())) {
459
+ return false ;
460
+ }
461
+ }
462
+
463
+ return true ;
464
+ }
465
+
380
466
private List <JavaClass > getInterfacesFromCache (List <String > interfacesNames ) {
381
467
List <JavaClass > interfaces = new ArrayList <>(interfacesNames .size ());
382
468
0 commit comments