Code Search for Developers
 
 
  

IntermediateVisitor.java from DrJava at Krugle


Show IntermediateVisitor.java syntax highlighted

/*BEGIN_COPYRIGHT_BLOCK
 *
 * Copyright (c) 2001-2007, JavaPLT group at Rice University (javaplt@rice.edu)
 * All rights reserved.
 * 
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *    * Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 *    * Redistributions in binary form must reproduce the above copyright
 *      notice, this list of conditions and the following disclaimer in the
 *      documentation and/or other materials provided with the distribution.
 *    * Neither the names of DrJava, the JavaPLT group, Rice University, nor the
 *      names of its contributors may be used to endorse or promote products
 *      derived from this software without specific prior written permission.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * This software is Open Source Initiative approved Open Source Software.
 * Open Source Initative Approved is a trademark of the Open Source Initiative.
 * 
 * This file is part of DrJava.  Download the current version of this project
 * from http://www.drjava.org/ or http://sourceforge.net/projects/drjava/
 * 
 * END_COPYRIGHT_BLOCK*/

package edu.rice.cs.javalanglevels;

import edu.rice.cs.javalanglevels.tree.*;
import edu.rice.cs.javalanglevels.parser.*;
import java.util.*;
import java.io.*;
import edu.rice.cs.plt.reflect.JavaVersion;

import junit.framework.TestCase;


/**
 * Top-level Language Level Visitor that represents the Intermediate Language Level.  Enforces constraints during the
 * first walk of the AST (checking for langauge specific errors and building the symbol table).
 * This class enforces things that are common to all contexts reachable at the Intermediate Language Level 
 * (i.e., inside class bodies, method bodies, interface bodies, etc), but also enforces specific top level 
 * constraints (i.e. you cannot have try catch statements at the top level, etc.)
 */
public class IntermediateVisitor extends LanguageLevelVisitor {
  
  /**
   * This constructor is called when creating a new instance of IntermediateVisitor.  The default 
   * value for className is the empty string.
   */
  public IntermediateVisitor(File file, String packageName, LinkedList<String> importedFiles, 
                         LinkedList<String> importedPackages,LinkedList<String> classNamesInThisFile, Hashtable<String, Pair<SourceInfo, LanguageLevelVisitor>> continuations) {
    super(file, packageName, importedFiles, importedPackages, classNamesInThisFile, continuations);
  }
  
  /**
   * This constructor is called when testing.  It initializes all of the static fields
   * of LanguageLevelVisitor.
   */
  public IntermediateVisitor(File file) {
    this(file, new LinkedList<Pair<String, JExpressionIF>>(), new Symboltable(), new Hashtable<String, Pair<SourceInfo, LanguageLevelVisitor>>(), new LinkedList<Pair<LanguageLevelVisitor, edu.rice.cs.javalanglevels.tree.SourceFile>>(), new Hashtable<SymbolData, LanguageLevelVisitor>(), JavaVersion.JAVA_5);
  }
    
   /**
   * This constructor is called from LanguageLevelVisitor and LanguageLevelConverter when they are instantiating a new
   * IntermediateVisitor to visit a new file with.  Package is set to "" by default.
   * @param file  The File corresponding to the source file we are visiting
   * @param errors  The list of errors that have been encountered so far.
   * @param symbolTable  The table of classes (types) that we have encountered
   * @param continuations  The table of classes we have encountered but still need to resolve
   * @param visitedFiles  The list of files we have visited
   * @param newSDs  The new symbol datas we have created (that will need to have constructors created for them after this pass is finished)
   * @param targetVersion  The version of the Java compiler ("1.4", "1.5", etc) that the user is using.  Important for doing autoboxing.
   */
  public IntermediateVisitor(File file, LinkedList<Pair<String, JExpressionIF>> errors, Symboltable symbolTable, Hashtable<String, Pair<SourceInfo, LanguageLevelVisitor>> continuations, LinkedList<Pair<LanguageLevelVisitor, SourceFile>> visitedFiles, Hashtable<SymbolData, LanguageLevelVisitor> newSDs, JavaVersion targetVersion) {
    super(file, "", new LinkedList<String>(), new LinkedList<String>(), new LinkedList<String>(), continuations);
    this.targetVersion = targetVersion;
    this.errors = errors;
    this.symbolTable = symbolTable;
    this.visitedFiles= visitedFiles;
    this._newSDs = newSDs;
    _hierarchy = new Hashtable<String, TypeDefBase>();//hierarchy;
    _classesToBeParsed = new Hashtable<String, Pair<TypeDefBase, LanguageLevelVisitor>>();
  }
  
  
  /**Only abstract, public, private, protected, and static are allowed at this level.*/
  public void forModifiersAndVisibilityDoFirst(ModifiersAndVisibility that) {
    String[] modifiersAndVisibility = that.getModifiers();
    StringBuffer sb = new StringBuffer();
    String temp;
    int count = 0;    
    for(int i = 0; i < modifiersAndVisibility.length; i++) {
      temp = modifiersAndVisibility[i];
      if (!(temp.equals("abstract") || temp.equals("public") || temp.equals("private") || temp.equals("protected") || temp.equals("static"))) {
        sb.append(" \"" + temp + "\"");
        count++;
      }
    }
    // check if any illegal keywords were found
    temp = "The keyword";
    if (sb.length() > 0) {
      if (count > 1) {
        temp = temp + "s";
      }
      _addAndIgnoreError(temp + sb.toString() + " cannot be used at the Intermediate level", that);
      return;
    }
    super.forModifiersAndVisibilityDoFirst(that);
  }

  
  /** Do not allow explicit Package Statements at the Intermediate Level. */
  public void forPackageStatementDoFirst(PackageStatement that) {
    _addError("Package statements cannot be used at the Intermediate level.  All Intermediate level classes and interfaces are assumed to be in the default package", that);
  }
  
  /**Do not allow inner classes at the Intermediate Level.*/
  public void forInnerClassDefDoFirst(InnerClassDef that) {
    _addError("Inner classes cannot be used at the Intermediate level", that);
  }

  /**Do not allow inner interfaces at the Intermediate Level.*/
    public void forInnerInterfaceDefDoFirst(InnerInterfaceDef that) {
    _addError("Nested interfaces cannot be used at the Intermediate level", that);
  }

  /**Do not allow static intiializers at the Intermediate Level.*/
  public void forStaticInitializerDoFirst(StaticInitializer that) {
    _addError("Static initializers cannot be used at the Intermediate level", that);
  }

  /**Do not allow labeled statements at the Intermediate Level.*/
  public void forLabeledStatementDoFirst(LabeledStatement that) {
    _addError("Labeled statements cannot be used at the Intermediate level", that);
  }

  /**Do not allow switch statements at the Intermediate Level.*/
  public void forSwitchStatementDoFirst(SwitchStatement that) {
    _addError("Switch statements cannot be used at the Intermediate level", that);
  }

  /**Do not allow while statements at the Intermediate Level.*/
  public void forWhileStatementDoFirst(WhileStatement that) {
    _addError("While statements cannot be used at the Intermediate level", that);
  }

  /**Do not allow do statements at the Intermediate Level.*/
  public void forDoStatementDoFirst(DoStatement that) {
    _addError("Do statements cannot be used at the Intermediate level", that);
  }

  /**Do not allow for statements at the Intermediate Level.*/
  public void forForStatementDoFirst(ForStatement that) {
    _addError("For statements cannot be used at the Intermediate level", that);
  }

  /**Do not allow break statements at the Intermediate Level.*/
  public void forBreakStatementDoFirst(BreakStatement that) {
    _addError("Break statements cannot be used at the Intermediate level", that);
  }

  /**Do not allow continue statements at the Intermediate Level.*/
  public void forContinueStatementDoFirst(ContinueStatement that) {
    _addError("Continue statements cannot be used at the Intermediate level", that);
  }

  /**Do not allow synchronized statements at the Intermediate Level.*/
  public void forSynchronizedStatementDoFirst(SynchronizedStatement that) {
    _addError("Synchronized statements cannot be used at the Intermediate level", that);
  }

  /**Do not allow try-catch statements at the Intermediate Level.*/
  public void forTryCatchStatementDoFirst(TryCatchStatement that) {
    _addAndIgnoreError("A try-catch statement cannot appear here", that);
  }

  /**Make sure that the formal parameter is not final*/
  public void forFormalParameterDoFirst(FormalParameter that) {
    if (that.isIsFinal()) {
      _addError("The keyword \"final\" cannot be used at the Intermediate level", that);
    }
    else {
      forJExpressionDoFirst(that);
    }
  }

  /**Do not allow type parameters (generics) at the Intermediate level*/
  public void forTypeParameterDoFirst(TypeParameter that) {
    _addError("Type Parameters cannot be used at the Intermediate level", that);
  }

  /**Only allow the 4 basic primitives: int, double, boolean, and char*/
  public void forPrimitiveTypeDoFirst(PrimitiveType that) {
    String name = that.getName();
    if (!(name.equals("int") || name.equals("double") || name.equals("boolean") || name.equals("char"))) {
      _addError("Only the primitive types \"int\", \"double\", \"boolean\", and \"char\" can be used at the Intermediate level", that);
    }
    else {
      forTypeDoFirst(that);
    }
  }

  /**Do not allow arrays at the Intermediate Level*/
  public void forArrayTypeDoFirst(ArrayType that) {
    _addError("Arrays cannot be used at the Intermediate level", that);
  }

  /**Do not allow conditional expressions at the Intermediate Level*/
  public void forConditionalExpressionDoFirst(ConditionalExpression that) {
    _addError("Conditional expressions cannot be used at the Intermediate level", that);
  }

  /**Do not allow instanceof expressions at the Intermediate Level*/
  public void forInstanceofExpressionDoFirst(InstanceofExpression that) {
    _addError("Instanceof expressions cannot be used at the Intermediate level", that);
  }
  
  
  /*Check to see if className is one of the classes declared in the current source file,
   * by looking through classNamesInThisFile.*/
  private boolean _isClassInCurrentFile(String className) {
    Iterator<String> iter = _classNamesInThisFile.iterator();
    while (iter.hasNext()) {
      String s = iter.next();
      if (s.equals(className) || s.endsWith("." + className)) {
        return true;
      }
    }
    return false;   
  }  
  
  /*
   * Use the doFirst method to make sure there aren't any errors with the declaration.  Then, 
   * use addSymbolData to create the appropriate symbol data, and then visit the class body.  
   * Finally, autogenerate the toString, equals, hashCode, and accessor
   * methods.  The constructor will be autogenerated right before the TypeChecking pass starts.
   * Once the class def has been handled, remove it from classesToBeParsed.
   */
  public void forClassDef(ClassDef that) {    
    forClassDefDoFirst(that);
    if (prune(that)) { return; }

    String className = getQualifiedClassName(that.getName().getText());
    SymbolData sd = addSymbolData(that, className);
   
    that.getMav().visit(this);
    that.getName().visit(this);
    for (int i = 0; i < that.getTypeParameters().length; i++) that.getTypeParameters()[i].visit(this);
    for (int i = 0; i < that.getInterfaces().length; i++) that.getInterfaces()[i].visit(this);
    
    if (sd != null) {
      that.getBody().visit(new ClassBodyIntermediateVisitor(sd, _file, _package, _importedFiles, _importedPackages, _classNamesInThisFile, continuations));
      createAccessors(sd, _file);
      createToString(sd);
      createHashCode(sd);
      createEquals(sd);
    }
    forClassDefOnly(that);

    _classesToBeParsed.remove(className);
  }

   /**
    * Use the doFirst method to make sure that there aren't any errors with the declaration.
    * Create a SymbolData corresponding to this interface and add it appropriately.
    * Then visit the body to handle anything defined inside the interface.
    * Once the interface has been resolved, remove it from _classesToBeParsed.
    */
  public void forInterfaceDef(InterfaceDef that) {
    forInterfaceDefDoFirst(that);
    if (prune(that)) { return; }
    String className = that.getName().getText();
    that.getMav().visit(this);
    that.getName().visit(this);
    for (int i = 0; i < that.getTypeParameters().length; i++) that.getTypeParameters()[i].visit(this);
    SymbolData sd = addSymbolData(that, getQualifiedClassName(className));
    if (sd != null) {
      sd.setInterface(true);
      that.getBody().visit(new InterfaceBodyIntermediateVisitor(sd, _file, _package, _importedFiles, _importedPackages, _classNamesInThisFile, continuations));
    }
      
    forInterfaceDefOnly(that);
    _classesToBeParsed.remove(getQualifiedClassName(className));
  }  
  
  
    /**
   * Call the super method to convert these to a VariableData array, then make sure that
   * each VariableData is final, as required at the Intermediate level.
   * @param enclosingData  The Data which contains the variables
   */
  protected VariableData[] _variableDeclaration2VariableData(VariableDeclaration vd, Data enclosingData) {
    VariableData[] vds = super._variableDeclaration2VariableData(vd, enclosingData);
    for (int i = 0; i < vds.length; i++) {
      if ((vds[i].hasModifier("static") && vds[i].getMav().getModifiers().length > 1) || (!vds[i].hasModifier("static") && vds[i].getMav().getModifiers().length > 0)) {
        StringBuffer s = new StringBuffer("the keyword(s) ");
        String[] modifiers = vds[i].getMav().getModifiers();
        for (int j = 0; j<modifiers.length; j++) {
          if (!modifiers[j].equals("static")) {s.append("\"" + modifiers[j] + "\" ");}
        }
        _addAndIgnoreError("You cannot use " + s.toString() + "to declare a field at the Intermediate level.  Only the keyword 'static' is allowed", vd);
      }
      if (vds[i].hasModifier("static")) {vds[i].addModifier("public");}
      else {vds[i].addModifier("private");}
      vds[i].setFinal();
    }
    return vds;
  }

  /**
   * Pass this call directly onto the language level visitor.  This is a hack to 
   * bypass the privateAndFinal setting when we are dealing with local variables.
   */
  protected VariableData[] llVariableDeclaration2VariableData(VariableDeclaration vd, Data enclosingData) {
    return super._variableDeclaration2VariableData(vd, enclosingData);
  }

 
  /**
   * Do the work that is shared between SimpleAnonymousClassInstantiations and ComplexAnonymousClassInstantiations.
   * Do not generate automatic accessors for the anonymous class--this will be done in type checker pass.
   * @param that  The AnonymousClassInstantiation being visited
   * @param enclosing  The enclosing Data
   * @param superC  The super class being instantiated--i.e. new A() { ...}, would have a super class of A.
   */
  public void anonymousClassInstantiationHelper(AnonymousClassInstantiation that, Data enclosing, SymbolData superC) {
    that.getArguments().visit(this); 
    
    //Get the SymbolData that will correspond to this anonymous class
    SymbolData sd = new SymbolData(getQualifiedClassName(enclosing.getSymbolData().getName()) + "$" + enclosing.getSymbolData().preincrementAnonymousInnerClassNum());
    enclosing.addInnerClass(sd);
    sd.setOuterData(enclosing);
    sd.setSuperClass(superC); //the super class is what was passed in
    sd.setPackage(_package);
    
    createToString(sd);
    createHashCode(sd);
    createEquals(sd);
    //accessors will be filled in in typeChecker pass
    
    //visit the body to get it all nice and resolved.
    that.getBody().visit(new ClassBodyIntermediateVisitor(sd, _file, _package, _importedFiles, _importedPackages, _classNamesInThisFile, continuations));

  }
  
  /**
   * Look up the super type of this class instantiation and add it to the symbol table.
   * Visit the body of the class instantiation.  All handling of this as an anonymous inner class (i.e. adding it to
   * the enclosing SD's list of inner classes, creating a symbol data for the anonyomous inner class, etc) will be handled
   * in the TypeChecker pass.  This is because no one will depend on that symbolData until we create it.
   * @param that  The SimpleAnonymousClassInstantiation being processed.
   */
  public void simpleAnonymousClassInstantiationHelper(SimpleAnonymousClassInstantiation that, Data data) {
    forSimpleAnonymousClassInstantiationDoFirst(that);
    if (prune(that)) { return; }

    //resolve the super class and make sure it will be in the SymbolTable.
    SymbolData superC = getSymbolData(that.getType().getName(), that.getSourceInfo());
    
    anonymousClassInstantiationHelper(that, data, superC);

    forSimpleAnonymousClassInstantiationOnly(that);
  }
  
  /**
   * Do not resolve the super class type of this instantiation, becuase it will have already been resolved (it
   * is an inner class of the enclosing of this instantiation.  When the enclosing was resolved, all of its inner classes should have
   * also been resolved).
   * Visit the body of the class instantiation.  
   * @param that  The ComplexAnonymousClassInstantiation being processed.
   * @param data  The enclosing data where this was sreferenced from.
   */
  public void complexAnonymousClassInstantiationHelper(ComplexAnonymousClassInstantiation that, Data data) {
    forComplexAnonymousClassInstantiationDoFirst(that);
    if (prune(that)) {return;}
    
    //visit the enclosing 
    that.getEnclosing().visit(this);
    
    //no need to resolve the super class of the type being instantiated, because it is a complex type, so its enclosing data should
    //get added to the symbolTable along with it wherever we resolved its enclosing data.
    
    //originally, make super class null.  This will be updated in the TypeChecker pass.
    anonymousClassInstantiationHelper(that, data, null);

    
    forComplexAnonymousClassInstantiationOnly(that);
  }
  
  
  
   /**
    * Test the methods declared in the above class.
    */
  public static class IntermediateVisitorTest extends TestCase {
    
    private IntermediateVisitor _iv;
    
    private SymbolData _sd1;
    private SymbolData _sd2;
    private SymbolData _sd3;
    private SymbolData _sd4;
    private SymbolData _sd5;
    private SymbolData _sd6;
    private ModifiersAndVisibility _publicMav = new ModifiersAndVisibility(JExprParser.NO_SOURCE_INFO, new String[] {"public"});
    private ModifiersAndVisibility _protectedMav = new ModifiersAndVisibility(JExprParser.NO_SOURCE_INFO, new String[] {"protected"});
    private ModifiersAndVisibility _privateMav = new ModifiersAndVisibility(JExprParser.NO_SOURCE_INFO, new String[] {"private"});
    private ModifiersAndVisibility _packageMav = new ModifiersAndVisibility(JExprParser.NO_SOURCE_INFO, new String[0]);
    private ModifiersAndVisibility _abstractMav = new ModifiersAndVisibility(JExprParser.NO_SOURCE_INFO, new String[] {"abstract"});
    private ModifiersAndVisibility _staticMav = new ModifiersAndVisibility(JExprParser.NO_SOURCE_INFO, new String[] {"static"});
    private ModifiersAndVisibility _finalMav = new ModifiersAndVisibility(JExprParser.NO_SOURCE_INFO, new String[] {"final"});
    
    
    public IntermediateVisitorTest() {
      this("");
    }
    public IntermediateVisitorTest(String name) {
      super(name);
//      _file = File.createTempFile("DrJava-test", ".java");
//      _iv = new ElementaryVisitor(new File(""), "", new LinkedList<String>(), new LinkedList<String>(), 
//                                 new LinkedList<String>());
          }
    
    public void setUp() {

      errors = new LinkedList<Pair<String, JExpressionIF>>();
      symbolTable = new Symboltable();
      visitedFiles = new LinkedList<Pair<LanguageLevelVisitor, edu.rice.cs.javalanglevels.tree.SourceFile>>();      
      _hierarchy = new Hashtable<String, TypeDefBase>();
      _classesToBeParsed = new Hashtable<String, Pair<TypeDefBase, LanguageLevelVisitor>>();
      _iv = new IntermediateVisitor(new File(""), errors, symbolTable, continuations, new LinkedList<Pair<LanguageLevelVisitor, edu.rice.cs.javalanglevels.tree.SourceFile>>(), new Hashtable<SymbolData, LanguageLevelVisitor>(), JavaVersion.JAVA_5);
      _iv.continuations = new Hashtable<String, Pair<SourceInfo, LanguageLevelVisitor>>();
      _iv._resetNonStaticFields();
      _iv._importedPackages.addFirst("java.lang");
      _errorAdded = false;
      _sd1 = new SymbolData("i.like.monkey");
      _sd2 = new SymbolData("i.like.giraffe");
      _sd3 = new SymbolData("zebra");
      _sd4 = new SymbolData("u.like.emu");
      _sd5 = new SymbolData("");
      _sd6 = new SymbolData("cebu");
    }
    
    public void testForModifiersAndVisibilityDoFirst() {
      
      //Check that the proper modifiers are allowed:
      _iv.forModifiersAndVisibilityDoFirst(_abstractMav);
      _iv.forModifiersAndVisibilityDoFirst(_publicMav);
      _iv.forModifiersAndVisibilityDoFirst(_privateMav);
      _iv.forModifiersAndVisibilityDoFirst(_protectedMav);
      _iv.forModifiersAndVisibilityDoFirst(_staticMav);
      
      ModifiersAndVisibility mavs = new ModifiersAndVisibility(JExprParser.NO_SOURCE_INFO, 
                                                                new String[] {"private", "static"});
       _iv.forModifiersAndVisibilityDoFirst(mavs);
      assertEquals("there should still be 0 errors", 0, errors.size());

      //check errors:
      
      _iv.forModifiersAndVisibilityDoFirst(_finalMav);
      assertEquals("there should now be 1 errors", 1, errors.size());
      assertEquals("The error message should be correct for private modifier:", "The keyword \"final\" cannot be used at the Intermediate level", errors.get(0).getFirst());

      ModifiersAndVisibility mavs2 = new ModifiersAndVisibility(JExprParser.NO_SOURCE_INFO, 
                                                                new String[] {"private", "final"});
     
      _iv.forModifiersAndVisibilityDoFirst(mavs2);
      assertEquals("There should now be 2 errors", 2, errors.size());
      assertEquals("The error message should be correct for 1 bad, 1 good modifier:", "The keyword \"final\" cannot be used at the Intermediate level", errors.get(1).getFirst());

      ModifiersAndVisibility mavs3 = new ModifiersAndVisibility(JExprParser.NO_SOURCE_INFO, 
                                                                new String[] {"final", "native"});
     
      _iv.forModifiersAndVisibilityDoFirst(mavs3);
      assertEquals("There should now be 3 errors", 3, errors.size());
      assertEquals("The error message should be correct for 2 bad modifiers:", "The keywords \"final\" \"native\" cannot be used at the Intermediate level", errors.get(2).getFirst());

      
    }
    
    public void testForClassDefDoFirst() {
      //check an example that works
      ClassDef cd0 = new ClassDef(JExprParser.NO_SOURCE_INFO, _publicMav, new Word(JExprParser.NO_SOURCE_INFO, "Lisa"),
                                  new TypeParameter[0], new ClassOrInterfaceType(JExprParser.NO_SOURCE_INFO, "java.lang.Object", new Type[0]), new ReferenceType[0], 
                                  new BracedBody(JExprParser.NO_SOURCE_INFO, new BodyItemI[0]));
      
      _iv.forClassDefDoFirst(cd0);
      assertEquals("should be no errors", 0, errors.size());
      
      //check that an error is not thrown if a class doesn't explicitely extend another class
      ClassDef cd1 = new ClassDef(JExprParser.NO_SOURCE_INFO, _publicMav, 
                                  new Word(JExprParser.NO_SOURCE_INFO, "Test"), new TypeParameter[0], JExprParser.NO_TYPE,
                                  new ReferenceType[0], new BracedBody(JExprParser.NO_SOURCE_INFO, new BodyItemI[0]));

      _iv.forClassDefDoFirst(cd1);
      assertEquals("there should still be 0 errors", 0, errors.size());
       
       //check that an error is not thrown if a class implements any interfaces.
       ClassDef cd2 = new ClassDef(JExprParser.NO_SOURCE_INFO, _publicMav, 
                                   new Word(JExprParser.NO_SOURCE_INFO, "Test"), new TypeParameter[0],
                                   new ClassOrInterfaceType(JExprParser.NO_SOURCE_INFO, "java.lang.Object", new Type[0]), 
                                   new ReferenceType[] {new ClassOrInterfaceType(JExprParser.NO_SOURCE_INFO, "java.lang.Object", new Type[0])}, 
                                   new BracedBody(JExprParser.NO_SOURCE_INFO, new BodyItemI[0]));

                                 
      _iv.forClassDefDoFirst(cd2);
      assertEquals("there should still be 0 errors", 0, errors.size());
    }
    
    public void testForFormalParameterDoFirst() {
      PrimitiveType pt = new PrimitiveType(JExprParser.NO_SOURCE_INFO, "int");
      Word w = new Word(JExprParser.NO_SOURCE_INFO, "param");
      UninitializedVariableDeclarator uvd = new UninitializedVariableDeclarator(JExprParser.NO_SOURCE_INFO, pt, w);
      
      // check an example that works
      FormalParameter fp = new FormalParameter(JExprParser.NO_SOURCE_INFO, uvd, false);
      _iv.forFormalParameterDoFirst(fp);
      assertEquals("should be no errors", 0, errors.size());
      
      // check that an error is thrown if the FormalParameter is final
      FormalParameter fp2 = new FormalParameter(JExprParser.NO_SOURCE_INFO, uvd, true);  
      _iv.forFormalParameterDoFirst(fp2);
      assertEquals("should be one error", 1, errors.size());
      assertEquals("The error message should be correct for a final parameter.", 
                   "The keyword \"final\" cannot be used at the Intermediate level", 
                   errors.getLast().getFirst());
    }
    
    public void test_NotAllowed() {
      SourceInfo noInfo = JExprParser.NO_SOURCE_INFO;
      Word w = new Word(JExprParser.NO_SOURCE_INFO, "word");
      TypeParameter[] tps = new TypeParameter[0];
      ReferenceType[] rts = new ReferenceType[0];
      BracedBody emptyBody = new BracedBody(JExprParser.NO_SOURCE_INFO, new BodyItemI[0]);
      ClassOrInterfaceType superClass = new ClassOrInterfaceType(JExprParser.NO_SOURCE_INFO, "java.lang.Object", new Type[0]);
      FormalParameter[] fps = new FormalParameter[0];
      CompoundWord cw = new CompoundWord(noInfo, new Word[0]);
      Statement stmt = new EmptyStatement(noInfo);
      Expression e = new NullLiteral(noInfo);
      Block b = new Block(noInfo, emptyBody);
      //      ClassModifier cm = ClassModifier.NONE;
      TypeVariable tv = new TypeVariable(noInfo, "name");
      
      InnerInterfaceDef ii = new InnerInterfaceDef(noInfo, _publicMav, w, tps, rts, emptyBody);
      InnerClassDef ic = new InnerClassDef(noInfo, _publicMav, w, tps, superClass, rts, emptyBody);
      
      StaticInitializer si = new StaticInitializer(noInfo, b);
      LabeledStatement ls = new LabeledStatement(noInfo, new Word(noInfo, "label"), stmt);
      SwitchStatement ss = new SwitchStatement(noInfo, e, new SwitchCase[0]);
      WhileStatement ws = new WhileStatement(noInfo, e, stmt);
      DoStatement ds = new DoStatement(noInfo, stmt, e);
      ForStatement fs = new ForStatement(noInfo, new UnparenthesizedExpressionList(noInfo, new Expression[] {e}), 
                                         e, new UnparenthesizedExpressionList(noInfo, new Expression[] {e}),
                                         stmt);
      BreakStatement bs = new UnlabeledBreakStatement(noInfo);
      ContinueStatement cs = new UnlabeledContinueStatement(noInfo);
      SynchronizedStatement syncs = new SynchronizedStatement(noInfo, e, b);
      TypeParameter tp = new TypeParameter(noInfo, tv, superClass);
      ArrayInitializer ai = new ArrayInitializer(noInfo, new VariableInitializerI[0]);
      ArrayType at = new ArrayType(noInfo, "myName", tv);
      VoidReturn vr = new VoidReturn(noInfo, "string");
      ConditionalExpression ce = new ConditionalExpression(noInfo, e, e, e);
      
      BracedBody hasBitOperator = new BracedBody(JExprParser.NO_SOURCE_INFO, new BodyItemI[] {new ExpressionStatement(JExprParser.NO_SOURCE_INFO, 
                                                                                                                      new BitwiseOrAssignmentExpression(JExprParser.NO_SOURCE_INFO, new SimpleNameReference(JExprParser.NO_SOURCE_INFO, new Word(JExprParser.NO_SOURCE_INFO, "i")), new IntegerLiteral(JExprParser.NO_SOURCE_INFO, 5)))});

      TryCatchStatement tcs = new NormalTryCatchStatement(noInfo, b, new CatchBlock[0]);

     
     si.visit(_iv);
     assertEquals("StaticInitializer is not allowed", "Static initializers cannot be used at the Intermediate level", errors.getLast().getFirst());

     ii.visit(_iv);
     assertEquals("InnerInterfaceDef is not allowed", "Nested interfaces cannot be used at the Intermediate level", errors.getLast().getFirst());
     
     ic.visit(_iv);
     assertEquals("InnerClassDef is not allowed", "Inner classes cannot be used at the Intermediate level", errors.getLast().getFirst());
     
     ls.visit(_iv);
     assertEquals("Labeled Statement is not allowed", "Labeled statements cannot be used at the Intermediate level", errors.getLast().getFirst());

     ss.visit(_iv);
     assertEquals("SwitchStatement is not allowed", "Switch statements cannot be used at the Intermediate level", errors.getLast().getFirst());

     ws.visit(_iv);
     assertEquals("WhileStatement is not allowed", "While statements cannot be used at the Intermediate level", errors.getLast().getFirst());

     ds.visit(_iv);
     assertEquals("DoStatement is not allowed", "Do statements cannot be used at the Intermediate level", errors.getLast().getFirst());

     fs.visit(_iv);
     assertEquals("ForStatement is not allowed", "For statements cannot be used at the Intermediate level", errors.getLast().getFirst());
     
     bs.visit(_iv);
     assertEquals("BreakStatement is not allowed", "Break statements cannot be used at the Intermediate level", errors.getLast().getFirst());

     cs.visit(_iv);
     assertEquals("ContinueStatement is not allowed", "Continue statements cannot be used at the Intermediate level", errors.getLast().getFirst());
   
     syncs.visit(_iv);
     assertEquals("SynchronizedStatement is not allowed", "Synchronized statements cannot be used at the Intermediate level", errors.getLast().getFirst());
    
     tp.visit(_iv);
     assertEquals("TypeParameters is not allowed", "Type Parameters cannot be used at the Intermediate level", errors.getLast().getFirst());

     at.visit(_iv);
     assertEquals("ArrayTypes is not allowed", "Arrays cannot be used at the Intermediate level", errors.getLast().getFirst());

     ce.visit(_iv);
     assertEquals("ConditionalExpression is not allowed", "Conditional expressions cannot be used at the Intermediate level", errors.getLast().getFirst());
     
     hasBitOperator.visit(_iv);
      assertEquals("Bitwise operators are not allowed", "Bitwise operators cannot be used at any language level", errors.getLast().getFirst());
      
     tcs.visit(_iv);
     assertEquals("try-catch statements are not allowed", "A try-catch statement cannot appear here", errors.getLast().getFirst());
    }
    
    public void testForPrimitiveTypeDoFirst() {
      
      SourceInfo noInfo = JExprParser.NO_SOURCE_INFO;
      
     //only primative types boolean, char, int, and double are allowed at Intermediate level. 
      PrimitiveType i = new PrimitiveType(noInfo, "int");
      PrimitiveType c = new PrimitiveType(noInfo, "char");
      PrimitiveType d = new PrimitiveType(noInfo, "double");
      PrimitiveType b = new PrimitiveType(noInfo, "boolean");
      
      i.visit(_iv);
      assertEquals("After visiting int, errors should still be 0", 0, errors.size());

      c.visit(_iv);
      assertEquals("After visiting char, errors should still be 0", 0, errors.size());
            
      d.visit(_iv);
      assertEquals("After visiting double, errors should still be 0", 0, errors.size());

      b.visit(_iv);
      assertEquals("After visiting boolean, errors should still be 0", 0, errors.size());
      
      //now the types that should throw an error:
      
      PrimitiveType byt = new PrimitiveType(noInfo, "byte");
      PrimitiveType s = new PrimitiveType(noInfo, "short");
      PrimitiveType l = new PrimitiveType(noInfo, "long");
      PrimitiveType f = new PrimitiveType(noInfo, "float");
      
      byt.visit(_iv);
      assertEquals("After visiting byte, errors should be 1", 1, errors.size());
      assertEquals("After byte, error message is correct", "Only the primitive types \"int\", \"double\", \"boolean\", and \"char\" can be used at the Intermediate level", errors.getLast().getFirst());

      s.visit(_iv);
      assertEquals("After visiting short, errors should be 2", 2, errors.size());
      assertEquals("After short, error message is correct", "Only the primitive types \"int\", \"double\", \"boolean\", and \"char\" can be used at the Intermediate level", errors.getLast().getFirst());

      l.visit(_iv);
      assertEquals("After visiting long, errors should be 3", 3, errors.size());
      assertEquals("After long, error message is correct", "Only the primitive types \"int\", \"double\", \"boolean\", and \"char\" can be used at the Intermediate level", errors.getLast().getFirst());

      f.visit(_iv);
      assertEquals("After visiting float, errors should be 4", 4, errors.size());
      assertEquals("After float, error message is correct", "Only the primitive types \"int\", \"double\", \"boolean\", and \"char\" can be used at the Intermediate level", errors.getLast().getFirst());
    }
    
    public void test_isClassInCurrentFile() {
     assertFalse("class not in file should return false", _iv._isClassInCurrentFile("NotInFile"));
     _iv._classNamesInThisFile.addLast("package.MyClass");
     assertTrue("full class name in file should return true", _iv._isClassInCurrentFile("package.MyClass"));
     assertTrue("unqualified class name in file should return true", _iv._isClassInCurrentFile("MyClass"));
     
     assertFalse("partial name in file, not same class, should return false", _iv._isClassInCurrentFile("Class"));
                
    }
    
    public void testCreateConstructor() {
      SymbolData sd = new SymbolData("ClassName", _publicMav, new TypeParameter[0], null, new LinkedList<SymbolData>(), null);
      VariableData v1 = new VariableData("i", _publicMav, SymbolData.INT_TYPE, false, sd);
      VariableData v2 = new VariableData("j", _publicMav, SymbolData.CHAR_TYPE, false, sd);
      VariableData v3 = new VariableData("var", _publicMav, SymbolData.DOUBLE_TYPE, false, sd);
      sd.addVar(v1);
      sd.addVar(v2);
      sd.setSuperClass(_sd1);
      
      MethodData md = new MethodData("ClassName", _publicMav, new TypeParameter[0], sd, 
                                   (VariableData[])sd.getVars().toArray(new VariableData[0]), 
                                   new String[0], 
                                   sd,
                                   null);
      md.addVars(md.getParams());
      _iv.createConstructor(sd);
      
      assertEquals("sd should have 1 method: its own constructor", md, sd.getMethods().getFirst());
      
      //since this is the only constructor in the symbol data, all the fields should be assigned to have a value after visiting sd.
      v1 = new VariableData("i", _publicMav, SymbolData.INT_TYPE, true, sd);
      v2 = new VariableData("j", _publicMav, SymbolData.CHAR_TYPE, true, sd);

      // We no longer do this in createConstructor
//      assertTrue("v1 should be correct--set to true", sd.getVars().contains(v1));
//      assertTrue("v2 should be correct--set to true", sd.getVars().contains(v2));
                 

      
      //now test a subclass of sd:
      SymbolData subSd = new SymbolData("Subclass",_publicMav, new TypeParameter[0], null, new LinkedList<SymbolData>(), null);
      subSd.addVar(v3);
      subSd.setSuperClass(sd);

      VariableData v1Param = new VariableData("super_i", _packageMav, SymbolData.INT_TYPE, true, null);
      VariableData v2Param = new VariableData("super_j", _packageMav, SymbolData.CHAR_TYPE, true, null);
      VariableData[] vars = {v1Param, v2Param, v3};
      MethodData md2 = new MethodData("Subclass", _publicMav, new TypeParameter[0], subSd,
                                      vars, new String[0], subSd, null);
      md2.addVars(md2.getParams());
                
      _iv.createConstructor(subSd);
      v1Param.setEnclosingData(subSd.getMethods().getFirst());
      v2Param.setEnclosingData(subSd.getMethods().getFirst());
      assertEquals("subSd should have 1 method: its own constructor.", md2, subSd.getMethods().getFirst());
    }
    
    public void test_getFieldAccessorName() {
      // This may change in the future if we change getFieldAccessorName
      assertEquals("Should correctly convert from lower case to upper case", "name", _iv.getFieldAccessorName("name"));
    }
    
    public void testCreateToString() {
      SymbolData sd = new SymbolData("ClassName", _publicMav, new TypeParameter[0], null, new LinkedList<SymbolData>(), null);
      
      MethodData md = new MethodData("toString", _publicMav,
                                     new TypeParameter[0],
                                     _iv.getSymbolData("String", _iv._makeSourceInfo("java.lang.String")), 
                                     new VariableData[0],
                                     new String[0], 
                                     sd,
                                     null); // no SourceInfo
      
      _iv.createToString(sd);
      assertEquals("sd should have 1 method: toString", md, sd.getMethods().getFirst());
    }
    
    public void testCreateHashCode() {
      SymbolData sd = new SymbolData("ClassName", _publicMav, new TypeParameter[0], null, new LinkedList<SymbolData>(), null);      
      MethodData md = new MethodData("hashCode",
                                   _publicMav, 
                                   new TypeParameter[0], 
                                   SymbolData.INT_TYPE, 
                                   new VariableData[0],
                                   new String[0], 
                                   sd,
                                   null);
      _iv.createHashCode(sd);
      assertEquals("sd should have 1 method: hashCode()", md, sd.getMethods().getFirst());
    }
    
    public void testCreateEquals() {
      SymbolData sd = new SymbolData("ClassName", _publicMav, new TypeParameter[0], null, new LinkedList<SymbolData>(), null);
      MethodData md = new MethodData("equals",
                                     _publicMav, 
                                     new TypeParameter[0], 
                                     SymbolData.BOOLEAN_TYPE, 
                                     new VariableData[] { new VariableData(_iv.getSymbolData("Object", _iv._makeSourceInfo("java.lang.Object"))) },
                                     new String[0], 
                                     sd,
                                     null);
                                     

      _iv.createEquals(sd);
      md.getParams()[0].setEnclosingData(sd.getMethods().getFirst());                               
      assertEquals("sd should have 1 method: equals()", md, sd.getMethods().getFirst());
    }
    
    public void testForClassDef() {
      //check an example that's not abstract
      _iv._package = "myPackage";
      ClassDef cd0 = new ClassDef(JExprParser.NO_SOURCE_INFO, _packageMav, new Word(JExprParser.NO_SOURCE_INFO, "Lisa"),
                                 new TypeParameter[0], 
                                  new ClassOrInterfaceType(JExprParser.NO_SOURCE_INFO, "Object", new Type[0]), new ReferenceType[0], 
                                  new BracedBody(JExprParser.NO_SOURCE_INFO, new BodyItemI[0])); 
      
      
      cd0.visit(_iv);
      assertEquals("There should be no errors", 0, errors.size());
      assertTrue("Should have resolved java.lang.Object", symbolTable.containsKey("java.lang.Object"));
      assertFalse("Should not be a continuation", symbolTable.get("java.lang.Object").isContinuation());
      SymbolData sd = symbolTable.get("myPackage.Lisa");
      assertTrue("Lisa should be in _newSDs", _newSDs.containsKey(sd));
      MethodData md2 = new MethodData("equals",
                                   _publicMav, 
                                   new TypeParameter[0], 
                                   SymbolData.BOOLEAN_TYPE, 
                                     new VariableData[] { new VariableData(_iv.getSymbolData("Object", _iv._makeSourceInfo("java.lang.Object"))) },
                                   new String[0], 
                                   sd,
                                   null);
                                   
      md2.getParams()[0].setEnclosingData(sd.getMethods().getLast());  
                             
      assertEquals("sd's last method should be equals()", md2, sd.getMethods().getLast());
      assertEquals("sd's package should be correct", "myPackage", sd.getPackage());
      
      //check an example that's abstract
      _iv._package = "";
      ClassDef cd1 = new ClassDef(JExprParser.NO_SOURCE_INFO, _abstractMav, new Word(JExprParser.NO_SOURCE_INFO, "Bart"),
                                  new TypeParameter[0], new ClassOrInterfaceType(JExprParser.NO_SOURCE_INFO, "System", new Type[0]), new ReferenceType[0], 
                                  new BracedBody(JExprParser.NO_SOURCE_INFO, new BodyItemI[0]));
      cd1.visit(_iv);
      assertEquals("There should be no errors", 0, errors.size());
      assertTrue("Should have resolved java.lang.System", symbolTable.containsKey("java.lang.System"));
      assertFalse("Should not be a continuation", symbolTable.get("java.lang.System").isContinuation());
      sd = symbolTable.get("Bart");
      
      assertEquals("There should be 3 methods", 3, sd.getMethods().size());
      
      
      //Check an example where the class extends TestCase, and has a test method that returns void.
      ConcreteMethodDef cmd = new ConcreteMethodDef(JExprParser.NO_SOURCE_INFO, 
                                                    _packageMav, 
                                                    new TypeParameter[0], 
                                                    new VoidReturn(JExprParser.NO_SOURCE_INFO, "void"), 
                                                    new Word(JExprParser.NO_SOURCE_INFO, "testMethodName"),
                                                    new FormalParameter[0],
                                                    new ReferenceType[0], 
                                                    new BracedBody(JExprParser.NO_SOURCE_INFO, new BodyItemI[0]));

      ClassDef cd3 = new ClassDef(JExprParser.NO_SOURCE_INFO, _abstractMav, new Word(JExprParser.NO_SOURCE_INFO, "TestSuper2"),
                                  new TypeParameter[0], new ClassOrInterfaceType(JExprParser.NO_SOURCE_INFO, "TestCase", new Type[0]), new ReferenceType[0], 
                                  new BracedBody(JExprParser.NO_SOURCE_INFO, new BodyItemI[] {cmd}));


      _iv._file=new File("TestSuper2.dj0");
      _iv._importedFiles.addLast("junit.framework.TestCase");
      symbolTable.put("junit.framework.TestCase", new SymbolData("junit.framework.TestCase"));
      cd3.visit(_iv);
      assertEquals("There should still just be no errors", 0, errors.size());
      assertNotNull("Should have looked up TestSuper2", symbolTable.get("TestSuper2"));
      
      //Check a method with void return, but name not starting with test, so it's not okay.
      //This is now checked in the type checker!
      ConcreteMethodDef cmd2 = new ConcreteMethodDef(JExprParser.NO_SOURCE_INFO, 
                                                    _packageMav, 
                                                    new TypeParameter[0], 
                                                    new VoidReturn(JExprParser.NO_SOURCE_INFO, "void"), 
                                                    new Word(JExprParser.NO_SOURCE_INFO, "uhOh"),
                                                    new FormalParameter[0],
                                                    new ReferenceType[0], 
                                                    new BracedBody(JExprParser.NO_SOURCE_INFO, new BodyItemI[0]));

      ClassDef cd4 = new ClassDef(JExprParser.NO_SOURCE_INFO, _abstractMav, new Word(JExprParser.NO_SOURCE_INFO, "TestVoidNoTestMethod"),
                                  new TypeParameter[0], new ClassOrInterfaceType(JExprParser.NO_SOURCE_INFO, "junit.framework.TestCase", new Type[0]), new ReferenceType[0], 
                                  new BracedBody(JExprParser.NO_SOURCE_INFO, new BodyItemI[] {cmd2}));



      _iv._file=new File("TestVoidNoTestMethod.dj0");
      cd4.visit(_iv);

      assertEquals("There should still be 0 errors", 0, errors.size());
      _iv._importedFiles.remove("junit.framework.TestCase");
      
    }
    
    
    public void testForInterfaceDef() {
      AbstractMethodDef amd = new AbstractMethodDef(JExprParser.NO_SOURCE_INFO, _publicMav, new TypeParameter[0], new PrimitiveType(JExprParser.NO_SOURCE_INFO, "int"),
                                                                                               new Word(JExprParser.NO_SOURCE_INFO, "myMethod"), new FormalParameter[0], new ReferenceType[0]);
      AbstractMethodDef amd2 = new AbstractMethodDef(JExprParser.NO_SOURCE_INFO, _publicMav, new TypeParameter[0], new PrimitiveType(JExprParser.NO_SOURCE_INFO, "int"),
                                                                                               new Word(JExprParser.NO_SOURCE_INFO, "myMethod"), new FormalParameter[0], new ReferenceType[0]);
      InterfaceDef id = new InterfaceDef(JExprParser.NO_SOURCE_INFO, _publicMav, new Word(JExprParser.NO_SOURCE_INFO, "id"), new TypeParameter[0], new ReferenceType[0], 
                                         new BracedBody(JExprParser.NO_SOURCE_INFO, 
                                                        new BodyItemI[] {amd}));
      InterfaceDef id2 = new InterfaceDef(JExprParser.NO_SOURCE_INFO, _publicMav, new Word(JExprParser.NO_SOURCE_INFO, "id2"), new TypeParameter[0], new ReferenceType[] {new ClassOrInterfaceType(JExprParser.NO_SOURCE_INFO, "id", new Type[0])}, 
                                         new BracedBody(JExprParser.NO_SOURCE_INFO, 
                                                        new BodyItemI[] {amd2}));
      SymbolData sd = new SymbolData("id", _publicMav, new TypeParameter[0], new LinkedList<SymbolData>(), null);
      sd.setIsContinuation(true);
      MethodData md = new MethodData("myMethod", _publicMav, new TypeParameter[0], SymbolData.INT_TYPE, new VariableData[0], new String[0], sd, amd);

      LinkedList<SymbolData> interfaces = new LinkedList<SymbolData>();
      interfaces.addLast(sd);
      SymbolData sd2 = new SymbolData("id2", _publicMav, new TypeParameter[0], interfaces, null);
      sd2.setIsContinuation(true);
      MethodData md2 = new MethodData("myMethod", _publicMav, new TypeParameter[0], SymbolData.INT_TYPE, new VariableData[0], new String[0], sd2, amd2);
      
      _iv.symbolTable.put("id", sd);
      _iv.symbolTable.put("id2", sd2);

      id.visit(_iv);
      id2.visit(_iv);

      assertEquals("Should be no errors", 0, errors.size());
      assertEquals("Should return the same symbol datas: id", sd, symbolTable.get("id"));
      assertEquals("Should return the same symbol datas:id2 ", sd2, symbolTable.get("id2"));
    }
   

    
    public void testCreateMethodData() {
      // Test one that doesn't work.
      MethodDef mdef = new ConcreteMethodDef(JExprParser.NO_SOURCE_INFO, 
                                                    _finalMav, 
                                                    new TypeParameter[0], 
                                                    new PrimitiveType(JExprParser.NO_SOURCE_INFO, "int"), 
                                                    new Word(JExprParser.NO_SOURCE_INFO, "methodName"),
                                                    new FormalParameter[0],
                                                    new ReferenceType[0], 
                                                    new BracedBody(JExprParser.NO_SOURCE_INFO, new BodyItemI[0]));
      
      MethodData mdata = new MethodData("methodName", _finalMav, new TypeParameter[0], SymbolData.INT_TYPE, 
                                   new VariableData[0], 
                                   new String[0],
                                   _sd1,
                                   null);
      assertEquals("Should return the correct MethodData", mdata, _iv.createMethodData(mdef, _sd1));
      assertEquals("There should be one error.", 1, errors.size());
      assertEquals("The error message should be correct.", "The keyword \"final\" cannot be used at the Intermediate level", errors.get(0).getFirst());
      
      // Test one that does work.
      mdef = new AbstractMethodDef(JExprParser.NO_SOURCE_INFO, 
                                   _abstractMav, 
                                   new TypeParameter[] { new TypeParameter(JExprParser.NO_SOURCE_INFO,
                                                                           new TypeVariable(JExprParser.NO_SOURCE_INFO, "T"),
                                                                           new TypeVariable(JExprParser.NO_SOURCE_INFO, "U"))},
                                   new VoidReturn(JExprParser.NO_SOURCE_INFO, "void"), 
                                   new Word(JExprParser.NO_SOURCE_INFO, "methodName"),
                                   new FormalParameter[] {
                                     new FormalParameter(JExprParser.NO_SOURCE_INFO, 
                                                         new UninitializedVariableDeclarator(JExprParser.NO_SOURCE_INFO, 
                                                                                             new PrimitiveType(JExprParser.NO_SOURCE_INFO, "double"), 
                                                                                             new Word (JExprParser.NO_SOURCE_INFO, "field1")),
                                                         false
                                                           ),
                                     new FormalParameter(JExprParser.NO_SOURCE_INFO, 
                                                         new UninitializedVariableDeclarator(JExprParser.NO_SOURCE_INFO, 
                                                                                             new PrimitiveType(JExprParser.NO_SOURCE_INFO, "int"), 
                                                                                             new Word (JExprParser.NO_SOURCE_INFO, "field1")),
                                                         false
                                                           )},
                                   new ReferenceType[] { new TypeVariable(JExprParser.NO_SOURCE_INFO, "X") }
                                   );
       mdata = new MethodData("methodName", 
                              _abstractMav, 
                              new TypeParameter[] { new TypeParameter(JExprParser.NO_SOURCE_INFO,
                                                                      new TypeVariable(JExprParser.NO_SOURCE_INFO, "T"),
                                                                      new TypeVariable(JExprParser.NO_SOURCE_INFO, "U"))}, 
                              SymbolData.VOID_TYPE, 
                              new VariableData[] { new VariableData("field1", _finalMav, SymbolData.DOUBLE_TYPE, true, null),
                                new VariableData("field1", _finalMav, SymbolData.INT_TYPE, true, null) }, 
                              new String[] { "X" },
                              _sd1,
                              null);
       
                              
       MethodData result = _iv.createMethodData(mdef, _sd1);
       mdata.getParams()[0].setEnclosingData(result);
       mdata.getParams()[1].setEnclosingData(result);
       // have to add the parameters to the vars manually
       mdata.addVars(new VariableData[] { new VariableData("field1", _finalMav, SymbolData.DOUBLE_TYPE, true, result) });                                                          
       assertEquals("Should return the correct MethodData", mdata, result);
       assertEquals("There should be 2 errors.", 2, errors.size());
       //This is now caught in the type checker.
       //assertEquals("The second error message should be correct.", "The keyword \"void\" cannot be used at the Intermediate level", errors.get(1).getFirst());
       assertEquals("The second error message should be correct.", "You cannot have two method parameters with the same name", errors.get(1).getFirst());
    }
    
    public void testSimpleAnonymousClassInstantiationHelper() {
     SimpleAnonymousClassInstantiation basic = new SimpleAnonymousClassInstantiation(JExprParser.NO_SOURCE_INFO, new ClassOrInterfaceType(JExprParser.NO_SOURCE_INFO, "Object", new Type[0]), 
                                                                        new ParenthesizedExpressionList(JExprParser.NO_SOURCE_INFO, new Expression[0]),
                                                                        new BracedBody(JExprParser.NO_SOURCE_INFO, new BodyItemI[0]));
    

     _iv._package = "i.like";
     _iv.simpleAnonymousClassInstantiationHelper(basic, _sd1);
     assertEquals("There should be no errors", 0, errors.size());
     SymbolData obj = symbolTable.get("java.lang.Object");
     assertNotNull("Object should be in the symbol table", obj);
     assertEquals("sd1 should have one inner class", 1, _sd1.getInnerClasses().size());
     SymbolData inner = _sd1.getInnerClasses().get(0);
     assertEquals("The inner class should have the proper name", "i.like.monkey$1", inner.getName());
     assertEquals("The inner class should have proper outer data", _sd1, inner.getOuterData());
     assertEquals("The inner class should have proper super class", obj, inner.getSuperClass());
     assertEquals("The inner class should have the right package", "i.like", inner.getPackage());
     assertEquals("The inner class should have 3 methods", 3, inner.getMethods().size());
    }

    
    public void testComplexAnonymousClassInstantiationHelper() {
     ComplexAnonymousClassInstantiation basic = new ComplexAnonymousClassInstantiation(JExprParser.NO_SOURCE_INFO, new SimpleNameReference(JExprParser.NO_SOURCE_INFO, new Word(JExprParser.NO_SOURCE_INFO, "java.lang.Object")),
                                                                                new ClassOrInterfaceType(JExprParser.NO_SOURCE_INFO, "Inner", new Type[0]), 
                                                                                new ParenthesizedExpressionList(JExprParser.NO_SOURCE_INFO, new Expression[0]),
                                                                                new BracedBody(JExprParser.NO_SOURCE_INFO, new BodyItemI[0]));

     _iv._package = "i.like";
     _iv.complexAnonymousClassInstantiationHelper(basic, _sd1);
     assertEquals("There should be no errors", 0, errors.size());
     SymbolData obj = symbolTable.get("java.lang.Object");
     assertNotNull("Object should be in the symbol table", obj);
     SymbolData objInner = symbolTable.get("java.lang.Object.Inner");
     assertEquals("sd1 should have one inner class", 1, _sd1.getInnerClasses().size());
     SymbolData inner = _sd1.getInnerClasses().get(0);
     assertEquals("The inner class should have the proper name", "i.like.monkey$1", inner.getName());
     assertEquals("The inner class should have proper outer data", _sd1, inner.getOuterData());
     assertEquals("The inner class should have null as its super class", null, inner.getSuperClass());
     assertEquals("The inner class should have the right package", "i.like", inner.getPackage());
     assertEquals("The inner class should have 3 methods", 3, inner.getMethods().size());
    }
    
    public void testForVariableDeclaration() {
      //make sure that if forVariableDeclaration is called with a AnonymousClassInstantiation, the symboldata is only added once.
      //this is to make sure an old bug stays fixed.
     SimpleAnonymousClassInstantiation basic = new SimpleAnonymousClassInstantiation(JExprParser.NO_SOURCE_INFO, new ClassOrInterfaceType(JExprParser.NO_SOURCE_INFO, "Object", new Type[0]), 
                                                                        new ParenthesizedExpressionList(JExprParser.NO_SOURCE_INFO, new Expression[0]),
                                                                        new BracedBody(JExprParser.NO_SOURCE_INFO, new BodyItemI[0]));
    

     
     VariableDeclarator[] d1 = {new InitializedVariableDeclarator(JExprParser.NO_SOURCE_INFO, new ClassOrInterfaceType(JExprParser.NO_SOURCE_INFO, "java.lang.Object", new Type[0]), new Word(JExprParser.NO_SOURCE_INFO, "b"), basic)};
     VariableDeclaration vd1 = new VariableDeclaration(JExprParser.NO_SOURCE_INFO,_publicMav, d1); 
     
     ClassBodyIntermediateVisitor cbiv = new ClassBodyIntermediateVisitor(_sd1, _iv._file, _iv._package, _iv._importedFiles, _iv._importedPackages, _iv._classNamesInThisFile, _iv.continuations);
     
     vd1.visit(cbiv);
     assertEquals("Should be 1 inner class of _sd1", 1, _sd1.getInnerClasses().size());
     
    }
    
    public void testForPackageStatementDoFirst() {
      PackageStatement ps = new PackageStatement(JExprParser.NO_SOURCE_INFO, new CompoundWord(JExprParser.NO_SOURCE_INFO, new Word[0]));
      ps.visit(_iv);
      assertEquals("Should be 1 error", 1, errors.size());
      assertEquals("Error message should be correct", "Package statements cannot be used at the Intermediate level.  All Intermediate level classes and interfaces are assumed to be in the default package", errors.getLast().getFirst());
  }
    
  }
}



See more files for this project here

DrJava

DrJava is a lightweight programming environment for Java designed to foster test-driven software development. It includes an intelligent program editor, an interactions pane for evaluating program text, a source level debugger, and a unit testing tool.

Project homepage: http://sourceforge.net/projects/drjava
Programming language(s): Java
License: other

  AdvancedLevelTest.java
  AdvancedVisitor.java
  ArrayData.java
  Augmentor.java
  BlockData.java
  Bob.java
  BodyBodyAdvancedVisitor.java
  BodyBodyElementaryVisitor.java
  BodyBodyIntermediateVisitor.java
  BodyData.java
  BodyTypeChecker.java
  CharConverter.java
  ClassBodyAdvancedVisitor.java
  ClassBodyElementaryVisitor.java
  ClassBodyIntermediateVisitor.java
  ClassBodyTypeChecker.java
  ConstructorBodyTypeChecker.java
  Data.java
  ElementaryLevelTest.java
  ElementaryVisitor.java
  ExpressionTypeChecker.java
  InstanceData.java
  InterfaceBodyAdvancedVisitor.java
  InterfaceBodyIntermediateVisitor.java
  InterfaceBodyTypeChecker.java
  IntermediateLevelTest.java
  IntermediateVisitor.java
  JExprParseException.java
  JExprParserTest.java
  JExpressionIFPrunableDepthFirstVisitor_void.java
  LValueTypeChecker.java
  LValueWithValueTypeChecker.java
  LanguageLevelConverter.java
  LanguageLevelVisitor.java
  MethodData.java
  PackageData.java
  Pair.java
  PrimitiveData.java
  SourceInfo.java
  SymbolData.java
  Symboltable.java
  TryCatchBodyTypeChecker.java
  TypeChecker.java
  TypeData.java
  VariableData.java
  VoidMethodsNotAllowedClassBodyTypeChecker.java
  jexpr.ast
  jexpr.jj