001    /*BEGIN_COPYRIGHT_BLOCK
002     * Copyright (c) 2001-2010, JavaPLT group at Rice University (drjava@rice.edu). All rights reserved. 
003     * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the 
004     * following conditions are met:
005     *    * Redistributions of source code must retain the above copyright notice, this list of conditions and the following
006     *      disclaimer.
007     *    * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the 
008     *      following disclaimer in the documentation and/or other materials provided with the distribution.
009     *    * Neither the names of DrJava, the JavaPLT group, Rice University, nor the names of its contributors may be used 
010     *      to endorse or promote products derived from this software without specific prior written permission.
011     * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
012     * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
013     * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
014     * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
015     * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
016     * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
017     * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
018     * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
019     * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
020     * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
021     * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
022     *
023     * This software is Open Source Initiative approved Open Source Software.
024     * Open Source Initative Approved is a trademark of the Open Source Initiative.
025     * 
026     * This file is part of DrJava.  Download the current version of this project
027     * from http://www.drjava.org/ or http://sourceforge.net/projects/drjava/
028     * 
029     * END_COPYRIGHT_BLOCK*/
030    
031    package edu.rice.cs.javalanglevels;
032    
033    import edu.rice.cs.javalanglevels.tree.*;
034    import edu.rice.cs.javalanglevels.parser.*;
035    import edu.rice.cs.javalanglevels.util.Utilities;
036    
037    import edu.rice.cs.plt.reflect.JavaVersion;
038    import edu.rice.cs.plt.iter.IterUtil;
039    import java.util.*;
040    import java.io.*;
041    
042    import junit.framework.TestCase;
043    
044    /** Language Level Visitor class that implements the FullJava Language Level.  Enforces constraints during the first 
045      * walk of the AST (checking for langauge specific errors and building the symbol table).  This class enforces some
046      * constraints imposed on an interface body at the FullJava Language Level. 
047      */
048    public class InterfaceBodyFullJavaVisitor extends FullJavaVisitor {
049      
050      /**The SymbolData corresponding to this interface, which encloses the body of the interface. */
051      private SymbolData _enclosing;
052      
053      /** Old constructor for InterfaceBodyFullJavaVisitor.
054        * @param sd             The SymbolData that encloses the context we are visiting.
055        * @param file           The source file this came from.
056        * @param packageName    The package the source file is in
057        * @importedFiles        A list of classes that were specifically imported
058        * @param importedPackages   A list of package names that were specifically imported
059        * @param classesInThisFile  A list of the classes that are yet to be defined in this source file
060        * @param continuations  A hashtable corresponding to the continuations (unresolved Symbol Datas) that will need to 
061        *                       be resolved
062        */
063      public InterfaceBodyFullJavaVisitor(SymbolData sd, 
064                                          File file, 
065                                          String packageName,
066                                          LinkedList<String> importedFiles, 
067                                          LinkedList<String> importedPackages, 
068                                          HashSet<String> classesInThisFile,
069                                          Hashtable<String, Triple<SourceInfo, LanguageLevelVisitor, SymbolData>> continuations,
070                                          LinkedList<Command> fixUps) {
071        super(file, packageName, sd.getName(), importedFiles, importedPackages, classesInThisFile, continuations, fixUps);
072        _enclosing = sd;
073    //    if (_enclosingClassName != sd.getName()) Utilities.show("enclosingClassName does not equal sd.getName(). Trace follows.\n" +
074    //                                                            Utilities.getStackTrace());
075      }
076      
077      /** Preferred constructor for InterfaceBodyFullJavaVisitor.
078        * @param sd             The SymbolData that encloses the context we are visiting.
079        * @param file           The source file this came from.
080        * @param packageName    The package the source file is in
081        * @importedFiles        A list of classes that were specifically imported
082        * @param importedPackages   A list of package names that were specifically imported
083        * @param classesInThisFile  A list of the classes that are yet to be defined in this source file
084        * @param continuations  A hashtable corresponding to the continuations (unresolved Symbol Datas) that will need to 
085        *                       be resolved
086        * @param genericTypes   A HashMap mapping in scope generic type names to their bounds (SymbolDatas).
087        */
088      public InterfaceBodyFullJavaVisitor(SymbolData sd, 
089                                          File file, 
090                                          String packageName,
091                                          LinkedList<String> importedFiles, 
092                                          LinkedList<String> importedPackages, 
093                                          HashSet<String> classesInThisFile,
094                                          Hashtable<String, Triple<SourceInfo, LanguageLevelVisitor, SymbolData>> continuations,
095                                          LinkedList<Command> fixUps,
096                                          HashMap<String, SymbolData> genericTypes) {
097        super(file, packageName, sd.getName(), importedFiles, importedPackages, classesInThisFile, continuations, fixUps,
098              genericTypes);
099        _enclosing = sd;
100    //    if (_enclosingClassName != sd.getName()) Utilities.show("enclosingClassName does not equal sd.getName(). Trace follows.\n" +
101    //                                                            Utilities.getStackTrace());
102      }
103      
104      /** Ignore Statement. */
105      public Void forStatementDoFirst(Statement that) { return null; }
106      
107      /*Throw an appropriate error*/
108      public Void forConcreteMethodDefDoFirst(ConcreteMethodDef that) {
109        _addError("You cannot have concrete methods definitions in interfaces", that);
110        return null;
111      }
112    
113      
114      /**Throw an appropriate error*/
115      public Void forInstanceInitializerDoFirst(InstanceInitializer that) {
116        _addError("This open brace must mark the beginning of an interface body", that);
117        return null;
118      }
119      
120      /** Ignore VariableDeclaration. */
121      public Void forVariableDeclarationOnly(VariableDeclaration that) { return null; }
122    
123      /**No This literal in interfaces--give an appropriate error*/
124      public Void forThisReferenceDoFirst(ThisReference that) {
125        _addAndIgnoreError("The field 'this' does not exist in interfaces.  Only classes have a 'this' field.", that);
126        return null;
127      }
128    
129      /** No super references for interfaces--give an appropriate error.*/
130      public Void forSuperReferenceDoFirst(SuperReference that) {
131        _addAndIgnoreError("The field 'super' does not exist in interfaces.  Only classes have a 'super' field", that);
132        return null;
133      }
134      
135      public Void forAbstractMethodDef(AbstractMethodDef that) {
136        forAbstractMethodDefDoFirst(that);
137        if (_checkError()) return null;
138        
139        assert _enclosing != null;
140        
141          // Process type parameters
142        TypeParameter[] tps = that.getTypeParams();
143    
144        // TODO !!! pass genericTypes as a parameter to createMethod and critical submethods.  The scope of the
145        // new generic types table includes all of createMethodData processing, notably processing the return type.
146        // Passing an extended generic types table to BodyBodyFullJavaVisitor is insufficient
147          
148        // Save a snapshot of _genericTypes
149        HashMap<String, SymbolData> oldGenericTypes = _genericTypes;
150        
151        // Rebind _genericTypes to a shallow copy of itself for use in processing this method. The temporary variable copy
152        // gets around a bug in javac in processing the SuppressWarnings statement.
153        @SuppressWarnings("unchecked")
154        HashMap<String, SymbolData> copy = (HashMap<String, SymbolData>)_genericTypes.clone();
155        _genericTypes = copy;
156        
157        if (tps != null) {  // extend genericTypes by new type variable bindings
158          for (TypeParameter tp: tps) {
159            final String typeName = tp.getVariable().getName();
160            final String boundName = tp.getBound().getName();
161            SymbolData boundSD = _identifyType(boundName, that.getSourceInfo(), _enclosingClassName);
162            if (boundSD == null) { // create a dummy SymbolData 
163              boundSD = symbolTable.get("java.lang.Object"); //  TODO: could create a separate unbound type variable singleton class?
164    //        System.err.println("Creating dummy SymbolData for bounding type " + typeName + " in inner class " + name);
165              // TODO!  !!!!! Create an appropriate fixUp mechanism
166            }
167    //        System.err.println("In method " + _enclosing + "." + that.getName().getText() + ", type " + typeName 
168    //                             + " is bound to " + boundSD);
169            _genericTypes.put(typeName, boundSD);
170          }
171        }
172        
173        MethodData md = createMethodData(that, _enclosing);
174        
175        //All interface methods are considered public by default: enforce this.
176        if (md.hasModifier("private")) {
177          _addAndIgnoreError("Interface methods cannot be private.  They must be public.", that.getMav());
178        }
179        if (md.hasModifier("protected")) {
180          _addAndIgnoreError("Interface methods cannot be protected.  They must be public.", that.getMav());
181        }
182        
183        // All interface methods are considered public by default.
184        md.addModifier("public");
185        md.addModifier("abstract"); // and all interface methods are abstract. 
186        String className = getUnqualifiedClassName(_enclosing.getName());
187        if (className.equals(md.getName())) {
188          _addAndIgnoreError("Only constructors can have the same name as the class they appear in, " + 
189                             "and constructors cannot appear in interfaces.", that);
190        }
191        else _enclosing.addMethod(md);
192    
193        _genericTypes = oldGenericTypes;
194        return null;
195      }
196      
197      /** Call the method in FullJavaVisitor since it's common to this ClassBodyFullJavaVisitor. */
198      public Void forInnerInterfaceDef(InnerInterfaceDef that) {
199        String relName = that.getName().getText();
200        handleInnerInterfaceDef(that, _enclosing, relName, getQualifiedClassName(_enclosing.getName()) + '.' + relName);
201        return null;
202      }
203      
204      /**Call the method in FullJavaVisitor; it's common to this ClassBodyAdvancedVisitor.*/
205      public Void forInnerClassDef(InnerClassDef that) {
206        String relName = that.getName().getText();
207        handleInnerClassDef(that, _enclosing, relName, getQualifiedClassName(_enclosing.getName()) + '.' + relName);
208        return null;
209      }
210      
211      /** Throw an error: Interfaces cannot have constructors */
212      public Void forConstructorDefDoFirst(ConstructorDef that) {
213        _addAndIgnoreError("Constructor definitions cannot appear in interfaces", that);
214        return null;
215      }
216      
217      /** Processes a static field declaration within an interface. Calls the super method to convert the VariableDeclaration
218        * to a VariableData array, then makes sure that each VariableData is final and static, as required in an
219        * interface.
220        * @param enclosingData  The Data immediately enclosing the variables
221        */
222      protected VariableData[] _variableDeclaration2VariableData(VariableDeclaration vd, Data enclosingData) {
223        VariableData[] vds = super._variableDeclaration2VariableData(vd, enclosingData);
224        for (int i = 0; i < vds.length; i++) {
225          vds[i].setFinalAndStatic();
226        }
227        return vds;
228      }
229    
230      /** Delegate to method in LLV */
231      public Void forComplexAnonymousClassInstantiation(ComplexAnonymousClassInstantiation that) {
232        complexAnonymousClassInstantiationHelper(that, _enclosing);  // TODO: the wrong enclosing context?
233        return null;
234      }
235    
236      /** Delegate to method in LLV*/
237      public Void forSimpleAnonymousClassInstantiation(SimpleAnonymousClassInstantiation that) {
238    //    System.err.println("Calling simpleAnonymousClassInstantiation Helper from InterfaceBody " + that.getSourceInfo());
239        simpleAnonymousClassInstantiationHelper(that, _enclosing);
240        return null;
241      }
242    
243      /** Test the methods in the above class. */
244      public static class InterfaceBodyFullJavaVisitorTest extends TestCase {
245        
246        private InterfaceBodyFullJavaVisitor _ibfv;
247        
248        private SymbolData _sd1;
249        private SymbolData _objectSD;
250         
251        private ModifiersAndVisibility _publicMav = new ModifiersAndVisibility(SourceInfo.NONE, new String[] {"public"});
252        private ModifiersAndVisibility _protectedMav = new ModifiersAndVisibility(SourceInfo.NONE, new String[] {"protected"});
253        private ModifiersAndVisibility _privateMav = new ModifiersAndVisibility(SourceInfo.NONE, new String[] {"private"});
254        private ModifiersAndVisibility _packageMav = new ModifiersAndVisibility(SourceInfo.NONE, new String[0]);
255        private ModifiersAndVisibility _abstractMav = new ModifiersAndVisibility(SourceInfo.NONE, new String[] {"abstract"});
256        private ModifiersAndVisibility _finalMav = new ModifiersAndVisibility(SourceInfo.NONE, new String[] {"final"});
257        
258        public InterfaceBodyFullJavaVisitorTest() { this(""); }
259        public InterfaceBodyFullJavaVisitorTest(String name) { super(name);  }
260        
261        public void setUp() {
262          errors = new LinkedList<Pair<String, JExpressionIF>>();
263          LanguageLevelConverter.symbolTable.clear();
264          LanguageLevelConverter._newSDs.clear();
265          LanguageLevelConverter.OPT = new Options(JavaVersion.JAVA_5, IterUtil.make(new File("lib/buildlib/junit.jar")));
266          visitedFiles = new LinkedList<Pair<LanguageLevelVisitor, edu.rice.cs.javalanglevels.tree.SourceFile>>();   
267          
268                
269          _sd1 = new SymbolData("MyInterface");
270          _sd1.setIsContinuation(false);
271          _sd1.setInterface(true);
272          _sd1.setPackage("");
273          _sd1.setTypeParameters(new TypeParameter[0]);
274          _sd1.setInterfaces(new ArrayList<SymbolData>());
275          
276          // NOTE: the following ensures that the symbolTable includes essential types
277          _ibfv = new InterfaceBodyFullJavaVisitor(_sd1, 
278                                                   new File(""), 
279                                                   "", 
280                                                   new LinkedList<String>(), 
281                                                   new LinkedList<String>(), 
282                                                   new HashSet<String>(), 
283                                                   new Hashtable<String, Triple<SourceInfo, LanguageLevelVisitor, SymbolData>>(),
284                                                   new LinkedList<Command>());
285          _ibfv._classesInThisFile = new HashSet<String>();
286          _ibfv.continuations = new Hashtable<String, Triple<SourceInfo, LanguageLevelVisitor, SymbolData>>();
287          _ibfv._importedPackages.addFirst("java.lang");
288          _ibfv._enclosingClassName = "MyInterface";
289    
290          _objectSD = LanguageLevelConverter.symbolTable.get("java.lang.Object");
291          _sd1.setSuperClass(_objectSD);
292          
293          LanguageLevelConverter.symbolTable.put("MyInterface", _sd1);
294    
295          _errorAdded = false;
296        }
297        
298        public void testForConcreteMethodDefDoFirst() {
299          // Check that an error is thrown
300          ConcreteMethodDef cmd = new ConcreteMethodDef(SourceInfo.NONE, 
301                                                        _publicMav, 
302                                                        new TypeParameter[0], 
303                                                        new PrimitiveType(SourceInfo.NONE, "int"), 
304                                                        new Word(SourceInfo.NONE, "methodName"),
305                                                        new FormalParameter[0],
306                                                        new ReferenceType[0], 
307                                                        new BracedBody(SourceInfo.NONE, new BodyItemI[0]));
308          cmd.visit(_ibfv);
309          assertEquals("There should not be 1 error", 1, errors.size());
310          assertEquals("The error message should be correct", "You cannot have concrete methods definitions in interfaces", 
311                       errors.getLast().getFirst());
312          
313        }
314        
315        public void testForAbstractMethodDefDoFirst() {
316          // Check one that works
317          _ibfv._enclosing.setMav(_abstractMav);
318          AbstractMethodDef amd2 = new AbstractMethodDef(SourceInfo.NONE, 
319                                                         _abstractMav, 
320                                                         new TypeParameter[0], 
321                                                         new PrimitiveType(SourceInfo.NONE, "double"), 
322                                                         new Word(SourceInfo.NONE, "methodName"),
323                                                         new FormalParameter[0],
324                                                         new ReferenceType[0]);
325          amd2.visit(_ibfv);
326          assertEquals("There should be no errors", 0, errors.size());
327          assertTrue("The method def should be public", 
328                     _ibfv._enclosing.getMethods().get(0).hasModifier("public"));
329    
330        }
331    
332        public void testForInstanceInitializerDoFirst() {
333          InstanceInitializer ii = 
334            new InstanceInitializer(SourceInfo.NONE, 
335                                    new Block(SourceInfo.NONE, 
336                                              new BracedBody(SourceInfo.NONE, new BodyItemI[0])));
337          ii.visit(_ibfv);
338          assertEquals("There should be one error.", 1, errors.size());
339          assertEquals("The error message should be correct.", 
340                       "This open brace must mark the beginning of an interface body", 
341                       errors.get(0).getFirst());    
342        }
343    
344        public void testForSimpleThisReferenceDoFirst() {
345         SimpleThisReference tl = new SimpleThisReference(SourceInfo.NONE);
346         tl.visit(_ibfv);
347         assertEquals("There should be one error", 1, errors.size());
348         assertEquals("The error message should be correct", 
349                      "The field 'this' does not exist in interfaces.  Only classes have a 'this' field.", 
350                      errors.get(0).getFirst());
351        }
352        
353        public void testForComplexThisReferenceDoFirst() {
354         ComplexThisReference tl = new ComplexThisReference(SourceInfo.NONE, 
355                                                            new NullLiteral(SourceInfo.NONE));
356         tl.visit(_ibfv);
357         assertEquals("There should be one error", 1, errors.size());
358         assertEquals("The error message should be correct", 
359                      "The field 'this' does not exist in interfaces.  Only classes have a 'this' field.", 
360                      errors.get(0).getFirst());
361    
362        }
363        
364        public void testForSimpleSuperReferenceDoFirst() {
365         SimpleSuperReference sr = new SimpleSuperReference(SourceInfo.NONE);
366         sr.visit(_ibfv);
367         assertEquals("There should be one error", 1, errors.size());
368         assertEquals("The error message should be correct", 
369                      "The field 'super' does not exist in interfaces.  Only classes have a 'super' field", 
370                      errors.get(0).getFirst());
371        }
372        
373        public void testForComplexSuperReferenceDoFirst() {
374          ComplexSuperReference cr = new ComplexSuperReference(SourceInfo.NONE, 
375                                                               new NullLiteral(SourceInfo.NONE));
376          cr.visit(_ibfv);
377          assertEquals("There should be one error", 1, errors.size());
378          assertEquals("The error message should be correct", 
379                       "The field 'super' does not exist in interfaces.  Only classes have a 'super' field", 
380                       errors.get(0).getFirst());
381        }
382        
383        public void xtestForVariableDeclarationDoFirst() {
384          //Check that if a field is initialized, no error is thrown
385          VariableDeclaration vdecl0 = new VariableDeclaration(SourceInfo.NONE,
386                                                           _packageMav,
387                                                           new VariableDeclarator[] {
388            new InitializedVariableDeclarator(SourceInfo.NONE, 
389                                              new PrimitiveType(SourceInfo.NONE, "double"), 
390                                              new Word (SourceInfo.NONE, "field0"), 
391                                              new DoubleLiteral(SourceInfo.NONE, 2.345))});
392    
393          vdecl0.visit(_ibfv);
394          assertEquals("There should be no errors", 0, errors.size());
395                                                               
396          
397          // Check that an error is thrown if the fields are not initialized
398          VariableDeclaration vdecl = new VariableDeclaration(SourceInfo.NONE,
399                                                           _packageMav,
400                                                           new VariableDeclarator[] {
401            new InitializedVariableDeclarator(SourceInfo.NONE, 
402                                   new PrimitiveType(SourceInfo.NONE, "double"), 
403                                   new Word (SourceInfo.NONE, "field1"),
404                                   new DoubleLiteral(SourceInfo.NONE, 2.45)),
405            new UninitializedVariableDeclarator(SourceInfo.NONE, 
406                                   new PrimitiveType(SourceInfo.NONE, "boolean"), 
407                                   new Word (SourceInfo.NONE, "field2"))});
408          vdecl.visit(_ibfv);
409          assertEquals("There should be one error", 1, errors.size());
410          assertEquals("The error message should be correct", 
411                       "All fields in interfaces must be assigned a value when they are declared", 
412                       errors.getLast().getFirst());
413        }
414        
415        public void testForAbstractMethodDef() {
416          // Test one that works.
417          MethodDef mdef = new AbstractMethodDef(SourceInfo.NONE, 
418                                                 _abstractMav, 
419                                                 new TypeParameter[0], 
420                                                 new PrimitiveType(SourceInfo.NONE, "int"), 
421                                                 new Word(SourceInfo.NONE, "methodName"),
422                                                 new FormalParameter[0],
423                                                 new ReferenceType[0]);
424          _ibfv._enclosing.setMav(_abstractMav);
425          mdef.visit(_ibfv);
426          assertEquals("There should not be any errors.", 0, errors.size());
427          
428          // Test one that doesn't work.
429          mdef = new AbstractMethodDef(SourceInfo.NONE, 
430                                                 _abstractMav, 
431                                                 new TypeParameter[0], 
432                                                 new PrimitiveType(SourceInfo.NONE, "int"), 
433                                                 new Word(SourceInfo.NONE, "MyInterface"),
434                                                 new FormalParameter[0],
435                                                 new ReferenceType[0]);
436          mdef.visit(_ibfv);
437          assertEquals("There should be one error.", 1, errors.size());
438          assertEquals("The error message should be correct.", 
439                       "Only constructors can have the same name as the class they appear in, and constructors cannot " 
440                         + "appear in interfaces.",
441                       errors.get(0).getFirst());
442          
443          //It's okay for the method to be public
444          AbstractMethodDef amd3 = new AbstractMethodDef(SourceInfo.NONE, 
445                                                         _publicMav, 
446                                                         new TypeParameter[0], 
447                                                         new PrimitiveType(SourceInfo.NONE, "double"), 
448                                                         new Word(SourceInfo.NONE, "methodName2"),
449                                                         new FormalParameter[0],
450                                                         new ReferenceType[0]);
451          amd3.visit(_ibfv);
452          assertEquals("There should still be one error", 1, errors.size());
453          assertTrue("The method def should be public", _ibfv._enclosing.getMethods().get(1).hasModifier("public"));
454    
455          //What if the method is called private? Should throw error
456          AbstractMethodDef amd4 = new AbstractMethodDef(SourceInfo.NONE, 
457                                                         _privateMav, 
458                                                         new TypeParameter[0], 
459                                                         new PrimitiveType(SourceInfo.NONE, "double"), 
460                                                         new Word(SourceInfo.NONE, "methodName3"),
461                                                         new FormalParameter[0],
462                                                         new ReferenceType[0]);
463          amd4.visit(_ibfv);
464          assertEquals("There should be two errors", 2, errors.size());
465          assertEquals("The error message should be correct", 
466                       "Interface methods cannot be private.  They must be public." , 
467                       errors.get(1).getFirst());
468        
469          //What if the method is protected: Should throw error
470          AbstractMethodDef amd5 = new AbstractMethodDef(SourceInfo.NONE, 
471                                                         _protectedMav, 
472                                                         new TypeParameter[0], 
473                                                         new PrimitiveType(SourceInfo.NONE, "double"), 
474                                                         new Word(SourceInfo.NONE, "methodName4"),
475                                                         new FormalParameter[0],
476                                                         new ReferenceType[0]);
477          amd5.visit(_ibfv);
478          assertEquals("There should be three errors", 3, errors.size());
479          assertEquals("The error message should be correct",
480                       "Interface methods cannot be protected.  They must be public." , 
481                       errors.get(2).getFirst());
482        }
483        
484    
485        public void testForInnerClassDef() {
486          _ibfv._enclosing = new SymbolData("MyInterface");
487          _ibfv._enclosing.setInterface(true);
488          
489    //      SymbolData obj = new SymbolData("java.lang.Object");
490          LanguageLevelConverter._newSDs.clear();
491    //      LanguageLevelConverter.symbolTable.put("java.lang.Object", obj);
492          
493          InnerClassDef cd1 = 
494            new InnerClassDef(SourceInfo.NONE, 
495                              _packageMav, 
496                              new Word(SourceInfo.NONE, "Bart"),
497                              new TypeParameter[0], 
498                              new ClassOrInterfaceType(SourceInfo.NONE, "java.lang.Object", new Type[0]), 
499                              new ReferenceType[0], 
500                              new BracedBody(SourceInfo.NONE, new BodyItemI[0]));
501          InnerClassDef cd0 = 
502            new InnerClassDef(SourceInfo.NONE, 
503                              _packageMav, 
504                              new Word(SourceInfo.NONE, "Lisa"),
505                              new TypeParameter[0], 
506                              new ClassOrInterfaceType(SourceInfo.NONE, "java.lang.Object", new Type[0]), 
507                              new ReferenceType[0], 
508                              new BracedBody(SourceInfo.NONE, new BodyItemI[] {cd1}));
509         
510    //      SymbolData sd0 = new SymbolData(_ibfv._enclosing.getName() + "$Lisa", _packageMav, new TypeParameter[0], obj, 
511    //                                      new ArrayList<SymbolData>(), null); 
512    //      SymbolData sd1 = 
513    //        new SymbolData(_ibfv._enclosing.getName() + "$Lisa$Bart", _packageMav, new TypeParameter[0], obj, 
514    //                       new ArrayList<SymbolData>(), null); 
515          
516    //      _ibfv._enclosing.addInnerClass(sd0);
517    //      sd0.setOuterData(_ibfv._enclosing);
518    
519    //      sd0.addInnerClass(sd1);
520    //      sd1.setOuterData(sd0);
521    //
522    //      sd0.setIsContinuation(true);
523    //      sd1.setIsContinuation(true);
524    //      LanguageLevelConverter._newSDs.clear();
525    //      LanguageLevelConverter.symbolTable.put(_ibfv._enclosing.getName() + "$Lisa", sd0);
526    
527          cd0.visit(_ibfv);
528    
529          SymbolData sd0 = _ibfv._enclosing.getInnerClassOrInterface("Lisa");
530          assertNotNull("Inner class Lisa exists", sd0);
531          
532          assertEquals("Lisa should have the correct outer data", _ibfv._enclosing, sd0.getOuterData());
533          assertTrue("_sd1 should be an interface", _sd1.isInterface());
534          assertFalse("sd0 should be a class", sd0.isInterface());
535          assertEquals("Lisa should have 0 methods", 0, sd0.getMethods().size());  
536          
537          SymbolData sd1 = sd0.getInnerClassOrInterface("Bart");
538          assertNotNull("Inner class Bart exists", sd1);
539          
540          assertEquals("Bart should have the correct outer data", sd0, sd1.getOuterData());
541          assertFalse("sd1 should be a class", sd1.isInterface());
542          assertEquals("Bart should have 0 methods", 0, sd1.getMethods().size());
543        }
544        
545        public void testForInnerInterfaceDef() {
546    
547          InnerInterfaceDef cd1 = 
548            new InnerInterfaceDef(SourceInfo.NONE, _packageMav, new Word(SourceInfo.NONE, "Bart"),
549                                  new TypeParameter[0], new ReferenceType[0], 
550                                  new BracedBody(SourceInfo.NONE, new BodyItemI[0]));
551          
552          InnerInterfaceDef cd0 = 
553            new InnerInterfaceDef(SourceInfo.NONE, _packageMav, new Word(SourceInfo.NONE, "Lisa"),
554                                  new TypeParameter[0], new ReferenceType[0], 
555                                  new BracedBody(SourceInfo.NONE, new BodyItemI[] {cd1}));
556          
557    //      SymbolData sd0 = new SymbolData(_ibfv._enclosing.getName() + "$Lisa", _packageMav, new TypeParameter[0], 
558    //                                      new ArrayList<SymbolData>(), null); 
559    //      SymbolData sd1 = new SymbolData(_ibfv._enclosing.getName() + "$Lisa$Bart", _packageMav, new TypeParameter[0], 
560    //                                      new ArrayList<SymbolData>(), null);
561    //      sd0.addInnerInterface(sd1);
562    //
563    //      
564    //      _ibfv._enclosing.addInnerInterface(sd0);
565    //      sd0.setOuterData(_ibfv._enclosing);
566    //
567    //      sd0.addInnerInterface(sd1);
568    //      sd1.setOuterData(sd0);
569    //
570    //      
571    //      sd0.setIsContinuation(true);
572    //      sd1.setIsContinuation(true);
573    //      LanguageLevelConverter._newSDs.clear();
574    //      LanguageLevelConverter.symbolTable.put(_ibfv._enclosing.getName() + "$Lisa", sd0);
575    //      LanguageLevelConverter._newSDs.clear();
576    //      LanguageLevelConverter.symbolTable.put(_ibfv._enclosing.getName() + "$Lisa$Bart", sd1);
577    
578          cd0.visit(_ibfv);
579    
580          SymbolData sd0 = _ibfv._enclosing.getInnerClassOrInterface("Lisa");
581          assertNotNull("Inner interfacae Lisa exists", sd0);
582          
583          assertEquals("Lisa should have the correct outer data", _ibfv._enclosing, sd0.getOuterData());
584          assertTrue("_sd1 should be an interface", _sd1.isInterface());
585          assertTrue("sd0 should be a interface", sd0.isInterface());
586          assertEquals("Lisa should have 0 methods", 0, sd0.getMethods().size());  
587          
588          SymbolData sd1 = sd0.getInnerClassOrInterface("Bart");
589          assertNotNull("Inner interface Bart exists", sd1);
590          
591          assertEquals("Bart should have the correct outer data", sd0, sd1.getOuterData());
592          assertTrue("sd1 should be an interface", sd1.isInterface());
593          assertEquals("Bart should have 0 methods", 0, sd1.getMethods().size());
594        }
595    
596        public void testForConstructorDef() {
597         ///this is a ConstructorDef with no formal paramaters and no throws
598          ConstructorDef cd =
599            new ConstructorDef(SourceInfo.NONE, new Word(SourceInfo.NONE, "MyClass"),
600                               _publicMav, new FormalParameter[0], new ReferenceType[0], 
601                                new BracedBody(SourceInfo.NONE, new BodyItemI[0]));
602    
603          // Check that the appropriate error is thrown.
604          cd.visit(_ibfv);
605          assertEquals("There should now be one error", 1, errors.size());
606          assertEquals("The error message should be correct", "Constructor definitions cannot appear in interfaces", 
607                       errors.get(0).getFirst());
608          
609        }
610        public void testDummy() { }
611      }
612    }