5858import org .eclipse .jdt .core .dom .TypeLiteral ;
5959import org .eclipse .jdt .core .dom .VariableDeclarationFragment ;
6060
61- // TODO: resource loading
61+ // TODO: resource loading using ResourceBundle.getBundle throws error when looking for format java.class
62+ // TODO: need real Class object Foo.class, not just Foo itself -- see Test_Class.java
6263
64+ // BH 8/30/2017 -- all i/o working, including printf and FileOutputStream
6365// BH 8/19/2017 -- String must implement CharSequence, so all .length() -> .length$()
6466// BH 8/19/2017 -- varargs logic fixed for missing argument
6567// BH 8/18/2017 -- array instanceof, reflection, componentType fixes
@@ -213,47 +215,59 @@ public boolean visit(AnonymousClassDeclaration node) {
213215
214216 ITypeBinding binding = node .resolveBinding ();
215217 ASTTypeVisitor typeVisitor = ((ASTTypeVisitor ) getAdaptable (ASTTypeVisitor .class ));
216- String anonClassName = getNameForBinding (binding );
217- String fullClassName = anonClassName ;
218- String shortClassName = anonClassName .substring (anonClassName . lastIndexOf ( '.' ) + 1 );
218+ String fullClassName = getNameForBinding (binding );
219+ int idx = fullClassName . lastIndexOf ( '.' ) ;
220+ String shortClassName = fullClassName .substring (idx + 1 );
219221 String className = typeVisitor .getClassName ();
222+ buffer .append ("(" );
223+
220224 // BH: add the anonymous class definition inline, not as a static,
221225 // and not requiring finalization of variables
222- buffer .append ("(" );
223226 addAnonymousFunctionWrapper (true );
224- buffer .append ("var C$ = Clazz.decorateAsClass (function () {\r \n " );
225- buffer .append ("Clazz.newInstance$ (this, arguments" );
226- if (!(node .getParent () instanceof EnumConstantDeclaration ))
227- buffer .append ("[0], true" );
228- buffer .append (");\r \n }, " );
229227
230- int idx = fullClassName .lastIndexOf ('.' );
231- if (idx >= 0 ) {
232- buffer .append (assureQualifiedName (shortenPackageName (fullClassName )));
228+ // add decorateAsClass
229+ buffer .append ("var C$ = Clazz.decorateAsClass (" );
230+ {
231+ // arg1 is the class definition function, C$, which is called in Clazz.$new().
232+ buffer .append ("function () {\r \n " );
233+ {
234+ // add the appropriate newInstance$ call
235+ buffer .append ("Clazz.newInstance$ (this, arguments" );
236+ if (!(node .getParent () instanceof EnumConstantDeclaration ))
237+ buffer .append ("[0], true" );
238+ buffer .append (");\r \n }, " );
239+ }
240+
241+ // arg2 is the package name or null
242+ buffer .append (idx >= 0 ? assureQualifiedName (shortenPackageName (fullClassName )) : "null" );
243+
244+ // arg3 is the full class name in quotes
233245 buffer .append (", \" " + fullClassName .substring (idx + 1 ) + "\" " );
234- } else {
235- buffer .append ("null, \" " + fullClassName + "\" " );
236- }
237246
238- ITypeBinding superclass = binding .getSuperclass ();
239- if (superclass != null ) {
240- String superclassName = superclass .getQualifiedName ();
241- superclassName = assureQualifiedName (removeJavaLang (superclassName ));
242- if (superclassName != null && superclassName .length () != 0 && !"Object" .equals (superclassName )) {
243- buffer .append (", " );
244- buffer .append (superclassName );
245- } else {
246- ITypeBinding [] declaredTypes = binding .getInterfaces ();
247- if (declaredTypes != null && declaredTypes .length > 0 ) {
248- superclassName = declaredTypes [0 ].getQualifiedName ();
249- if (superclassName != null && superclassName .length () > 0 ) {
250- superclassName = assureQualifiedName (removeJavaLang (superclassName ));
251- buffer .append (", null, " );
252- buffer .append (superclassName );
247+ // arg4 is the superclass
248+ // arg5 is the superinterface
249+ // (only one or the other is ever non-null)
250+ if (binding .getSuperclass () != null ) {
251+ String superclassName = getSuperclassName (binding );
252+ if (superclassName != null ) {
253+ // superclass, not superinterface
254+ buffer .append (", " );
255+ buffer .append (superclassName );
256+ } else {
257+ // no superclass other than Object -- look for
258+ // superInterface
259+ ITypeBinding [] declaredTypes = binding .getInterfaces ();
260+ if (declaredTypes != null && declaredTypes .length > 0 ) {
261+ String superinterfaceName = declaredTypes [0 ].getQualifiedName ();
262+ if (superinterfaceName != null && superinterfaceName .length () > 0 ) {
263+ buffer .append (", null, " );
264+ buffer .append (assureQualifiedName (removeJavaLang (superinterfaceName )));
265+ }
253266 }
254267 }
255268 }
256269 }
270+ // close decorateAsClass
257271 buffer .append (");\r \n " );
258272
259273 String oldClassName = className ;
@@ -271,8 +285,6 @@ public boolean visit(AnonymousClassDeclaration node) {
271285 }
272286 }
273287
274- // addDefaultConstructor();
275-
276288 for (Iterator <?> iter = bodyDeclarations .iterator (); iter .hasNext ();) {
277289 BodyDeclaration element = (BodyDeclaration ) iter .next ();
278290 if (element instanceof FieldDeclaration && isStatic (element .getModifiers ()))
@@ -281,9 +293,9 @@ public boolean visit(AnonymousClassDeclaration node) {
281293
282294 typeVisitor .setClassName (oldClassName );
283295 buffer .append (staticFieldDefBuffer );
284-
285296 staticFieldDefBuffer = oldStaticDefBuffer ;
286297
298+ // close the anonymous function wrapper
287299 addAnonymousFunctionWrapper (false );
288300 buffer .append (")" );
289301
@@ -1187,8 +1199,8 @@ public boolean visit(MethodDeclaration node) {
11871199 // as it is too risky to do this -- lose all initialization.
11881200 @ SuppressWarnings ("unchecked" )
11891201 List <ASTNode > statements = node .getBody ().statements ();
1190- ASTNode firstStatement = statements . get ( 0 ) ;
1191- if (statements .size () == 0 || !(firstStatement instanceof SuperConstructorInvocation )
1202+ ASTNode firstStatement ;
1203+ if (statements .size () == 0 || !(( firstStatement = statements . get ( 0 )) instanceof SuperConstructorInvocation )
11921204 && !(firstStatement instanceof ConstructorInvocation )) {
11931205 buffer .append ("{\r \n " );
11941206 IMethodBinding binding = node .resolveBinding ();
@@ -1844,7 +1856,10 @@ public boolean visit(SuperFieldAccess node) {
18441856 public boolean visit (SuperMethodInvocation node ) {
18451857 IMethodBinding mBinding = node .resolveMethodBinding ();
18461858 String name = getJ2SName (node .getName ()) + getJ2SParamQualifier (null , mBinding );
1847- buffer .append ("C$.superClazz.prototype." ).append (name ).append (".apply(this, arguments)" );
1859+ // BH if this is a call to super.clone() and there is no superclass, or the superclass is Object,
1860+ // then we need to invoke Clazz.clone(this) directly instead of calling C$.superClazz.clone()
1861+ buffer .append ("clone" .equals (name ) && getSuperclassName (mBinding .getDeclaringClass ()) == null
1862+ ? "Clazz.clone(this)" : "C$.superClazz.prototype." + name + ".apply(this, arguments)" );
18481863 return false ;
18491864 }
18501865
@@ -2009,21 +2024,8 @@ public void endVisit(TypeDeclaration node) {
20092024
20102025 Type superClassType = null ;
20112026 if (!isInterface ) {
2012- // add superclass name
2027+ buffer . append ( ", " ). append ( "" + getSuperclassName ( node . resolveBinding ()));
20132028 superClassType = node .getSuperclassType ();
2014- String superClassName = "null" ;
2015- ITypeBinding typeBinding = node .resolveBinding ();
2016- if (typeBinding != null ) {
2017- ITypeBinding superclass = typeBinding .getSuperclass ();
2018- if (superclass != null ) {
2019- String clazzName = superclass .getQualifiedName ();
2020- clazzName = assureQualifiedName (removeJavaLang (clazzName ));
2021- if (clazzName != null && clazzName .length () != 0 && !"Object" .equals (clazzName )) {
2022- superClassName = clazzName ;
2023- }
2024- }
2025- }
2026- buffer .append (", " ).append (superClassName );
20272029 }
20282030 // Add superinterfaces
20292031 buffer .append (", " );
@@ -2244,6 +2246,25 @@ public void endVisit(TypeDeclaration node) {
22442246 super .endVisit (node );
22452247 }
22462248
2249+ /**
2250+ * return the superclass name, provided it is not Object or ""
2251+ *
2252+ * @param typeBinding
2253+ * @return superclass name or null
2254+ */
2255+ private String getSuperclassName (ITypeBinding typeBinding ) {
2256+ if (typeBinding != null ) {
2257+ ITypeBinding superclass = typeBinding .getSuperclass ();
2258+ if (superclass != null ) {
2259+ String clazzName = superclass .getQualifiedName ();
2260+ clazzName = assureQualifiedName (removeJavaLang (clazzName ));
2261+ if (clazzName != null && clazzName .length () != 0 && !"Object" .equals (clazzName ))
2262+ return clazzName ;
2263+ }
2264+ }
2265+ return null ;
2266+ }
2267+
22472268 private void appendDefaultValue (Type type ) {
22482269 if (type .isPrimitiveType ()) {
22492270 PrimitiveType pType = (PrimitiveType ) type ;
0 commit comments