001    /*BEGIN_COPYRIGHT_BLOCK
002     *
003     * Copyright (c) 2001-2010, JavaPLT group at Rice University (drjava@rice.edu)
004     * All rights reserved.
005     * 
006     * Redistribution and use in source and binary forms, with or without
007     * modification, are permitted provided that the following conditions are met:
008     *    * Redistributions of source code must retain the above copyright
009     *      notice, this list of conditions and the following disclaimer.
010     *    * Redistributions in binary form must reproduce the above copyright
011     *      notice, this list of conditions and the following disclaimer in the
012     *      documentation and/or other materials provided with the distribution.
013     *    * Neither the names of DrJava, the JavaPLT group, Rice University, nor the
014     *      names of its contributors may be used to endorse or promote products
015     *      derived from this software without specific prior written permission.
016     * 
017     * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
018     * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
019     * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
020     * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
021     * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
022     * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
023     * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
024     * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
025     * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
026     * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
027     * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
028     *
029     * This software is Open Source Initiative approved Open Source Software.
030     * Open Source Initative Approved is a trademark of the Open Source Initiative.
031     * 
032     * This file is part of DrJava.  Download the current version of this project
033     * from http://www.drjava.org/ or http://sourceforge.net/projects/drjava/
034     * 
035     * END_COPYRIGHT_BLOCK*/
036    
037    package edu.rice.cs.javalanglevels;
038    
039    import edu.rice.cs.javalanglevels.tree.*;
040    import edu.rice.cs.javalanglevels.parser.*;
041    import java.util.*;
042    import java.io.*;
043    import edu.rice.cs.plt.reflect.JavaVersion;
044    import edu.rice.cs.plt.iter.*;
045    
046    import junit.framework.TestCase;
047    
048    
049    /** Top-level Language Level Visitor that processes the Full Java Language Level.  It constructs a symbol table from a
050      * Java source file if possible.  It does not attempt to check for errors since Full Java files are compiled by javac.
051      */
052    public class FullJavaVisitor extends LanguageLevelVisitor {
053      
054      /* Inheriting the following fields:
055       * 
056       File _file;
057       String _package;
058       String _enclosingClassName;
059       LinkedList<String> _importedFiles;
060       LinkedList<String> _importedPackages;
061       HashMap<String, SymbolData> _generic types
062       *
063       */
064    
065      /** Main constructor, which is called from sites where the genericTypes table is not empty. */
066      public FullJavaVisitor(File file, 
067                             String packageName, 
068                             String enclosingClassName,
069                             LinkedList<String> importedFiles, 
070                             LinkedList<String> importedPackages,
071                             HashSet<String> classesInThisFile, 
072                             Hashtable<String, Triple<SourceInfo, LanguageLevelVisitor, SymbolData>> continuations,
073                             LinkedList<Command> fixUps,
074                             HashMap<String, SymbolData> genericTypes) {
075        super(file, packageName, enclosingClassName, importedFiles, importedPackages, classesInThisFile, continuations, 
076              fixUps, genericTypes);
077      }
078      
079      
080      /** This constructor is called from sites where no generic type variables are in scope. */
081      public FullJavaVisitor(File file, 
082                             String packageName, 
083                             String enclosingClassName,
084                             LinkedList<String> importedFiles, 
085                             LinkedList<String> importedPackages,
086                             HashSet<String> classesInThisFile, 
087                             Hashtable<String, Triple<SourceInfo, LanguageLevelVisitor, SymbolData>> continuations,
088                             LinkedList<Command> fixUps) {
089        this(file, packageName, enclosingClassName, importedFiles, importedPackages, classesInThisFile, continuations, 
090             fixUps, new HashMap<String, SymbolData>());
091      }
092      
093      /** This constructor is called only in testing.  It initializes all of the static fields of LanguageLevelVisitor. */
094      public FullJavaVisitor(File file) {
095        this(file, 
096             new LinkedList<Pair<String, JExpressionIF>>(),
097             new Hashtable<String, Triple<SourceInfo, LanguageLevelVisitor, SymbolData>>(),
098             new LinkedList<Command>(),
099             new LinkedList<Pair<LanguageLevelVisitor, SourceFile>>());
100      }
101      
102      /** This constructor is called from LanguageLevelConverter when it is instantiating a new
103        * FullJavaVisitor to visit a new file.  Package is set to "" by default.  The generic
104        * types table (_genericTypes) is set to an emtpy HashMap by default.
105        * @param file  The File corresponding to the source file we are visiting
106        * @param errors  The list of errors that have been encountered so far.
107        * @param continuations  The table of classes we have encountered but still need to resolve
108        * @param visitedFiles  The list of files we have visited
109        */
110      public FullJavaVisitor(File file, 
111                             LinkedList<Pair<String, JExpressionIF>> errors, 
112                             Hashtable<String, Triple<SourceInfo, LanguageLevelVisitor, SymbolData>> continuations,
113                             LinkedList<Command> fixUps,
114                             LinkedList<Pair<LanguageLevelVisitor, SourceFile>> visitedFiles) {
115        this(file, new LinkedList<String>(), errors, continuations, fixUps, visitedFiles);
116      }
117    
118      /** This constructor is called from LanguageLevelConverter when it is instantiating a new
119        * FullJavaVisitor to visit a new file.  Package is set to "" by default.
120        * @param file  The File corresponding to the source file we are visiting
121        * @param importedPackages The list of strings describing the imported packages for this file
122        * @param errors  The list of errors that have been encountered so far.
123        * @param continuations  The table of classes we have encountered but still need to resolve
124        * @param visitedFiles  The list of files we have visited
125        */
126      public FullJavaVisitor(File file,
127                             LinkedList<String> importedPackages,
128                             LinkedList<Pair<String, JExpressionIF>> errors, 
129                             Hashtable<String, Triple<SourceInfo, LanguageLevelVisitor, SymbolData>> continuations,
130                             LinkedList<Command> fixUps,
131                             LinkedList<Pair<LanguageLevelVisitor, SourceFile>> visitedFiles) {
132        this(file, "", null, new LinkedList<String>(), importedPackages, new HashSet<String>(), continuations, fixUps);
133        this.errors = errors;
134        this.visitedFiles= visitedFiles; //new LinkedList<Pair<LanguageLevelVisitor, SourceFile>>();
135    //    _hierarchy = new Hashtable<String, TypeDefBase>();//hierarchy;
136      }
137    
138      /** At the FullJava Level, there is no code augmentation.  If we are working with a class that has no constructor,
139        * we must record fact that has an implicit 0-ary default constructor.
140        * @param sd  The SymbolData we are checking
141       */
142      public void createConstructor(SymbolData sd) {
143        SymbolData superSd = sd.getSuperClass();
144        
145        //If sd is a continuation, there was an error somewhere else.  just return.
146        if (sd.isContinuation()) return;
147        
148        String name = getUnqualifiedClassName(sd.getName());
149        
150        // if sd already has a constructor, just return.
151        boolean hasOtherConstructor = sd.hasMethod(name);
152        if (hasOtherConstructor) {
153              LanguageLevelConverter._newSDs.remove(sd); // this won't do anything if sd is not in _newSDs.
154    //          System.err.println(sd + " removed from _newSDs.  _newSDs = " + LanguageLevelConverter._newSDs);
155              return;
156        }
157        
158        // otherwise, it doesn't have a constructor, so let's add it!
159        MethodData md = MethodData.make(name,
160                                        new ModifiersAndVisibility(SourceInfo.NONE, new String[] {"public"}), 
161                                        new TypeParameter[0], 
162                                        sd, 
163                                        new VariableData[0], // No Parameters
164                                        new String[0], 
165                                        sd,
166                                        null);
167    
168        addGeneratedMethod(sd, md);
169        LanguageLevelConverter._newSDs.remove(sd); // does nothing if sd is not in _newSDs.
170      }
171      
172      /** Process the inner class def and then resolve it and store it in
173        * the outer class's list of inner classes.  This method is common to both ClassBodyFullJavaVisitor
174        * and InterfaceBodyIntermediateVisitor but needs the correct Data so we pass it in.  This method is tested
175        * in those files.  We use the fully qualified name along with the $'s so we don't accidentally conflict with an
176        * actual class in the symbol table.
177        * @param that  The AST Node for the inner class def
178        * @param data  The Data that encloses this inner class.  This is a Data because the inner class can be in a class 
179        *              or a method.
180        * @param relName The relative name of the inner class including no qualifiers
181        * @param name  The qualified name of the inner class including the qualified name of the enclosing data followed by 
182        *              a $.  For local classes, we append a number after the $ corresponding to the order that the local 
183        *              class appears in the enclosing class and then put the name of the class.  For anonymous classes, we 
184        *              only put a number after the $.  For example, if class A has a method B that has a local class C, then
185        *              name should be "A$1C".
186        */
187      protected void handleInnerClassDef(InnerClassDef that, Data data, String relName, String name) {
188    //    if (_file.getName().endsWith("MultipleNested.dj2")) 
189    //      System.err.println("********** Processing InnerClassDef for " + name + " defined in " + data.getName());
190        
191        assert (data instanceof SymbolData) || (data instanceof MethodData);
192    //    assert (data instanceof SymbolData) ? data.getName().equals(_enclosingClassName) : true;
193        
194        forInnerClassDefDoFirst(that);
195        if (prune(that)) return;
196    
197        that.getMav().visit(this);
198        that.getName().visit(this);
199        
200        // Create a new generic types table for visiting this inner class.
201        @SuppressWarnings("unchecked")
202        HashMap<String, SymbolData> genericTypes = (HashMap<String, SymbolData>) _genericTypes.clone();
203        TypeParameter[] tps = that.getTypeParameters();
204        for (TypeParameter tp: tps) {
205          final String typeName = tp.getVariable().getName();
206          final String boundName = tp.getBound().getName();
207          SymbolData boundSD = _identifyType(boundName, that.getSourceInfo(), _enclosingClassName);
208          if (boundSD == null) { // create a dummy SymbolData 
209            boundSD = symbolTable.get("java.lang.Object"); //  TODO: could create a separate SymbolData.NOT_BOUND singleton class?
210    //        System.err.println("Creating dummy SymbolData for bounding type " + typeName + " in inner class " + name);
211          }
212          genericTypes.put(typeName, boundSD);
213        }
214        
215        /* The following two lines apparently do nothing.  Note that they are NOT in the scope of the new generic types
216         * table.  TODO: confirm that these two lines do nothing and eliminate them. */
217        that.getSuperclass().visit(this);
218        for (int i = 0; i < that.getInterfaces().length; i++) that.getInterfaces()[i].visit(this);
219        
220        /* The following line is NOT in the scope of the new generic type table but should be.  Since we are not
221         * performing generic type checking, we may get away with the error.  TODO: refactor this code to
222         * create a new LLV for processing a generic class. */
223        SymbolData sd = defineInnerSymbolData(that, relName, name, data);
224        // The preceding only fails if there is an error in the program
225        
226        if (sd != null) { // We have a symbol data to work with, so visit the body using the new generic types table
227          identifyInnerClasses(that);
228          ClassBodyFullJavaVisitor cbfjv =
229            new ClassBodyFullJavaVisitor(sd, _file, _package, _importedFiles, _importedPackages, _classesInThisFile, 
230                                         continuations, fixUps, genericTypes);
231          that.getBody().visit(cbfjv);
232        }
233       
234        // Inner classes are not put into _classesInThisFile since they are parsed whenever their outer classes are parsed.
235    
236        forInnerClassDefOnly(that);
237      }
238      
239      /** Process the inner interface, and resolve it and store it in the
240        * outer class's list of inner classes.  This method is common to both ClassBodyIntermediateVisitor
241        * and InterfaceBodyIntermediateVisitor but needs the correct SymbolData so we pass it in.  This method is tested
242        * in those files.
243        */
244      protected void handleInnerInterfaceDef(InnerInterfaceDef that, Data data, String relName, String name) {
245    //    System.err.println("Processing InnerInterfaceDef for " + name);
246        assert (data instanceof SymbolData) || (data instanceof MethodData);
247        
248        forInnerInterfaceDefDoFirst(that);
249        if (prune(that)) return;
250        
251        that.getMav().visit(this);
252        that.getName().visit(this);
253    
254        // Create a new generic types table for visiting this inner class.
255        // TODO: refactor this code to combine common code patterns in this method and forInnerClassDef
256        @SuppressWarnings("unchecked")
257        HashMap<String, SymbolData> genericTypes = (HashMap<String, SymbolData>) _genericTypes.clone();
258        TypeParameter[] tps = that.getTypeParameters();
259        for (TypeParameter tp: tps) {
260          final String typeName = tp.getVariable().getName();
261          final String boundName = tp.getBound().getName();
262          SymbolData boundSD = _identifyType(boundName, that.getSourceInfo(), _enclosingClassName);
263          if (boundSD == null) { // create a dummy SymbolData 
264            boundSD = symbolTable.get("java.lang.Object"); //  TODO: could create a separate SymbolData.NOT_BOUND singleton class?
265    //        System.err.println("Creating dummy SymbolData for bounding type " + typeName + " in inner class " + name);
266            // TODO!  !!!!! Create an appropriate fixUp mechanism
267          }
268          genericTypes.put(typeName, boundSD);
269        }
270        
271        /* The following line apparently does nothing.  Note that it is NOT in the scope of the new generic types
272         * table.  TODO: confirm that this line does nothing and eliminate it. */
273        for (int i = 0; i < that.getInterfaces().length; i++) that.getInterfaces()[i].visit(this);
274        
275        /* The following line is NOT in the scope of the new generic type table but should be.  Since we are not
276         * performing generic type checking, we may get away with the error.  TODO: refactor this code to
277         * create a new LLV for processing a generic class. */
278        SymbolData sd = defineInnerSymbolData(that, relName, name, data);  // only returns null if error is encountered
279        
280        if (sd != null) { // We have a symbol data to work with, so visit the body using the new generic types table
281          sd.setInterface(true);
282          identifyInnerClasses(that);
283          InterfaceBodyFullJavaVisitor ibfjv = 
284            new InterfaceBodyFullJavaVisitor(sd, _file, _package, _importedFiles, _importedPackages, _classesInThisFile, 
285                                             continuations, fixUps, genericTypes);
286          that.getBody().visit(ibfjv);
287        }
288    
289        forInnerInterfaceDefOnly(that);
290      }
291      
292      /** Process ModifiersAndVisibility. */
293      public Void forModifiersAndVisibilityDoFirst(ModifiersAndVisibility that) {
294        String[] modifiersAndVisibility = that.getModifiers();
295        StringBuffer sb = new StringBuffer();
296        String temp;
297        int count = 0;    
298        for(int i = 0; i < modifiersAndVisibility.length; i++) {
299          temp = modifiersAndVisibility[i];
300          if (!(temp.equals("abstract") || temp.equals("public") || temp.equals("private") || temp.equals("protected") || 
301                temp.equals("static") || temp.equals("final"))) {
302            sb.append(" \"" + temp + "\"");
303            count++;
304          }
305        }
306        // Do NOT check for illegal keywords.  We are only building a symbol table.  The javac compiler checks for errors.
307        return super.forModifiersAndVisibilityDoFirst(that);
308      }
309    
310      /** Process SwitchStatement. */
311      public Void forSwitchStatementDoFirst(SwitchStatement that) { return super.forSwitchStatementDoFirst(that); }
312      
313      /* Ignore instance initializer. */
314      public Void forInstanceInitializerDoFirst(InstanceInitializer that) { return null; }
315      
316      /* Ignore static initializer. */
317      public Void forStaticInitializerDoFirst(StaticInitializer that) { return null; }
318      
319      /* Ignore labeled statement. */
320      public Void forLabeledStatementDoFirst(LabeledStatement that) { return null; }
321    
322      /* Ignore LabeledBreakStatement. */
323      public Void forLabeledBreakStatementDoFirst(LabeledBreakStatement that) { return null; }
324     
325      /* Ignore LabeledContinue Statement. */
326      public Void forLabeledContinueStatementDoFirst(LabeledContinueStatement that) { return null; }
327    
328      /* Ignore SynchronizedStatement. */
329      public Void forSynchronizedStatementDoFirst(SynchronizedStatement that) { return null; }
330    
331      /** Ignore TypeParameter. */
332      public Void forTypeParameterDoFirst(TypeParameter that) { return null; }
333    
334      /** Ignore ConditionalExpression. */
335      public Void forConditionalExpressionDoFirst(ConditionalExpression that) { return null; }
336    
337      /** Ignore instanceofExpression. */
338      public Void forInstanceofExpressionDoFirst(InstanceofExpression that) { return null; }
339    
340      /** Process PrimitiveType. */
341      public Void forPrimitiveTypeDoFirst(PrimitiveType that) { return super.forPrimitiveTypeDoFirst(that); }
342    
343    //  /* Process TryCatchStatement. */
344    //  public Void forTryCatchStatementDoFirst(TryCatchStatement that) {
345    //    return super.forTryCatchStatementDoFirst(that);
346    //  }
347      
348      /** Check to see if the specified className is a class defined in the current file.
349        * If it is, it will be stored in _classesInThisFile.
350        */
351      private boolean _isClassInCurrentFile(String className) {
352        Iterator<String> iter = _classesInThisFile.iterator();
353        while (iter.hasNext()) {
354          String s = iter.next();
355          if (s.equals(className) || s.endsWith('.' + className)) return true;
356        }
357        return false;   
358      }
359      
360      /** This overriding is a hack.  The parameters to a static method can be referenced within the method itself,
361        *  even though they are not declared to be static fields.  Making them static has no effect on any other processing.
362        */
363      protected String[] getFormalParameterMav(Data d) { 
364        return (d.hasModifier("static")) ? new String[] {"static"} : new String[] { };
365      }
366      
367      /** Use the doFirst method to make sure there aren't any errors with the declaration.  Then, use defineSymbolData to 
368        * create the appropriate symbol data, and then visit the class body.
369        * Once the ClassDef has been handled, remove the class from _classesInThisFile so we know it's been taken care of.
370        * @param that  The ClassDef being handled.
371        * TODO: refactor with same method in IntermediateVisitor; almost identical.
372        */
373      public Void forClassDef(ClassDef that) {    
374        forClassDefDoFirst(that);
375        if (prune(that)) return null;
376        
377        that.getMav().visit(this);
378        that.getName().visit(this);
379    
380        String className = getQualifiedClassName(that.getName().getText());
381    
382        // Create a new generic types table for visiting this class.
383        // TODO: refactor this code to combine common code patterns in this method and forInnerClassDef
384        @SuppressWarnings("unchecked")
385        HashMap<String, SymbolData> genericTypes = (HashMap<String, SymbolData>) _genericTypes.clone();
386        TypeParameter[] tps = that.getTypeParameters();
387        for (TypeParameter tp: tps) {
388          final String typeName = tp.getVariable().getName();
389          final String boundName = tp.getBound().getName();
390          SymbolData boundSD = _identifyType(boundName, that.getSourceInfo(), _enclosingClassName);
391          if (boundSD == null) { // create a dummy SymbolData 
392            boundSD = symbolTable.get("java.lang.Object"); //  TODO: could create a separate SymbolData.NOT_BOUND singleton class?
393    //        System.err.println("Creating dummy SymbolData for bounding type " + typeName + " in inner class " + name);
394          }
395          genericTypes.put(typeName, boundSD);
396        }
397        
398        /* The following line is NOT in the scope of the new generic type table but should be.  Since we are not
399         * performing generic type checking, we may get away with the error.  TODO: refactor this code to
400         * create a new LLV for processing a generic class. */
401        SymbolData sd = defineSymbolData(that, className);
402        
403        /* The following two lines apparently do nothing. They are in the wrong generic type scope. */
404        that.getSuperclass().visit(this);
405        for (int i = 0; i < that.getInterfaces().length; i++) that.getInterfaces()[i].visit(this);
406        
407        if (sd != null) {
408    //      System.err.println("********** Calling identifyInnerClasses for SymbolData " + sd.getName());
409          identifyInnerClasses(that);
410          ClassBodyFullJavaVisitor cbfjv = 
411            new ClassBodyFullJavaVisitor(sd, _file, _package, _importedFiles, _importedPackages, _classesInThisFile, 
412                                         continuations, fixUps, genericTypes);
413          that.getBody().visit(cbfjv);
414        }
415        forClassDefOnly(that);
416        
417        return null;
418      }
419    
420      /** This is a noop, because we do not do code augmentation at the Advanced Level. */
421      protected void createToString(SymbolData sd) { return; }
422    
423      /** This is a noop, because we do not do code augmentation at the Advanced Level. */
424      protected void createHashCode(SymbolData sd) { return; }
425        
426      /** This is a noop, because we do not do code augmentation at the Advanced Level. */
427      protected void createEquals(SymbolData sd) { return; }    
428       
429      /** Create a SymbolData corresponding to this interface and add it appropriately.
430        * Then visit the body to handle anything defined inside the interface.
431        * Once the interface has been resolved, remove it from _classesInThisFile.
432        * TODO: refactor with same method in IntermediateVisitor; they appear identical
433        */
434      public Void forInterfaceDef(InterfaceDef that) {
435        forInterfaceDefDoFirst(that);
436        if (prune(that)) return null;
437    
438        String className = getQualifiedClassName(that.getName().getText());
439    //    if (className.equals("listFW.IList")) System.err.println("Attempting to define symbol " + className);
440        
441        SymbolData sd = defineSymbolData(that, className);  
442        // TODO: should the preceding statement follow interface processing in 345
443            
444        // Note: sd can only be null if an error occurs in defineSymbol
445        if (sd != null) sd.setInterface(true);
446        
447        that.getMav().visit(this);
448        that.getName().visit(this); 
449        
450        // Create a new generic types table for visiting this interface.
451        // TODO: refactor this code to combine common code patterns in this method and forInnerClassDef
452        @SuppressWarnings("unchecked")
453        HashMap<String, SymbolData> genericTypes = (HashMap<String, SymbolData>) _genericTypes.clone();
454        TypeParameter[] tps = that.getTypeParameters();
455        for (TypeParameter tp: tps) {
456          final String typeName = tp.getVariable().getName();
457          final String boundName = tp.getBound().getName();
458          SymbolData boundSD = _identifyType(boundName, that.getSourceInfo(), _enclosingClassName);
459          if (boundSD == null) { // create a dummy SymbolData 
460            boundSD = symbolTable.get("java.lang.Object"); //  TODO: could create a separate SymbolData.NOT_BOUND singleton class?
461    //        System.err.println("Creating dummy SymbolData for bounding type " + typeName + " in inner class " + name);
462          }
463          genericTypes.put(typeName, boundSD);
464        }
465        
466        /* The following line apparently does nothing.  Note that it is NOT in the scope of the new generic types
467         * table.  TODO: confirm that this line does nothing and eliminate it. */
468        for (int i = 0; i < that.getInterfaces().length; i++) that.getInterfaces()[i].visit(this);
469        
470        if (sd != null) {
471          sd.setInterface(true);
472          identifyInnerClasses(that);
473          InterfaceBodyFullJavaVisitor ibfjv =
474            new InterfaceBodyFullJavaVisitor(sd, _file, _package, _importedFiles, _importedPackages, _classesInThisFile, 
475                                             continuations, fixUps, genericTypes);
476          that.getBody().visit(ibfjv);
477        }
478        
479        forInterfaceDefOnly(that);
480        _classesInThisFile.remove(className);
481        return null;
482      }
483      
484      /** Look up the super type of this class instantiation and add it to the symbol table.  Visit the body of the class
485        * instantiation.  All handling of this as an anonymous inner class (i.e. adding it to the enclosing SD's list of
486        * inner classes, creating a symbol data for the anonyomous inner class, etc) is handled in the TypeChecker pass.  
487        * This is because no one will depend on that symbolData until we create it.
488        * @param that       The SimpleAnonymousClassInstantiation being processed.
489        * @param enclosing  The SymbolData of the enclosing class.
490        */
491      public void simpleAnonymousClassInstantiationHelper(SimpleAnonymousClassInstantiation that, SymbolData enclosing) {
492        /* Nested inner computation (e.g., new E().new W()) breaks conformity checking.  So we suppress it. */
493      }
494      
495      /** Do not resolve the super class type of this instantiation, because it will have already been resolved (it
496        * is an inner class of the enclosing of this instantiation.  When the enclosing was resolved, all of its inner 
497        * classes should have also been resolved).
498        * Visit the body of the class instantiation.  
499        * @param that  The ComplexAnonymousClassInstantiation being processed.
500        * @param enclosing  The SymbolData of the enclosing class.
501        */
502      public void complexAnonymousClassInstantiationHelper(ComplexAnonymousClassInstantiation that, SymbolData enclosing) {
503        /* Nested inner computation (e.g., new E().new W()) breaks conformity checking.  So we suppress it. */
504      }
505      
506      /* Resolve the ArrayType by looking it up. */  
507      public Void forArrayType(ArrayType that) {
508        forArrayTypeDoFirst(that);
509        if (prune(that)) return null;
510    //    System.err.println("###### getSymbolData on " + that.getName() + " SHOULD BE ARRAY NAME");
511        getSymbolData(that.getName(), that.getSourceInfo());
512        return null;
513      }
514      
515      /** Test the methods defined in the enclosing class.  There is a test method corresponding to almost every method in 
516        * the above class.
517        * TODO:  WHICH IS WRONG!  Many of the methods in FullJavaVisitor are invoked at the level of ClassBodyFullJavaVisitor
518        * and BodyBodyFullJavaVisitor.  Moreover, they rely on overrides that are present only at that subclass level.  Move
519        * the tests that relate to subclasses to the appropriate subclasses!
520        */
521      public static class FullJavaVisitorTest extends TestCase {
522        
523        /*Some initial initializations:*/
524        private FullJavaVisitor _fv;
525        
526        private SymbolData _sd1;
527        private SymbolData _sd2;
528        private SymbolData _sd3;
529        private SymbolData _sd4;
530        private SymbolData _sd5;
531        private SymbolData _sd6;
532        private SymbolData _objectSD;
533        
534        private ModifiersAndVisibility _publicMav = new ModifiersAndVisibility(SourceInfo.NONE, new String[] {"public"});
535        private ModifiersAndVisibility _protectedMav = 
536          new ModifiersAndVisibility(SourceInfo.NONE, new String[] {"protected"});
537        private ModifiersAndVisibility _privateMav = 
538          new ModifiersAndVisibility(SourceInfo.NONE, new String[] {"private"});
539        private ModifiersAndVisibility _packageMav = new ModifiersAndVisibility(SourceInfo.NONE, new String[0]);
540        private ModifiersAndVisibility _abstractMav = 
541          new ModifiersAndVisibility(SourceInfo.NONE, new String[] {"abstract"});
542        private ModifiersAndVisibility _staticMav = new ModifiersAndVisibility(SourceInfo.NONE, new String[] {"static"});
543        private ModifiersAndVisibility _finalMav = new ModifiersAndVisibility(SourceInfo.NONE, new String[] {"final"});
544        private ModifiersAndVisibility _volatileMav = 
545          new ModifiersAndVisibility(SourceInfo.NONE, new String[]{"volatile"});
546        
547        public FullJavaVisitorTest() { this(""); }
548        public FullJavaVisitorTest(String name) { super(name); }
549        
550        public void setUp() {
551          errors = new LinkedList<Pair<String, JExpressionIF>>();
552          LanguageLevelConverter.symbolTable.clear();
553          LanguageLevelConverter._newSDs.clear();
554          LanguageLevelConverter.OPT = new Options(JavaVersion.JAVA_5, IterUtil.make(new File("lib/buildlib/junit.jar")));
555          visitedFiles = new LinkedList<Pair<LanguageLevelVisitor, edu.rice.cs.javalanglevels.tree.SourceFile>>();      
556    //      _hierarchy = new Hashtable<String, TypeDefBase>();
557          _fv = new FullJavaVisitor(new File(""), 
558                                    errors,
559                                    continuations,
560                                    new LinkedList<Command>(),
561                                    new LinkedList<Pair<LanguageLevelVisitor, SourceFile>>());
562          _fv._classesInThisFile = new HashSet<String>();
563          _fv.continuations = new Hashtable<String, Triple<SourceInfo, LanguageLevelVisitor, SymbolData>>();
564          _fv._importedPackages.addFirst("java.lang");
565          _errorAdded = false;
566          
567          _sd1 = new SymbolData("i.like.monkey");
568          _sd2 = new SymbolData("i.like.giraffe");
569          _sd3 = new SymbolData("zebra");
570          _sd4 = new SymbolData("u.like.emu");
571          _sd5 = new SymbolData("");
572          _sd6 = new SymbolData("cebu");
573          
574          _sd1.setIsContinuation(false);
575          _sd1.setInterface(false);
576          _sd1.setPackage("i.like");
577          _sd1.setTypeParameters(new TypeParameter[0]);
578          _sd1.setInterfaces(new ArrayList<SymbolData>()); 
579          
580          _objectSD = LanguageLevelConverter.symbolTable.get("java.lang.Object");
581          _sd1.setSuperClass(_objectSD);
582          
583          _fv._enclosingClassName = "i.like.monkey";
584          _fv.symbolTable.put("i.like.monkey", _sd1);
585    
586          _sd1.setSuperClass(_objectSD);
587          _errorAdded = false;  // static field of this.  TODO: fix this!
588        }
589        
590        public void initTopLevel() {
591          _fv._enclosingClassName = null;
592        }
593        
594        public void testForModifiersAndVisibilityDoFirst() {
595          
596          //Check that the proper modifiers are allowed:
597          _fv.forModifiersAndVisibilityDoFirst(_abstractMav);
598          _fv.forModifiersAndVisibilityDoFirst(_publicMav);
599          _fv.forModifiersAndVisibilityDoFirst(_privateMav);
600          _fv.forModifiersAndVisibilityDoFirst(_protectedMav);
601          _fv.forModifiersAndVisibilityDoFirst(_staticMav);
602          _fv.forModifiersAndVisibilityDoFirst(_finalMav);
603          
604          ModifiersAndVisibility mavs = new ModifiersAndVisibility(SourceInfo.NONE, 
605                                                                   new String[] {"private", "static"});
606           _fv.forModifiersAndVisibilityDoFirst(mavs);
607          assertEquals("there should still be 0 errors", 0, errors.size());
608    
609          //check errors:
610          
611          _fv.forModifiersAndVisibilityDoFirst(_volatileMav);
612          assertEquals("there should now be no errors", 0, errors.size());
613    //      assertEquals("The error message should be correct for private modifier:", 
614    //                   "The keyword \"volatile\" cannot be used at the Advanced level", 
615    //                   errors.get(0).getFirst());
616    
617          ModifiersAndVisibility mavs2 = new ModifiersAndVisibility(SourceInfo.NONE, 
618                                                                    new String[] {"final", "volatile"});
619         
620          _fv.forModifiersAndVisibilityDoFirst(mavs2);
621          assertEquals("There should now be 1 error", 1, errors.size());
622          assertEquals("The error message should be correct for 1 bad, 1 good modifier:", 
623                       "Illegal combination of modifiers. Can't use final and volatile together.", 
624                       errors.get(0).getFirst());
625    
626          ModifiersAndVisibility mavs3 = new ModifiersAndVisibility(SourceInfo.NONE, 
627                                                                    new String[] {"synchronized", "native"});
628         
629          _fv.forModifiersAndVisibilityDoFirst(mavs3);
630          assertEquals("There should now be 1 errors", 1, errors.size());
631    //      assertEquals("The error message should be correct for 2 bad modifiers:", 
632    //                   "The keywords \"synchronized\" \"native\" cannot be used at the Advanced level", 
633    //                   errors.get(1).getFirst());
634        }
635        
636        public void testForClassDefDoFirst() {
637    //      System.err.println("*** Starting testForClassDefDoFirst");
638          // check an example that works
639          ClassDef cd0 = new ClassDef(SourceInfo.NONE, _publicMav,
640                                      new Word(SourceInfo.NONE, "Lisa"),
641                                      new TypeParameter[0], 
642                                      new ClassOrInterfaceType(SourceInfo.NONE, "java.lang.Object", new Type[0]), 
643                                      new ReferenceType[0], 
644                                      new BracedBody(SourceInfo.NONE, new BodyItemI[0]));
645          
646          _fv.forClassDefDoFirst(cd0);
647          assertEquals("should be no errors", 0, errors.size());
648          
649          // check that an error is not thrown if a class doesn't explicitely extend another class
650          ClassDef cd1 = new ClassDef(SourceInfo.NONE, _publicMav, 
651                                      new Word(SourceInfo.NONE, "Test"), new TypeParameter[0], JExprParser.NO_TYPE,
652                                      new ReferenceType[0], new BracedBody(SourceInfo.NONE, new BodyItemI[0]));
653    
654          _fv.forClassDefDoFirst(cd1);
655          assertEquals("there should still be 0 errors", 0, errors.size());
656           
657          //check that an error is not thrown if a class implements any interfaces.
658          ReferenceType rt2 = new ClassOrInterfaceType(SourceInfo.NONE, "java.lang.Object", new Type[0]);
659          ClassDef cd2 = new ClassDef(SourceInfo.NONE, _publicMav, 
660                                       new Word(SourceInfo.NONE, "Test"), new TypeParameter[0], 
661                                       new ClassOrInterfaceType(SourceInfo.NONE, "java.lang.Object", new Type[0]),
662                                       new ReferenceType[] { rt2 }, 
663                                       new BracedBody(SourceInfo.NONE, new BodyItemI[0]));
664    
665                                     
666          _fv.forClassDefDoFirst(cd2);
667          assertEquals("there should still be 0 errors", 0, errors.size());
668    //      System.err.println("Ending testForClassDefDoFirst");
669        }
670        
671        public void testForFormalParameterDoFirst() {
672          PrimitiveType pt = new PrimitiveType(SourceInfo.NONE, "int");
673          Word w = new Word(SourceInfo.NONE, "param");
674          UninitializedVariableDeclarator uvd = new UninitializedVariableDeclarator(SourceInfo.NONE, pt, w);
675          
676          // check an example that works
677          FormalParameter fp = new FormalParameter(SourceInfo.NONE, uvd, false);
678          _fv.forFormalParameterDoFirst(fp);
679          assertEquals("should be no errors", 0, errors.size());
680          
681          // check that no errors are thrown if the FormalParameter is final
682          FormalParameter fp2 = new FormalParameter(SourceInfo.NONE, uvd, true);  
683          _fv.forFormalParameterDoFirst(fp2);
684          assertEquals("should still be no errors", 0, errors.size());
685        }
686        
687        public void test_NotAllowed() {
688          SourceInfo noInfo = SourceInfo.NONE;
689          Word w = new Word(SourceInfo.NONE, "word");
690          TypeParameter[] tps = new TypeParameter[0];
691          ReferenceType[] rts = new ReferenceType[0];
692          BracedBody emptyBody = new BracedBody(SourceInfo.NONE, new BodyItemI[0]);
693          UnbracedBody emptyUnbracedBody = new UnbracedBody(SourceInfo.NONE, new BodyItemI[0]);
694          ClassOrInterfaceType superClass = new ClassOrInterfaceType(SourceInfo.NONE, "java.lang.Object", new Type[0]);
695          FormalParameter[] fps = new FormalParameter[0];
696          CompoundWord cw = new CompoundWord(noInfo, new Word[0]);
697          Statement stmt = new EmptyStatement(noInfo);
698          Expression e = new EmptyExpression(noInfo);
699          Block b = new Block(noInfo, emptyBody);
700          //      ClassModifier cm = ClassModifier.NONE;
701          TypeVariable tv = new TypeVariable(noInfo, "name");
702          
703          InnerInterfaceDef ii = new InnerInterfaceDef(noInfo, _publicMav, w, tps, rts, emptyBody);
704          InnerClassDef ic = new InnerClassDef(noInfo, _publicMav, w, tps, superClass, rts, emptyBody);
705          
706          StaticInitializer si = new StaticInitializer(noInfo, b);
707          LabeledStatement ls = new LabeledStatement(noInfo, new Word(noInfo, "label"), stmt);
708    
709          LabeledBreakStatement bs = new LabeledBreakStatement(noInfo, new Word(noInfo, "myLabel"));
710          LabeledContinueStatement cs = new LabeledContinueStatement(noInfo, new Word(noInfo, "yourLabel"));
711          SimpleNameReference snr = new SimpleNameReference(noInfo, w);
712          SynchronizedStatement syncs = new SynchronizedStatement(noInfo, snr, b);
713          TypeParameter tp = new TypeParameter(noInfo, tv, superClass);
714          ConditionalExpression ce = new ConditionalExpression(noInfo, snr, snr, snr);
715          
716          TryCatchStatement tcs = new NormalTryCatchStatement(noInfo, b, new CatchBlock[0]);
717          SwitchCase defaultSc = new DefaultCase(SourceInfo.NONE, emptyUnbracedBody);
718          SwitchStatement ssBadDefault = 
719            new SwitchStatement(noInfo, new IntegerLiteral(SourceInfo.NONE, 5), new SwitchCase[]{defaultSc, defaultSc});
720         
721         si.visit(_fv);
722         assertEquals("There should be 0 errors", 0, errors.size());
723    
724         ls.visit(_fv);
725         assertEquals("There should be 0 errors", 0, errors.size());
726    
727         bs.visit(_fv);
728         assertEquals("There should be 0 errors", 0, errors.size());
729    
730         cs.visit(_fv);
731         assertEquals("There should be 0 errors", 0, errors.size());
732         
733         syncs.visit(_fv);
734         assertEquals("There should be 0 errors", 0, errors.size());
735        
736         tp.visit(_fv);
737         assertEquals("There should be 0 errors", 0, errors.size());
738    
739         ce.visit(_fv);
740         assertEquals("There should be 0 errors", 0, errors.size());
741         
742         tcs.visit(_fv);
743         assertEquals("There should be 0 errors", 0, errors.size());
744         
745         ssBadDefault.visit(_fv);
746         assertEquals("There should be 0 errors", 0, errors.size());
747         }
748        
749        public void testForPrimitiveTypeDoFirst() {
750          
751          SourceInfo noInfo = SourceInfo.NONE;
752          
753          //only primative types boolean, char, int, and double are allowed at Intermediate level. 
754          PrimitiveType i = new PrimitiveType(noInfo, "int");
755          PrimitiveType c = new PrimitiveType(noInfo, "char");
756          PrimitiveType d = new PrimitiveType(noInfo, "double");
757          PrimitiveType b = new PrimitiveType(noInfo, "boolean");
758          
759          i.visit(_fv);
760          assertEquals("After visiting int, errors should still be 0", 0, errors.size());
761          
762          c.visit(_fv);
763          assertEquals("After visiting char, errors should still be 0", 0, errors.size());
764          
765          d.visit(_fv);
766          assertEquals("After visiting double, errors should still be 0", 0, errors.size());
767          
768          b.visit(_fv);
769          assertEquals("After visiting boolean, errors should still be 0", 0, errors.size());
770          
771          // now the types that formerly threw errors:
772          
773          PrimitiveType byt = new PrimitiveType(noInfo, "byte");
774          PrimitiveType s = new PrimitiveType(noInfo, "short");
775          PrimitiveType l = new PrimitiveType(noInfo, "long");
776          PrimitiveType f = new PrimitiveType(noInfo, "float");
777          
778          byt.visit(_fv);
779          assertEquals("After visiting byte, errors should be 0", 0, errors.size());
780          
781          s.visit(_fv);
782          assertEquals("After visiting short, errors should be 0", 0, errors.size());
783          
784          l.visit(_fv);
785          assertEquals("After visiting long, errors should be 0", 0, errors.size());
786          
787          f.visit(_fv);
788          assertEquals("After visiting float, errors should be 0", 0, errors.size());
789        }
790        
791        public void testForArrayType() {
792    //      System.err.println("**** Starting testForArrayType");
793          SymbolData sd = new SymbolData("Name");
794          sd.setIsContinuation(false);
795          sd.setInterface(false);
796          sd.setPackage("");
797          sd.setTypeParameters(new TypeParameter[0]);
798          sd.setInterfaces(new ArrayList<SymbolData>()); 
799          sd.setSuperClass(LanguageLevelConverter.symbolTable.get("java.lang.Object"));
800          LanguageLevelConverter.symbolTable.put("Name", sd);
801                           
802          ArrayInitializer ai = new ArrayInitializer(SourceInfo.NONE, new VariableInitializerI[0]);
803          TypeVariable tv = new TypeVariable(SourceInfo.NONE, "Name");
804          ArrayType at = new ArrayType(SourceInfo.NONE, "Name[]", tv);
805          
806          at.visit(_fv);
807          assertEquals("There should be no errors", 0, errors.size());
808          SymbolData asd = LanguageLevelConverter.symbolTable.get("Name[]");
809          assertNotNull("asd should not be null", asd);
810          ArrayData ad = (ArrayData) asd;
811          assertEquals("ad should have an elt sd of name 'Name'", "Name", ad.getElementType().getName());
812          
813          //Test a multi-dimensional array
814          tv = new TypeVariable(SourceInfo.NONE, "java.lang.Object");
815          at = new ArrayType(SourceInfo.NONE, "Object[]", tv);
816          ArrayType at2 = new ArrayType(SourceInfo.NONE, "Object[][]", at);
817    
818          at2.visit(_fv);
819          assertEquals("There should be no errors", 0, errors.size());
820          assertNotNull("Object should be in the symbolTable", LanguageLevelConverter.symbolTable.get("java.lang.Object"));
821          assertNotNull("Object[] should be in the symbolTable", 
822                        LanguageLevelConverter.symbolTable.get("java.lang.Object[]"));
823          assertNotNull("Object[][] should be in the symbolTable", 
824                        LanguageLevelConverter.symbolTable.get("java.lang.Object[][]"));
825        }
826        
827        // TODO: resurrect a test of this method
828    //    public void testCreateConstructor() {
829    //      SymbolData sd = 
830    //        new SymbolData("ClassName", _publicMav, new TypeParameter[0], null, new LinkedList<SymbolData>(), null);
831    //      VariableData v1 = new VariableData("i", _publicMav, SymbolData.INT_TYPE, false, sd);
832    //      VariableData v2 = new VariableData("j", _publicMav, SymbolData.CHAR_TYPE, false, sd);
833    //      VariableData v3 = new VariableData("var", _publicMav, SymbolData.DOUBLE_TYPE, false, sd);
834    //      sd.addVar(v1);
835    //      sd.addVar(v2);
836    //      sd.setSuperClass(_sd1);
837    //      
838    //      MethodData md = new MethodData("ClassName", _publicMav, new TypeParameter[0], sd, 
839    //                                   new VariableData[0], 
840    //                                   new String[0], 
841    //                                   sd,
842    //                                   null);
843    //      md.addVars(md.getParams());
844    //      _fv.createConstructor(sd);
845    //      
846    //      assertEquals("sd should have 1 method: its own constructor", md, sd.getMethods().getFirst());
847    //      
848    //      // since this is the only constructor in the symbol data, all the fields should be assigned to have a value after 
849    //      // visiting sd.
850    //      v1 = new VariableData("i", _publicMav, SymbolData.INT_TYPE, true, sd);
851    //      v2 = new VariableData("j", _publicMav, SymbolData.CHAR_TYPE, true, sd);
852    //
853    //      
854    //      //now test a subclass of sd:
855    //      SymbolData subSd = 
856    //        new SymbolData("Subclass",_publicMav, new TypeParameter[0], null, new ArrayList<SymbolData>(), null);
857    //      subSd.addVar(v3);
858    //      subSd.setSuperClass(sd);
859    //
860    //      
861    //      VariableData v1Param = new VariableData("super_i", _packageMav, SymbolData.INT_TYPE, true, null);
862    //      VariableData v2Param = new VariableData("super_j", _packageMav, SymbolData.CHAR_TYPE, true, null);
863    //      VariableData[] vars = {v1Param, v2Param, v3};
864    //      MethodData md2 = new MethodData("Subclass", _publicMav, new TypeParameter[0], subSd,
865    //                                      new VariableData[0], new String[0], subSd, null);
866    //      md2.addVars(md2.getParams());
867    //                
868    //      _fv.createConstructor(subSd);
869    //      v1Param.setEnclosingData(subSd.getMethods().getFirst());
870    //      v2Param.setEnclosingData(subSd.getMethods().getFirst());
871    //      assertEquals("subSd should have 1 method: its own constructor.", md2, subSd.getMethods().getFirst());
872    //    }
873    //    
874    //    public void xtest_getFieldAccessorName() {
875    //      // This may change in the future if we change getFieldAccessorName
876    //      assertEquals("Should correctly convert from lower case to upper case", "name", _fv.getFieldAccessorName("name"));
877    //    }
878        
879        //ToString, HashCode, and Equals should be no-ops.
880        public void testCreateToString() {
881          SymbolData sd = 
882            new SymbolData("ClassName", _publicMav, new TypeParameter[0], null, new ArrayList<SymbolData>(), null);
883          _fv.createToString(sd);
884          //should have been no-op
885          assertEquals("sd should have no methods", 0, sd.getMethods().size());
886        }
887        
888        public void testCreateHashCode() {
889          SymbolData sd = 
890            new SymbolData("ClassName", _publicMav, new TypeParameter[0], null, new ArrayList<SymbolData>(), null);      
891          _fv.createHashCode(sd);
892          //should have been no-op
893          assertEquals("sd should have 0 methods", 0, sd.getMethods().size());
894        }
895        
896        public void testCreateEquals() {
897          SymbolData sd = 
898            new SymbolData("ClassName", _publicMav, new TypeParameter[0], null, new ArrayList<SymbolData>(), null);
899          _fv.createEquals(sd);
900          //should have been no-op
901          assertEquals("sd should have 0 methods", 0, sd.getMethods().size());
902        }
903        
904        public void testForClassDef() {
905    //      System.err.println("**** Starting testForClassDef");
906          //check an example that's not abstract
907          
908          // Top-level init
909          initTopLevel();
910          
911          ClassDef cd0 = 
912            new ClassDef(SourceInfo.NONE, _packageMav, 
913                         new Word(SourceInfo.NONE, "Lisa"),
914                         new TypeParameter[0], 
915                         new ClassOrInterfaceType(SourceInfo.NONE, "java.lang.Object", new Type[0]), 
916                         new ReferenceType[0], 
917                         new BracedBody(SourceInfo.NONE, new BodyItemI[0])); 
918          
919          cd0.visit(_fv);
920          assertEquals("There should be no errors", 0, errors.size());
921          assertTrue("Should have resolved java.lang.Object", 
922                     LanguageLevelConverter.symbolTable.containsKey("java.lang.Object"));
923          assertFalse("Should not be a continuation", 
924                      LanguageLevelConverter.symbolTable.get("java.lang.Object").isContinuation());
925          SymbolData sd = LanguageLevelConverter.symbolTable.get("Lisa");
926          assertTrue("Lisa should be in _newSDs", LanguageLevelConverter._newSDs.containsKey(sd));
927          assertEquals("sd should have no methods", 0, sd.getMethods().size());
928          assertEquals("sd's package should be correct", "", sd.getPackage());
929          
930          // check an example that's abstract
931          assert _fv._package == "";
932          ClassDef cd1 = 
933            new ClassDef(SourceInfo.NONE, _abstractMav, new Word(SourceInfo.NONE, "Bart"),
934                         new TypeParameter[0], 
935                         new ClassOrInterfaceType(SourceInfo.NONE, "System", new Type[0]), 
936                         new ReferenceType[0], 
937                         new BracedBody(SourceInfo.NONE, new BodyItemI[0]));
938          cd1.visit(_fv);
939          assertEquals("There should be no errors", 0, errors.size());
940          assertTrue("Should have resolved java.lang.System", 
941                     LanguageLevelConverter.symbolTable.containsKey("java.lang.System"));
942          assertFalse("Should not be a continuation", 
943                      LanguageLevelConverter.symbolTable.get("java.lang.System").isContinuation());
944          sd = LanguageLevelConverter.symbolTable.get("Bart");
945          
946          assertEquals("There should be 0 methods", 0, sd.getMethods().size()); //(no code augmentation is done)
947          
948          //Check an example where the class extends TestCase, and has a test method that returns void.
949          ConcreteMethodDef cmd = new ConcreteMethodDef(SourceInfo.NONE, 
950                                                        _packageMav, 
951                                                        new TypeParameter[0], 
952                                                        new VoidReturn(SourceInfo.NONE, "void"), 
953                                                        new Word(SourceInfo.NONE, "testMethodName"),
954                                                        new FormalParameter[0],
955                                                        new ReferenceType[0], 
956                                                        new BracedBody(SourceInfo.NONE, new BodyItemI[0]));
957    
958          ClassDef cd3 = 
959            new ClassDef(SourceInfo.NONE, 
960                         _abstractMav, 
961                         new Word(SourceInfo.NONE, "TestSuper2"),
962                         new TypeParameter[0], new ClassOrInterfaceType(SourceInfo.NONE, "TestCase", new Type[0]), 
963                         new ReferenceType[0], 
964                         new BracedBody(SourceInfo.NONE, new BodyItemI[] {cmd}));
965    
966    
967          _fv._file = new File("TestSuper2.dj2");
968          _fv._importedFiles.addLast("junit.framework.TestCase");
969          LanguageLevelConverter.symbolTable.put("junit.framework.TestCase", new SymbolData("junit.framework.TestCase"));
970          cd3.visit(_fv);
971          assertEquals("There should still just be no errors", 0, errors.size());
972          assertNotNull("Should have looked up TestSuper2", 
973                        LanguageLevelConverter.symbolTable.get("TestSuper2"));
974          
975          //Check a method with void return, but name not starting with test, so it's not okay.
976          //This is now checked in the type checker!
977          ConcreteMethodDef cmd2 = new ConcreteMethodDef(SourceInfo.NONE, 
978                                                        _packageMav, 
979                                                        new TypeParameter[0], 
980                                                        new VoidReturn(SourceInfo.NONE, "void"), 
981                                                        new Word(SourceInfo.NONE, "uhOh"),
982                                                        new FormalParameter[0],
983                                                        new ReferenceType[0], 
984                                                        new BracedBody(SourceInfo.NONE, new BodyItemI[0]));
985    
986          ClassDef cd4 = 
987            new ClassDef(SourceInfo.NONE, 
988                         _abstractMav, 
989                         new Word(SourceInfo.NONE, "TestVoidNoTestMethod"),
990                         new TypeParameter[0], 
991                         new ClassOrInterfaceType(SourceInfo.NONE,"junit.framework.TestCase", new Type[0]), 
992                         new ReferenceType[0], 
993                         new BracedBody(SourceInfo.NONE, new BodyItemI[] { cmd2 }));
994    
995          _fv._file = new File("TestVoidNoTestMethod.dj2");
996          cd4.visit(_fv);
997    
998          assertEquals("There should still be 0 errors", 0, errors.size());
999          _fv._importedFiles.remove("junit.framework.TestCase"); 
1000    //      System.err.println("**** Ending testForClassDef");
1001        }
1002        
1003        public void testForInterfaceDef() {
1004          AbstractMethodDef amd = 
1005            new AbstractMethodDef(SourceInfo.NONE, 
1006                                  _publicMav, 
1007                                  new TypeParameter[0], 
1008                                  new PrimitiveType(SourceInfo.NONE, "int"),
1009                                  new Word(SourceInfo.NONE, "myMethod"), 
1010                                  new FormalParameter[0], 
1011                                  new ReferenceType[0]);
1012          AbstractMethodDef amd2 = 
1013            new AbstractMethodDef(SourceInfo.NONE, 
1014                                  _publicMav, 
1015                                  new TypeParameter[0], 
1016                                  new PrimitiveType(SourceInfo.NONE, "int"),
1017                                  new Word(SourceInfo.NONE, "myMethod"), 
1018                                  new FormalParameter[0], 
1019                                  new ReferenceType[0]);
1020          InterfaceDef id = 
1021            new InterfaceDef(SourceInfo.NONE, 
1022                             _publicMav, 
1023                             new Word(SourceInfo.NONE, "id"), 
1024                             new TypeParameter[0], 
1025                             new ReferenceType[0], 
1026                             new BracedBody(SourceInfo.NONE, new BodyItemI[] { amd }));
1027          InterfaceDef id2 = 
1028            new InterfaceDef(SourceInfo.NONE, 
1029                             _publicMav, 
1030                             new Word(SourceInfo.NONE, "id2"), 
1031                             new TypeParameter[0], 
1032                             new ReferenceType[] { new ClassOrInterfaceType(SourceInfo.NONE, "id", new Type[0]) }, 
1033                             new BracedBody(SourceInfo.NONE, new BodyItemI[] { amd2 }));
1034          SymbolData sd = new SymbolData("i.like.monkey.id", _publicMav, new TypeParameter[0], new ArrayList<SymbolData>(), null);
1035          sd.setIsContinuation(true);
1036          MethodData md = 
1037            new MethodData("myMethod", _publicMav, new TypeParameter[0], SymbolData.INT_TYPE, new VariableData[0], 
1038                           new String[0], sd, amd);
1039    
1040          ArrayList<SymbolData> interfaces = new ArrayList<SymbolData>();
1041          interfaces.add(sd);
1042          SymbolData sd2 = new SymbolData("i.like.monkey.id2", _publicMav, new TypeParameter[0], interfaces, null);
1043          sd2.setIsContinuation(true);
1044          MethodData md2 = 
1045            new MethodData("myMethod", _publicMav, new TypeParameter[0], SymbolData.INT_TYPE, new VariableData[0], 
1046                           new String[0], sd2, amd2);
1047          
1048          LanguageLevelConverter.symbolTable.put("i.like.monkey.id", sd);
1049          LanguageLevelConverter.symbolTable.put("i.like.monkey.id2", sd2);
1050    
1051          id.visit(_fv);
1052          id2.visit(_fv);
1053          assertEquals("Should be no errors", 0, errors.size());
1054          assertEquals("Should return the same symbol datas: id", sd, 
1055                       LanguageLevelConverter.symbolTable.get("i.like.monkey.id"));
1056          assertEquals("Should return the same symbol datas:id2 ", sd2, 
1057                       LanguageLevelConverter.symbolTable.get("i.like.monkey.id2"));
1058        }
1059        
1060        public void testHandleInnerClassDef() { 
1061    //      System.err.println("**** Starting testHandleInnerClassDef");
1062          // setUp has created a FullJavaVisitor which initializes the symbolTable
1063          
1064    //      LanguageLevelConverter.symbolTable.put("java.lang.Object", _objectSD);
1065          InnerClassDef cd1 = 
1066            new InnerClassDef(SourceInfo.NONE, 
1067                              _packageMav, 
1068                              new Word(SourceInfo.NONE, "Bart"),
1069                              new TypeParameter[0], 
1070                              new ClassOrInterfaceType(SourceInfo.NONE, "java.lang.Object", new Type[0]), 
1071                              new ReferenceType[0], 
1072                              new BracedBody(SourceInfo.NONE, new BodyItemI[0]));
1073          InnerClassDef cd0 = 
1074            new InnerClassDef(SourceInfo.NONE, 
1075                              _packageMav, 
1076                              new Word(SourceInfo.NONE, "Lisa"),
1077                              new TypeParameter[0], 
1078                              new ClassOrInterfaceType(SourceInfo.NONE, "java.lang.Object", new Type[0]), 
1079                              new ReferenceType[0], 
1080                              new BracedBody(SourceInfo.NONE, new BodyItemI[] { cd1 }));
1081    
1082    //      SymbolData outerData = new SymbolData("i.eat.potato");
1083    //      outerData.setIsContinuation(false);
1084    //      outerData.setSuperClass(_objectSD);
1085                                             
1086    //      SymbolData sd0 = 
1087    //        new SymbolData(outerData.getName() + "$Lisa", _packageMav, new TypeParameter[0], _objectSD, 
1088    //                       new ArrayList<SymbolData>(), null); 
1089    //      SymbolData sd1 = 
1090    //        new SymbolData(outerData.getName() + "$Lisa$Bart", _packageMav, new TypeParameter[0], _objectSD, 
1091    //                       new ArrayList<SymbolData>(), null); 
1092    //      
1093    //      outerData.addInnerClass(sd0);
1094    //      sd0.setOuterData(outerData);
1095    //
1096    //      sd0.addInnerClass(sd1);
1097    //      sd1.setOuterData(sd0);
1098    
1099    //      sd0.setIsContinuation(true);
1100    //      sd1.setIsContinuation(true);      
1101                
1102    //      LanguageLevelConverter.symbolTable.put(outerData.getName() + "$Lisa", sd0);
1103    
1104          _fv.handleInnerClassDef(cd0, _sd1, "Lisa", _sd1.getName() + ".Lisa");                        
1105                                  
1106          SymbolData sd0 = _sd1.getInnerClassOrInterface("Lisa");
1107          assertEquals("There should be no errors", 0, errors.size());
1108          assertNotNull("Lisa is inner class of i.like.monkey", sd0);
1109          assertEquals("sd0 should have the correct outer data", _sd1, sd0.getOuterData());
1110          assertEquals("Lisa should have 0 methods", 0, sd0.getMethods().size());
1111          assertNotNull("symbolTable contains fully qualified name for Lisa", 
1112                        _fv.getQualifiedSymbolData("i.like.monkey.Lisa"));
1113          
1114          SymbolData sd1 = sd0.getInnerClassOrInterface("Bart");
1115          assertEquals("There should be no errors", 0, errors.size());
1116          assertNotNull("Bart is inner class of Lisa", sd1);
1117          assertEquals("sd1 should have the correct outer data", sd0, sd1.getOuterData());
1118          assertEquals("Bart should have 0 methods", 0, sd1.getMethods().size());
1119          assertNotNull("symbolTable contains fully qualified name for Bart", 
1120                        _fv.getQualifiedSymbolData("i.like.monkey.Lisa.Bart"));
1121    //      System.err.println("**** Ending testHandleInnerClassDef");
1122        }
1123        
1124        public void xtestHandleInnerInterfaceDef() {
1125          InnerInterfaceDef cd1 = 
1126            new InnerInterfaceDef(SourceInfo.NONE, _packageMav, new Word(SourceInfo.NONE, "Bart"),
1127                                  new TypeParameter[0], new ReferenceType[0], 
1128                                  new BracedBody(SourceInfo.NONE, new BodyItemI[0]));
1129          
1130          InnerInterfaceDef cd0 = 
1131            new InnerInterfaceDef(SourceInfo.NONE, _packageMav, new Word(SourceInfo.NONE, "Lisa"),
1132                                  new TypeParameter[0], new ReferenceType[0], 
1133                                  new BracedBody(SourceInfo.NONE, new BodyItemI[] { cd1 }));
1134    
1135          SymbolData outerData = new SymbolData("i.drink.vanilla.coke");
1136    
1137          
1138          SymbolData sd0 = 
1139            new SymbolData(outerData.getName() + "$Lisa", _packageMav, new TypeParameter[0], new ArrayList<SymbolData>(), 
1140                           null); 
1141          SymbolData sd1 = 
1142            new SymbolData(outerData.getName() + "$Lisa$Bart", _packageMav, new TypeParameter[0], 
1143                           new ArrayList<SymbolData>(), null);
1144          sd0.addInnerInterface(sd1);
1145          sd0.setIsContinuation(true);
1146          sd1.setIsContinuation(true);
1147    
1148          outerData.addInnerInterface(sd0);
1149          sd0.setOuterData(outerData);
1150    
1151          sd0.addInnerInterface(sd1);
1152          sd1.setOuterData(sd0);
1153    
1154          sd0.setIsContinuation(true);
1155          sd1.setIsContinuation(true);
1156    
1157          
1158          _fv.handleInnerInterfaceDef(cd0, outerData, "Lisa", outerData.getName() + "$Lisa");
1159    
1160          SymbolData sd = outerData.getInnerClassOrInterface("Lisa");
1161          
1162          assertEquals("There should be no errors", 0, errors.size());
1163          assertEquals("This symbolData should now have sd0 as an inner interface", sd0, sd);
1164          assertEquals("sd0 should have the correct outer data", outerData, sd0.getOuterData());
1165          assertEquals("sd1 should have the correct outer data", sd0, sd1.getOuterData());
1166          assertEquals("Sd should now have sd1 as an inner interface", sd1, sd.getInnerClassOrInterface("Bart"));
1167          assertTrue("Lisa should be an interface", sd0.isInterface());
1168          assertTrue("Bart should be an interface", sd1.isInterface());
1169        }
1170        
1171        
1172        public void testCreateMethodData() {
1173          // Test one that doesn't work at the old advanced level
1174          MethodDef mdef = new ConcreteMethodDef(SourceInfo.NONE, 
1175                                                        _volatileMav, 
1176                                                        new TypeParameter[0], 
1177                                                        new PrimitiveType(SourceInfo.NONE, "int"), 
1178                                                        new Word(SourceInfo.NONE, "methodName"),
1179                                                        new FormalParameter[0],
1180                                                        new ReferenceType[0], 
1181                                                        new BracedBody(SourceInfo.NONE, new BodyItemI[0]));
1182          
1183          MethodData mdata = new MethodData("methodName", _volatileMav, new TypeParameter[0], SymbolData.INT_TYPE, 
1184                                       new VariableData[0], 
1185                                       new String[0],
1186                                       _sd1,
1187                                       null);
1188          assertEquals("Should return the correct MethodData", mdata, _fv.createMethodData(mdef, _sd1));
1189          assertEquals("There should be no errors", 0, errors.size());
1190    
1191          mdef = new ConcreteMethodDef(SourceInfo.NONE, 
1192                                                        _finalMav, 
1193                                                        new TypeParameter[0], 
1194                                                        new PrimitiveType(SourceInfo.NONE, "int"), 
1195                                                        new Word(SourceInfo.NONE, "methodName2"),
1196                                                        new FormalParameter[0],
1197                                                        new ReferenceType[0], 
1198                                                        new BracedBody(SourceInfo.NONE, new BodyItemI[0]));
1199          
1200          mdata = new MethodData("methodName2", _finalMav, new TypeParameter[0], SymbolData.INT_TYPE, 
1201                                       new VariableData[0], 
1202                                       new String[0],
1203                                       _sd1,
1204                                       null);
1205          assertEquals("Should return the correct MethodData", mdata, _fv.createMethodData(mdef, _sd1));
1206          assertEquals("There should still be no errors", 0, errors.size());
1207    
1208          
1209          // Test one that does work.
1210          FormalParameter fp1 =
1211            new FormalParameter(SourceInfo.NONE, 
1212                                new UninitializedVariableDeclarator(SourceInfo.NONE, 
1213                                                                    new PrimitiveType(SourceInfo.NONE, "double"), 
1214                                                                    new Word (SourceInfo.NONE, "field1")),
1215                                false);
1216          FormalParameter fp2 =
1217            new FormalParameter(SourceInfo.NONE, 
1218                                new UninitializedVariableDeclarator(SourceInfo.NONE, 
1219                                                                    new PrimitiveType(SourceInfo.NONE, "int"), 
1220                                                                    new Word (SourceInfo.NONE, "field1")),
1221                                false);
1222          mdef =
1223            new AbstractMethodDef(SourceInfo.NONE, 
1224                                  _abstractMav, 
1225                                  new TypeParameter[] { new TypeParameter(SourceInfo.NONE,
1226                                                                          new TypeVariable(SourceInfo.NONE, "T"),
1227                                                                          new TypeVariable(SourceInfo.NONE, "U"))},
1228                                  new VoidReturn(SourceInfo.NONE, "void"), 
1229                                  new Word(SourceInfo.NONE, "methodName"),
1230                                  new FormalParameter[] {fp1, fp2},
1231                                  new ReferenceType[] { new TypeVariable(SourceInfo.NONE, "X") });
1232          VariableData[] vardatas =
1233            new VariableData[] { new VariableData("field1", _finalMav, SymbolData.DOUBLE_TYPE, true, null),
1234                                 new VariableData("field1", _finalMav, SymbolData.INT_TYPE, true, null) };
1235          mdata = new MethodData("methodName", 
1236                                 _abstractMav, 
1237                                 new TypeParameter[] { new TypeParameter(SourceInfo.NONE,
1238                                                                         new TypeVariable(SourceInfo.NONE, "T"),
1239                                                                         new TypeVariable(SourceInfo.NONE, "U"))}, 
1240                                 SymbolData.VOID_TYPE, 
1241                                 vardatas, 
1242                                 new String[] { "X" },
1243                                 _sd1,
1244                                 null);
1245          
1246          mdata.getParams()[0].setEnclosingData(mdata);
1247          mdata.getParams()[1].setEnclosingData(mdata);
1248          
1249          MethodData expectedMethod = _fv.createMethodData(mdef, _sd1);
1250          
1251          // have to add the parameters to the vars manually
1252          mdata.getParams()[0].setEnclosingData(expectedMethod);
1253          mdata.getParams()[1].setEnclosingData(expectedMethod);
1254          VariableData[] vd = new VariableData[] { 
1255            new VariableData("f,ield1", _finalMav, SymbolData.DOUBLE_TYPE, true, expectedMethod)
1256          };
1257          mdata.addVars(vd);  
1258    //      assertEquals("Should return the correct MethodData", mdata, expectedMethod);
1259          assertEquals("There should be 1 error", 1, errors.size());
1260          assertEquals("The first error message should be correct.", 
1261                       "You cannot have two method parameters with the same name", errors.get(0).getFirst());
1262        }
1263        
1264        /* NOTE: This is test excluded because the tested method is now a no-op. */
1265        public void xtestSimpleAnonymousClassInstantiationHelper() {
1266    //      System.err.println("**** Starting testSimpleAnonymousClassInstantiationHelper");
1267          SimpleAnonymousClassInstantiation basic = 
1268            new SimpleAnonymousClassInstantiation(SourceInfo.NONE, 
1269                                                  new ClassOrInterfaceType(SourceInfo.NONE, "java.lang.Object", new Type[0]), 
1270                                                  new ParenthesizedExpressionList(SourceInfo.NONE, new Expression[0]),
1271                                                  new BracedBody(SourceInfo.NONE, new BodyItemI[0]));
1272          
1273    
1274         _fv._package = "i.like";
1275         _fv.simpleAnonymousClassInstantiationHelper(basic, _sd1);
1276         assertEquals("There should be no errors", 0, errors.size());
1277         assertNotNull("Object should be in the symbol table", _objectSD);
1278         assertEquals("_sd1 should have one inner class", 1, _sd1.getInnerClasses().size());
1279         SymbolData inner = _sd1.getInnerClasses().get(0);
1280         assertEquals("The inner class should have the proper name", "i.like.monkey$1", inner.getName());
1281         assertEquals("The inner class should have proper outer data", _sd1, inner.getOuterData());
1282         assertEquals("The inner class should have proper super class", _objectSD, inner.getSuperClass());
1283         assertEquals("The inner class should have the right package", "i.like", inner.getPackage());
1284         assertEquals("The inner class should have 0 methods", 0, inner.getMethods().size());
1285         
1286    //     System.err.println("**** Ending testSimpleAnonymousClassInstantiationHelper");
1287        }
1288    
1289        /* NOTE: This is test excluded because the tested method is now a no-op. */
1290        public void xtestComplexAnonymousClassInstantiationHelper() {
1291          ComplexAnonymousClassInstantiation basic = 
1292            new ComplexAnonymousClassInstantiation(SourceInfo.NONE, 
1293                                                   new SimpleNameReference(SourceInfo.NONE,
1294                                                                           new Word(SourceInfo.NONE, "java.lang.Object")),
1295                                                   new ClassOrInterfaceType(SourceInfo.NONE, "Inner", new Type[0]), 
1296                                                   new ParenthesizedExpressionList(SourceInfo.NONE, new Expression[0]),
1297                                                   new BracedBody(SourceInfo.NONE, new BodyItemI[0]));
1298    
1299         _fv._package = "i.like";
1300         _fv._enclosingClassName = "i.like.monkey";
1301         _fv.complexAnonymousClassInstantiationHelper(basic, _sd1);  // TODO: the wrong enclosing context?
1302         assertEquals("There should be no errors", 0, errors.size());
1303         SymbolData obj = LanguageLevelConverter.symbolTable.get("java.lang.Object");
1304         assertNotNull("Object should be in the symbol table", obj);
1305         SymbolData objInner = LanguageLevelConverter.symbolTable.get("java.lang.Object.Inner");
1306         assertEquals("sd1 should have one inner class", 1, _sd1.getInnerClasses().size());
1307         SymbolData inner = _sd1.getInnerClasses().get(0);
1308         assertEquals("The inner class should have the proper name", "i.like.monkey$1", inner.getName());
1309         assertEquals("The inner class should have proper outer data", _sd1, inner.getOuterData());
1310         assertEquals("The inner class should have null as its super class", null, inner.getSuperClass());
1311         assertEquals("The inner class should have the right package", "i.like", inner.getPackage());
1312         assertEquals("The inner class should have 0 methods", 0, inner.getMethods().size());
1313        }
1314    
1315        /* NOTE: the following test is excluded because the anonymous class helper functions are now no-ops. */
1316        public void xtestForVariableDeclaration() {
1317          // Make sure that if forVariableDeclaration is called with a AnonymousClassInstantiation, the symbolData is only 
1318          // added once.  This is to make sure an old bug stays fixed.
1319          SimpleAnonymousClassInstantiation basic = 
1320            new SimpleAnonymousClassInstantiation(SourceInfo.NONE, 
1321                                                  new ClassOrInterfaceType(SourceInfo.NONE, "java.lang.Object", new Type[0]), 
1322                                                  new ParenthesizedExpressionList(SourceInfo.NONE, new Expression[0]),
1323                                                  new BracedBody(SourceInfo.NONE, new BodyItemI[0]));
1324          VariableDeclarator[] d1 = {
1325            new InitializedVariableDeclarator(SourceInfo.NONE, 
1326                                              new ClassOrInterfaceType(SourceInfo.NONE, "java.lang.Object", new Type[0]), 
1327                                              new Word(SourceInfo.NONE, "b"), basic)
1328          };
1329          VariableDeclaration vd1 = new VariableDeclaration(SourceInfo.NONE,_publicMav, d1); 
1330          
1331          ClassBodyFullJavaVisitor cbav = 
1332            new ClassBodyFullJavaVisitor(_sd1, _sd1.getName(), _fv._file, _fv._package, _fv._importedFiles, _fv._importedPackages, 
1333                                         _fv._classesInThisFile, _fv.continuations, _fv.fixUps);
1334          vd1.visit(cbav);
1335          assertEquals("Should be 1 inner class of _sd1", 1, _sd1.getInnerClasses().size());
1336    //      System.err.println("**** Completed testForVariableDeclaration");
1337        }
1338        
1339        public void testDummy() { }
1340      }
1341    }