Clover coverage report - Java Language Levels Test Coverage (javalanglevels-20120305-r5436)
Coverage timestamp: Sun Mar 4 2012 22:02:46 CST
file stats: LOC: 838   Methods: 19
NCLOC: 613   Classes: 2
 
 Source file Conditionals Statements Methods TOTAL
ClassBodyTypeChecker.java 76.1% 95.2% 89.5% 91.3%
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.JExprParser;
 41    import java.util.*;
 42    import java.io.*;
 43    import edu.rice.cs.plt.reflect.JavaVersion;
 44    import edu.rice.cs.plt.iter.*;
 45   
 46    import junit.framework.TestCase;
 47   
 48    /** Do the TypeChecking appropriate to the context of a class body. Common to all Language Levels. */
 49    public class ClassBodyTypeChecker extends SpecialTypeChecker {
 50   
 51    /**The SymbolData corresponding to this class.*/
 52    private SymbolData _symbolData;
 53   
 54    /**True if we encounter a ConstructorDef while visiting the body.*/
 55    protected boolean hasConstructor;
 56   
 57    /** Constructor for ClassBodyTypeChecker. Adds all the variables in the symbol data to the list of what can be seen
 58    * from this context, since class fields can always be seen.
 59    * @param sd The SymbolData of the class we are type checking.
 60    * @param file The File corresponding to the source file we are checking.
 61    * @param packageName The package of the source file.
 62    * @param importedFiles A list of the names of the classes that are specifically imported in the source file
 63    * @param importedPackages A list of the names of the packages that are imported in the source file.
 64    * @param vars A list of the variable datas that can be seen and have been given a value before this context
 65    * @param thrown The exceptions that are thrown
 66    */
 67  146 public ClassBodyTypeChecker(SymbolData sd, File file, String packageName, LinkedList<String> importedFiles,
 68    LinkedList<String> importedPackages, LinkedList<VariableData> vars,
 69    LinkedList<Pair<SymbolData, JExpression>> thrown) {
 70  146 super(sd, file, packageName, importedFiles, importedPackages, vars, thrown);
 71  0 if (sd == null) throw new RuntimeException("SymbolData is null in new ClassBodyTypeChecker operation");
 72  146 _symbolData = sd;
 73  146 hasConstructor = false;
 74  146 assert _vars == vars;
 75   
 76  146 LinkedList<VariableData> classVars = sd.getVars();
 77   
 78    // for (VariableData vd: classVars) {
 79    // if (vd.isFinal() && vd.gotValue()) thingsThatHaveBeenAssigned.addLast(vd);
 80    // }
 81   
 82  146 _vars.addAll(classVars);
 83   
 84  146 LinkedList<VariableData> superVars = sd.getAllSuperVars();
 85  146 for (VariableData vd: superVars) {
 86  1 if (vd.isFinal() && vd.gotValue()) thingsThatHaveBeenAssigned.addLast(vd);
 87    }
 88  146 _vars.addAll(superVars);
 89    }
 90   
 91    /** @return the symbol data corresponding to the class we are visiting*/
 92  0 protected Data _getData() { return _symbolData; }
 93   
 94    /** We need to do this so that expressions (which should only occur in variable initializers and
 95    * initializer blocks) can know which fields have already been declared
 96    */
 97  89 public TypeData forUninitializedVariableDeclaratorOnly(UninitializedVariableDeclarator that,
 98    TypeData typeRes,
 99    TypeData nameRes) {
 100  89 Word name = that.getName();
 101  89 String text = that.getName().getText();
 102  89 VariableData vd = getFieldOrVariable(text, _symbolData, _symbolData, name);
 103  89 if (vd == null) {
 104  0 throw new RuntimeException("The field " + text + " was not found in " + _symbolData.getName() + '.');
 105    }
 106  89 _vars.addLast(vd);
 107  89 return null;
 108    }
 109   
 110    /** Make sure the method is not missing a return type.
 111    * If expected and actual are both not null, then their relationship (i.e.
 112    * is actual a subclass of expected) is checked when the value return statement that returns
 113    * actual is processed.
 114    */
 115  107 private void _checkReturnType(SymbolData expected, SymbolData actual, ConcreteMethodDef that) {
 116    // If the return type is void, the BodyTypeChecker will make sure there are no return statements with expressions.
 117  107 if (expected == SymbolData.VOID_TYPE) {
 118  9 if (actual == null || actual == SymbolData.VOID_TYPE) {
 119    // correct, do nothing
 120    }
 121    }
 122    else {
 123  98 if (actual == null) {
 124  2 _addError("This method is missing a return statement.", that);
 125    }
 126    }
 127    }
 128   
 129    /** Finds the corresponding MethodData for this constructor first. Then visits the body, making sure that
 130    * all final fields are assigned a value and that no final fields are reassigned.
 131    */
 132  19 public TypeData forConstructorDef(ConstructorDef that) {
 133  19 hasConstructor = true;
 134  19 final TypeData mavRes = that.getMav().visit(this);
 135  19 final TypeData[] parameters_result = makeArrayOfRetType(that.getParameters().length);
 136  19 final TypeData[] throwsRes = makeArrayOfRetType(that.getThrows().length);
 137  19 for (int i = 0; i < that.getThrows().length; i++) {
 138  0 throwsRes[i] = getSymbolData(that.getThrows()[i].getName(), _symbolData, that); //that.getThrows()[i].visit(this);
 139    }
 140   
 141    // We need to match the name and params.
 142    // First find the correct MethodData.
 143  19 MethodData md = null;
 144  19 FormalParameter[] fParams = that.getParameters();
 145  19 String[] paramTypes = new String[fParams.length];
 146  19 for (int i = 0; i < fParams.length; i++) {
 147  8 paramTypes[i] = fParams[i].getDeclarator().getType().getName();
 148    }
 149  19 LinkedList<MethodData> mds = _symbolData.getMethods();
 150  19 Iterator<MethodData> iter = mds.iterator();
 151  21 while (iter.hasNext()) {
 152  21 boolean match = true;
 153  21 MethodData tempMd = iter.next();
 154  21 if (tempMd.getName().equals(LanguageLevelVisitor.getUnqualifiedClassName(_symbolData.getName()))) {
 155    // Check the params.
 156  21 VariableData[] vds = tempMd.getParams();
 157  21 if (paramTypes.length == vds.length) {
 158  19 for (int i = 0; i < paramTypes.length; i++) {
 159    // The parameters should be in order. Must also check the unqualified form of the VariableData's type.
 160  8 if(!vds[i].getType().getName().equals(paramTypes[i]) &&
 161    !LanguageLevelVisitor.getUnqualifiedClassName(vds[i].getType().getName()).equals(paramTypes[i])) {
 162  0 match = false;
 163  0 break;
 164    }
 165    }
 166  19 if (match) {
 167  19 md = tempMd;
 168  19 break;
 169    }
 170    }
 171    }
 172    }
 173  0 if (md == null) { throw
 174    new RuntimeException("The constructor " + LanguageLevelVisitor.getUnqualifiedClassName(_symbolData.getName()) +
 175    " was not in the class " + _symbolData.getName() + '.');
 176    }
 177   
 178  19 LinkedList<VariableData> ll = new LinkedList<VariableData>();// = cloneVariableDataList(_vars);
 179  19 VariableData[] vds = md.getParams();
 180  19 for (int i = 0; i<vds.length; i++) {
 181  8 ll.addLast(vds[i]);
 182    }
 183  19 ll.addAll(cloneVariableDataList(_vars));
 184   
 185  19 ConstructorBodyTypeChecker btc = new ConstructorBodyTypeChecker(md, _file, _package, _importedFiles, _importedPackages, ll, new LinkedList<Pair<SymbolData, JExpression>>());
 186  19 final TypeData bodyRes = that.getStatements().visit(btc);
 187   
 188    //make sure the constructor assigns a value to any uninitialized fields (i.e. final fields)
 189  19 LinkedList<VariableData> sdVars = _symbolData.getVars();
 190  19 for (int i = 0; i < sdVars.size(); i++) { // Non-finals automatically get values, so only need to check finals
 191  21 if (! sdVars.get(i).hasValue()) {
 192  1 _addError("The final field " + sdVars.get(i).getName() + " has not been initialized. Make sure you give it a value in this constructor", that);
 193  1 return null;
 194    }
 195    }
 196   
 197  18 _symbolData.decrementConstructorCount();
 198   
 199   
 200  18 if (_symbolData.getConstructorCount() > 0) {
 201  2 unassignVariableDatas(btc.thingsThatHaveBeenAssigned);
 202    }
 203   
 204  18 return forConstructorDefOnly(that, mavRes, parameters_result, throwsRes, bodyRes);
 205    }
 206   
 207   
 208    /*Basically, a no-op*/
 209  18 public TypeData forConstructorDefOnly(ConstructorDef that, TypeData mavRes, TypeData[] parameters_result, TypeData[] throwsRes, TypeData bodyRes) {
 210  18 return forJExpressionOnly(that);
 211    }
 212   
 213    /** Visit all of the fields of the ConcreteMethodDef, and resolve everything. Then, find
 214    * the corresponding MethodData in the SymbolData's list of methods. It must match both in name and parameter
 215    * types. Keep track of what has been assigned before we visit the method body, and then visit the
 216    * method body. Then, make sure the return type of the method is okay, and unassign any variables
 217    * for which the assignment should not be visible outside the scope of the method.
 218    */
 219  103 public TypeData forConcreteMethodDef(ConcreteMethodDef that) {
 220  103 final TypeData mavRes = that.getMav().visit(this);
 221  103 final TypeData[] typeParamsRes = makeArrayOfRetType(that.getTypeParams().length);
 222  103 for (int i = 0; i < that.getTypeParams().length; i++) {
 223  0 typeParamsRes[i] = that.getTypeParams()[i].visit(this);
 224    }
 225  103 final SymbolData resRes = getSymbolData(that.getResult().getName(), _symbolData, that);
 226  103 final TypeData nameRes = that.getName().visit(this);
 227  103 final TypeData[] throwsRes = makeArrayOfRetType(that.getThrows().length);
 228  103 for (int i = 0; i < that.getThrows().length; i++) {
 229  1 throwsRes[i] = getSymbolData(that.getThrows()[i].getName(), _symbolData, that.getThrows()[i]);
 230    }
 231    // We need to match the name and params.
 232    // First find the correct MethodData.
 233  103 MethodData md = null;
 234  103 FormalParameter[] fParams = that.getParams();
 235  103 String[] paramTypes = new String[fParams.length];
 236  103 for (int i = 0; i < fParams.length; i++) {
 237  53 paramTypes[i] = fParams[i].getDeclarator().getType().getName();
 238    }
 239  103 LinkedList<MethodData> mds = _symbolData.getMethods();
 240  103 Iterator<MethodData> iter = mds.iterator();
 241  103 while (iter.hasNext()) {
 242  187 boolean match = false;
 243  187 MethodData tempMd = iter.next();
 244  187 if (tempMd.getName().equals(that.getName().getText())) {
 245  104 match = true;
 246   
 247    // Check the params.
 248  104 VariableData[] vds = tempMd.getParams();
 249  104 if (paramTypes.length == vds.length) {
 250  102 for (int i = 0; i < paramTypes.length; i++) {
 251    // The parameters should be in order. Must also check the unqualified form of the VariableData's type.
 252  51 if(!vds[i].getType().getName().equals(paramTypes[i]) &&
 253    !LanguageLevelVisitor.getUnqualifiedClassName(vds[i].getType().getName()).equals(paramTypes[i])) {
 254  0 match = false;
 255  0 break;
 256    }
 257    }
 258  102 if (match) {
 259  102 md = tempMd;
 260  102 break;
 261    }
 262    }
 263    }
 264    }
 265  103 if (md == null) {
 266  1 throw new RuntimeException("Internal Program Error: The method " + that.getName().getText() + " was not in the class " + _symbolData.getName() + ". Please report this bug.");
 267    }
 268   
 269  102 LinkedList<VariableData> ll = new LinkedList<VariableData>();
 270  102 VariableData[] vds = md.getParams();
 271  102 for (int i = 0; i < vds.length; i++) {
 272  51 ll.addLast(vds[i]);
 273    }
 274  102 ll.addAll(cloneVariableDataList(_vars));
 275   
 276  102 LinkedList<VariableData> thingsWeAssigned = new LinkedList<VariableData>();
 277  102 for (int i = 0; i<_symbolData.getVars().size(); i++) {
 278  68 VariableData tempVd = _symbolData.getVars().get(i);
 279  68 if (tempVd.gotValue()) { //then this variable did not have a value previously.
 280  0 thingsWeAssigned.addLast(tempVd);
 281    }
 282    }
 283   
 284  102 BodyTypeChecker btc = new BodyTypeChecker(md, _file, _package, _importedFiles, _importedPackages, ll,
 285    new LinkedList<Pair<SymbolData, JExpression>>());
 286   
 287  102 TypeData bodyRes = that.getBody().visit(btc); // We assume that this will return an InstanceData -- the return type of the body
 288   
 289    // This checks to see that the method returns the correct type. It throws its own errors.
 290  94 if (bodyRes != null) {bodyRes = bodyRes.getSymbolData();}
 291  102 _checkReturnType(md.getReturnType(), (SymbolData) bodyRes, that);
 292  102 if (md.getReturnType() != null) {
 293    // Ensure that this method doesn't override another method with a different return type.
 294  102 SymbolData.checkDifferentReturnTypes(md, _symbolData, LanguageLevelConverter.OPT.javaVersion());
 295    }
 296   
 297    // This is not used because this call eventually invokes the forUninitializedVariableDeclarator method above.
 298  102 final TypeData[] paramsRes = makeArrayOfRetType(that.getParams().length);
 299    //
 300    // // Why oh why is this necessary; these variables aren't even in scope elsewhere; they should be invisible!!!!
 301    // for (int i = 0; i < thingsWeAssigned.size(); i++) {
 302    // thingsWeAssigned.get(i).lostValue();
 303    // }
 304  102 return resRes;
 305    }
 306   
 307    /*
 308    * Make sure that this method does not override another method with a different return type,
 309    * since this is not allowed in java.
 310    */
 311  3 public TypeData forAbstractMethodDef(AbstractMethodDef that) {
 312  3 final TypeData mavRes = that.getMav().visit(this);
 313  3 final TypeData[] typeParamsRes = makeArrayOfRetType(that.getTypeParams().length);
 314  3 for (int i = 0; i < that.getTypeParams().length; i++) {
 315  0 typeParamsRes[i] = that.getTypeParams()[i].visit(this);
 316    }
 317  3 final SymbolData resRes = getSymbolData(that.getResult().getName(), _symbolData, that);
 318  3 final TypeData nameRes = that.getName().visit(this);
 319   
 320    // This is not used because this call eventually invokes the forUninitializedVariableDeclarator method above.
 321  3 final TypeData[] paramsRes = makeArrayOfRetType(that.getParams().length);
 322  3 for (int i = 0; i<paramsRes.length; i++) {
 323  2 paramsRes[i] = getSymbolData(that.getParams()[i].getDeclarator().getType().getName(), _symbolData, that.getParams()[i]);
 324    }
 325  3 final TypeData[] throwsRes = makeArrayOfRetType(that.getThrows().length);
 326  3 for (int i = 0; i < that.getThrows().length; i++) {
 327  0 throwsRes[i] = getSymbolData(that.getThrows()[i].getName(), _symbolData, that.getThrows()[i]);
 328    }
 329    // Ensure that this method doesn't override another method with a different return type.
 330  3 MethodData md = _symbolData.getMethod(that.getName().getText(), paramsRes);
 331  3 if (md == null) {
 332  0 throw new RuntimeException("Internal Program Error: Could not find the method " + that.getName().getText() + " in class " + _symbolData.getName() +". Please report this bug.");
 333    }
 334  3 SymbolData.checkDifferentReturnTypes(md, _symbolData, LanguageLevelConverter.OPT.javaVersion());
 335   
 336  3 return resRes;
 337    }
 338   
 339    /*Try to resolve the type, and then make sure it can be seen from where we are. */
 340  9 public TypeData forTypeOnly(Type that) {
 341  9 Data sd = getSymbolData(that.getName(), _symbolData, that);
 342  9 if (sd != null) {sd = sd.getOuterData();}
 343  9 while (sd != null && !LanguageLevelVisitor.isJavaLibraryClass(sd.getSymbolData().getName())) {
 344  3 if (!checkAccess(that, sd.getMav(), sd.getName(), sd.getSymbolData(), _symbolData, "class or interface")) {
 345  1 return null;
 346    }
 347  2 sd = sd.getOuterData();
 348    }
 349  8 return forJExpressionOnly(that);
 350    }
 351   
 352    /**
 353    * Test the methods that are defined above.
 354    */
 355    public static class ClassBodyTypeCheckerTest extends TestCase {
 356   
 357    private ClassBodyTypeChecker _cbbtc;
 358   
 359    private SymbolData _sd1;
 360    private SymbolData _sd2;
 361    private SymbolData _sd3;
 362    private SymbolData _sd4;
 363    private SymbolData _sd5;
 364    private SymbolData _sd6;
 365    private ModifiersAndVisibility _publicMav = new ModifiersAndVisibility(SourceInfo.NONE, new String[] {"public"});
 366    private ModifiersAndVisibility _protectedMav = new ModifiersAndVisibility(SourceInfo.NONE, new String[] {"protected"});
 367    private ModifiersAndVisibility _privateMav = new ModifiersAndVisibility(SourceInfo.NONE, new String[] {"private"});
 368    private ModifiersAndVisibility _packageMav = new ModifiersAndVisibility(SourceInfo.NONE, new String[0]);
 369    private ModifiersAndVisibility _abstractMav = new ModifiersAndVisibility(SourceInfo.NONE, new String[] {"abstract"});
 370    private ModifiersAndVisibility _finalMav = new ModifiersAndVisibility(SourceInfo.NONE, new String[] {"final"});
 371   
 372   
 373  0 public ClassBodyTypeCheckerTest() {
 374  0 this("");
 375    }
 376  7 public ClassBodyTypeCheckerTest(String name) {
 377  7 super(name);
 378    }
 379   
 380  7 public void setUp() {
 381  7 _sd1 = new SymbolData("i.like.monkey");
 382  7 _sd2 = new SymbolData("i.like.giraffe");
 383  7 _sd3 = new SymbolData("zebra");
 384  7 _sd4 = new SymbolData("u.like.emu");
 385  7 _sd5 = new SymbolData("");
 386  7 _sd6 = new SymbolData("cebu");
 387   
 388  7 errors = new LinkedList<Pair<String, JExpressionIF>>();
 389  7 LanguageLevelConverter.symbolTable.clear();
 390  7 LanguageLevelConverter._newSDs.clear();
 391  7 _cbbtc =
 392    new ClassBodyTypeChecker(_sd1, new File(""), "", new LinkedList<String>(), new LinkedList<String>(),
 393    new LinkedList<VariableData>(), new LinkedList<Pair<SymbolData, JExpression>>());
 394  7 LanguageLevelConverter.OPT = new Options(JavaVersion.JAVA_5, EmptyIterable.<File>make());
 395  7 _cbbtc._importedPackages.addFirst("java.lang");
 396    }
 397   
 398  1 public void testForUninitializedVariableDeclaratorOnly() {
 399  1 VariableData vd1 = new VariableData("Mojo", _publicMav, SymbolData.INT_TYPE, false, _cbbtc._data);
 400  1 _sd1.addVar(vd1);
 401  1 UninitializedVariableDeclarator uvd =
 402    new UninitializedVariableDeclarator(SourceInfo.NONE,
 403    new PrimitiveType(SourceInfo.NONE, "int"),
 404    new Word(SourceInfo.NONE, "Mojo"));
 405    // uvd.visit(_cbbtc);
 406  1 _cbbtc.forUninitializedVariableDeclaratorOnly(uvd, SymbolData.INT_TYPE, null);
 407  1 assertTrue("_vars should contain Mojo.", _cbbtc._vars.contains(vd1));
 408    }
 409   
 410  1 public void testForInitializedVariableDeclaratorOnly() {
 411  1 VariableData vd1 = new VariableData("Mojo", _publicMav, SymbolData.INT_TYPE, false, _cbbtc._data);
 412  1 _sd1.addVar(vd1);
 413  1 InitializedVariableDeclarator ivd = new InitializedVariableDeclarator(SourceInfo.NONE,
 414    new PrimitiveType(SourceInfo.NONE, "int"),
 415    new Word(SourceInfo.NONE, "Mojo"),
 416    new IntegerLiteral(SourceInfo.NONE, 1));
 417  1 ivd.visit(_cbbtc);
 418  1 assertEquals("There should be no errors.", 0, errors.size());
 419  1 assertTrue("_vars should contain Mojo.", _cbbtc._vars.contains(vd1));
 420  1 ivd = new InitializedVariableDeclarator(SourceInfo.NONE,
 421    new PrimitiveType(SourceInfo.NONE, "int"),
 422    new Word(SourceInfo.NONE, "Santa's Little Helper"),
 423    new IntegerLiteral(SourceInfo.NONE, 1));
 424  1 try {
 425  1 ivd.visit(_cbbtc);
 426  0 fail("Should have thrown a RuntimeException because there's no field named Santa's Little Helper.");
 427    }
 428    catch (RuntimeException re) {
 429  1 assertEquals("The error message should be correct.", "Internal Program Error: The field or variable Santa's Little Helper was not found in this block. Please report this bug.", re.getMessage());
 430    }
 431    }
 432   
 433  1 public void test_checkReturnType() {
 434    /* Check tests that should work correctly first. */
 435  1 _cbbtc._checkReturnType(SymbolData.VOID_TYPE, null, null);
 436  1 _cbbtc._checkReturnType(SymbolData.VOID_TYPE, SymbolData.VOID_TYPE, null);
 437  1 _cbbtc._checkReturnType(SymbolData.INT_TYPE, SymbolData.INT_TYPE, null);
 438  1 _cbbtc._checkReturnType(SymbolData.DOUBLE_TYPE, SymbolData.INT_TYPE, null);
 439   
 440  1 assertEquals("There should be no errors.", 0, errors.size());
 441   
 442    /* Check tests that should each throw an error. */
 443  1 _cbbtc._checkReturnType(SymbolData.INT_TYPE, null, null);
 444  1 assertEquals("There should now be 1 error", 1, errors.size());
 445  1 assertEquals("The error message should be correct", "This method is missing a return statement.", errors.get(0).getFirst());
 446   
 447    }
 448   
 449  1 public void testForConcreteMethodDef() {
 450  1 FormalParameter[] fps = new FormalParameter[] {
 451    new FormalParameter(SourceInfo.NONE,
 452    new UninitializedVariableDeclarator(SourceInfo.NONE,
 453    new PrimitiveType(SourceInfo.NONE, "double"),
 454    new Word (SourceInfo.NONE, "field1")),
 455    false),
 456    new FormalParameter(SourceInfo.NONE,
 457    new UninitializedVariableDeclarator(SourceInfo.NONE,
 458    new PrimitiveType(SourceInfo.NONE, "boolean"),
 459    new Word (SourceInfo.NONE, "field2")),
 460    false)};
 461  1 ConcreteMethodDef cmd = new ConcreteMethodDef(SourceInfo.NONE,
 462    _packageMav,
 463    new TypeParameter[0],
 464    new PrimitiveType(SourceInfo.NONE, "int"),
 465    new Word(SourceInfo.NONE, "methodName"),
 466    fps,
 467    new ReferenceType[0],
 468    new BracedBody(SourceInfo.NONE, new BodyItemI[] {
 469    new ValueReturnStatement(SourceInfo.NONE, new IntegerLiteral(SourceInfo.NONE, 5) )}));
 470  1 MethodData md = new MethodData("methodName",
 471    _packageMav,
 472    new TypeParameter[0],
 473    SymbolData.INT_TYPE,
 474    new VariableData[] { new VariableData(SymbolData.DOUBLE_TYPE), new VariableData(SymbolData.BOOLEAN_TYPE) },
 475    new String[0],
 476    _sd1,
 477    null); // no SourceInfo
 478  1 _sd1.addMethod(md);
 479  1 cmd.visit(_cbbtc);
 480  1 assertEquals("There should be no errors.", 0, errors.size());
 481   
 482  1 cmd = new ConcreteMethodDef(SourceInfo.NONE,
 483    _packageMav,
 484    new TypeParameter[0],
 485    new PrimitiveType(SourceInfo.NONE, "int"),
 486    new Word(SourceInfo.NONE, "Selma"),
 487    fps,
 488    new ReferenceType[0],
 489    new BracedBody(SourceInfo.NONE, new BodyItemI[] {
 490    new ValueReturnStatement(SourceInfo.NONE,
 491    new IntegerLiteral(SourceInfo.NONE, 5))}));
 492   
 493  1 try {
 494  1 cmd.visit(_cbbtc);
 495  0 fail("Should have thrown a RuntimeException because there's no method named Selma.");
 496    }
 497    catch (RuntimeException re) {
 498  1 assertEquals("The error message should be correct.", "Internal Program Error: The method Selma was not in the class i.like.monkey. Please report this bug.", re.getMessage());
 499    }
 500   
 501   
 502    //Check that an uninitialized variable is caught:
 503  1 PrimitiveType intt = new PrimitiveType(SourceInfo.NONE, "int");
 504  1 UninitializedVariableDeclarator uvd = new UninitializedVariableDeclarator(SourceInfo.NONE, intt, new Word(SourceInfo.NONE, "i"));
 505   
 506  1 Statement s = new ValueReturnStatement(SourceInfo.NONE, new SimpleNameReference(SourceInfo.NONE, new Word(SourceInfo.NONE, "i")));
 507  1 ConcreteMethodDef cmd0 = new ConcreteMethodDef(SourceInfo.NONE, _publicMav, new TypeParameter[0], intt,
 508    new Word(SourceInfo.NONE, "invalidMethod"), new FormalParameter[0],
 509    new ReferenceType[0], new BracedBody(SourceInfo.NONE, new BodyItemI[] {new VariableDeclaration(SourceInfo.NONE, _packageMav, new UninitializedVariableDeclarator[]{uvd}), s}));
 510  1 VariableData vd = new VariableData("i", _packageMav, SymbolData.INT_TYPE, false, null);
 511  1 MethodData md0 = new MethodData("invalidMethod", _publicMav, new TypeParameter[0], SymbolData.INT_TYPE,
 512    new VariableData[0], new String[0], _sd1, cmd0);
 513  1 _sd1.addMethod(md0);
 514  1 vd.setEnclosingData(md0);
 515  1 md0.addVar(vd);
 516   
 517  1 _cbbtc = new ClassBodyTypeChecker(_sd1, _cbbtc._file, _cbbtc._package, _cbbtc._importedFiles, _cbbtc._importedPackages, new LinkedList<VariableData>(), new LinkedList<Pair<SymbolData, JExpression>>());
 518  1 cmd0.visit(_cbbtc);
 519  1 assertEquals("There should be 1 error", 1, errors.size());
 520  1 assertEquals("The error message should be correct", "You cannot use i because it may not have been given a value", errors.get(0).getFirst());
 521   
 522   
 523   
 524    //Check that the lexical scope of an if then statement is handled correctly.
 525  1 Expression te = new LessThanExpression(SourceInfo.NONE,
 526    new SimpleNameReference(SourceInfo.NONE, new Word(SourceInfo.NONE, "j")),
 527    new IntegerLiteral(SourceInfo.NONE, 5));
 528  1 Statement ts = new ExpressionStatement(SourceInfo.NONE, new SimpleAssignmentExpression(SourceInfo.NONE, new SimpleNameReference(SourceInfo.NONE, new Word(SourceInfo.NONE, "i")), new IntegerLiteral(SourceInfo.NONE, 10)));
 529  1 IfThenStatement ift = new IfThenStatement(SourceInfo.NONE, te, ts);
 530   
 531   
 532  1 FormalParameter param = new FormalParameter(SourceInfo.NONE, new UninitializedVariableDeclarator(SourceInfo.NONE, intt, new Word(SourceInfo.NONE, "j")), false);
 533  1 BracedBody bb = new BracedBody(SourceInfo.NONE, new BodyItemI[] {new VariableDeclaration(SourceInfo.NONE, _packageMav, new UninitializedVariableDeclarator[]{uvd}), ift,
 534    new ValueReturnStatement(SourceInfo.NONE, new SimpleNameReference(SourceInfo.NONE, new Word(SourceInfo.NONE, "i")))});
 535   
 536  1 ConcreteMethodDef cmd1 = new ConcreteMethodDef(SourceInfo.NONE, _publicMav, new TypeParameter[0],
 537    intt, new Word(SourceInfo.NONE, "myMethod"), new FormalParameter[] {param},
 538    new ReferenceType[0], bb);
 539   
 540  1 VariableData vd1 = new VariableData("j", _packageMav, SymbolData.INT_TYPE, true, null);
 541  1 VariableData vd2 = new VariableData("i", _packageMav, SymbolData.INT_TYPE, false, null);
 542  1 MethodData md1 = new MethodData("myMethod", _publicMav, new TypeParameter[0], SymbolData.INT_TYPE,
 543    new VariableData[] {vd1}, new String[0], _sd1, cmd1);
 544  1 _sd1.addMethod(md1);
 545  1 vd1.setEnclosingData(md1);
 546  1 vd2.setEnclosingData(md1);
 547  1 md1.addVar(vd1);
 548  1 md1.addVar(vd2);
 549   
 550  1 _cbbtc = new ClassBodyTypeChecker(_sd1, _cbbtc._file, _cbbtc._package, _cbbtc._importedFiles, _cbbtc._importedPackages, new LinkedList<VariableData>(), new LinkedList<Pair<SymbolData, JExpression>>());
 551  1 cmd1.visit(_cbbtc);
 552   
 553  1 assertEquals("There should still be 1 error", 1, errors.size()); // Generated error is duplicate
 554  1 assertEquals("The error message should be correct", "You cannot use i because it may not have been given a value",
 555    errors.get(0).getFirst());
 556   
 557    //Check that a final variable cannot be reassigned to
 558  1 s = new ValueReturnStatement(SourceInfo.NONE, new SimpleNameReference(SourceInfo.NONE,
 559    new Word(SourceInfo.NONE, "i")));
 560  1 VariableDeclaration i =
 561    new VariableDeclaration(SourceInfo.NONE, _packageMav, new UninitializedVariableDeclarator[]{uvd});
 562  1 ExpressionStatement se =
 563    new ExpressionStatement(SourceInfo.NONE,
 564    new SimpleAssignmentExpression(SourceInfo.NONE,
 565    new SimpleNameReference(SourceInfo.NONE,
 566    new Word(SourceInfo.NONE, "i")),
 567    new IntegerLiteral(SourceInfo.NONE, 2)));
 568  1 ExpressionStatement se2 =
 569    new ExpressionStatement(SourceInfo.NONE,
 570    new SimpleAssignmentExpression(SourceInfo.NONE,
 571    new SimpleNameReference(SourceInfo.NONE,
 572    new Word(SourceInfo.NONE, "i")),
 573    new IntegerLiteral(SourceInfo.NONE, 5)));
 574   
 575  1 BracedBody b = new BracedBody(SourceInfo.NONE, new BodyItemI[] {i, se, se2, s});
 576  1 ConcreteMethodDef cmd2 =
 577    new ConcreteMethodDef(SourceInfo.NONE,
 578    _publicMav,
 579    new TypeParameter[0], intt,
 580    new Word(SourceInfo.NONE, "doubleAssignmentMethod"),
 581    new FormalParameter[0],
 582    new ReferenceType[0], b);
 583   
 584  1 VariableData vdi = new VariableData("i", _finalMav, SymbolData.INT_TYPE, false, null);
 585  1 MethodData md2 = new MethodData("doubleAssignmentMethod", _publicMav, new TypeParameter[0], SymbolData.INT_TYPE,
 586    new VariableData[0], new String[0], _sd1, cmd2);
 587  1 _sd1.addMethod(md2);
 588  1 vdi.setEnclosingData(md2);
 589   
 590  1 md2.addVar(vdi);
 591   
 592  1 _cbbtc = new ClassBodyTypeChecker(_sd1, _cbbtc._file, _cbbtc._package, _cbbtc._importedFiles, _cbbtc._importedPackages, new LinkedList<VariableData>(), new LinkedList<Pair<SymbolData, JExpression>>());
 593  1 cmd2.visit(_cbbtc);
 594  1 assertEquals("There should now be 2 error2", 2, errors.size());
 595  1 assertEquals("The error message should be correct",
 596    "You cannot assign a value to i because it is immutable and has already been given a value",
 597    errors.get(1).getFirst());
 598   
 599   
 600    //test that if a variable is assigned in a branch of the if, and then returned, it is okay.
 601  1 te = new LessThanExpression(SourceInfo.NONE, new SimpleNameReference(SourceInfo.NONE, new Word(SourceInfo.NONE, "j")),
 602    new IntegerLiteral(SourceInfo.NONE, 5));
 603  1 Statement assignStatement = new ExpressionStatement(SourceInfo.NONE, new SimpleAssignmentExpression(SourceInfo.NONE, new SimpleNameReference(SourceInfo.NONE, new Word(SourceInfo.NONE, "i")), new IntegerLiteral(SourceInfo.NONE, 10)));
 604  1 Statement returnStatement = new ValueReturnStatement(SourceInfo.NONE, new SimpleNameReference(SourceInfo.NONE, new Word(SourceInfo.NONE, "i")));
 605  1 ts = new Block(SourceInfo.NONE, new BracedBody(SourceInfo.NONE, new BodyItemI[] {assignStatement, returnStatement}));
 606  1 ift = new IfThenStatement(SourceInfo.NONE, te, ts);
 607   
 608  1 bb = new BracedBody(SourceInfo.NONE, new BodyItemI[] {new VariableDeclaration(SourceInfo.NONE, _packageMav, new UninitializedVariableDeclarator[]{uvd}),
 609    ift,
 610    new ValueReturnStatement(SourceInfo.NONE,
 611    new IntegerLiteral(SourceInfo.NONE, 5))});
 612   
 613  1 ConcreteMethodDef cmd4 = new ConcreteMethodDef(SourceInfo.NONE, _publicMav, new TypeParameter[0],
 614    intt, new Word(SourceInfo.NONE, "myMethod3"), new FormalParameter[] {param},
 615    new ReferenceType[0], bb);
 616   
 617  1 vd1 = new VariableData("j", _packageMav, SymbolData.INT_TYPE, true, null);
 618  1 vd2 = new VariableData("i", _packageMav, SymbolData.INT_TYPE, false, null);
 619  1 md1 = new MethodData("myMethod3", _publicMav, new TypeParameter[0], SymbolData.INT_TYPE,
 620    new VariableData[] {vd1}, new String[0], _sd1, cmd4);
 621  1 md1.addVar(vd1);
 622  1 md1.addVar(vd2);
 623   
 624  1 vd1.setEnclosingData(md1);
 625  1 vd2.setEnclosingData(md1);
 626   
 627   
 628  1 _sd1.addMethod(md1);
 629  1 _cbbtc = new ClassBodyTypeChecker(_sd1, _cbbtc._file, _cbbtc._package, _cbbtc._importedFiles, _cbbtc._importedPackages, new LinkedList<VariableData>(), new LinkedList<Pair<SymbolData, JExpression>>());
 630   
 631   
 632  1 md1.addBlock(new BlockData(md1));
 633  1 cmd4.visit(_cbbtc);
 634  1 assertEquals("There should still be 2 errors", 2, errors.size());
 635    }
 636   
 637  1 public void testCheckDifferentReturnTypes() {
 638  1 SymbolData superSd = new SymbolData("aiya");
 639  1 _sd1.setSuperClass(superSd);
 640  1 MethodData md3 = new MethodData("methodName",
 641    _publicMav,
 642    new TypeParameter[0],
 643    SymbolData.CHAR_TYPE,
 644    new VariableData[0],
 645    new String[0],
 646    null,
 647    null);
 648  1 superSd.addMethod(md3);
 649  1 MethodData md4 = new MethodData("methodName",
 650    _publicMav,
 651    new TypeParameter[0],
 652    SymbolData.INT_TYPE,
 653    new VariableData[0],
 654    new String[0],
 655    superSd,
 656    null);
 657  1 MethodDef mDef = new ConcreteMethodDef(SourceInfo.NONE, _publicMav, new TypeParameter[0], new PrimitiveType(SourceInfo.NONE, "int"),
 658    new Word(SourceInfo.NONE, "methodName"), new FormalParameter[0], new ReferenceType[0],
 659    new BracedBody(SourceInfo.NONE, new BodyItemI[] {new ValueReturnStatement(SourceInfo.NONE, new IntegerLiteral(SourceInfo.NONE, 76))}));
 660  1 _sd1.addMethod(md4);
 661  1 _cbbtc._symbolData = _sd1;
 662  1 mDef.visit(_cbbtc);
 663  1 assertEquals("There should be one error.", 1, errors.size());
 664  1 assertEquals("The error message should be correct", "methodName() in " + _sd1.getName() + " cannot override methodName() in aiya; attempting to use different return types",
 665    errors.get(0).getFirst());
 666  1 mDef = new AbstractMethodDef(SourceInfo.NONE, _publicMav, new TypeParameter[0], new PrimitiveType(SourceInfo.NONE, "int"),
 667    new Word(SourceInfo.NONE, "methodName"), new FormalParameter[0], new ReferenceType[0]);
 668   
 669  1 mDef.visit(_cbbtc);
 670  1 assertEquals("There should be two errors.", 2, errors.size());
 671  1 assertEquals("The error message should be correct", "methodName() in " + _sd1.getName() + " cannot override methodName() in aiya; attempting to use different return types",
 672    errors.get(1).getFirst());
 673    }
 674   
 675  1 public void testForTypeOnly() {
 676  1 Type t = new PrimitiveType(SourceInfo.NONE, "double");
 677  1 t.visit(_cbbtc);
 678  1 assertEquals("There should be no errors", 0, errors.size());
 679   
 680  1 SymbolData sd = new SymbolData("Adam");
 681  1 sd.setIsContinuation(false);
 682  1 symbolTable.put("Adam", sd);
 683  1 sd.setMav(_publicMav);
 684  1 t = new ClassOrInterfaceType(SourceInfo.NONE, "Adam", new Type[0]);
 685  1 t.visit(_cbbtc);
 686  1 assertEquals("There should still be no errors", 0, errors.size());
 687   
 688  1 SymbolData innerSd = new SymbolData("Adam$Wulf");
 689  1 innerSd.setIsContinuation(false);
 690  1 sd.addInnerClass(innerSd);
 691  1 innerSd.setOuterData(sd);
 692  1 innerSd.setMav(_publicMav);
 693  1 _cbbtc.symbolTable.put("USaigehgihdsgslghdlighs", innerSd);
 694  1 t = new ClassOrInterfaceType(SourceInfo.NONE, "Adam.Wulf", new Type[0]);
 695  1 t.visit(_cbbtc);
 696  1 assertEquals("There should still be no errors", 0, errors.size());
 697   
 698  1 innerSd.setMav(_privateMav);
 699  1 t = new ClassOrInterfaceType(SourceInfo.NONE, "Adam.Wulf", new Type[0]);
 700  1 t.visit(_cbbtc);
 701   
 702  1 String tcSD = _cbbtc._symbolData.getName();
 703  1 assertEquals("There should be one error", 1, errors.size());
 704  1 assertEquals("The error message should be correct",
 705    "The class or interface Adam.Wulf in Adam.Wulf is private and cannot be accessed from " + tcSD,
 706    errors.get(0).getFirst());
 707   
 708  1 sd.setMav(_privateMav);
 709  1 innerSd.setMav(_publicMav);
 710  1 t = new ClassOrInterfaceType(SourceInfo.NONE, "Adam.Wulf", new Type[0]);
 711  1 t.visit(_cbbtc);
 712  1 assertEquals("There should be two errors", 2, errors.size());
 713  1 assertEquals("The error message should be correct",
 714    "The class or interface Adam in Adam is private and cannot be accessed from " + tcSD,
 715    errors.get(1).getFirst());
 716    }
 717   
 718  1 public void testForConstructorDef() {
 719  1 VariableDeclarator[] vds =
 720    new VariableDeclarator[] { new UninitializedVariableDeclarator(SourceInfo.NONE,
 721    new PrimitiveType(SourceInfo.NONE, "int"),
 722    new Word(SourceInfo.NONE, "i"))};
 723   
 724  1 VariableDeclaration vd = new VariableDeclaration(SourceInfo.NONE, _finalMav, vds);
 725  1 SimpleNameReference snr =
 726    new SimpleNameReference(SourceInfo.NONE, new Word(SourceInfo.NONE, "i"));
 727  1 ExpressionStatement es =
 728    new ExpressionStatement(SourceInfo.NONE,
 729    new SimpleAssignmentExpression(SourceInfo.NONE,
 730    snr,
 731    new IntegerLiteral(SourceInfo.NONE, 1)));
 732  1 BracedBody cbb = new BracedBody(SourceInfo.NONE, new BodyItemI[] { es });
 733  1 ConstructorDef cd = new ConstructorDef(SourceInfo.NONE,
 734    new Word(SourceInfo.NONE, "Jimes"),
 735    _publicMav,
 736    new FormalParameter[0],
 737    new ReferenceType[0],
 738    cbb);
 739  1 BracedBody b = new BracedBody(SourceInfo.NONE, new BodyItemI[] {vd, cd});
 740  1 ClassDef classDef =
 741    new ClassDef(SourceInfo.NONE,
 742    _publicMav,
 743    new Word(SourceInfo.NONE, "Jimes"),
 744    new TypeParameter[0],
 745    new ClassOrInterfaceType(SourceInfo.NONE, "java.io.StreamTokenizer", new Type[0]),
 746    new ReferenceType[0],
 747    b);
 748   
 749  1 SymbolData jimes = new SymbolData("Jimes");
 750  1 VariableData vData = new VariableData("i", _finalMav, SymbolData.INT_TYPE, false, jimes);
 751  1 _cbbtc._file = new File("Jimes.dj0");
 752  1 jimes.setMav(_publicMav);
 753  1 jimes.setIsContinuation(false);
 754  1 jimes.addVar(vData);
 755   
 756  1 symbolTable.put("Jimes", jimes);
 757   
 758    // SymbolData obj = _cbbtc.getSymbolData("java.lang.Object", new NullLiteral(SourceInfo.NONE), false, true);
 759  1 SymbolData tokenizer = _cbbtc.getSymbolData("java.io.StreamTokenizer", new NullLiteral(SourceInfo.NONE), false, true);
 760  1 jimes.setSuperClass(tokenizer);
 761  1 SymbolData jutc = defineTestCaseClass();
 762   
 763  1 assert symbolTable.contains(tokenizer);
 764  1 assert symbolTable.contains(jutc);
 765   
 766  1 MethodData md =
 767    new MethodData("Jimes", _publicMav, new TypeParameter[0], jimes, new VariableData[0], new String[0], jimes, cd);
 768  1 MethodData objMd =
 769    new MethodData("java.lang.Object", _publicMav, new TypeParameter[0], tokenizer, new VariableData[0],
 770    new String[0], tokenizer, cd);
 771  1 jimes.addMethod(md);
 772   
 773    // assumes an explicit super call with no arguments
 774  1 classDef.visit(_cbbtc);
 775  1 assertEquals("There should be one error", 1, errors.size());
 776  1 assertEquals("Error message should be correct",
 777    "You must invoke one of java.io.StreamTokenizer's constructors here. You can either explicitly "
 778    + "invoke one of its exisitng constructors or add a constructor with signature: StreamTokenizer().",
 779    errors.getLast().getFirst());
 780   
 781    // test that a constructor can set the value of a final field
 782  1 tokenizer.addMethod(objMd); //give super class constructor
 783  1 vData.lostValue();
 784   
 785  1 classDef.visit(_cbbtc);
 786  1 assertEquals("There should still be one error", 1, errors.size());
 787   
 788    // Since we are going to traverse classDef again, we are resetting the error log.
 789  1 errors.clear();
 790    // test that if the constructor does not assign a value to the final field, then an error is thrown
 791  1 vData.lostValue();
 792  1 cbb = new BracedBody(SourceInfo.NONE, new BodyItemI[] {});
 793  1 cd = new ConstructorDef(SourceInfo.NONE,
 794    new Word(SourceInfo.NONE, "Jimes"),
 795    _publicMav,
 796    new FormalParameter[0],
 797    new ReferenceType[0],
 798    cbb);
 799  1 b = new BracedBody(SourceInfo.NONE, new BodyItemI[] {vd, cd});
 800  1 classDef = new ClassDef(SourceInfo.NONE,
 801    _publicMav,
 802    new Word(SourceInfo.NONE, "Jimes"),
 803    new TypeParameter[0],
 804    new ClassOrInterfaceType(SourceInfo.NONE, "java.lang.Object", new Type[0]),
 805    new ReferenceType[0], b);
 806   
 807    // System.err.println("***** Starting traversal of classDef");
 808  1 classDef.visit(_cbbtc);
 809    // System.err.println("Error 3 for line 803 of ClassBodyTypeChecker is: " + errors.get(2).getFirst());
 810    // System.err.println("Error 2 for line 803 of ClassBodyTypeChecker is: " + errors.get(1).getFirst());
 811    // System.err.println("Error 1 for line 803 of ClassBodyTypeChecker is: " + errors.get(0).getFirst());
 812   
 813  1 assertEquals("There should be 2 errors now", 2, errors.size());
 814   
 815  1 assertEquals("The second error message should be correct",
 816    "The final field i has not been initialized. Make sure you give it a value in this constructor",
 817    errors.getLast().getFirst());
 818   
 819    //test the case of a constructor that makes a call to another constructor
 820  1 vData = new VariableData("j", _finalMav, SymbolData.INT_TYPE, false, jimes);
 821  1 jimes.setVars(new LinkedList<VariableData>());
 822  1 jimes.addVar(vData);
 823   
 824  1 LinkedList<VariableData> vs = new LinkedList<VariableData>();
 825  1 vs.addLast(vData);
 826  1 _cbbtc = new ClassBodyTypeChecker(jimes, new File(""), "", new LinkedList<String>(), new LinkedList<String>(), vs, new LinkedList<Pair<SymbolData, JExpression>>());
 827  1 ExpressionStatement assign = new ExpressionStatement(SourceInfo.NONE, new SimpleAssignmentExpression(SourceInfo.NONE, new SimpleNameReference(SourceInfo.NONE, new Word(SourceInfo.NONE, "j")), new IntegerLiteral(SourceInfo.NONE, 45)));
 828  1 b = new BracedBody(SourceInfo.NONE, new BodyItemI[] {new ExpressionStatement(SourceInfo.NONE, new SimpleThisConstructorInvocation(SourceInfo.NONE, new ParenthesizedExpressionList(SourceInfo.NONE, new Expression[0]))), assign});
 829  1 cd = new ConstructorDef(SourceInfo.NONE, new Word(SourceInfo.NONE, "name"), _publicMav, new FormalParameter[0], new ReferenceType[0], b);
 830  1 cd.visit(_cbbtc);
 831  1 assertEquals("There should now be 3 errors", 3, errors.size());
 832  1 assertEquals("The error message should be correct","You cannot assign a value to j because it is immutable and has already been given a value" , errors.getLast().getFirst());
 833   
 834   
 835    }
 836   
 837    }
 838    }