99import java .io .PrintStream ;
1010import java .util .ArrayDeque ;
1111import java .util .ArrayList ;
12+ import java .util .Arrays ;
1213import java .util .HashMap ;
1314import java .util .HashSet ;
1415import java .util .List ;
@@ -141,6 +142,9 @@ private Binding[] processRows(List<DataRow> rows) throws IOException {
141142 String classname = dataRow .getBaseClassname ();
142143 boolean isJavaExtend = classes .containsKey (classname );
143144 if (isJavaExtend ) {
145+
146+ // System.out.println("SBG: DataRow: baseClassName: " + classname + ", suffix: " + dataRow.getSuffix() + ", interfaces: " + String.join(", ", Arrays.asList(dataRow.getInterfaces())) + ", jsFileName: " + dataRow.getJsFilename());
147+
144148 Binding binding = generateBinding (dataRow , interfaceNames );
145149
146150 if (binding != null ) {
@@ -187,42 +191,56 @@ private String getNormalizedName(String filename) {
187191 private Map <String , List <Method >> getPublicApi (JavaClass clazz ) {
188192 Map <String , List <Method >> api = new HashMap <String , List <Method >>();
189193 JavaClass currentClass = clazz ;
194+ String clazzName = clazz .getClassName ();
190195 while (true ) {
191196 String currentClassname = currentClass .getClassName ();
192- List <Method > methods = new ArrayList <Method >();
193- for (Method m : currentClass .getMethods ()) {
194- methods .add (m );
195- }
196- collectInterfaceMethods (clazz , methods );
197- for (Method m : methods ) {
198- if (!m .isSynthetic () && (m .isPublic () || m .isProtected ()) && !m .isStatic ()) {
199- String name = m .getName ();
200-
201- List <Method > methodGroup ;
202- if (api .containsKey (name )) {
203- methodGroup = api .get (name );
204- } else {
205- methodGroup = new ArrayList <Method >();
206- api .put (name , methodGroup );
207- }
208- boolean found = false ;
209- String methodSig = m .getSignature ();
210- for (Method m1 : methodGroup ) {
211- found = methodSig .equals (m1 .getSignature ());
212- if (found ) {
213- break ;
197+
198+ boolean shouldCollectMethods = !(!clazzName .equals (currentClassname ) && currentClass .isAbstract ());
199+
200+ if (shouldCollectMethods || currentClass .isInterface ()) {
201+ // Don't include abstract parent class's methods to avoid compilation issues
202+ // where a child class has 2 methods, of the same type, with just a
203+ // return type/parameter type that differs by being of a superclass of the class being extended.
204+ // see Test testCanCompileBindingClassExtendingAnExtendedClassWithMethodsWithTheSameSignature
205+ List <Method > methods = new ArrayList <Method >();
206+ for (Method m : currentClass .getMethods ()) {
207+ methods .add (m );
208+ }
209+
210+ // System.out.println("SBG: getPublicApi:collectInterfaceMethods classname: " + currentClassname);
211+
212+ collectInterfaceMethods (clazz , methods );
213+ for (Method m : methods ) {
214+ if (!m .isSynthetic () && (m .isPublic () || m .isProtected ()) && !m .isStatic ()) {
215+ String name = m .getName ();
216+
217+ List <Method > methodGroup ;
218+ if (api .containsKey (name )) {
219+ methodGroup = api .get (name );
220+ } else {
221+ methodGroup = new ArrayList <Method >();
222+ api .put (name , methodGroup );
223+ }
224+ boolean found = false ;
225+ String methodSig = m .getSignature ();
226+ for (Method m1 : methodGroup ) {
227+ found = methodSig .equals (m1 .getSignature ());
228+ if (found ) {
229+ break ;
230+ }
231+ }
232+ if (!found ) {
233+ methodGroup .add (m );
214234 }
215- }
216- if (!found ) {
217- methodGroup .add (m );
218235 }
219236 }
220237 }
221238
222239 if (currentClassname .equals ("java.lang.Object" )) {
223240 break ;
224241 } else {
225- currentClass = classes .get (currentClass .getSuperclassName ());
242+ String superClassName = currentClass .getSuperclassName ();
243+ currentClass = classes .get (superClassName .replace ('$' , '.' ));
226244 }
227245 }
228246 return api ;
@@ -640,6 +658,7 @@ private void writeType(Type t, Writer w) {
640658
641659 private void collectInterfaceMethods (JavaClass clazz , List <Method > methods ) {
642660 JavaClass currentClass = clazz ;
661+
643662 while (true ) {
644663 String currentClassname = currentClass .getClassName ();
645664
@@ -663,7 +682,8 @@ private void collectInterfaceMethods(JavaClass clazz, List<Method> methods) {
663682 if (currentClassname .equals ("java.lang.Object" )) {
664683 break ;
665684 } else {
666- currentClass = classes .get (currentClass .getSuperclassName ());
685+ String superClassName = currentClass .getSuperclassName ();
686+ currentClass = classes .get (superClassName .replace ('$' , '.' ));
667687 }
668688 }
669689 }
@@ -686,7 +706,8 @@ private boolean isApplicationClass(JavaClass clazz, Map<String, JavaClass> class
686706 break ;
687707 }
688708
689- currentClass = classes .get (currentClass .getSuperclassName ());
709+ String superClassName = currentClass .getSuperclassName ();
710+ currentClass = classes .get (superClassName .replace ('$' , '.' ));
690711 }
691712
692713 return isApplicationClass ;
0 commit comments