Clover coverage report - Java Language Levels Test Coverage (javalanglevels-20120305-r5436)
Coverage timestamp: Sun Mar 4 2012 22:02:46 CST
file stats: LOC: 903   Methods: 30
NCLOC: 584   Classes: 2
 
 Source file Conditionals Statements Methods TOTAL
ClassBodyFullJavaVisitor.java 55.3% 58.2% 73.3% 59.2%
coverage coverage
 1    /*BEGIN_COPYRIGHT_BLOCK
 2    *
 3    * Copyright (c) 2001-2010, JavaPLT group at Rice University (drjava@rice.edu)
 4    * All rights reserved.
 5    *
 6    * Redistribution and use in source and binary forms, with or without
 7    * modification, are permitted provided that the following conditions are met:
 8    * * Redistributions of source code must retain the above copyright
 9    * notice, this list of conditions and the following disclaimer.
 10    * * Redistributions in binary form must reproduce the above copyright
 11    * notice, this list of conditions and the following disclaimer in the
 12    * documentation and/or other materials provided with the distribution.
 13    * * Neither the names of DrJava, the JavaPLT group, Rice University, nor the
 14    * names of its contributors may be used to endorse or promote products
 15    * derived from this software without specific prior written permission.
 16    *
 17    * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 18    * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 19    * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 20    * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 21    * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 22    * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 23    * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 24    * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 25    * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 26    * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 27    * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 28    *
 29    * This software is Open Source Initiative approved Open Source Software.
 30    * Open Source Initative Approved is a trademark of the Open Source Initiative.
 31    *
 32    * This file is part of DrJava. Download the current version of this project
 33    * from http://www.drjava.org/ or http://sourceforge.net/projects/drjava/
 34    *
 35    * END_COPYRIGHT_BLOCK*/
 36   
 37    package edu.rice.cs.javalanglevels;
 38   
 39    import edu.rice.cs.javalanglevels.tree.*;
 40    import edu.rice.cs.javalanglevels.parser.*;
 41    import edu.rice.cs.javalanglevels.util.*;
 42    import java.util.*;
 43    import java.io.*;
 44   
 45    import junit.framework.TestCase;
 46   
 47    /** Class body walking LanguageLevelVisitor for the FullJava Language Level. Builds the symbol table for a .java file
 48    * without performing any syntax checking. This file will also be compiled by javac, which will catch the syntax
 49    * errors.
 50    */
 51    public class ClassBodyFullJavaVisitor extends FullJavaVisitor {
 52   
 53    /**The SymbolData corresponding to this class.*/
 54    private SymbolData _enclosing;
 55   
 56    /** Deprecated onstructor for ClassBodyFullJavaVisitor.
 57    * @param sd The SymbolData that encloses the context we are visiting. Must be non-null.
 58    * @param className The name of the enclosing class. Must be non-null and non-empty.
 59    * @param file The source file this came from.
 60    * @param packageName The package the source file is in
 61    * @importedFiles A list of classes that were specifically imported
 62    * @param importedPackages A list of package names that were specifically imported
 63    * @param classesInThisFile A list of the classes that are yet to be defined in this source file
 64    * @param continuations A hashtable corresponding to the continuations (unresolved Symbol Datas) that will need to
 65    * be resolved
 66    * TODO: coalesce className and enclosingClassName
 67    */
 68  12 public ClassBodyFullJavaVisitor(SymbolData sd,
 69    String className,
 70    File file,
 71    String packageName,
 72    LinkedList<String> importedFiles,
 73    LinkedList<String> importedPackages,
 74    HashSet<String> classesInThisFile,
 75    Hashtable<String, Triple<SourceInfo, LanguageLevelVisitor, SymbolData>> continuations,
 76    LinkedList<Command> fixUps) {
 77  12 super(file, packageName, className, importedFiles, importedPackages, classesInThisFile, continuations, fixUps);
 78  12 _enclosing = sd;
 79  12 assert sd != null && className != null && ! className.equals("");
 80    }
 81   
 82    /** Preferred constructor for ClassBodyFullJavaVisitor.
 83    * @param sd The SymbolData that encloses the context we are visiting. Must be non-null.ty.
 84    * @param file The source file this came from.
 85    * @param packageName The package the source file is in
 86    * @importedFiles A list of classes that were specifically imported
 87    * @param importedPackages A list of package names that were specifically imported
 88    * @param classesInThisFile A list of the classes that are yet to be defined in this source file
 89    * @param continuations A hashtable corresponding to the continuations (unresolved Symbol Datas) that will need to
 90    * be resolved
 91    * TODO: coalesce className and enclosingClassName
 92    */
 93  82 public ClassBodyFullJavaVisitor(SymbolData sd,
 94    File file,
 95    String packageName,
 96    LinkedList<String> importedFiles,
 97    LinkedList<String> importedPackages,
 98    HashSet<String> classesInThisFile,
 99    Hashtable<String, Triple<SourceInfo, LanguageLevelVisitor, SymbolData>> continuations,
 100    LinkedList<Command> fixUps,
 101    HashMap<String, SymbolData> genericTypes) {
 102  82 super(file, packageName, sd.getName(), importedFiles, importedPackages, classesInThisFile, continuations, fixUps,
 103    genericTypes);
 104  82 _enclosing = sd;
 105  82 assert sd != null;
 106    }
 107   
 108    /* Ignore ForStatement. */
 109  0 public Void forStatementDoFirst(Statement that) { return null; }
 110   
 111    /** Ignore ConcreteMethodDef. */
 112   
 113    /** Ignore AbstractMake sure that this abstract method def is declared to be abstract. */
 114  3 public Void forAbstractMethodDefDoFirst(AbstractMethodDef that) {
 115   
 116    // ModifiersAndVisibility mav = that.getMav();
 117    // String[] modifiers = mav.getModifiers();
 118  3 if (! _enclosing.isInterface() && ! _enclosing.hasModifier("abstract")) { // interfaces not yet marked abstract
 119  1 _addError("Abstract methods can only be declared in abstract classes", that);
 120    }
 121  3 return super.forAbstractMethodDefDoFirst(that);
 122    }
 123   
 124    /*Add an appropriate error*/
 125  1 public Void forInstanceInitializerDoFirst(InstanceInitializer that) {
 126  1 _addError("This open brace must mark the beginning of a method or class body", that);
 127  1 return null;
 128    }
 129   
 130    /** Processes a field declaration. Converts the VariableDeclaration to VariableData[]. Adds the variable datas to
 131    * the symbol data, and gives an error if two fields have the same names
 132    */
 133  53 public Void forVariableDeclarationOnly(VariableDeclaration that) {
 134    // System.err.println("forVariableDeclarationOnly called in ClassBodyFullJavaVisitor for " + that);
 135  53 VariableData[] vds = _variableDeclaration2VariableData(that, _enclosing);
 136    // System.err.println(" ## generated vds = " + Arrays.toString(vds));
 137   
 138    // Add the variable datas to the symbol data
 139  53 if (! _enclosing.addVars(vds)) {
 140  1 _addAndIgnoreError("You cannot have two fields with the same name. Either you already have a field by that "
 141    + "name in this class, or one of your superclasses or interfaces has a field by that name",
 142    that);
 143    }
 144  53 return null;
 145    }
 146   
 147    /** Create a method data corresponding to this method declaration, and then visit the
 148    * concrete method def with a new bodybody visitor, passing it the enclosing method data.
 149    * Make sure the method name is different from the class name.
 150    */
 151  42 public Void forConcreteMethodDef(ConcreteMethodDef that) {
 152  42 forConcreteMethodDefDoFirst(that);
 153  1 if (prune(that)) return null;
 154  41 assert _enclosing != null;
 155   
 156  41 TypeParameter[] tps = that.getTypeParams();
 157   
 158    // TODO !!! pass genericTypes as a parameter to createMethod and critical submethods. The scope of the
 159    // new generic types table includes all of createMethodData processing, notably processing the return type.
 160    // Passing an extended generic types table to BodyBodyFullJavaVisitor is insufficient
 161   
 162    // Save a snapshot of _genericTypes
 163  41 HashMap<String, SymbolData> oldGenericTypes = _genericTypes;
 164   
 165    // Rebind _genericTypes to a shallow copy of itself for use in processing this method. The temporary variable copy
 166    // gets around a bug in javac in processing the SuppressWarnings statement.
 167  41 @SuppressWarnings("unchecked")
 168    HashMap<String, SymbolData> copy = (HashMap<String, SymbolData>) _genericTypes.clone();
 169  41 _genericTypes = copy;
 170   
 171  41 if (tps != null && tps.length > 0) { // extend genericTypes by new polymorphic method type variable bindings
 172    // Utilities.show("forConcreteMethodDef encountered a non-empty type parameters list:\n" + Arrays.toString(tps));
 173    // System.err.println("forConcreteMethodDef encountered a non-empty type parameters list:\n" + Arrays.toString(tps));
 174  0 for (TypeParameter tp: tps) {
 175  0 final String typeName = tp.getVariable().getName();
 176  0 final String boundName = tp.getBound().getName();
 177    // System.err.println("***** Type variable " + typeName + " is bound to " + boundName);
 178  0 SymbolData boundSD = _identifyType(boundName, that.getSourceInfo(), _enclosingClassName);
 179    // System.err.println("***** Corresponding SymbolData is " + boundSD);
 180    // Utilities.show("Type variable " + typeName + " is bound to " + boundName + " Corresponding SD is " + boundSD);
 181    // TODO: could create a separate unbound type variable singleton class?
 182  0 if (boundSD == null) { // create a dummy SymbolData
 183  0 boundSD = symbolTable.get("java.lang.Object");
 184    // System.err.println("Creating dummy SymbolData for bounding type " + typeName + " in inner class " + name);
 185    // TODO! !!!!! Create an appropriate fixUp mechanism
 186    }
 187    // System.err.println("In method " + _enclosing + "." + that.getName().getText() + ", type " + typeName
 188    // + " is bound to " + boundSD);
 189  0 _genericTypes.put(typeName, boundSD);
 190    }
 191    }
 192   
 193  41 MethodData md = createMethodData(that, _enclosing);
 194  41 String className = getUnqualifiedClassName(_enclosing.getName());
 195   
 196  41 if (className.equals(md.getName())) {
 197  0 _addAndIgnoreError("Only constructors can have the same name as the class they appear in, and constructors "
 198    + "do not have an explicit return type",
 199    that);
 200    }
 201  41 else _enclosing.addMethod(md);
 202  41 that.getBody().visit(new BodyBodyFullJavaVisitor(md, _file, _package, _enclosingClassName, _importedFiles,
 203    _importedPackages,
 204    _classesInThisFile, continuations, fixUps,
 205    new HashSet<String>(), _genericTypes));
 206  41 _genericTypes = oldGenericTypes;
 207  41 return null;
 208    }
 209   
 210    /** Creates a MethodData corresponding to this method declaration. Ensures that the method name is different from the
 211    * class name.
 212    */
 213  3 public Void forAbstractMethodDef(AbstractMethodDef that) {
 214  3 forAbstractMethodDefDoFirst(that);
 215  2 if (prune(that)) return null;
 216   
 217  1 assert _enclosing != null;
 218   
 219    // Process type parameters
 220  1 TypeParameter[] tps = that.getTypeParams();
 221   
 222    // TODO !!! pass genericTypes as a parameter to createMethod and critical submethods. The scope of the
 223    // new generic types table includes all of createMethodData processing, notably processing the return type.
 224    // Passing an extended generic types table to BodyBodyFullJavaVisitor is insufficient
 225   
 226    // Save a snapshot of _genericTypes
 227  1 HashMap<String, SymbolData> oldGenericTypes = _genericTypes;
 228   
 229    // Rebind _genericTypes to a shallow copy of itself for use in processing this method. The temporary variable copy
 230    // gets around a bug in javac in processing the SuppressWarnings statement.
 231  1 @SuppressWarnings("unchecked")
 232    HashMap<String, SymbolData> copy = (HashMap<String, SymbolData>)_genericTypes.clone();
 233  1 _genericTypes = copy;
 234   
 235  1 if (tps != null) { // extend genericTypes by new type variable bindings
 236  1 for (TypeParameter tp: tps) {
 237  0 final String typeName = tp.getVariable().getName();
 238  0 final String boundName = tp.getBound().getName();
 239  0 SymbolData boundSD = _identifyType(boundName, that.getSourceInfo(), _enclosingClassName);
 240  0 if (boundSD == null) { // create a dummy SymbolData
 241  0 boundSD = symbolTable.get("java.lang.Object"); // TODO: could create a separate unbound type variable singleton class?
 242    // System.err.println("Creating dummy SymbolData for bounding type " + typeName + " in inner class " + name);
 243    // TODO! !!!!! Create an appropriate fixUp mechanism
 244    }
 245    // System.err.println("In method " + _enclosing + "." + that.getName().getText() + ", type " + typeName
 246    // + " is bound to " + boundSD);
 247  0 _genericTypes.put(typeName, boundSD);
 248    }
 249    }
 250   
 251  1 MethodData md = createMethodData(that, _enclosing);
 252  1 String className = getUnqualifiedClassName(_enclosing.getName());
 253  1 if (className.equals(md.getName())) {
 254  0 _addAndIgnoreError("Only constructors can have the same name as the class they appear in, and constructors do "
 255    + "not have an explicit return type",
 256    that);
 257    }
 258  1 else _enclosing.addMethod(md);
 259  1 _genericTypes = oldGenericTypes;
 260  1 return null;
 261    }
 262   
 263    /**Call the method in FullJavaVisitor since it's common to this and FullJavaBodyFullJavaVisitor. */
 264  2 public Void forInnerInterfaceDef(InnerInterfaceDef that) {
 265  2 String relName = that.getName().getText();
 266  2 handleInnerInterfaceDef(that, _enclosing, relName, getQualifiedClassName(_enclosing.getName()) + '.' + relName);
 267  2 return null;
 268    }
 269   
 270    /**Call the method in FullJavaVisitor since it's common to this and FullJavaBodyFullJavaVisitor. */
 271  18 public Void forInnerClassDef(InnerClassDef that) {
 272  18 String relName = that.getName().getText();
 273  18 handleInnerClassDef(that, _enclosing, relName, getQualifiedClassName(_enclosing.getName()) + '.' + relName);
 274  18 return null;
 275    }
 276   
 277    /** Create a constructor corresponding to the specifications in the ConstructorDef, and then
 278    * visit the constructor body, passing the constructor as the enclosing data.
 279    */
 280  11 public Void forConstructorDef(ConstructorDef that) {
 281  11 forConstructorDefDoFirst(that);
 282  0 if (prune(that)) return null;
 283   
 284  11 that.getMav().visit(this);
 285  11 String name = getUnqualifiedClassName(that.getName().getText());
 286  11 if ((that.getName().getText().indexOf('.') != -1 && ! that.getName().getText().equals(_enclosing.getName()))
 287    || ! name.equals(getUnqualifiedClassName(_enclosing.getName()))) {
 288  0 _addAndIgnoreError("The constructor return type and class name must match", that);
 289    }
 290   
 291    // Turn the thrown exceptions from a ReferenceType[] to a String[]
 292  11 String[] throwStrings = referenceType2String(that.getThrows());
 293   
 294  11 SymbolData returnType = _enclosing;
 295  11 MethodData md = MethodData.make(name, that.getMav(), new TypeParameter[0], returnType,
 296    new VariableData[0], throwStrings, _enclosing, that); // VariableData is dummy
 297   
 298  11 _checkError(); // reset check flag
 299    // Turn the parameters from a FormalParameterList to a VariableData[]
 300  11 VariableData[] vds = formalParameters2VariableData(that.getParameters(), _enclosing);
 301  11 if (! _checkError()) { //if there was an error converting the formalParameters, don't use them.
 302  11 md.setParams(vds);
 303  11 if (!md.addVars(vds)) {
 304  0 _addAndIgnoreError("You cannot have two method parameters with the same name", that);
 305    }
 306    }
 307   
 308  11 _enclosing.addMethod(md);
 309  11 that.getStatements().visit(new BodyBodyFullJavaVisitor(md, _file, _package, _enclosingClassName, _importedFiles,
 310    _importedPackages, _classesInThisFile, continuations, fixUps,
 311    new HashSet<String>()));
 312   
 313    //note that we have seen a constructor.
 314  11 _enclosing.incrementConstructorCount();
 315  11 return null;
 316    }
 317   
 318    /** Delegate to method in LanguageLevelVisitor */
 319  1 public Void forComplexAnonymousClassInstantiation(ComplexAnonymousClassInstantiation that) {
 320  1 complexAnonymousClassInstantiationHelper(that, _enclosing); // TODO: the wrong enclosing context?
 321  1 return null;
 322    }
 323   
 324    /**Delegate to method in LanguageLevelVisitor */
 325  4 public Void forSimpleAnonymousClassInstantiation(SimpleAnonymousClassInstantiation that) {
 326  4 simpleAnonymousClassInstantiationHelper(that, _enclosing);
 327  4 return null;
 328    }
 329   
 330    /** Check for problems with modifiers that are specific to method definitions. */
 331  126 public Void forModifiersAndVisibilityDoFirst(ModifiersAndVisibility that) {
 332  126 String[] modifiers = that.getModifiers();
 333    // System.err.println("***Checking for bad modifers in " + Arrays.toString(modifiers) + " isAbstact = " +
 334    // Utilities.isAbstract(modifiers) + " isStatic = " + Utilities.isStatic(modifiers));
 335  0 if (Utilities.isAbstract(modifiers) && Utilities.isStatic(modifiers)) _badModifiers("static", "abstract", that);
 336  126 return super.forModifiersAndVisibilityDoFirst(that);
 337    }
 338   
 339    /** Test the methods that are declared above. */
 340    public static class ClassBodyFullJavaVisitorTest extends TestCase {
 341   
 342    private ClassBodyFullJavaVisitor _cbfjv;
 343   
 344    private SymbolData _sd1;
 345    private ModifiersAndVisibility _publicMav = new ModifiersAndVisibility(SourceInfo.NONE, new String[] {"public"});
 346    private ModifiersAndVisibility _protectedMav =
 347    new ModifiersAndVisibility(SourceInfo.NONE, new String[] {"protected"});
 348    private ModifiersAndVisibility _privateMav =
 349    new ModifiersAndVisibility(SourceInfo.NONE, new String[] {"private"});
 350    private ModifiersAndVisibility _packageMav = new ModifiersAndVisibility(SourceInfo.NONE, new String[0]);
 351    private ModifiersAndVisibility _abstractMav =
 352    new ModifiersAndVisibility(SourceInfo.NONE, new String[] {"abstract"});
 353    private ModifiersAndVisibility _finalMav = new ModifiersAndVisibility(SourceInfo.NONE, new String[] {"final"});
 354    private ModifiersAndVisibility _staticMav = new ModifiersAndVisibility(SourceInfo.NONE, new String[] {"static"});
 355    private ModifiersAndVisibility _abstractStaticMav =
 356    new ModifiersAndVisibility(SourceInfo.NONE, new String[] {"abstract", "static"});
 357    private ModifiersAndVisibility _finalStaticMav =
 358    new ModifiersAndVisibility(SourceInfo.NONE, new String[] {"static", "final"});
 359   
 360   
 361  0 public ClassBodyFullJavaVisitorTest() { this(""); }
 362  7 public ClassBodyFullJavaVisitorTest(String name) { super(name); }
 363   
 364  7 public void setUp() {
 365  7 _sd1 = new SymbolData("i.like.monkey"); // creates a continuation
 366   
 367  7 errors = new LinkedList<Pair<String, JExpressionIF>>();
 368  7 LanguageLevelConverter.symbolTable.clear();
 369  7 LanguageLevelConverter.symbolTable.put("i.like.monkey", _sd1);
 370  7 LanguageLevelConverter._newSDs.clear();
 371  7 visitedFiles = new LinkedList<Pair<LanguageLevelVisitor, edu.rice.cs.javalanglevels.tree.SourceFile>>();
 372    // _hierarchy = new Hashtable<String, TypeDefBase>();
 373  7 _cbfjv = new ClassBodyFullJavaVisitor(_sd1,
 374    "i.like.monkey",
 375    new File(""),
 376    "",
 377    new LinkedList<String>(),
 378    new LinkedList<String>(),
 379    new HashSet<String>(),
 380    new Hashtable<String, Triple<SourceInfo, LanguageLevelVisitor, SymbolData>>(),
 381    new LinkedList<Command>());
 382  7 _cbfjv._classesInThisFile = new HashSet<String>();
 383  7 _cbfjv.continuations = new Hashtable<String, Triple<SourceInfo, LanguageLevelVisitor, SymbolData>>(); // no _sd1
 384    // _cbfjv._resetNonStaticFields();
 385  7 _cbfjv._importedPackages.addFirst("java.lang");
 386   
 387  7 _errorAdded = false;
 388    }
 389   
 390  1 public void testForConcreteMethodDefDoFirst() {
 391    // Check one that works
 392  1 ConcreteMethodDef cmd = new ConcreteMethodDef(SourceInfo.NONE,
 393    _publicMav,
 394    new TypeParameter[0],
 395    new PrimitiveType(SourceInfo.NONE, "int"),
 396    new Word(SourceInfo.NONE, "methodName1"),
 397    new FormalParameter[0],
 398    new ReferenceType[0],
 399    new BracedBody(SourceInfo.NONE, new BodyItemI[0]));
 400  1 cmd.visit(_cbfjv);
 401  1 assertEquals("There should not be any errors", 0, errors.size());
 402   
 403    // Check one that doesn't work because it is declared abstract but is actually a concrete method
 404  1 ConcreteMethodDef cmd2 = new ConcreteMethodDef(SourceInfo.NONE,
 405    _abstractMav,
 406    new TypeParameter[0],
 407    new PrimitiveType(SourceInfo.NONE, "double"),
 408    new Word(SourceInfo.NONE, "methodName2"),
 409    new FormalParameter[0],
 410    new ReferenceType[0],
 411    new BracedBody(SourceInfo.NONE, new BodyItemI[0]));
 412  1 cmd2.visit(_cbfjv);
 413  1 assertEquals("There should be one error", 1, errors.size());
 414  1 assertEquals("The error message should be correct",
 415    "Methods that have a braced body cannot be declared \"abstract\"",
 416    errors.get(0).getFirst());
 417   
 418    //Check that a static method does not result in an error.
 419  1 ConcreteMethodDef cmd3 = new ConcreteMethodDef(SourceInfo.NONE,
 420    _staticMav,
 421    new TypeParameter[0],
 422    new PrimitiveType(SourceInfo.NONE, "double"),
 423    new Word(SourceInfo.NONE, "methodName2"),
 424    new FormalParameter[0],
 425    new ReferenceType[0],
 426    new BracedBody(SourceInfo.NONE, new BodyItemI[0]));
 427  1 cmd3.visit(_cbfjv);
 428  1 assertEquals("There should still be one error", 1, errors.size());
 429   
 430   
 431    }
 432   
 433  1 public void testForAbstractMethodDefDoFirst() {
 434    // Check one that doesn't work
 435  1 AbstractMethodDef amd = new AbstractMethodDef(SourceInfo.NONE,
 436    _abstractMav,
 437    new TypeParameter[0],
 438    new PrimitiveType(SourceInfo.NONE, "int"),
 439    new Word(SourceInfo.NONE, "methodName"),
 440    new FormalParameter[0],
 441    new ReferenceType[0]);
 442  1 amd.visit(_cbfjv);
 443  1 assertEquals("There should be one error.", 1, errors.size());
 444  1 assertEquals("The error message should be correct.", "Abstract methods can only be declared in abstract classes",
 445    errors.get(0).getFirst());
 446   
 447    // Check one that works
 448  1 _cbfjv._enclosing.setMav(_abstractMav);
 449  1 AbstractMethodDef amd2 = new AbstractMethodDef(SourceInfo.NONE,
 450    _abstractMav,
 451    new TypeParameter[0],
 452    new PrimitiveType(SourceInfo.NONE, "double"),
 453    new Word(SourceInfo.NONE, "methodName"),
 454    new FormalParameter[0],
 455    new ReferenceType[0]);
 456  1 amd2.visit(_cbfjv);
 457  1 assertEquals("There should still be one error", 1, errors.size());
 458   
 459    // Check that static methods are now allowed at the FullJava level.
 460  1 AbstractMethodDef amd3 = new AbstractMethodDef(SourceInfo.NONE,
 461    _abstractStaticMav,
 462    new TypeParameter[0],
 463    new PrimitiveType(SourceInfo.NONE, "double"),
 464    new Word(SourceInfo.NONE, "methodName2"),
 465    new FormalParameter[0],
 466    new ReferenceType[0]);
 467  1 amd3.visit(_cbfjv);
 468  1 assertEquals("There should be two errors", 2, errors.size());
 469  1 assertEquals("The error message should be correct.",
 470    "Illegal combination of modifiers. Can't use static and abstract together.",
 471    errors.get(1).getFirst());
 472    }
 473   
 474  1 public void testForInstanceInitializerDoFirst() {
 475  1 InstanceInitializer ii = new InstanceInitializer(SourceInfo.NONE,
 476    new Block(SourceInfo.NONE,
 477    new BracedBody(SourceInfo.NONE, new BodyItemI[0])));
 478  1 ii.visit(_cbfjv);
 479  1 assertEquals("There should be one error.", 1, errors.size());
 480  1 assertEquals("The error message should be correct.",
 481    "This open brace must mark the beginning of a method or class body", errors.get(0).getFirst());
 482    }
 483   
 484  1 public void testForVariableDeclaration() {
 485   
 486  1 ArrayInitializer ai = new ArrayInitializer(SourceInfo.NONE, new VariableInitializerI[0]);
 487  1 TypeVariable tv = new TypeVariable(SourceInfo.NONE, "String");
 488  1 SymbolData _string = LanguageLevelConverter.symbolTable.get("java.lang.String");
 489  1 assertNotNull("java.lang.String already in table", _string);
 490  1 ArrayType at = new ArrayType(SourceInfo.NONE, "String[]", tv);
 491   
 492  1 VariableDeclarator vd =
 493    new UninitializedVariableDeclarator(SourceInfo.NONE, at, new Word(SourceInfo.NONE, "myArray"));
 494   
 495  1 VariableDeclaration vdecl =
 496    new VariableDeclaration(SourceInfo.NONE, _publicMav, new VariableDeclarator[] { vd });
 497  1 assertEquals("There should be no errors", 0, errors.size());
 498   
 499    // System.err.println("*** Beginning traversal of VariableDeclaration with String[]");
 500  1 vdecl.visit(_cbfjv);
 501    // System.err.println("Traversal of VariableDeclaration above is complete");
 502  1 assertEquals("There should be no errors", 0, errors.size());
 503    // System.err.println("That error is: " + errors.getLast().getFirst());
 504   
 505  1 SymbolData bob = LanguageLevelConverter.symbolTable.get("java.lang.String[]");
 506    // System.err.println("Getting READY to fail");
 507    // try { Thread.sleep(1000); } catch (Exception e) { };
 508  1 assertNotNull("bob should not be null", bob);
 509    }
 510   
 511    /* These test is shared with BodyIntermediateVisitor, perhaps we could factor it out. */
 512   
 513  1 public void testForVariableDeclarationOnly() {
 514    // Check one that works
 515  1 VariableDeclaration vdecl = new VariableDeclaration(SourceInfo.NONE,
 516    _packageMav,
 517    new VariableDeclarator[] {
 518    new UninitializedVariableDeclarator(SourceInfo.NONE,
 519    new PrimitiveType(SourceInfo.NONE, "double"),
 520    new Word (SourceInfo.NONE, "field1")),
 521    new UninitializedVariableDeclarator(SourceInfo.NONE,
 522    new PrimitiveType(SourceInfo.NONE, "boolean"),
 523    new Word (SourceInfo.NONE, "field2"))});
 524  1 VariableData vd1 = new VariableData("field1", _packageMav, SymbolData.DOUBLE_TYPE, false, _cbfjv._enclosing);
 525  1 VariableData vd2 = new VariableData("field2", _packageMav, SymbolData.BOOLEAN_TYPE, false, _cbfjv._enclosing);
 526  1 vdecl.visit(_cbfjv);
 527  1 assertEquals("There should not be any errors.", 0, errors.size());
 528   
 529    // System.err.println("_sd1 vars = " + _sd1.getVars());
 530  1 assertTrue("field1 was added.", _sd1.getVars().contains(vd1));
 531  1 assertTrue("field2 was added.", _sd1.getVars().contains(vd2));
 532   
 533    // Check one that doesn't work
 534  1 VariableDeclaration vdecl2 =
 535    new VariableDeclaration(SourceInfo.NONE,
 536    _packageMav,
 537    new VariableDeclarator[] {
 538    new UninitializedVariableDeclarator(SourceInfo.NONE,
 539    new PrimitiveType(SourceInfo.NONE, "double"),
 540    new Word(SourceInfo.NONE, "field3")),
 541    new UninitializedVariableDeclarator(SourceInfo.NONE,
 542    new PrimitiveType(SourceInfo.NONE, "int"),
 543    new Word(SourceInfo.NONE, "field3"))});
 544  1 VariableData vd3 = new VariableData("field3", _packageMav, SymbolData.DOUBLE_TYPE, false, _cbfjv._enclosing);
 545  1 vdecl2.visit(_cbfjv);
 546  1 assertEquals("There should be one error.", 1, errors.size());
 547  1 assertEquals("The error message should be correct",
 548    "You cannot have two fields with the same name. Either you already have a field by that name in "
 549    + "this class, or one of your superclasses or interfaces has a field by that name",
 550    errors.get(0).getFirst());
 551    // System.err.println("_sd1 vars = " + _sd1.getVars());
 552  1 assertTrue("field3 was added.", _sd1.getVars().contains(vd3));
 553   
 554    //Check a static field that has not been assigned (won't work)
 555  1 VariableDeclaration vdecl3 = new VariableDeclaration(SourceInfo.NONE,
 556    _staticMav,
 557    new VariableDeclarator[] {
 558    new UninitializedVariableDeclarator(SourceInfo.NONE,
 559    new PrimitiveType(SourceInfo.NONE, "double"),
 560    new Word (SourceInfo.NONE, "field4"))});
 561    // true value for hasAssigned in next line based on default initialization provided by Java. GOOD IDEA?
 562  1 VariableData vd4 = new VariableData("field4", _staticMav, SymbolData.DOUBLE_TYPE, false, _cbfjv._enclosing);
 563  1 vdecl3.visit(_cbfjv);
 564    // System.err.println("vd4 = " + vd4);
 565  1 assertEquals("There should still be one error", 1, errors.size());
 566    // assertEquals("The error message should be correct", "All static fields must be initialized",
 567    // errors.get(1).getFirst());
 568    // System.err.println("_sd1 vars = " + _sd1.getVars());
 569  1 assertTrue("field4 was added.", _sd1.getVars().contains(vd4));
 570   
 571    //Check a non-static field that has been assigned. (will work);
 572  1 VariableDeclaration vdecl5 = new VariableDeclaration(SourceInfo.NONE,
 573    _publicMav,
 574    new VariableDeclarator[] {
 575    new InitializedVariableDeclarator(SourceInfo.NONE,
 576    new PrimitiveType(SourceInfo.NONE, "double"),
 577    new Word(SourceInfo.NONE, "field5"),
 578    new DoubleLiteral(SourceInfo.NONE, 2.4))});
 579  1 vdecl5.visit(_cbfjv);
 580  1 VariableData vd5 = new VariableData("field5", _publicMav, SymbolData.DOUBLE_TYPE, true, _cbfjv._enclosing);
 581  1 vd5.setHasInitializer(true);
 582  1 assertEquals("There should still be one error", 1, errors.size());
 583  1 assertTrue("Field 5 was added.", _sd1.getVars().contains(vd5));
 584   
 585    // //check one that overrides the super class's field
 586    // VariableDeclaration vdecl6 = new VariableDeclaration(SourceInfo.NONE,
 587    // _packageMav,
 588    // new VariableDeclarator[] {
 589    // new UninitializedVariableDeclarator(SourceInfo.NONE,
 590    // new PrimitiveType(SourceInfo.NONE, "double"),
 591    // new Word(SourceInfo.NONE, "field6"))});
 592    //
 593    //
 594    // VariableData vd6 = new VariableData("field6", _packageMav, SymbolData.DOUBLE_TYPE, true, _cbfjv._enclosing);
 595    // SymbolData myData = new SymbolData("myData");
 596    // myData.addVar(vd6);
 597    // _cbfjv._enclosing.setSuperClass(myData);
 598    // vdecl6.visit(_cbfjv);
 599    // assertEquals("There should be two errors.", 2, errors.size());
 600    // assertEquals("The error message should be correct",
 601    // "You cannot have two fields with the same name. Either you already have a field by that name in "
 602    // + "this class, or one of your superclasses or interfaces has a field by that name",
 603    // errors.get(1).getFirst());
 604   
 605    }
 606   
 607  1 public void testFormalParameters2VariableData() {
 608  1 FormalParameter[] fps = new FormalParameter[] {
 609    new FormalParameter(SourceInfo.NONE,
 610    new UninitializedVariableDeclarator(SourceInfo.NONE,
 611    new PrimitiveType(SourceInfo.NONE, "double"),
 612    new Word (SourceInfo.NONE, "field1")),
 613    false),
 614    new FormalParameter(SourceInfo.NONE,
 615    new UninitializedVariableDeclarator(SourceInfo.NONE,
 616    new PrimitiveType(SourceInfo.NONE, "boolean"),
 617    new Word (SourceInfo.NONE, "field2")),
 618    false)};
 619   
 620   
 621  1 VariableData vd1 = new VariableData("field1", _packageMav, SymbolData.DOUBLE_TYPE, true, _cbfjv._enclosing);
 622  1 VariableData vd2 = new VariableData("field2", _packageMav, SymbolData.BOOLEAN_TYPE, true, _cbfjv._enclosing);
 623   
 624  1 VariableData[] mVds = new VariableData[] { vd1, vd2 };
 625   
 626  1 MethodData aMethod = new MethodData("method",
 627    _publicMav,
 628    new TypeParameter[0],
 629    _cbfjv._enclosing,
 630    mVds,
 631    new String[0],
 632    _cbfjv._enclosing,
 633    null);
 634   
 635  1 VariableData[] vds = _cbfjv.formalParameters2VariableData(fps, _cbfjv._enclosing);
 636  1 assertEquals("There should not be any errors.", 0, errors.size());
 637  1 assertEquals("vd1 should be the first entry in vds.", vd1, vds[0]);
 638  1 assertEquals("vd2 should be the second entry in vds.", vd2, vds[1]);
 639    }
 640   
 641   
 642   
 643   
 644   
 645  0 public void xtestForConcreteMethodDef() {
 646    // Test one that works.
 647  0 MethodDef mdef = new ConcreteMethodDef(SourceInfo.NONE,
 648    _packageMav,
 649    new TypeParameter[0],
 650    new PrimitiveType(SourceInfo.NONE, "int"),
 651    new Word(SourceInfo.NONE, "methodName"),
 652    new FormalParameter[0],
 653    new ReferenceType[0],
 654    new BracedBody(SourceInfo.NONE, new BodyItemI[0]));
 655  0 mdef.visit(_cbfjv);
 656  0 assertEquals("There should not be any errors.", 0, errors.size());
 657    // Test one that doesn't work.
 658  0 mdef = new ConcreteMethodDef(SourceInfo.NONE,
 659    _packageMav,
 660    new TypeParameter[0],
 661    new PrimitiveType(SourceInfo.NONE, "int"),
 662    new Word(SourceInfo.NONE, "monkey"),
 663    new FormalParameter[0],
 664    new ReferenceType[0],
 665    new BracedBody(SourceInfo.NONE, new BodyItemI[0]));
 666  0 mdef.visit(_cbfjv);
 667  0 assertEquals("There should be one error.", 1, errors.size());
 668  0 assertEquals("The error message should be correct.",
 669    "Only constructors can have the same name as the class they appear in, and constructors do not have an explicit return type",
 670    errors.get(0).getFirst());
 671    }
 672   
 673  0 public void xtestForAbstractMethodDef() {
 674    // Test one that works.
 675  0 MethodDef mdef = new AbstractMethodDef(SourceInfo.NONE,
 676    _abstractMav,
 677    new TypeParameter[0],
 678    new PrimitiveType(SourceInfo.NONE, "int"),
 679    new Word(SourceInfo.NONE, "methodName"),
 680    new FormalParameter[0],
 681    new ReferenceType[0]);
 682  0 _cbfjv._enclosing.setMav(_abstractMav);
 683  0 mdef.visit(_cbfjv);
 684  0 assertEquals("There should not be any errors.", 0, errors.size());
 685    // Test one that doesn't work.
 686  0 mdef = new AbstractMethodDef(SourceInfo.NONE,
 687    _abstractMav,
 688    new TypeParameter[0],
 689    new PrimitiveType(SourceInfo.NONE, "int"),
 690    new Word(SourceInfo.NONE, "monkey"),
 691    new FormalParameter[0],
 692    new ReferenceType[0]);
 693  0 mdef.visit(_cbfjv);
 694  0 assertEquals("There should be one error.", 1, errors.size());
 695  0 assertEquals("The error message should be correct.",
 696    "Only constructors can have the same name as the class they appear in, and constructors do not have an explicit return type",
 697    errors.get(0).getFirst());
 698    }
 699   
 700   
 701  0 public void xtestForInitializedVariableDeclaratorDoFirst() {
 702  0 InitializedVariableDeclarator ivd = new InitializedVariableDeclarator(SourceInfo.NONE,
 703    new PrimitiveType(SourceInfo.NONE, "int"),
 704    new Word(SourceInfo.NONE, "i"),
 705    new IntegerLiteral(SourceInfo.NONE, 2));
 706   
 707  0 ivd.visit(_cbfjv);
 708   
 709  0 assertEquals("There should be no errors now", 0, errors.size());
 710    }
 711   
 712  0 public void xtestForInnerClassDef() {
 713  0 SymbolData obj = new SymbolData("java.lang.Object");
 714  0 LanguageLevelConverter.symbolTable.put("java.lang.Object", obj);
 715  0 InnerClassDef cd1 = new InnerClassDef(SourceInfo.NONE, _packageMav, new Word(SourceInfo.NONE, "Bart"),
 716    new TypeParameter[0], new ClassOrInterfaceType(SourceInfo.NONE, "java.lang.Object", new Type[0]), new ReferenceType[0],
 717    new BracedBody(SourceInfo.NONE, new BodyItemI[0]));
 718  0 InnerClassDef cd0 = new InnerClassDef(SourceInfo.NONE, _packageMav, new Word(SourceInfo.NONE, "Lisa"),
 719    new TypeParameter[0], new ClassOrInterfaceType(SourceInfo.NONE, "java.lang.Object", new Type[0]), new ReferenceType[0],
 720    new BracedBody(SourceInfo.NONE, new BodyItemI[] {cd1}));
 721   
 722   
 723  0 SymbolData sd0 = new SymbolData(_cbfjv._enclosing.getName() + "$Lisa", _packageMav, new TypeParameter[0], obj,
 724    new ArrayList<SymbolData>(), null);
 725  0 _cbfjv._enclosing.addInnerClass(sd0);
 726  0 sd0.setOuterData(_cbfjv._enclosing);
 727  0 SymbolData sd1 = new SymbolData(_cbfjv._enclosing.getName() + "$Lisa$Bart", _packageMav, new TypeParameter[0],
 728    obj, new ArrayList<SymbolData>(), null);
 729  0 sd0.addInnerClass(sd1);
 730  0 sd1.setOuterData(sd0);
 731   
 732  0 sd0.setIsContinuation(true);
 733  0 sd1.setIsContinuation(true);
 734   
 735   
 736   
 737  0 LanguageLevelConverter.symbolTable.put(_cbfjv._enclosing.getName() + "$Lisa", sd0);
 738    // LanguageLevelConverter.symbolTable.put(_cbfjv._enclosing.getName() + "$Lisa$Bart", sd1);
 739   
 740  0 cd0.visit(_cbfjv);
 741   
 742    // sd0.setName("Lisa");
 743    // sd1.setName("Bart");
 744   
 745  0 SymbolData sd = _cbfjv._enclosing.getInnerClassOrInterface("Lisa");
 746  0 assertEquals("There should be no errors", 0, errors.size());
 747  0 assertEquals("This symbolData should now have sd0 as an inner class", sd0, sd);
 748  0 assertEquals("sd0 should have the correct outer data", _cbfjv._enclosing, sd0.getOuterData());
 749  0 assertEquals("sd1 should have the correct outer data", sd0, sd1.getOuterData());
 750  0 assertEquals("Sd should now have sd1 as an inner class", sd1, sd.getInnerClassOrInterface("Bart"));
 751   
 752   
 753  0 assertEquals("Lisa should have 0 methods", 0, sd0.getMethods().size());
 754   
 755    }
 756   
 757  0 public void xtestForInnerInterfaceDef() {
 758    // SymbolData obj = new SymbolData("java.lang.Object");
 759    // LanguageLevelConverter.symbolTable.put("java.lang.Object", obj);
 760  0 InnerInterfaceDef cd1 = new InnerInterfaceDef(SourceInfo.NONE, _packageMav, new Word(SourceInfo.NONE, "Bart"),
 761    new TypeParameter[0], new ReferenceType[0],
 762    new BracedBody(SourceInfo.NONE, new BodyItemI[0]));
 763   
 764  0 InnerInterfaceDef cd0 = new InnerInterfaceDef(SourceInfo.NONE, _packageMav, new Word(SourceInfo.NONE, "Lisa"),
 765    new TypeParameter[0], new ReferenceType[0],
 766    new BracedBody(SourceInfo.NONE, new BodyItemI[] {cd1}));
 767   
 768  0 SymbolData sd0 = new SymbolData(_cbfjv._enclosing.getName() + "$Lisa", _packageMav, new TypeParameter[0],
 769    new ArrayList<SymbolData>(), null);
 770  0 SymbolData sd1 = new SymbolData(_cbfjv._enclosing.getName() + "$Lisa$Bart", _packageMav, new TypeParameter[0],
 771    new ArrayList<SymbolData>(), null);
 772  0 sd0.addInnerInterface(sd1);
 773  0 sd0.setIsContinuation(true);
 774  0 sd1.setIsContinuation(true);
 775   
 776  0 _cbfjv._enclosing.addInnerInterface(sd0);
 777  0 sd0.setOuterData(_cbfjv._enclosing);
 778   
 779  0 sd0.addInnerInterface(sd1);
 780  0 sd1.setOuterData(sd0);
 781   
 782    //
 783    // LanguageLevelConverter.symbolTable.put(_cbfjv._enclosing.getName() + "$Lisa", sd0);
 784    // LanguageLevelConverter.symbolTable.put(_cbfjv._enclosing.getName() + "$Lisa$Bart", sd1);
 785   
 786  0 cd0.visit(_cbfjv);
 787   
 788  0 SymbolData sd = _cbfjv._enclosing.getInnerClassOrInterface("Lisa");
 789   
 790  0 assertEquals("There should be no errors", 0, errors.size());
 791  0 assertEquals("This symbolData should now have sd0 as an inner interface", sd0, sd);
 792  0 assertEquals("sd0 should have the correct outer data", _cbfjv._enclosing, sd0.getOuterData());
 793  0 assertEquals("sd1 should have the correct outer data", sd0, sd1.getOuterData());
 794  0 assertEquals("Sd should now have sd1 as an inner interface", sd1, sd.getInnerClassOrInterface("Bart"));
 795  0 assertTrue("Lisa should be an interface", sd0.isInterface());
 796  0 assertTrue("Bart should be an interface", sd1.isInterface());
 797   
 798   
 799    }
 800   
 801  0 public void xtestForConstructorDef() {
 802    //this is a ConstructorDef with no formal parameters and no throws
 803  0 ConstructorDef cd = new ConstructorDef(SourceInfo.NONE, new Word(SourceInfo.NONE, "MyClass"), _publicMav, new FormalParameter[0], new ReferenceType[0],
 804    new BracedBody(SourceInfo.NONE, new BodyItemI[0]));
 805   
 806    //What if constructor name and SymbolData name don't match? Should throw an error.
 807  0 _cbfjv._enclosing = new SymbolData("NotRightName");
 808  0 cd.visit(_cbfjv);
 809  0 assertEquals("Should be 1 error", 1, errors.size());
 810  0 assertEquals("Error message should be correct", "The constructor return type and class name must match", errors.getLast().getFirst());
 811   
 812    //If they are the same, it should work just fine.
 813  0 _cbfjv._enclosing = new SymbolData("MyClass");
 814   
 815  0 MethodData constructor = new MethodData("MyClass",
 816    _publicMav,
 817    new TypeParameter[0],
 818    _cbfjv._enclosing,
 819    new VariableData[0],
 820    new String[0],
 821    _cbfjv._enclosing,
 822    null);
 823   
 824   
 825  0 cd.visit(_cbfjv);
 826   
 827   
 828  0 assertEquals("Should still be 1 error", 1, errors.size());
 829  0 assertEquals("SymbolData should have 1 method", 1, _cbfjv._enclosing.getMethods().size());
 830  0 assertTrue("SymbolData's constructor should be correct", _cbfjv._enclosing.getMethods().contains(constructor));
 831   
 832    //With a ConstructorDef with more throws and variables, should work okay.
 833  0 FormalParameter fp =
 834    new FormalParameter(SourceInfo.NONE,
 835    new UninitializedVariableDeclarator(SourceInfo.NONE,
 836    new PrimitiveType(SourceInfo.NONE, "int"),
 837    new Word(SourceInfo.NONE, "i")),
 838    false);
 839  0 ReferenceType rt = new TypeVariable(SourceInfo.NONE, "MyMadeUpException");
 840  0 ConstructorDef cd2 =
 841    new ConstructorDef(SourceInfo.NONE,
 842    new Word(SourceInfo.NONE, "MyClass"),
 843    _publicMav,
 844    new FormalParameter[] {fp},
 845    new ReferenceType[] {rt},
 846    new BracedBody(SourceInfo.NONE, new BodyItemI[0]));
 847   
 848  0 VariableData vd = new VariableData("i", _finalMav, SymbolData.INT_TYPE, true, null);
 849  0 MethodData constructor2 = new MethodData("MyClass", _publicMav, new TypeParameter[0], _cbfjv._enclosing,
 850    new VariableData[] {vd},
 851    new String[] {"MyMadeUpException"},
 852    _cbfjv._enclosing,
 853    null);
 854   
 855   
 856   
 857  0 constructor2.addVar(vd);
 858  0 cd2.visit(_cbfjv);
 859  0 vd.setEnclosingData(_cbfjv._enclosing.getMethods().getLast());
 860  0 assertEquals("Should still be 1 error", 1, errors.size());
 861  0 assertEquals("SymbolData should have 2 methods", 2, _cbfjv._enclosing.getMethods().size());
 862   
 863  0 assertTrue("SymbolData should have new constructor", _cbfjv._enclosing.getMethods().contains(constructor2));
 864   
 865   
 866    //If two variable names are duplicated, should throw an error.
 867  0 FormalParameter fp2 =
 868    new FormalParameter(SourceInfo.NONE,
 869    new UninitializedVariableDeclarator(SourceInfo.NONE,
 870    new PrimitiveType(SourceInfo.NONE, "double"),
 871    new Word(SourceInfo.NONE, "i")),
 872    false);
 873   
 874  0 ConstructorDef cd3 =
 875    new ConstructorDef(SourceInfo.NONE,
 876    new Word(SourceInfo.NONE, "MyClass"),
 877    _publicMav,
 878    new FormalParameter[] {fp, fp2},
 879    new ReferenceType[] {rt},
 880    new BracedBody(SourceInfo.NONE, new BodyItemI[0]));
 881  0 cd3.visit(_cbfjv);
 882   
 883  0 assertEquals("Should now be 2 errors", 2, errors.size());
 884  0 assertEquals("Error message should be correct","You cannot have two method parameters with the same name" ,
 885    errors.getLast().getFirst());
 886   
 887    //Test that an error is thrown if the class name and constructor name are packaged differently
 888  0 _cbfjv._enclosing.setName("package.MyClass2");
 889  0 ConstructorDef cd4 =
 890    new ConstructorDef(SourceInfo.NONE,
 891    new Word(SourceInfo.NONE, "different.MyClass2"),
 892    _publicMav,
 893    new FormalParameter[0],
 894    new ReferenceType[0],
 895    new BracedBody(SourceInfo.NONE, new BodyItemI[0]));
 896  0 cd4.visit(_cbfjv);
 897   
 898  0 assertEquals("There should now be 3 errors", 3, errors.size());
 899  0 assertEquals("Error message should be correct", "The constructor return type and class name must match", errors.getLast().getFirst());
 900    }
 901  1 public void testDummy() { }
 902    }
 903    }