33import com .google .googlejavaformat .java .Formatter ;
44import com .google .googlejavaformat .java .FormatterException ;
55
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-
236import org .apache .bcel .classfile .JavaClass ;
247import org .apache .bcel .classfile .Method ;
8+ import org .apache .commons .io .FileUtils ;
259import org .nativescript .staticbindinggenerator .files .FileSystemHelper ;
10+ import org .nativescript .staticbindinggenerator .files .impl .ClassesCollection ;
2611import 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 ;
2716import org .nativescript .staticbindinggenerator .generating .parsing .classes .hierarchy .generics .GenericHierarchyView ;
17+ import org .nativescript .staticbindinggenerator .generating .parsing .classes .hierarchy .generics .GenericParameters ;
2818import org .nativescript .staticbindinggenerator .generating .parsing .classes .hierarchy .generics .impl .GenericSignatureReader ;
2919import org .nativescript .staticbindinggenerator .generating .parsing .classes .hierarchy .generics .impl .GenericsAwareClassHierarchyParserImpl ;
3020import org .nativescript .staticbindinggenerator .generating .parsing .methods .InheritedMethodsCollector ;
4535import org .nativescript .staticbindinggenerator .generating .writing .impl .MethodsWriterImpl ;
4636import org .nativescript .staticbindinggenerator .generating .writing .impl .PackageNameWriterImpl ;
4737import 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 ;
5256
5357public class Generator {
5458
@@ -71,6 +75,7 @@ public class Generator {
7175 private final FileSystemHelper fileSystemHelper ;
7276 private final boolean suppressCallJSMethodExceptions ;
7377 private final AndroidClassChecker androidClassChecker ;
78+ private Set <String > nonPublicNestedClasses ;
7479
7580 public Generator (File outputDir , List <DataRow > libs ) throws IOException {
7681 this (outputDir , libs , false , false );
@@ -80,7 +85,9 @@ public Generator(File outputDir, List<DataRow> libs, boolean suppressCallJSMetho
8085 this .outputDir = outputDir ;
8186 this .libs = libs ;
8287 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 ();
8491 androidClassChecker = new AndroidClassCheckerImpl (classes );
8592 this .suppressCallJSMethodExceptions = suppressCallJSMethodExceptions ;
8693 }
@@ -122,6 +129,9 @@ public Binding[] generateBindings(String filename) throws IOException, ClassNotF
122129
123130 public Binding generateBinding (DataRow dataRow , HashSet <String > interfaceNames ) throws ClassNotFoundException {
124131 JavaClass clazz = getClass (dataRow .getBaseClassname ());
132+ if (!canClassBeExtended (clazz )) {
133+ return null ;
134+ }
125135
126136 boolean hasSpecifiedName = !dataRow .getFilename ().isEmpty ();
127137 String packageName = hasSpecifiedName ? getBaseDir (dataRow .getFilename ()) : (DEFAULT_PACKAGE_NAME + "." + clazz .getPackageName ());
@@ -159,7 +169,6 @@ public Binding generateBinding(DataRow dataRow, HashSet<String> interfaceNames)
159169 Writer w = new Writer ();
160170
161171 writeBinding (w , dataRow , clazz , packageName , name );
162-
163172 String classname = dataRow .getFilename ();
164173
165174 try {
@@ -168,8 +177,28 @@ public Binding generateBinding(DataRow dataRow, HashSet<String> interfaceNames)
168177 } catch (FormatterException e ) {
169178 return new Binding (new File (baseDir , normalizedName + JAVA_EXT ), w .toString (), classname );
170179 }
180+ }
181+
182+ private boolean canClassBeExtended (JavaClass javaClass ) {
183+ if (javaClass .isInterface () && (javaClass .isProtected () || javaClass .isPublic ())) {
184+ return true ;
185+ }
171186
187+ if (javaClass .isFinal () || (!javaClass .isProtected () && !javaClass .isPublic ())) {
188+ return false ;
189+ }
172190
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 ;
173202 }
174203
175204 public Binding generateBinding (DataRow dataRow ) throws ClassNotFoundException {
@@ -223,17 +252,19 @@ private String getNormalizedName(String filename) {
223252 return sb .toString ();
224253 }
225254
226- private Map < String , JavaClass > readClasses (List <DataRow > libs ) {
255+ private ClassesCollection readClasses (List <DataRow > libs ) {
227256 Map <String , JavaClass > map = new HashMap <String , JavaClass >();
257+ Set <String > nonPublicNestedClasses = new HashSet <>();
228258 if (libs != null ) {
229259 for (DataRow dr : libs ) {
230260 String lib = dr .getRow ();
231261 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 ());
234265 }
235266 }
236- return map ;
267+ return new ClassesCollection ( map , nonPublicNestedClasses ) ;
237268 }
238269
239270
@@ -248,24 +279,48 @@ private String getSimpleClassname(String classname) {
248279 }
249280
250281 private void writeBinding (Writer w , DataRow dataRow , JavaClass clazz , String packageName , String name ) {
282+ GenericHierarchyView genView = new GenericsAwareClassHierarchyParserImpl (new GenericSignatureReader (), classes ).getClassHierarchy (clazz );
283+
251284 writePackageNameToWriter (w , packageName );
252285 writeImportsToWriter (w , clazz , packageName );
253- writeClassBeginningToWriter (w , clazz , dataRow .getInterfaces (), name , dataRow );
286+ writeClassBeginningToWriter (w , clazz , dataRow .getInterfaces (), name , dataRow , genView );
254287 writeFieldsToWriter (w , clazz );
255-
256- GenericHierarchyView genView = new GenericsAwareClassHierarchyParserImpl (new GenericSignatureReader (), classes ).getClassHierarchy (clazz );
257288 writeConstructorsToWriter (w , clazz , dataRow , name , genView );
258289 writeMethodsToWriter (w , genView , clazz , Arrays .asList (dataRow .getMethods ()), Arrays .asList (dataRow .getInterfaces ()), packageName );
259290 writeClassEndToWriter (w );
260291 }
261292
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 ) {
263294 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+ }
266320
267321 boolean hasCustomJsName = !dataRow .getFilename ().isEmpty ();
268322
323+ String extendedClassName = extendedClassNameBuilder .toString ();
269324 if (hasCustomJsName ) {
270325 if (clazz .isInterface ()) { // extending an interface
271326 classWriter .writeBeginningOfNamedClassImplementingSingleInterface (generatedClassName , dataRow .getJsFilename (), extendedClassName );
@@ -358,14 +413,15 @@ private void writeMethodsToWriter(Writer writer, GenericHierarchyView genericHie
358413 for (ReifiedJavaMethod overridableMethod : inheritedMethodsView .getOverridableImplementedMethods ()) {
359414 for (String userImplementedMethodName : userImplementedMethods ) {
360415 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+ }
364421 }
365422 }
366423 }
367424
368-
369425 if (isApplicationClass ) {
370426 String normalizedClassName = BcelNamingUtil .resolveClassName (clazz .getClassName ());
371427 methodsWriter .writeGetInstanceMethod (normalizedClassName );
@@ -377,6 +433,36 @@ private void writeMethodsToWriter(Writer writer, GenericHierarchyView genericHie
377433 }
378434 }
379435
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+
380466 private List <JavaClass > getInterfacesFromCache (List <String > interfacesNames ) {
381467 List <JavaClass > interfaces = new ArrayList <>(interfacesNames .size ());
382468
0 commit comments