Clover coverage report - Java Language Levels Test Coverage (javalanglevels-20120305-r5436)
Coverage timestamp: Sun Mar 4 2012 22:02:46 CST
file stats: LOC: 3,385   Methods: 85
NCLOC: 2,322   Classes: 3
 
 Source file Conditionals Statements Methods TOTAL
BodyTypeChecker.java 76.5% 97.4% 91.8% 94.4%
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    /** TypeChecks the context of a body, such as a method body. Common to all Language Levels.*/
 49    public class BodyTypeChecker extends SpecialTypeChecker {
 50    /** The MethodData of this method. */
 51    protected BodyData _bodyData;
 52   
 53    /** Constructor for BodyTypeChecker. Calls the super constructor for everything except bodyData, which we store here
 54    * in order to have the proper type at compile time. (SpecialTypeChecker stores it as a Data).
 55    * @param bodyData The enclosing BodyData for the context we are type checking.
 56    * @param file The File corresponding to the source file.
 57    * @param packageName The package name from the source file.
 58    * @param importedFiles The names of the files that are specifically imported (through a class import statement) in
 59    * the source file.
 60    * @param importedPackages The names of all the packages that are imported through a package import statement in the
 61    * source file.
 62    * @param vars The list of VariableData that have already been defined (used so we can make sure we don't use a
 63    * variable before it has been defined).
 64    * @param thrown The list of exceptions thrown in this body
 65    */
 66  446 public BodyTypeChecker(BodyData bodyData, File file, String packageName, LinkedList<String> importedFiles,
 67    LinkedList<String> importedPackages, LinkedList<VariableData> vars,
 68    LinkedList<Pair<SymbolData, JExpression>> thrown) {
 69  446 super(bodyData, file, packageName, importedFiles, importedPackages, vars, thrown);
 70  446 _bodyData = bodyData;
 71    }
 72   
 73    /** @return the bodyData (enclosing data) for this context. */
 74  12 protected Data _getData() { return _bodyData; }
 75   
 76    /** @return the instance data of the class/interface enclosing this body data. */
 77  0 public TypeData forSimpleThisReferenceOnly(SimpleThisReference that) {
 78  0 return _bodyData.getSymbolData().getInstanceData();
 79    }
 80   
 81    /** @return the instance data of the super class of the class enclosing this body data. */
 82  0 public TypeData forSimpleSuperReferenceOnly(SimpleSuperReference that) {
 83  0 return _bodyData.getSymbolData().getSuperClass().getInstanceData();
 84    }
 85   
 86    /** Create a new instance of this class for visiting inner bodies. */
 87  166 protected BodyTypeChecker createANewInstanceOfMe(BodyData bodyData,
 88    File file,
 89    String pakage,
 90    LinkedList<String> importedFiles,
 91    LinkedList<String> importedPackages,
 92    LinkedList<VariableData> vars,
 93    LinkedList<Pair<SymbolData, JExpression>> thrown) {
 94  166 return new BodyTypeChecker(bodyData, file, pakage, importedFiles, importedPackages, vars, thrown);
 95    }
 96   
 97    /* There is currently no way to differentiate between a block statement and
 98    * an instance initializer in a braced body given the general nature of a
 99    * braced body. Whenever an instance initialization is visited in a method
 100    * body, we must assume that it is a block statement.
 101    */
 102  0 public TypeData forInstanceInitializer(InstanceInitializer that) {
 103  0 return forBlock(that.getCode());
 104    }
 105   
 106    /** We need to do this so that expressions (which should only occur in variable initializers and
 107    * initializer blocks) can know which fields have already been declared. Add all the variable
 108    * datas that are declared in this declarator to the list of variables that are visibile from where we are.
 109    */
 110  15 public TypeData forUninitializedVariableDeclaratorOnly(UninitializedVariableDeclarator that,
 111    TypeData typeRes,
 112    TypeData nameRes) {
 113  15 _vars.addLast(_bodyData.getVar(that.getName().getText()));
 114  15 return null;
 115    }
 116   
 117   
 118    /** Look at the result of each item in the body. If one is not null and does not correspond to an Expression
 119    * Statement, then that means that that statement returns a value. Check to make sure that there are no
 120    * statements following it. If there are, then those statements are unreachable so give an error.
 121    * @param that The Body we were type checking
 122    * @param items_result Array of results for each item in the body that was visited.
 123    */
 124  282 public TypeData forBodyOnly(Body that, TypeData[] items_result) {
 125  282 for (int i = 0; i < items_result.length; i++) {
 126  298 if (items_result[i] != null && !(that.getStatements()[i] instanceof ExpressionStatement)) {
 127   
 128    // Found a statement that returns a value.
 129  190 if (i < items_result.length - 1) {
 130   
 131    // there must be unreachable statements
 132  1 _addError("Unreachable statement.", (JExpression)that.getStatements()[i+1]);
 133    }
 134    // either way, return the result to keep on type-checking.
 135  190 return items_result[i];
 136    }
 137    }
 138  92 return null;
 139    }
 140   
 141    /** Delegates to forBodyOnly. */
 142  72 public TypeData forBracedBodyOnly(BracedBody that, TypeData[] items_result) {
 143  72 return forBodyOnly(that, items_result);
 144    }
 145   
 146    /** Delegates to forBodyOnly. */
 147  0 public TypeData forUnbracedBodyOnly(UnbracedBody that, TypeData[] items_result) {
 148  0 return forBodyOnly(that, items_result);
 149    }
 150   
 151   
 152    /** Make sure the enclosing method data is declared to return void. If it is not, give an error.
 153    * @return the type the method is declared to return.
 154    */
 155  4 public TypeData forVoidReturnStatementOnly(VoidReturnStatement that) {
 156  4 MethodData md = _bodyData.getMethodData();
 157  4 if (md.getReturnType() != SymbolData.VOID_TYPE) {
 158  1 _addError("Cannot return void when the method's expected return type is not void.", that);
 159   
 160    // Return the correct type to allow type-checking to continue.
 161  1 return md.getReturnType().getInstanceData();
 162    }
 163  3 return SymbolData.VOID_TYPE.getInstanceData();
 164    }
 165   
 166    /** Visit the value being returned to determine its type. Do the necessary bookkeeping and
 167    * then delegate to forValueReturnStatementOnly.
 168    */
 169  133 public TypeData forValueReturnStatement(ValueReturnStatement that) {
 170  133 ExpressionTypeChecker etc =
 171    new ExpressionTypeChecker(_data, _file, _package, _importedFiles, _importedPackages, _vars, _thrown);
 172  133 TypeData valueRes = that.getValue().visit(etc);
 173  133 thingsThatHaveBeenAssigned.addAll(etc.thingsThatHaveBeenAssigned);
 174  133 return forValueReturnStatementOnly(that, valueRes);
 175    }
 176   
 177    /** Make sure that the enclosing method is declared to throw the same type as the return statement
 178    * is trying to return. Also make sure that what is being returned is an instance of the type,
 179    * not the type itself.
 180    */
 181  132 public TypeData forValueReturnStatementOnly(ValueReturnStatement that, TypeData valueRes) {
 182  132 MethodData md = _bodyData.getMethodData();
 183  132 SymbolData expected = md.getReturnType();
 184   
 185  132 if (expected == null) {
 186    // There was an error processing the method's return type; return the result type
 187  0 return valueRes;
 188    }
 189   
 190  132 if (valueRes == null || ! assertFound(valueRes, that)) {
 191    // There was an error parsing the return type, return the expected type.
 192  1 return expected.getInstanceData();
 193    }
 194   
 195  131 if (valueRes != null && !valueRes.isInstanceType()) {
 196  1 _addError("You cannot return a class or interface name. Perhaps you meant to say " + valueRes.getName() +
 197    ".class or to create an instance", that);
 198  1 return valueRes.getInstanceData();
 199    }
 200   
 201  130 if (expected == SymbolData.VOID_TYPE) {
 202  1 _addError("Cannot return a value when the method's expected return type is void.", that);
 203    // Return the correc type to allow type-checking to continue.
 204  1 return SymbolData.VOID_TYPE.getInstanceData();
 205    }
 206  129 else if (!_isAssignableFrom(expected, valueRes.getSymbolData())) {
 207  3 _addError("This method expected to return type: " + '"' + expected.getName() + '"'
 208    + " but here returned type: " + '"' + valueRes.getName() + '"',
 209    that);
 210    }
 211  129 return valueRes;
 212    }
 213   
 214    /** First, visit the condition expression of the for statement with a special visitor that
 215    * makes sure no assignment is done.
 216    * Then, visit the condition expression with the ExpressionTypeChecker which will do all the
 217    * normal expression stuff.
 218    * Then, visit the update and and code (block) of the for statement with this visitor.
 219    * Be very careful about maintaing the various scopes here.
 220    */
 221  6 public TypeData forForStatement(ForStatement that) {
 222  6 Boolean expOk = Boolean.TRUE;
 223  6 if (that.getCondition() instanceof Expression) {
 224  4 Expression exp = (Expression) that.getCondition();
 225    // Assignment cannot be used in this expression
 226  4 expOk = exp.visit(new NoAssignmentAllowedInExpression("the conditional expression of a for-statement"));
 227    }
 228   
 229  6 LinkedList<VariableData> newVars = cloneVariableDataList(_vars);
 230  6 BodyTypeChecker btc =
 231    createANewInstanceOfMe(_bodyData, _file, _package, _importedFiles, _importedPackages, newVars, _thrown);
 232  6 final TypeData init_result = that.getInit().visit(btc);
 233   
 234  6 ExpressionTypeChecker etc =
 235    new ExpressionTypeChecker(_data, _file, _package, _importedFiles, _importedPackages, btc._vars, _thrown);
 236  6 final TypeData condition_result = that.getCondition().visit(etc);
 237  6 btc.thingsThatHaveBeenAssigned.addAll(etc.thingsThatHaveBeenAssigned);
 238  6 final TypeData update_result = that.getUpdate().visit(btc);
 239  6 final TypeData codeRes = that.getCode().visit(btc);
 240   
 241    // Now, change any VariableDatas that were given a value in the ForStatement back to having been unassigned since
 242    // its code is not necessarily executed.
 243  6 unassignVariableDatas(btc.thingsThatHaveBeenAssigned);
 244  6 if (expOk.booleanValue())
 245  5 return forForStatementOnly(that, init_result, condition_result, update_result, codeRes);
 246  1 else {return null;}
 247    }
 248   
 249   
 250    /* Make sure that the conditional expression has the right type. */
 251  8 public TypeData forForStatementOnly(ForStatement that, TypeData init_result, TypeData condition_result,
 252    TypeData update_result, TypeData codeRes) {
 253  8 if (condition_result != null && assertFound(condition_result, that)) {
 254  7 if (!condition_result.isInstanceType()) {
 255  1 _addError("This for-statement's conditional expression must be a boolean value. Instead, it is a class or " +
 256    "interface name", that);
 257    }
 258  6 else if (!condition_result.getSymbolData().isBooleanType(LanguageLevelConverter.OPT.javaVersion())) {
 259  1 _addError("This for-statement's conditional expression must be a boolean value. Instead, its type is " +
 260    condition_result.getName(), that);
 261    }
 262    }
 263  8 return null;
 264    }
 265   
 266    /** First, visit the condition expression of the if statement with a special visitor that
 267    * makes sure no assignment is done.
 268    * Then, visit the condition expression with the ExpressionTypeChecker which will do all the
 269    * normal expression stuff.
 270    * Then, visit the body of the if statement with this visitor.
 271    * Be very careful about maintaing the various scopes here.
 272    */
 273  12 public TypeData forIfThenStatement(IfThenStatement that) {
 274  12 Boolean expOk = Boolean.TRUE;
 275  12 if (that.getTestExpression() instanceof Expression) {
 276  12 Expression exp = that.getTestExpression();
 277    // Assignment cannot be used in this expression
 278  12 expOk = exp.visit(new NoAssignmentAllowedInExpression("the conditional expression of an if-then statement"));
 279    }
 280   
 281    // Update what has been assigned here with results from test expression, because any variables it sees or assigns
 282    // will be visible in the rest of the body.
 283  12 ExpressionTypeChecker etc = new ExpressionTypeChecker(_data, _file, _package, _importedFiles, _importedPackages,
 284    _vars, _thrown);
 285  12 final TypeData testExpression_result = that.getTestExpression().visit(etc);
 286  12 thingsThatHaveBeenAssigned.addAll(etc.thingsThatHaveBeenAssigned);
 287   
 288    //Use a new visitor for the body of the then statement--it is a different lexical scope, so we want to track the
 289    //variables seperately.
 290  12 BodyTypeChecker btc = createANewInstanceOfMe(_bodyData, _file, _package, _importedFiles, _importedPackages,
 291    cloneVariableDataList(_vars), _thrown);
 292  12 final TypeData thenStatement_result = that.getThenStatement().visit(btc);
 293   
 294    //Now, change any VariableDatas that were given a value in the ThenStatement back to having been unassigned
 295  12 unassignVariableDatas(btc.thingsThatHaveBeenAssigned);
 296   
 297  11 if (expOk.booleanValue()) {return forIfThenStatementOnly(that, testExpression_result, thenStatement_result);}
 298  1 return null;
 299    }
 300   
 301    /* Make sure that the conditional expression has the right type. */
 302  14 public TypeData forIfThenStatementOnly(IfThenStatement that, TypeData testExpression_result,
 303    TypeData thenStatement_result) {
 304  14 if (testExpression_result != null && assertFound(testExpression_result, that.getTestExpression())) {
 305  14 if (!testExpression_result.isInstanceType()) {
 306  1 _addError("This if-then-statement's conditional expression must be a boolean value. Instead, it is a class " +
 307    "or interface name", that);
 308    }
 309  13 else if (!testExpression_result.getSymbolData().isBooleanType(LanguageLevelConverter.OPT.javaVersion())) {
 310  1 _addError("This if-then-statement's conditional expression must be a boolean value. Instead, its type is " +
 311    testExpression_result.getName(), that.getTestExpression());
 312    }
 313    }
 314  14 return null;
 315    }
 316   
 317   
 318    /** First, visit the condition expression of the if-then-else statement with a special visitor that
 319    * makes sure no assignment is done.
 320    * Then, visit the condition expression with the ExpressionTypeChecker which will do all the
 321    * normal expression stuff.
 322    * Then, visit the body of the if statement and the else with this visitor.
 323    * Be very careful about maintaing the various scopes here.
 324    */
 325  27 public TypeData forIfThenElseStatement(IfThenElseStatement that) {
 326  27 Boolean expOk = Boolean.TRUE;
 327  27 if (that.getTestExpression() instanceof Expression) {
 328  27 Expression exp = that.getTestExpression();
 329    // Assignment cannot be used in this expression
 330  27 expOk = exp.visit(new NoAssignmentAllowedInExpression("the conditional expression of an if-then-else statement"));
 331    }
 332   
 333    // Update list of what has been assigned with one from test expression, because any variables it sees or assigns
 334    // will be visible in the rest of the body.
 335  27 ExpressionTypeChecker etc = new ExpressionTypeChecker(_data, _file, _package, _importedFiles, _importedPackages,
 336    _vars, _thrown);
 337  27 final TypeData testExpression_result = that.getTestExpression().visit(etc);
 338  27 thingsThatHaveBeenAssigned = etc.thingsThatHaveBeenAssigned;
 339   
 340    //Use a new visitor for the body of the then statement--it is a different lexical scope, so we want to track the
 341    //variables seperately.
 342  27 BodyTypeChecker btcThen = createANewInstanceOfMe(_bodyData, _file, _package, _importedFiles, _importedPackages,
 343    cloneVariableDataList(_vars), _thrown);
 344  27 final TypeData thenStatement_result = that.getThenStatement().visit(btcThen);
 345    //Now, change any VariableDatas that were given a value in the ThenStatement back to having been unassigned
 346  27 unassignVariableDatas(btcThen.thingsThatHaveBeenAssigned);
 347   
 348   
 349    //Use a new visitor for the body of the else statement--it is a different lexical scope, so we want to track the
 350    //variables seperately.
 351  27 BodyTypeChecker btcElse = createANewInstanceOfMe(_bodyData, _file, _package, _importedFiles, _importedPackages,
 352    cloneVariableDataList(_vars), _thrown);
 353  27 final TypeData elseStatement_result = that.getElseStatement().visit(btcElse);
 354    //Now, change any VariableDatas that were given a value in the ElseStatement back to having been unassigned
 355  27 unassignVariableDatas(btcElse.thingsThatHaveBeenAssigned);
 356   
 357    //Now compare the two lists of VariableDatas, and reassign those that were assigned in both branches.
 358  27 reassignVariableDatas(btcThen.thingsThatHaveBeenAssigned, btcElse.thingsThatHaveBeenAssigned);
 359   
 360  26 if (expOk.booleanValue()) {return forIfThenElseStatementOnly(that, testExpression_result, thenStatement_result,
 361    elseStatement_result);}
 362  1 return null;
 363    }
 364   
 365    /** Make sure that the conditional expression has the right type, and if both branches of the
 366    * if/else return, return a value the common super type of the two return types.
 367    * We assume that thenStatement_result and elseStatement_result are InstanceDatas
 368    */
 369  26 public TypeData forIfThenElseStatementOnly(IfThenElseStatement that, TypeData testExpression_result,
 370    TypeData thenStatement_result, TypeData elseStatement_result) {
 371  26 if (testExpression_result != null && assertFound(testExpression_result, that.getTestExpression())) {
 372  26 if (!testExpression_result.isInstanceType()) {
 373  1 _addError("This if-then-else statement's conditional expression must be a boolean value. Instead, it is a " +
 374    "class or interface name",
 375    that);
 376    }
 377  25 else if (!testExpression_result.getSymbolData().isBooleanType(LanguageLevelConverter.OPT.javaVersion())) {
 378  1 _addError("This if-then-else statement's conditional expression must be a boolean value. Instead, its type is "
 379    + testExpression_result.getName(), that.getTestExpression());
 380    }
 381    }
 382   
 383  9 if (testExpression_result == null || thenStatement_result == null || elseStatement_result == null) return null;
 384   
 385    // We don't throw an error here because if the then and else branches return incompatible types,
 386    // there must have already been an error thrown in forValueReturnStatementOnly
 387    // that indicates that one of the return statements is returning the wrong type.
 388  17 SymbolData result = getCommonSuperType(thenStatement_result.getSymbolData(), elseStatement_result.getSymbolData());
 389  0 if (result==null) {return null;}
 390  17 return result.getInstanceData();
 391    }
 392   
 393    /** First, visit the condition expression of the while statement with a special visitor that
 394    * makes sure no assignment is done.
 395    * Then, visit the condition expression with the ExpressionTypeChecker which will do all the
 396    * normal expression stuff.
 397    * Then, visit the body with this visitor.
 398    * Be very careful about maintaing the various scopes here.
 399    */
 400  3 public TypeData forWhileStatement(WhileStatement that) {
 401  3 Boolean expOk = Boolean.TRUE;
 402  3 if (that.getCondition() instanceof Expression) {
 403  3 Expression exp = that.getCondition();
 404    // Assignment cannot be used in this expression
 405  3 expOk = exp.visit(new NoAssignmentAllowedInExpression("the condition expression of a while statement"));
 406    }
 407   
 408    // Visit the condition expression with an expression type checker and
 409    // then update list of what was assigned, because it will always be visited so it is in the same scope as the
 410    // enclosing body.
 411  3 ExpressionTypeChecker etc = new ExpressionTypeChecker(_data, _file, _package, _importedFiles, _importedPackages,
 412    _vars, _thrown);
 413  3 final TypeData condition_result = that.getCondition().visit(etc);
 414  3 thingsThatHaveBeenAssigned.addAll(etc.thingsThatHaveBeenAssigned);
 415   
 416    //Use a new visitor for the body of the while statement--it is a different lexical scope, so we want to track the
 417    //variables seperately.
 418  3 BodyTypeChecker btc = createANewInstanceOfMe(_bodyData, _file, _package, _importedFiles, _importedPackages,
 419    cloneVariableDataList(_vars), _thrown);
 420  3 final TypeData codeRes = that.getCode().visit(btc);
 421  3 unassignVariableDatas(btc.thingsThatHaveBeenAssigned);
 422  2 if (expOk.booleanValue()) {return forWhileStatementOnly(that, condition_result, codeRes);}
 423  1 return null;
 424    }
 425   
 426    /** Make sure that the condition statement of the while returns type boolean. */
 427  5 public TypeData forWhileStatementOnly(WhileStatement that, TypeData condition_result, TypeData codeRes) {
 428  5 if (condition_result != null && assertFound(condition_result, that.getCondition())) {
 429  5 if (! condition_result.isInstanceType()) {
 430  1 _addError("This while-statement's conditional expression must be a boolean value. Instead, it is a class or " +
 431    "interface name", that);
 432    }
 433  4 else if (!condition_result.getSymbolData().isBooleanType(LanguageLevelConverter.OPT.javaVersion())) {
 434  1 _addError("This while-statement's conditional expression must be a boolean value. Instead, its type is " +
 435    condition_result.getName(), that.getCondition());
 436    }
 437    }
 438  5 return null;
 439    }
 440   
 441    /** First, visit the body of the do statement with a body type checker.
 442    * Then, visit the condition expression of the do statement with a special visitor that
 443    * makes sure no assignment is done.
 444    * Then, visit the condition expression with the ExpressionTypeChecker which will do all the
 445    * normal expression stuff.
 446    * Be very careful about maintaing the various scopes here.
 447    */
 448  3 public TypeData forDoStatement(DoStatement that) {
 449    //Use a new visitor for the body of the do statement--it is a different lexical scope, so we want to track the
 450    //variables seperately.
 451  3 BodyTypeChecker btc = createANewInstanceOfMe(_bodyData, _file, _package, _importedFiles, _importedPackages,
 452    cloneVariableDataList(_vars), _thrown);
 453  3 final TypeData codeRes = that.getCode().visit(btc);
 454  3 unassignVariableDatas(btc.thingsThatHaveBeenAssigned);
 455   
 456  3 Boolean expOk = Boolean.TRUE;
 457  3 if (that.getCondition() instanceof Expression) {
 458  3 Expression exp = that.getCondition();
 459    // Assignment cannot be used in this expression
 460  3 expOk = exp.visit(new NoAssignmentAllowedInExpression("the condition expression of a do statement"));
 461    }
 462   
 463    // Visit the condition statement with a new ExpressionTypeChecker, then update the thingsThatHaveBeenAssigned list, since it is in the same scope as the body.
 464  3 ExpressionTypeChecker etc = new ExpressionTypeChecker(_data, _file, _package, _importedFiles, _importedPackages, _vars, _thrown);
 465  3 final TypeData condition_result = that.getCondition().visit(etc);
 466  3 thingsThatHaveBeenAssigned.addAll(etc.thingsThatHaveBeenAssigned);
 467   
 468  2 if (expOk.booleanValue()) {return forDoStatementOnly(that, codeRes, condition_result);}
 469  1 return null;
 470   
 471    }
 472   
 473   
 474    /**Make sure that the condition statement of the while returns type boolean. */
 475  5 public TypeData forDoStatementOnly(DoStatement that, TypeData codeRes, TypeData condition_result) {
 476  5 if (condition_result != null && assertFound(condition_result, that.getCondition())) {
 477  5 if (!condition_result.isInstanceType()) {
 478  1 _addError("This do-statement's conditional expression must be a boolean value. Instead, it is a class or interface name", that.getCondition());
 479    }
 480  4 else if (!condition_result.getSymbolData().isBooleanType(LanguageLevelConverter.OPT.javaVersion())) {
 481  1 _addError("This do-statement's conditional expression must be a boolean value. Instead, its type is " + condition_result.getName(), that.getCondition());
 482    }
 483    }
 484  2 if (codeRes == null) {return null;}
 485  3 return codeRes.getInstanceData();
 486    }
 487   
 488    /*Handle the switch statement(explained within the method)*/
 489  11 public TypeData forSwitchStatement(SwitchStatement that) {
 490  11 Expression exp = that.getTest();
 491    //make sure no assignments are made in the switch stmt expression
 492  11 exp.visit(new NoAssignmentAllowedInExpression("the switch expression of a switch statement"));
 493   
 494    //Visit the test with this visitor, because it is in the scope of the method
 495  11 ExpressionTypeChecker etc = new ExpressionTypeChecker(_data, _file, _package, _importedFiles, _importedPackages, _vars, _thrown);
 496  11 final TypeData testRes = that.getTest().visit(etc);
 497  11 thingsThatHaveBeenAssigned.addAll(etc.thingsThatHaveBeenAssigned);
 498   
 499    //The test result of a switch statement must be either an int or a char, according to the JLS.
 500  0 if (testRes == null || !assertFound(testRes, exp)) {return null;}
 501  11 if (!(_isAssignableFrom(SymbolData.INT_TYPE, testRes.getSymbolData()) || _isAssignableFrom(SymbolData.CHAR_TYPE, testRes.getSymbolData()))) {
 502  1 _addError("The switch expression must be either an int or a char. You have used a " + testRes.getSymbolData().getName(), that.getTest());
 503    }
 504   
 505  11 final TypeData[] cases_result = makeArrayOfRetType(that.getCases().length);
 506  11 BodyTypeChecker[] btcs = new BodyTypeChecker[that.getCases().length];
 507  11 HashSet<Integer> labels = new HashSet<Integer>();
 508  11 LinkedList<VariableData> variablesAssigned = new LinkedList<VariableData>();
 509  11 boolean seenDefault = false;
 510  11 boolean hadCaseReturn = false;
 511   
 512    /**
 513    * Loop over all the cases, type-checking them and then checking that no labels are duplicated
 514    * and only one default statement is present.
 515    */
 516  11 for (int i = 0; i < that.getCases().length; i++) {
 517  26 SwitchCase sc = that.getCases()[i];
 518  26 btcs[i] = createANewInstanceOfMe(_bodyData, _file, _package, _importedFiles, _importedPackages, cloneVariableDataList(_vars), _thrown);
 519  26 cases_result[i] = sc.visit(btcs[i]);
 520  26 if (sc instanceof LabeledCase) {
 521  18 LabeledCase lc = (LabeledCase) sc;
 522    //Get the label, make sure it is an int or char, and then put it in our hash set.
 523  18 Integer toCheck = null;
 524  18 if (lc.getLabel() instanceof CharLiteral) {
 525  0 toCheck = (int) ((CharLiteral) lc.getLabel()).getValue();
 526    }
 527  18 if (lc.getLabel() instanceof IntegerLiteral) {
 528  18 toCheck = ((IntegerLiteral) lc.getLabel()).getValue();
 529    }
 530  18 if (toCheck != null) {
 531  18 if (labels.contains(toCheck))
 532  1 _addError("You cannot have two switch cases with the same label " + toCheck, lc.getLabel());
 533  17 else labels.add(toCheck);
 534    }
 535    }
 536    else {
 537  1 if (seenDefault) _addError("A switch statement can only have one default case", sc);
 538  8 seenDefault = true;
 539    }
 540   
 541    // Compare the variables assigned, and let variablesAssigned store the variables that have been assigned in every
 542    // case that returns or breaks up to this one and are also assigned in this one
 543    // if we're in the last case, we treat it as a break even though that may not happen explicitly
 544   
 545  26 if (cases_result[i] != null || (i == cases_result.length - 1)) {
 546  17 if (! hadCaseReturn) {
 547  9 variablesAssigned = btcs[i].thingsThatHaveBeenAssigned;
 548  9 hadCaseReturn = true;
 549    }
 550    else {
 551  8 Iterator<VariableData> iter = variablesAssigned.iterator();
 552  8 while (iter.hasNext()) {
 553  0 if (!btcs[i].thingsThatHaveBeenAssigned.contains(iter.next())) {iter.remove();}
 554    }
 555    }
 556    }
 557   
 558    //Now, change any VariableDatas that were given a value in the case statement back to having been unassigned
 559  26 unassignVariableDatas(btcs[i].thingsThatHaveBeenAssigned);
 560    }
 561   
 562    //Now assign a value to all variables that were assigned in each case branch, if there was a default case
 563  11 if (seenDefault) {
 564  3 for (VariableData vd : variablesAssigned) vd.gotValue();
 565    }
 566  11 return forSwitchStatementOnly(that, testRes, cases_result, seenDefault);
 567    }
 568   
 569    /** Here, we follow the following rules for determining what to return:
 570    * If there is not a default block, the statement does not return.
 571    * If the result from any of the blocks is NOT_FOUND, the statement does not return. (NOT_FOUND signifies that a
 572    * break statement was seen). If the last block does not return, then the statement does not return.
 573    */
 574  16 public TypeData forSwitchStatementOnly(SwitchStatement that, TypeData testRes, TypeData[] cases_result,
 575    boolean sawDefault) {
 576   
 577    /**If we did not see a default block, this statement cannot be guaranteed to return*/
 578  5 if (!sawDefault) return null;
 579   
 580    /**If any of the blocks are NOT_FOUND, then the statement does not return.*/
 581  11 for (int i = 0; i<cases_result.length; i++) {
 582  7 if (cases_result[i] != null && cases_result[i].getSymbolData() == SymbolData.NOT_FOUND) {return null;}
 583    }
 584   
 585    /**If the last block does not return, then the statement also does not return. */
 586  3 if (cases_result[cases_result.length-1] == null) return null;
 587   
 588  1 return _bodyData.getMethodData().getReturnType().getInstanceData();
 589    }
 590   
 591   
 592    /** Make sure that the label for this LabeledCase is correct. The label must be a constant expression of type int or
 593    * char. Then delegate to the super class to handle the braced body of the switch case. */
 594  24 public TypeData forLabeledCase(LabeledCase that) {
 595  24 ExpressionTypeChecker etc = new ExpressionTypeChecker(_data, _file, _package, _importedFiles, _importedPackages,
 596    _vars, _thrown);
 597  24 final TypeData label_result = that.getLabel().visit(etc);
 598  24 thingsThatHaveBeenAssigned.addAll(etc.thingsThatHaveBeenAssigned);
 599  24 Expression exp = that.getLabel();
 600   
 601  0 if (label_result == null || !assertFound(label_result, exp)) return null;
 602   
 603    //we allow constant expressions of the form -5 or 5, but nothing else.
 604  24 if (!(exp instanceof LexicalLiteral || exp instanceof NumericUnaryExpression &&
 605    ((NumericUnaryExpression) exp).getValue() instanceof LexicalLiteral)) {
 606  2 _addError("The labels of a switch statement must be constants. You are using a more complicated expression of" +
 607    " type " + label_result.getSymbolData().getName(),
 608    that.getLabel());
 609    }
 610  22 else if (!_isAssignableFrom(SymbolData.INT_TYPE, label_result.getSymbolData())) {
 611  1 _addError("The labels of a switch statement must be constants of int or char type. You specified a constant of" +
 612    " type " + label_result.getSymbolData().getName(),
 613    that.getLabel());
 614    }
 615   
 616  24 return forSwitchCase(that);
 617    }
 618   
 619    /** Delegate handling this default case to its superclass. */
 620  11 public TypeData forDefaultCase(DefaultCase that) { return forSwitchCase(that); }
 621   
 622    /** Visit the Braced Body of this SwitchCase, and return the result. */
 623  39 public TypeData forSwitchCase(SwitchCase that) {
 624  39 final TypeData codeRes = that.getCode().visit(this);
 625   
 626    //If the case falls through (i.e. returns null) but has some statements in it, then there is an error.
 627    //We only want to allow fall through for multiple labels, of the form:
 628    /** 'a':
 629    * 'b':
 630    * return 5;
 631    */
 632   
 633  39 if (codeRes == null && that.getCode().getStatements().length > 0) {
 634  2 _addError("You must end a non-empty switch case with a break or return statement at the Advanced level", that);
 635    }
 636  39 return codeRes;
 637    }
 638   
 639    /* Visit the block, and update with what it assigns. Return the result of visiting the block. */
 640  80 public TypeData forBlock(Block that) {
 641  80 BlockData bd = _bodyData.getNextBlock();
 642  80 if (bd == null)
 643  0 throw new RuntimeException("Internal Program Error: Enclosing body does not contain this block." +
 644    " Please report this bug");
 645   
 646  80 BodyTypeChecker btc = createANewInstanceOfMe(bd, _file, _package, _importedFiles, _importedPackages,
 647    cloneVariableDataList(_vars), _thrown);
 648  80 TypeData statements_result = that.getStatements().visit(btc);
 649  80 thingsThatHaveBeenAssigned.addAll(btc.thingsThatHaveBeenAssigned);
 650  80 return statements_result;
 651    }
 652   
 653   
 654    /*Try to resolve the type and make sure it can be referenced from this context (i.e. is accessible).*/
 655  0 public TypeData forTypeOnly(Type that) {
 656  0 Data sd = getSymbolData(that.getName(), _data, that);
 657  0 while (sd != null && !LanguageLevelVisitor.isJavaLibraryClass(sd.getSymbolData().getName())) {
 658  0 if (!checkAccess(that, sd.getMav(), sd.getName(), sd.getSymbolData(), _bodyData.getSymbolData(), "class")) {
 659  0 return null;
 660    }
 661  0 sd = sd.getOuterData();
 662    }
 663  0 return null;
 664    }
 665   
 666    /** Makes sure that no super class of any exception is caught before the current exception's catch block. */
 667  36 protected void checkDuplicateExceptions(TryCatchStatement that) {
 668    // Make sure that the user isn't throwing duplicate exceptions
 669  36 LinkedList<SymbolData> catchBlockExceptions = new LinkedList<SymbolData>();
 670  36 CatchBlock[] catchBlocks = that.getCatchBlocks();
 671  36 for (int i = 0; i < catchBlocks.length; i++) {
 672  23 catchBlockExceptions.addLast(getSymbolData(catchBlocks[i].getException().getDeclarator().getType().getName(),
 673    _data, catchBlocks[i].getException()));
 674    }
 675  36 for (int i = 0; i < catchBlockExceptions.size(); i++) {
 676  23 for (int j = i+1; j < catchBlockExceptions.size(); j++) {
 677  10 if (catchBlockExceptions.get(j) != null && catchBlockExceptions.get(j).isSubClassOf(catchBlockExceptions.get(i))) {
 678  3 _addError("Exception " + catchBlockExceptions.get(j).getName() +
 679    " has already been caught", catchBlocks[j].getException());
 680    }
 681    }
 682    }
 683    }
 684   
 685    /** Check if the two given SymbolDatas have a common super type. If so, return it, else return null. */
 686  45 protected SymbolData getCommonSuperType(SymbolData s1, SymbolData s2) {
 687  45 if ((s1 == null) && (s2 == null)) {
 688  0 return null;
 689    }
 690   
 691  0 if (s1 == SymbolData.NOT_FOUND && s2 != null) {return SymbolData.NOT_FOUND;}
 692  2 if (s2 == SymbolData.NOT_FOUND && s1 != null) {return SymbolData.NOT_FOUND;}
 693   
 694  0 if (s1 == null && s1 != SymbolData.NOT_FOUND) { return s2; }
 695  25 if (s2 == null && s1 != SymbolData.NOT_FOUND) {return s1;}
 696  0 if (s1==null || s2==null) {return null;}
 697  6 if (s1 == SymbolData.EXCEPTION) { return s2; }
 698  0 if (s2 == SymbolData.EXCEPTION) { return s1; }
 699   
 700    // See if s1 and s2 have a common super class.
 701  12 SymbolData sd = getCommonSuperTypeBaseCase(s1, s2);
 702  9 if (sd != null ) { return sd; }
 703  3 sd = getCommonSuperTypeBaseCase(s2, s1);
 704  0 if (sd != null) { return sd; }
 705   
 706    //If s1's superClass is null, then we have gone all the way through the superclass hierarchy without finding a matching class.
 707  3 if (s1.getSuperClass() == null) {
 708    //return null;
 709    //since we know that Object should be the super class of everything, return Object.
 710  3 return getSymbolData("java.lang.Object", _data, new NullLiteral(SourceInfo.NONE));
 711    }
 712   
 713    // Recur on the super class chain.
 714  0 sd = getCommonSuperType(s1.getSuperClass(), s2);
 715  0 if (sd != null) {
 716  0 return sd;
 717    }
 718   
 719    // Recur on each interface.
 720  0 for (SymbolData currSd : s1.getInterfaces()) {
 721  0 sd = getCommonSuperType(currSd, s2);
 722  0 if (sd != null) {
 723  0 return sd;
 724    }
 725    }
 726  0 return null;
 727    }
 728   
 729   
 730    /** @return true if the symbol data is the generic SymbolData.EXCEPTIOn class or if it extends java.lang.Throwable*/
 731  0 protected boolean isException(SymbolData sd) {
 732  0 return sd == SymbolData.EXCEPTION ||
 733    sd.isSubClassOf(getSymbolData("java.lang.Throwable", new NullLiteral(SourceInfo.NONE), false, false));
 734    }
 735   
 736    /** Returns the least restrictive type returned by the try block and catch blocks. Returns null
 737    * if this try-catch statement doesn't necessarily return a value.
 738    */
 739  38 protected InstanceData tryCatchLeastRestrictiveType(InstanceData tryBlockRes, InstanceData[] catchBlocksRes,
 740    InstanceData finallyBlock_result) {
 741    // Return the common superclass or null if there exists a block that doesn't return a value(except the finally block)
 742  38 if (tryBlockRes == null || tryBlockRes == SymbolData.NOT_FOUND.getInstanceData())
 743  3 return finallyBlock_result;
 744  35 TypeData leastRestrictiveType = tryBlockRes;
 745  35 for (int i = 0; i < catchBlocksRes.length; i++) {
 746  7 if (catchBlocksRes[i] == null) return finallyBlock_result;
 747  21 if (catchBlocksRes[i] != SymbolData.NOT_FOUND.getInstanceData() &&
 748    _isAssignableFrom(catchBlocksRes[i].getSymbolData(), leastRestrictiveType.getSymbolData())) {
 749  10 leastRestrictiveType = catchBlocksRes[i];
 750    }
 751    }
 752   
 753  28 SymbolData result;
 754  0 if (leastRestrictiveType == null && finallyBlock_result == null) return null;
 755  0 else if (leastRestrictiveType == null) result = getCommonSuperType(null, finallyBlock_result.getSymbolData());
 756  25 else if (finallyBlock_result == null) result = getCommonSuperType(leastRestrictiveType.getSymbolData(), null);
 757  3 else result = getCommonSuperType(leastRestrictiveType.getSymbolData(), finallyBlock_result.getSymbolData());
 758   
 759  28 if (result != null) return result.getInstanceData();
 760  0 return null;
 761    }
 762   
 763    /** Return true if the Exception is unchecked, and false otherwise.
 764    * An exception is unchecked if it does not extend either java.lang.RuntimeException or java.lang.Error,
 765    * and is not declared to be thrown by the enclosing method.
 766    * @param sd The SymbolData of the Exception we are checking.
 767    * @param that The JExpression passed to getSymbolData for error purposes.
 768    */
 769  63 public boolean isUncaughtCheckedException(SymbolData sd, JExpression that) {
 770  63 if (isCheckedException(sd, that)) {
 771  45 MethodData md = _bodyData.getMethodData();
 772  45 for (int i = 0; i<md.getThrown().length; i++) {
 773    //If the Exception matches an exception declared to be thrown by the enclosing method, it is not unchecked.
 774  17 if (sd.isSubClassOf(getSymbolData(md.getThrown()[i], _data, that))) {return false;}
 775    }
 776  28 return true;
 777    }
 778  18 return false;
 779    }
 780   
 781    /** Make sure that every exception that is caught could have been thrown in the try statement */
 782  32 protected void makeSureCaughtStuffWasThrown(TryCatchStatement that, SymbolData[] caught_array, LinkedList<Pair<SymbolData, JExpression>> thrown) {
 783    // Make sure every Exception that is caught could actually be thrown
 784  32 for (int i = 0; i < caught_array.length; i++) {
 785  19 SymbolData currCaughtSD = caught_array[i];
 786    // System.err.println("currCaughtSD = " + currCaughtSD + " isChecked = " + isCheckedException(currCaughtSD, that));
 787  19 boolean foundThrownException = false;
 788  19 if (isCheckedException(currCaughtSD, that) &&
 789    ! currCaughtSD.getName().equals("java.lang.Exception") &&
 790    ! currCaughtSD.getName().equals("java.lang.Throwable")) {
 791    // System.err.println("Checking thrown");
 792  14 for (Pair<SymbolData, JExpression> p : thrown) {
 793  28 SymbolData sd = p.getFirst();
 794  28 if (sd.isSubClassOf(currCaughtSD)) {
 795  15 foundThrownException = true;
 796    }
 797    }
 798  14 if (!foundThrownException) {
 799    // System.err.println("Calling _addError for " + currCaughtSD);
 800  2 _addError("The exception " + currCaughtSD.getName() +
 801    " is never thrown in the body of the corresponding try block",
 802    that.getCatchBlocks()[i]);
 803    }
 804    }
 805    }
 806    }
 807   
 808    /** Make sure that every Exception in thrown is either in caught or in the list of what can be thrown from where we are.
 809    * Also make sure that every Exception that is declared to be thrown or caught is actually thrown.
 810    * @param that The TryCatchStatement we are currently working with
 811    * @param caught_array The SymbolData[] of exceptions that are explicitely caught.
 812    * @param thrown The LinkedList of SymbolData of exceptions that are thrown. This will be modified.
 813    */
 814  18 protected void compareThrownAndCaught(TryCatchStatement that, SymbolData[] caught_array,
 815    LinkedList<Pair<SymbolData, JExpression>> thrown) {
 816  18 LinkedList<SymbolData> caught = new LinkedList<SymbolData>();
 817  18 for (int i = 0; i<caught_array.length; i++) {
 818  13 caught.addLast(caught_array[i]);
 819    }
 820   
 821    //Make sure that every Exception in thrown is either caught or in the list of what can be thrown
 822  18 for (Pair<SymbolData, JExpression> p : thrown) {
 823  21 SymbolData sd = p.getFirst();
 824  21 JExpression j = p.getSecond();
 825  21 if (isUncaughtCheckedException(sd, j)) {
 826  16 boolean foundCatchBlock = false;
 827  16 for (SymbolData currCaughtSD : caught) {
 828  16 if (sd.isSubClassOf(currCaughtSD)) {
 829  10 foundCatchBlock = true;
 830    }
 831    }
 832    // Check if this exception is a checked exception and is not declared to be thrown by the enclosing method
 833    //This is a checked exception. It should have been caught.
 834  16 if (! foundCatchBlock) {
 835  6 handleUncheckedException(sd, j);
 836    }
 837    }
 838    }
 839   
 840  18 makeSureCaughtStuffWasThrown(that, caught_array, thrown);
 841    }
 842   
 843    /** Assumes that tryBlockRes, catchBlocksRes, and finallyBlock_result are InstanceDatas. */
 844  14 public TypeData forTryCatchFinallyStatementOnly(TryCatchFinallyStatement that, TypeData tryBlockRes, TypeData[] catchBlocksRes, TypeData finallyBlock_result) {
 845  14 checkDuplicateExceptions(that);
 846   
 847    //we know ids are instance datas, but we have to do this to cast them properly.
 848  14 InstanceData[] ids = new InstanceData[catchBlocksRes.length];
 849  14 for (int i = 0; i<ids.length; i++) {
 850  3 if (catchBlocksRes[i] != null) {
 851  0 ids[i]=catchBlocksRes[i].getInstanceData();
 852    }
 853  3 else {ids[i]=null;}
 854    }
 855   
 856    /**Make sure null pointer exceptions don't happen.*/
 857  0 if (tryBlockRes == null && finallyBlock_result==null) {return tryCatchLeastRestrictiveType(null, ids, null);}
 858  0 if (tryBlockRes == null) {return tryCatchLeastRestrictiveType(null, ids, finallyBlock_result.getInstanceData());}
 859  11 if (finallyBlock_result == null) {return tryCatchLeastRestrictiveType(tryBlockRes.getInstanceData(), ids, null);}
 860   
 861  3 return tryCatchLeastRestrictiveType(tryBlockRes.getInstanceData(), ids, finallyBlock_result.getInstanceData());
 862    }
 863   
 864    /*Visit the try block, catch blocks, and finally block. Add any exceptions that are not caught to thrown.*/
 865  14 public TypeData forTryCatchFinallyStatement(TryCatchFinallyStatement that) {
 866   
 867  14 BodyTypeChecker btc = new TryCatchBodyTypeChecker(_bodyData, _file, _package, _importedFiles, _importedPackages, cloneVariableDataList(_vars), new LinkedList<Pair<SymbolData, JExpression>>());
 868  14 final TypeData tryBlockRes = that.getTryBlock().visit(btc);
 869   
 870  14 unassignVariableDatas(btc.thingsThatHaveBeenAssigned);
 871   
 872  14 BodyTypeChecker[] catchTCs = new BodyTypeChecker[that.getCatchBlocks().length];
 873  14 LinkedList<LinkedList<VariableData>> catchVars = new LinkedList<LinkedList<VariableData>>();
 874  14 CatchBlock[] catchBlocks = that.getCatchBlocks();
 875  14 final TypeData[] catchBlocksRes = makeArrayOfRetType(catchBlocks.length);
 876  14 final SymbolData[] caughtExceptions = new SymbolData[catchBlocks.length];
 877   
 878  14 for (int i = 0; i < catchBlocks.length; i++) {
 879  3 catchTCs[i] = createANewInstanceOfMe(_bodyData, _file, _package, _importedFiles, _importedPackages, cloneVariableDataList(_vars), _thrown);
 880  3 catchBlocksRes[i] = catchBlocks[i].visit(catchTCs[i]);
 881  3 unassignVariableDatas(catchTCs[i].thingsThatHaveBeenAssigned);
 882  3 catchVars.addLast(catchTCs[i].thingsThatHaveBeenAssigned);
 883  3 caughtExceptions[i] = getSymbolData(catchBlocks[i].getException().getDeclarator().getType().getName(), _data, catchBlocks[i]);
 884    }
 885   
 886  14 BodyTypeChecker btcFinally = createANewInstanceOfMe(_bodyData, _file, _package, _importedFiles, _importedPackages, cloneVariableDataList(_vars), _thrown);
 887  14 TypeData finallyBlock_result = that.getFinallyBlock().visit(btcFinally);
 888    //leave anything that was assigned in the finally block assigned. It is always visited.
 889   
 890    //Give values to anything assigned in the try and catch blocks.
 891  14 reassignLotsaVariableDatas(btc.thingsThatHaveBeenAssigned, catchVars);
 892   
 893    //If the finallyBlock didn't end abruptly, need to check thrown and caught
 894   
 895  14 if (finallyBlock_result == null) {
 896  10 compareThrownAndCaught(that, caughtExceptions, btc._thrown);
 897    }
 898   
 899    else { /**It is like thrown is empty--any exceptions in it don't need to be caught.*/
 900  4 _thrown = new LinkedList<Pair<SymbolData, JExpression>>();
 901    }
 902   
 903  14 if (finallyBlock_result == SymbolData.NOT_FOUND.getInstanceData()) {
 904  1 finallyBlock_result = null;
 905    }
 906   
 907    // Add the exceptions thrown by btc to our thrown list.
 908  14 if (this instanceof TryCatchBodyTypeChecker) {
 909  5 _thrown.addAll(btc._thrown);
 910    }
 911   
 912  14 return forTryCatchFinallyStatementOnly(that, tryBlockRes, catchBlocksRes, finallyBlock_result);
 913    }
 914   
 915   
 916    /** Resolves the type of the exception, and visits the body, making sure the exception variable
 917    * is in scope.
 918    */
 919  13 public TypeData forCatchBlock(CatchBlock that) {
 920  13 VariableDeclarator dec = that.getException().getDeclarator();
 921  13 SymbolData exception_result = getSymbolData(dec.getType().getName(), _data, dec.getType());
 922   
 923  13 BlockData bd = _bodyData.getNextBlock();
 924  0 if (bd == null) { throw new RuntimeException("Internal Program Error: Enclosing body does not contain this block. Please report this bug"); }
 925  13 VariableData vd = bd.getVar(dec.getName().getText());
 926  0 if (vd == null) { throw new RuntimeException("Internal Program Error: Catch block does not contain its exception variable. Please report this bug"); }
 927  13 LinkedList<VariableData> newVars = cloneVariableDataList(_vars);
 928  13 newVars.addLast(vd);
 929  13 BodyTypeChecker btc = createANewInstanceOfMe(bd, _file, _package, _importedFiles, _importedPackages, newVars, _thrown);
 930  13 TypeData block_result = that.getBlock().getStatements().visit(btc);
 931  13 thingsThatHaveBeenAssigned.addAll(btc.thingsThatHaveBeenAssigned);
 932  13 return forCatchBlockOnly(that, exception_result, block_result);
 933    }
 934   
 935    /*Return the result of visiting the body*/
 936  13 public TypeData forCatchBlockOnly(CatchBlock that, SymbolData exception_result, TypeData block_result) {
 937  13 return block_result;
 938    }
 939   
 940    /**Assumes that tryBlockRes, catchBlocksRes, and finallyBlock_result are InstanceDatas*/
 941  15 public TypeData forNormalTryCatchStatementOnly(NormalTryCatchStatement that, TypeData tryBlockRes, TypeData[] catchBlocksRes) {
 942  15 checkDuplicateExceptions(that);
 943  15 InstanceData[] ids = new InstanceData[catchBlocksRes.length];
 944  15 for (int i = 0; i<catchBlocksRes.length; i++) {
 945  10 ids[i]=(InstanceData) catchBlocksRes[i];
 946   
 947    }
 948   
 949  15 return tryCatchLeastRestrictiveType((InstanceData) tryBlockRes, ids, null);
 950    }
 951   
 952    /*no finally block*/
 953  15 public TypeData forNormalTryCatchStatement(NormalTryCatchStatement that) {
 954  15 BodyTypeChecker btc = new TryCatchBodyTypeChecker(_bodyData, _file, _package, _importedFiles, _importedPackages, cloneVariableDataList(_vars), new LinkedList<Pair<SymbolData, JExpression>>());
 955  15 final TypeData tryBlockRes = that.getTryBlock().visit(btc);
 956  15 unassignVariableDatas(btc.thingsThatHaveBeenAssigned);
 957   
 958  15 LinkedList<LinkedList<VariableData>> catchVars = new LinkedList<LinkedList<VariableData>>();
 959  15 BodyTypeChecker[] catchTCs = new BodyTypeChecker[that.getCatchBlocks().length];
 960   
 961  15 CatchBlock[] catchBlocks = that.getCatchBlocks();
 962  15 final TypeData[] catchBlocksRes = makeArrayOfRetType(catchBlocks.length);
 963  15 final SymbolData[] caughtExceptions = new SymbolData[catchBlocks.length];
 964  15 for (int i = 0; i < catchBlocks.length; i++) {
 965  10 catchTCs[i] = createANewInstanceOfMe(_bodyData, _file, _package, _importedFiles, _importedPackages, cloneVariableDataList(_vars), _thrown);
 966  10 catchBlocksRes[i] = catchBlocks[i].visit(catchTCs[i]);
 967  10 unassignVariableDatas(catchTCs[i].thingsThatHaveBeenAssigned);
 968  10 catchVars.addLast(catchTCs[i].thingsThatHaveBeenAssigned);
 969  10 caughtExceptions[i] = getSymbolData(catchBlocks[i].getException().getDeclarator().getType().getName(), _data, catchBlocks[i]);
 970    }
 971   
 972    //Give values to anything assigned in the try and catch blocks.
 973  15 reassignLotsaVariableDatas(btc.thingsThatHaveBeenAssigned, catchVars);
 974   
 975  15 compareThrownAndCaught(that, caughtExceptions, btc._thrown);
 976   
 977    // Add the exceptions thrown by btc to our thrown list.
 978  15 if (this instanceof TryCatchBodyTypeChecker) {
 979  5 _thrown.addAll(btc._thrown);
 980    }
 981  15 return forNormalTryCatchStatementOnly(that, tryBlockRes, catchBlocksRes);
 982    }
 983   
 984   
 985    /* A special visitor that does not allow assignment in any expressions*/
 986    private class NoAssignmentAllowedInExpression extends JExpressionIFAbstractVisitor<Boolean> {
 987    String _location;
 988  60 private NoAssignmentAllowedInExpression(String location) { _location = location; }
 989   
 990    /** Most expressions do not involve assignment. */
 991  54 public Boolean defaultCase(JExpressionIF that) { return Boolean.TRUE; }
 992   
 993    /* Throw an appropriate error*/
 994  1 public Boolean forIncrementExpression(IncrementExpression that) {
 995  1 _addError("You cannot use an increment or decrement expression in " + _location + " at any language level", that);
 996  1 return Boolean.FALSE;
 997    }
 998   
 999    /*Throw an appropriate error*/
 1000  2 public Boolean forAssignmentExpression(AssignmentExpression that) {
 1001  2 _addError("You cannot use an assignment expression in " + _location + " at any language level", that);
 1002  2 return Boolean.FALSE;
 1003    }
 1004   
 1005    /*Throw an appropriate error*/
 1006  3 public Boolean forSimpleAssignmentExpression(SimpleAssignmentExpression that) {
 1007  3 _addError("You cannot use an assignment expression in " + _location + " at any language level" + ". Perhaps you meant to compare two values with '=='", that);
 1008  3 return Boolean.FALSE;
 1009    }
 1010   
 1011    }
 1012   
 1013    /** Test the methods in the above class. */
 1014    public static class BodyTypeCheckerTest extends TestCase {
 1015   
 1016    private BodyTypeChecker _bbtc;
 1017   
 1018    private BodyData _bd1;
 1019    private BodyData _bd2;
 1020   
 1021    private SymbolData _sd1;
 1022    private SymbolData _sd2;
 1023    private SymbolData _sd3;
 1024    private SymbolData _sd4;
 1025    private SymbolData _sd5;
 1026    private SymbolData _sd6;
 1027    private ModifiersAndVisibility _publicMav = new ModifiersAndVisibility(SourceInfo.NONE, new String[] {"public"});
 1028    private ModifiersAndVisibility _protectedMav =
 1029    new ModifiersAndVisibility(SourceInfo.NONE, new String[] {"protected"});
 1030    private ModifiersAndVisibility _privateMav =
 1031    new ModifiersAndVisibility(SourceInfo.NONE, new String[] {"private"});
 1032    private ModifiersAndVisibility _packageMav = new ModifiersAndVisibility(SourceInfo.NONE, new String[0]);
 1033    private ModifiersAndVisibility _abstractMav =
 1034    new ModifiersAndVisibility(SourceInfo.NONE, new String[] {"abstract"});
 1035    private ModifiersAndVisibility _finalMav = new ModifiersAndVisibility(SourceInfo.NONE, new String[] {"final"});
 1036   
 1037  0 public BodyTypeCheckerTest() { this(""); }
 1038  34 public BodyTypeCheckerTest(String name) { super(name); }
 1039   
 1040  34 public void setUp() {
 1041  34 _sd1 = new SymbolData("i.like.monkey");
 1042  34 _sd2 = new SymbolData("i.like.giraffe");
 1043  34 _sd3 = new SymbolData("zebra");
 1044  34 _sd4 = new SymbolData("u.like.emu");
 1045  34 _sd5 = new SymbolData("");
 1046  34 _sd6 = new SymbolData("cebu");
 1047   
 1048  34 _bd1 = new MethodData("methodName1",
 1049    _packageMav,
 1050    new TypeParameter[0],
 1051    SymbolData.INT_TYPE,
 1052    new VariableData[] { new VariableData("i", _publicMav, SymbolData.INT_TYPE, true, null), new VariableData(SymbolData.BOOLEAN_TYPE) },
 1053    new String[0],
 1054    _sd1,
 1055    null); // no SourceInfo
 1056  34 ((MethodData)_bd1).getParams()[0].setEnclosingData(_bd1);
 1057  34 ((MethodData)_bd1).getParams()[1].setEnclosingData(_bd1);
 1058   
 1059  34 _bd2 = new MethodData("methodName2",
 1060    _packageMav,
 1061    new TypeParameter[0],
 1062    SymbolData.VOID_TYPE,
 1063    new VariableData[] { new VariableData(SymbolData.INT_TYPE) },
 1064    new String[0],
 1065    _sd1,
 1066    null); // no SourceInfo);
 1067  34 ((MethodData)_bd2).getParams()[0].setEnclosingData(_bd2);
 1068   
 1069  34 errors = new LinkedList<Pair<String, JExpressionIF>>();
 1070  34 LanguageLevelConverter.symbolTable.clear();
 1071  34 LanguageLevelConverter._newSDs.clear();
 1072  34 _bd1.addEnclosingData(_sd1);
 1073  34 _bd1.addVars(((MethodData)_bd1).getParams());
 1074  34 _bd2.addVars(((MethodData)_bd2).getParams());
 1075  34 _bbtc = new BodyTypeChecker(_bd1, new File(""), "", new LinkedList<String>(), new LinkedList<String>(),
 1076    new LinkedList<VariableData>(), new LinkedList<Pair<SymbolData,JExpression>>());
 1077  34 LanguageLevelConverter.OPT = new Options(JavaVersion.JAVA_5, EmptyIterable.<File>make());
 1078  34 _bbtc._importedPackages.addFirst("java.lang");
 1079    }
 1080   
 1081  1 public void testForUninitializedVariableDeclaratorOnly() {
 1082  1 VariableData vd1 = new VariableData("Mojo", _publicMav, SymbolData.INT_TYPE, false, _bd1);
 1083  1 _bd1.addVar(vd1);
 1084  1 UninitializedVariableDeclarator uvd = new UninitializedVariableDeclarator(SourceInfo.NONE,
 1085    new PrimitiveType(SourceInfo.NONE, "int"),
 1086    new Word(SourceInfo.NONE, "Mojo"));
 1087  1 uvd.visit(_bbtc);
 1088  1 assertTrue("_vars should contain Mojo.", _bbtc._vars.contains(vd1));
 1089    }
 1090   
 1091  1 public void testForInitializedVariableDeclaratorOnly() {
 1092  1 _bbtc.symbolTable.put("int", SymbolData.INT_TYPE);
 1093  1 VariableData vd1 = new VariableData("Mojo", _publicMav, SymbolData.INT_TYPE, true, _bd1);
 1094  1 _bd1.addVar(vd1);
 1095  1 InitializedVariableDeclarator ivd = new InitializedVariableDeclarator(SourceInfo.NONE,
 1096    new PrimitiveType(SourceInfo.NONE, "int"),
 1097    new Word(SourceInfo.NONE, "Mojo"),
 1098    new IntegerLiteral(SourceInfo.NONE, 1));
 1099  1 ivd.visit(_bbtc);
 1100  1 assertEquals("There should be no errors.", 0, errors.size());
 1101  1 assertTrue("_vars should contain Mojo.", _bbtc._vars.contains(vd1));
 1102  1 ivd = new InitializedVariableDeclarator(SourceInfo.NONE,
 1103    new PrimitiveType(SourceInfo.NONE, "int"),
 1104    new Word(SourceInfo.NONE, "Santa's Little Helper"),
 1105    new IntegerLiteral(SourceInfo.NONE, 1));
 1106  1 try {
 1107  1 ivd.visit(_bbtc);
 1108  0 fail("Should have thrown a RuntimeException because there's no field named Santa's Little Helper.");
 1109    }
 1110    catch (RuntimeException re) {
 1111  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());
 1112    }
 1113    }
 1114   
 1115  1 public void testForBracedBodyOnly() {
 1116    // Test one that works.
 1117  1 BracedBody bb1 = new BracedBody(SourceInfo.NONE,
 1118    new BodyItemI[] { new ValueReturnStatement(SourceInfo.NONE,
 1119    new IntegerLiteral(SourceInfo.NONE, 1))});
 1120  1 TypeData sd = bb1.visit(_bbtc);
 1121  1 assertEquals("There should be no errors", 0, errors.size());
 1122  1 assertEquals("Should return int type", SymbolData.INT_TYPE.getInstanceData(), sd);
 1123  1 BracedBody bb2 = new BracedBody(SourceInfo.NONE,
 1124    new BodyItemI[] { new ValueReturnStatement(SourceInfo.NONE,
 1125    new CharLiteral(SourceInfo.NONE, 'e'))});
 1126    //test another one that works.
 1127  1 sd = bb2.visit(_bbtc);
 1128  1 assertEquals("There should be no errors", 0, errors.size());
 1129  1 assertEquals("Should return char type", SymbolData.CHAR_TYPE.getInstanceData(), sd);
 1130  1 BracedBody bb3 = new BracedBody(SourceInfo.NONE,
 1131    new BodyItemI[] { new ValueReturnStatement(SourceInfo.NONE,
 1132    new IntegerLiteral(SourceInfo.NONE, 1)),
 1133    new ValueReturnStatement(SourceInfo.NONE,
 1134    new CharLiteral(SourceInfo.NONE, 'e'))});
 1135    //test one that should throw an error: unreachable return statement.
 1136  1 sd = bb3.visit(_bbtc);
 1137  1 assertEquals("There should be one error", 1, errors.size());
 1138  1 assertEquals("The error message should be correct", "Unreachable statement.", errors.get(0).getFirst());
 1139  1 assertEquals("Should return int type", SymbolData.INT_TYPE.getInstanceData(), sd);
 1140   
 1141  1 BracedBody bb4 = new BracedBody(SourceInfo.NONE,
 1142    new BodyItemI[0]);
 1143    //test empty body. should return null.
 1144  1 sd = bb4.visit(_bbtc);
 1145  1 assertEquals("There should still be one error", 1, errors.size());
 1146  1 assertEquals("The error message should still be be correct", "Unreachable statement.", errors.get(0).getFirst());
 1147  1 assertEquals("Should return null", null, sd);
 1148    }
 1149   
 1150  1 public void testForVoidReturnStatementOnly() {
 1151  1 _bbtc._bodyData = _bd2; //this body data has a void return type
 1152   
 1153    //test one that works
 1154  1 BracedBody bb1 = new BracedBody(SourceInfo.NONE,
 1155    new BodyItemI[] { new VoidReturnStatement(SourceInfo.NONE)});
 1156   
 1157  1 TypeData sd = bb1.visit(_bbtc);
 1158   
 1159  1 assertEquals("There should be no errors.", 0, errors.size());
 1160  1 assertEquals("Should return void type.", SymbolData.VOID_TYPE.getInstanceData(), sd);
 1161   
 1162    //test with a method that doesn't return void.
 1163  1 _bbtc._bodyData = _bd1;
 1164  1 sd = bb1.visit(_bbtc);
 1165  1 assertEquals("There should be one error", 1, errors.size());
 1166  1 assertEquals("Should return int type", SymbolData.INT_TYPE.getInstanceData(), sd);
 1167  1 assertEquals("Error message should be correct", "Cannot return void when the method's expected return type is not void.", errors.get(0).getFirst());
 1168   
 1169    }
 1170   
 1171  1 public void testforValueReturnStatementOnly() {
 1172    //value return statement returns something that is not a subclass the method return type
 1173  1 BracedBody bb1 = new BracedBody(SourceInfo.NONE,
 1174    new BodyItemI[] { new ValueReturnStatement(SourceInfo.NONE,
 1175    new BooleanLiteral(SourceInfo.NONE, true))});
 1176  1 TypeData sd = bb1.visit(_bbtc);
 1177  1 assertEquals("There should be one error", 1, errors.size());
 1178  1 assertEquals("Should return boolean type", SymbolData.BOOLEAN_TYPE.getInstanceData(), sd);
 1179  1 assertEquals("Error message should be correct",
 1180    "This method expected to return type: \"int\" but here returned type: \"boolean\"", errors.get(0).getFirst());
 1181   
 1182    //value return statement returns something that is assignable from the method return type
 1183  1 BracedBody bb2 = new BracedBody(SourceInfo.NONE,
 1184    new BodyItemI[] { new ValueReturnStatement(SourceInfo.NONE,
 1185    new CharLiteral(SourceInfo.NONE, 'c'))});
 1186  1 sd = bb2.visit(_bbtc);
 1187  1 assertEquals("There should be still be one error", 1, errors.size());
 1188  1 assertEquals("Should return char type", SymbolData.CHAR_TYPE.getInstanceData(), sd);
 1189  1 assertEquals("Error message should still be correct", "This method expected to return type: \"int\" but here returned type: \"boolean\"", errors.get(0).getFirst());
 1190   
 1191   
 1192    //method returns void
 1193  1 _bbtc._bodyData = _bd2; //this body data has a void return type
 1194   
 1195  1 BracedBody bb3 = new BracedBody(SourceInfo.NONE,
 1196    new BodyItemI[] { new ValueReturnStatement(SourceInfo.NONE,
 1197    new IntegerLiteral(SourceInfo.NONE, 1))});
 1198   
 1199  1 sd = bb3.visit(_bbtc);
 1200  1 assertEquals("There should be two errors", 2, errors.size());
 1201  1 assertEquals("Should return void type", SymbolData.VOID_TYPE.getInstanceData(), sd);
 1202  1 assertEquals("Error message should be correct", "Cannot return a value when the method's expected return type is void.", errors.get(1).getFirst());
 1203   
 1204    // Test where the return value is a class name.
 1205  1 BracedBody bb4 = new BracedBody(SourceInfo.NONE,
 1206    new BodyItemI[] { new ValueReturnStatement(SourceInfo.NONE,
 1207    new SimpleNameReference(SourceInfo.NONE, new Word(SourceInfo.NONE, "int")))});
 1208   
 1209  1 sd = bb4.visit(_bbtc);
 1210  1 assertEquals("There should be 3 errors", 3, errors.size());
 1211  1 assertEquals("Should return int type", SymbolData.INT_TYPE.getInstanceData(), sd);
 1212  1 assertEquals("Error message should be correct", "You cannot return a class or interface name. Perhaps you meant to say int.class or to create an instance", errors.getLast().getFirst());
 1213   
 1214    }
 1215   
 1216  1 public void testForIfThenElseStatementOnly() {
 1217    //test if the expression is not of boolean type
 1218  1 IfThenElseStatement ites1 = new IfThenElseStatement(SourceInfo.NONE,
 1219    new IntegerLiteral(SourceInfo.NONE, 1),
 1220    new ValueReturnStatement(SourceInfo.NONE, new IntegerLiteral(SourceInfo.NONE, 4)),
 1221    new ValueReturnStatement(SourceInfo.NONE, new CharLiteral(SourceInfo.NONE, 'j')));
 1222   
 1223  1 TypeData sd = ites1.visit(_bbtc);
 1224  1 assertEquals("There should be one error", 1, errors.size());
 1225  1 assertEquals("Error message should be correct", "This if-then-else statement's conditional expression must be a boolean value. Instead, its type is int", errors.get(0).getFirst());
 1226   
 1227  1 assertEquals("Should return integer type", SymbolData.INT_TYPE.getInstanceData(), sd);
 1228   
 1229   
 1230    //test if the branches do not return subtypes of each other
 1231  1 IfThenElseStatement ites2 = new IfThenElseStatement(SourceInfo.NONE,
 1232    new BooleanLiteral(SourceInfo.NONE, true),
 1233    new ValueReturnStatement(SourceInfo.NONE, new IntegerLiteral(SourceInfo.NONE, 4)),
 1234    new ValueReturnStatement(SourceInfo.NONE, new BooleanLiteral(SourceInfo.NONE, true)));
 1235   
 1236  1 sd = ites2.visit(_bbtc);
 1237  1 assertEquals("There should be two errors", 2, errors.size());
 1238   
 1239  1 assertEquals("Should return Object type", "java.lang.Object", sd.getName());
 1240  1 assertEquals("Error message should be correct",
 1241    "This method expected to return type: \"int\" but here returned type: \"boolean\"",
 1242    errors.get(1).getFirst());
 1243   
 1244    //test if they do return subtypes of each other
 1245  1 IfThenElseStatement ites3 = new IfThenElseStatement(SourceInfo.NONE,
 1246    new BooleanLiteral(SourceInfo.NONE, true),
 1247    new ValueReturnStatement(SourceInfo.NONE, new IntegerLiteral(SourceInfo.NONE, 4)),
 1248    new ValueReturnStatement(SourceInfo.NONE, new CharLiteral(SourceInfo.NONE, 'f')));
 1249   
 1250  1 sd = ites3.visit(_bbtc);
 1251  1 assertEquals("There should still be two errors", 2, errors.size());
 1252  1 assertEquals("Should return int type", SymbolData.INT_TYPE.getInstanceData(), sd);
 1253   
 1254    //test if neither branch returns
 1255  1 IfThenElseStatement ites4 = new IfThenElseStatement(SourceInfo.NONE,
 1256    new BooleanLiteral(SourceInfo.NONE, true),
 1257    new EmptyStatement(SourceInfo.NONE),
 1258    new EmptyStatement(SourceInfo.NONE));
 1259   
 1260  1 sd = ites4.visit(_bbtc);
 1261  1 assertEquals("There should still be two errors", 2, errors.size());
 1262  1 assertEquals("Should return null type", null, sd);
 1263   
 1264    //test if only one branch returns
 1265  1 IfThenElseStatement ites5 = new IfThenElseStatement(SourceInfo.NONE,
 1266    new BooleanLiteral(SourceInfo.NONE, true),
 1267    new EmptyStatement(SourceInfo.NONE),
 1268    new ValueReturnStatement(SourceInfo.NONE, new IntegerLiteral(SourceInfo.NONE, 3)));
 1269   
 1270  1 sd = ites5.visit(_bbtc);
 1271  1 assertEquals("There should still be two errors", 2, errors.size());
 1272  1 assertEquals("Should return null type", null, sd);
 1273   
 1274   
 1275    // Test for the word "boolean" as the condition.
 1276  1 IfThenElseStatement ites6 = new IfThenElseStatement(SourceInfo.NONE,
 1277    new SimpleNameReference(SourceInfo.NONE, new Word(SourceInfo.NONE, "boolean")),
 1278    new ValueReturnStatement(SourceInfo.NONE, new IntegerLiteral(SourceInfo.NONE, 4)),
 1279    new ValueReturnStatement(SourceInfo.NONE, new IntegerLiteral(SourceInfo.NONE, 4)));
 1280   
 1281  1 sd = ites6.visit(_bbtc);
 1282  1 assertEquals("There should be 3 errors", 3, errors.size());
 1283   
 1284  1 assertEquals("Should return Integer type", SymbolData.INT_TYPE.getInstanceData(), sd);
 1285  1 assertEquals("Error message should be correct",
 1286    "This if-then-else statement's conditional expression must be a boolean value. Instead, it is a class or interface name",
 1287    errors.get(2).getFirst());
 1288    }
 1289   
 1290  1 public void testForBlock() {
 1291    //Check that a block can reference fields in its enclosing method.
 1292  1 Block b = new Block(SourceInfo.NONE,
 1293    new BracedBody(SourceInfo.NONE,
 1294    new BodyItemI[] { new ValueReturnStatement(SourceInfo.NONE,
 1295    new SimpleNameReference(SourceInfo.NONE, new Word(SourceInfo.NONE, "i")))}));
 1296  1 _bbtc._bodyData.addBlock(new BlockData(_bbtc._bodyData));
 1297  1 LinkedList<VariableData> vars = new LinkedList<VariableData>();
 1298  1 vars.addLast(new VariableData("i", _publicMav, SymbolData.INT_TYPE, true, _bd1));
 1299  1 _bbtc._vars = vars;
 1300  1 TypeData sd = b.visit(_bbtc);
 1301  1 assertEquals("There should not be any errors.", 0, errors.size());
 1302  1 assertEquals("Should return int type.", SymbolData.INT_TYPE.getInstanceData(), sd);
 1303    }
 1304   
 1305  1 public void testForIfThenStatementOnly() {
 1306  1 SymbolData sd1 = SymbolData.BOOLEAN_TYPE;
 1307  1 SymbolData sd2 = SymbolData.INT_TYPE;
 1308   
 1309  1 IfThenStatement its = new IfThenStatement(SourceInfo.NONE,
 1310    new NullLiteral(SourceInfo.NONE),
 1311    new EmptyStatement(SourceInfo.NONE));
 1312   
 1313   
 1314    //test a correct condition type
 1315  1 assertEquals("sd1 is boolean type, so should not add error. Returns null.", null,
 1316    _bbtc.forIfThenStatementOnly(its, sd1.getInstanceData(), null));
 1317  1 assertEquals("No errors should have been added", 0, errors.size());
 1318   
 1319    //test an incorrect condition type
 1320  1 assertEquals("sd2 is not boolean type, so should add error. Returns null.", null,
 1321    _bbtc.forIfThenStatementOnly(its, sd2.getInstanceData(), null));
 1322  1 assertEquals("Should now be one error.", 1, errors.size());
 1323  1 assertEquals("Error message should be correct.", "This if-then-statement's conditional expression must be a boolean value. Instead, its type is int", errors.getLast().getFirst());
 1324   
 1325    //test "bool" as a condition
 1326  1 assertEquals("sd1 is not an instance, so should add error. Returns null.", null,
 1327    _bbtc.forIfThenStatementOnly(its, sd1, null));
 1328  1 assertEquals("Should now be 2 errors.", 2, errors.size());
 1329  1 assertEquals("Error message should be correct.", "This if-then-statement's conditional expression must be a boolean value. Instead, it is a class or interface name", errors.getLast().getFirst());
 1330    }
 1331   
 1332  1 public void testForIfThenStatement() {
 1333    //Test that the proper variable assignment happens.
 1334    //here, a variable is only assigned in the then branch, so it should not be set after it returns.
 1335  1 Expression te = new LessThanExpression(SourceInfo.NONE,
 1336    new SimpleNameReference(SourceInfo.NONE,
 1337    new Word(SourceInfo.NONE, "j")),
 1338    new IntegerLiteral(SourceInfo.NONE, 5));
 1339  1 Statement ts =
 1340    new ExpressionStatement(SourceInfo.NONE,
 1341    new SimpleAssignmentExpression(SourceInfo.NONE,
 1342    new SimpleNameReference(SourceInfo.NONE,
 1343    new Word(SourceInfo.NONE, "i")),
 1344    new IntegerLiteral(SourceInfo.NONE, 10)));
 1345  1 IfThenStatement ift = new IfThenStatement(SourceInfo.NONE, te, ts);
 1346   
 1347  1 PrimitiveType intt = new PrimitiveType(SourceInfo.NONE, "int");
 1348  1 UninitializedVariableDeclarator uvd =
 1349    new UninitializedVariableDeclarator(SourceInfo.NONE, intt, new Word(SourceInfo.NONE, "i"));
 1350  1 FormalParameter param =
 1351    new FormalParameter(SourceInfo.NONE,
 1352    new UninitializedVariableDeclarator(SourceInfo.NONE, intt,
 1353    new Word(SourceInfo.NONE, "j")), false);
 1354  1 BracedBody bb = new BracedBody(SourceInfo.NONE, new BodyItemI[] {
 1355    new VariableDeclaration(SourceInfo.NONE, _packageMav, new UninitializedVariableDeclarator[]{uvd}), ift});
 1356   
 1357  1 ConcreteMethodDef cmd1 = new ConcreteMethodDef(SourceInfo.NONE, _publicMav, new TypeParameter[0],
 1358    intt, new Word(SourceInfo.NONE, "myMethod"), new FormalParameter[] {param},
 1359    new ReferenceType[0], bb);
 1360   
 1361  1 VariableData vd1 = new VariableData("j", _packageMav, SymbolData.INT_TYPE, true, null);
 1362  1 VariableData vd2 = new VariableData("i", _packageMav, SymbolData.INT_TYPE, false, null);
 1363  1 MethodData md1 = new MethodData("myMethod", _publicMav, new TypeParameter[0], SymbolData.INT_TYPE,
 1364    new VariableData[] {vd1}, new String[0], _sd1, cmd1);
 1365   
 1366  1 vd1.setEnclosingData(md1);
 1367  1 vd2.setEnclosingData(md1);
 1368  1 md1.addVar(vd1);
 1369  1 md1.addVar(vd2);
 1370   
 1371  1 LinkedList<VariableData> vars = new LinkedList<VariableData>();
 1372  1 vars.addLast(vd1);
 1373  1 vars.addLast(vd2);
 1374  1 _bbtc = new BodyTypeChecker(md1, _bbtc._file, _bbtc._package, _bbtc._importedFiles, _bbtc._importedPackages, vars,
 1375    new LinkedList<Pair<SymbolData, JExpression>>());
 1376  1 _bbtc._bodyData = md1;
 1377  1 _bbtc._data = md1;
 1378   
 1379   
 1380   
 1381  1 ift.visit(_bbtc);
 1382  1 assertTrue("vd1 should be assigned", vd1.hasValue());
 1383  1 assertFalse("vd2 should not be assigned", vd2.hasValue());
 1384   
 1385   
 1386    //Here, a variable is assigned before the if, so it should still have a value after the if.
 1387   
 1388  1 vd1 = new VariableData("j", _packageMav, SymbolData.INT_TYPE, true, null);
 1389  1 vd2 = new VariableData("i", _packageMav, SymbolData.INT_TYPE, true, null);
 1390  1 md1 = new MethodData("myMethod", _publicMav, new TypeParameter[0], SymbolData.INT_TYPE,
 1391    new VariableData[] {vd1}, new String[0], _sd1, cmd1);
 1392   
 1393  1 vd1.setEnclosingData(md1);
 1394  1 vd2.setEnclosingData(md1);
 1395  1 md1.addVar(vd1);
 1396  1 md1.addVar(vd2);
 1397   
 1398  1 vars = new LinkedList<VariableData>();
 1399  1 vars.addLast(vd1);
 1400  1 vars.addLast(vd2);
 1401  1 _bbtc = new BodyTypeChecker(md1, _bbtc._file, _bbtc._package, _bbtc._importedFiles, _bbtc._importedPackages, vars,
 1402    new LinkedList<Pair<SymbolData, JExpression>>());
 1403  1 _bbtc._bodyData = md1;
 1404  1 _bbtc._data = md1;
 1405   
 1406  1 ift.visit(_bbtc);
 1407  1 assertTrue("vd1 should be assigned", vd1.hasValue());
 1408  1 assertTrue("vd2 should also be assigned", vd2.hasValue());
 1409   
 1410   
 1411    //test that if a variable is assigned in a branch of the if, and then returned, it is okay.
 1412  1 te = new LessThanExpression(SourceInfo.NONE,
 1413    new SimpleNameReference(SourceInfo.NONE,
 1414    new Word(SourceInfo.NONE, "j")),
 1415    new IntegerLiteral(SourceInfo.NONE, 5));
 1416  1 Statement assignStatement =
 1417    new ExpressionStatement(SourceInfo.NONE,
 1418    new SimpleAssignmentExpression(SourceInfo.NONE,
 1419    new SimpleNameReference(SourceInfo.NONE,
 1420    new Word(SourceInfo.NONE, "i")),
 1421    new IntegerLiteral(SourceInfo.NONE, 10)));
 1422  1 Statement returnStatement =
 1423    new ValueReturnStatement(SourceInfo.NONE,
 1424    new SimpleNameReference(SourceInfo.NONE, new Word(SourceInfo.NONE, "i")));
 1425  1 ts = new Block(SourceInfo.NONE, new BracedBody(SourceInfo.NONE, new BodyItemI[] {assignStatement, returnStatement}));
 1426  1 ift = new IfThenStatement(SourceInfo.NONE, te, ts);
 1427   
 1428  1 bb = new BracedBody(SourceInfo.NONE, new BodyItemI[] {new VariableDeclaration(SourceInfo.NONE, _packageMav, new UninitializedVariableDeclarator[]{uvd}), ift});
 1429   
 1430  1 cmd1 = new ConcreteMethodDef(SourceInfo.NONE, _publicMav, new TypeParameter[0],
 1431    intt, new Word(SourceInfo.NONE, "myMethod"), new FormalParameter[] {param},
 1432    new ReferenceType[0], bb);
 1433   
 1434  1 vd1 = new VariableData("j", _packageMav, SymbolData.INT_TYPE, true, null);
 1435  1 vd2 = new VariableData("i", _packageMav, SymbolData.INT_TYPE, false, null);
 1436  1 md1 = new MethodData("myMethod", _publicMav, new TypeParameter[0], SymbolData.INT_TYPE,
 1437    new VariableData[] {vd1}, new String[0], _sd1, cmd1);
 1438   
 1439  1 vd1.setEnclosingData(md1);
 1440  1 vd2.setEnclosingData(md1);
 1441  1 md1.addVar(vd1);
 1442  1 md1.addVar(vd2);
 1443   
 1444  1 vars = new LinkedList<VariableData>();
 1445  1 vars.addLast(vd1);
 1446  1 vars.addLast(vd2);
 1447  1 _bbtc = new BodyTypeChecker(md1, _bbtc._file, _bbtc._package, _bbtc._importedFiles, _bbtc._importedPackages, vars, new LinkedList<Pair<SymbolData, JExpression>>());
 1448  1 _bbtc._bodyData = md1;
 1449  1 _bbtc._data = md1;
 1450   
 1451  1 _bbtc._bodyData.addBlock(new BlockData(_bbtc._bodyData));
 1452   
 1453  1 ift.visit(_bbtc);
 1454  1 assertTrue("vd1 should be assigned", vd1.hasValue());
 1455  1 assertFalse("vd2 should not be assigned", vd2.hasValue());
 1456  1 assertEquals("There should be no errors", 0, errors.size());
 1457  1 errors = new LinkedList<Pair<String, JExpressionIF>>();
 1458   
 1459    // Test that an assignment in the if-expression throws an error
 1460  1 te = new LessThanExpression(SourceInfo.NONE, new SimpleNameReference(SourceInfo.NONE, new Word(SourceInfo.NONE, "j")),
 1461    new IntegerLiteral(SourceInfo.NONE, 5));
 1462  1 ts = new ExpressionStatement(SourceInfo.NONE, new SimpleAssignmentExpression(SourceInfo.NONE, new SimpleNameReference(SourceInfo.NONE, new Word(SourceInfo.NONE, "i")), new IntegerLiteral(SourceInfo.NONE, 10)));
 1463  1 ift = new IfThenStatement(SourceInfo.NONE, te, ts);
 1464  1 bb = new BracedBody(SourceInfo.NONE, new BodyItemI[] {new VariableDeclaration(SourceInfo.NONE, _packageMav, new UninitializedVariableDeclarator[]{uvd}), ift});
 1465   
 1466  1 cmd1 = new ConcreteMethodDef(SourceInfo.NONE, _publicMav, new TypeParameter[0],
 1467    intt, new Word(SourceInfo.NONE, "myMethod"), new FormalParameter[] {param},
 1468    new ReferenceType[0], bb);
 1469   
 1470  1 vd1 = new VariableData("b", _packageMav, SymbolData.BOOLEAN_TYPE, true, null);
 1471  1 vd2 = new VariableData("i", _packageMav, SymbolData.INT_TYPE, false, null);
 1472  1 md1 = new MethodData("myMethod", _publicMav, new TypeParameter[0], SymbolData.INT_TYPE,
 1473    new VariableData[] {vd1}, new String[0], _sd1, cmd1);
 1474   
 1475  1 vd1.setEnclosingData(md1);
 1476  1 vd2.setEnclosingData(md1);
 1477   
 1478  1 md1.addVar(vd1);
 1479  1 md1.addVar(vd2);
 1480   
 1481  1 vars = new LinkedList<VariableData>();
 1482  1 vars.addLast(vd1);
 1483  1 vars.addLast(vd2);
 1484  1 _bbtc = new BodyTypeChecker(md1, _bbtc._file, _bbtc._package, _bbtc._importedFiles, _bbtc._importedPackages, vars, new LinkedList<Pair<SymbolData, JExpression>>());
 1485  1 _bbtc._bodyData = md1;
 1486  1 _bbtc._data = md1;
 1487   
 1488  1 te = new SimpleAssignmentExpression(SourceInfo.NONE, new SimpleNameReference(SourceInfo.NONE, new Word(SourceInfo.NONE, "b")),
 1489    new BooleanLiteral(SourceInfo.NONE, true));
 1490  1 ts = new ExpressionStatement(SourceInfo.NONE,
 1491    new SimpleAssignmentExpression(SourceInfo.NONE,
 1492    new SimpleNameReference(SourceInfo.NONE,
 1493    new Word(SourceInfo.NONE, "i")),
 1494    new IntegerLiteral(SourceInfo.NONE, 10)));
 1495  1 ift = new IfThenStatement(SourceInfo.NONE, te, ts);
 1496   
 1497  1 ift.visit(_bbtc);
 1498  1 assertEquals("There should now be one error", 1, errors.size());
 1499  1 assertEquals("Error message should be correct", "You cannot use an assignment expression in the conditional " +
 1500    "expression of an if-then statement at any language level. Perhaps you meant to compare two " +
 1501    "values with '=='",
 1502    errors.get(0).getFirst());
 1503   
 1504   
 1505    }
 1506   
 1507  1 public void testForIfThenElseStatement() {
 1508   
 1509    //Test that the proper variable assignment happens.
 1510    //here, a variable is only assigned in the then branch, so it should not be set after it returns.
 1511  1 Expression te = new LessThanExpression(SourceInfo.NONE, new SimpleNameReference(SourceInfo.NONE, new Word(SourceInfo.NONE, "j")),
 1512    new IntegerLiteral(SourceInfo.NONE, 5));
 1513  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)));
 1514   
 1515  1 IfThenElseStatement ift = new IfThenElseStatement(SourceInfo.NONE, te, ts, new EmptyStatement(SourceInfo.NONE));
 1516   
 1517  1 PrimitiveType intt = new PrimitiveType(SourceInfo.NONE, "int");
 1518  1 UninitializedVariableDeclarator uvd = new UninitializedVariableDeclarator(SourceInfo.NONE, intt, new Word(SourceInfo.NONE, "i"));
 1519  1 FormalParameter param = new FormalParameter(SourceInfo.NONE, new UninitializedVariableDeclarator(SourceInfo.NONE, intt, new Word(SourceInfo.NONE, "j")), false);
 1520  1 BracedBody bb = new BracedBody(SourceInfo.NONE, new BodyItemI[] {new VariableDeclaration(SourceInfo.NONE, _packageMav, new UninitializedVariableDeclarator[]{uvd}), ift});
 1521   
 1522  1 ConcreteMethodDef cmd1 = new ConcreteMethodDef(SourceInfo.NONE, _publicMav, new TypeParameter[0],
 1523    intt, new Word(SourceInfo.NONE, "myMethod"), new FormalParameter[] {param},
 1524    new ReferenceType[0], bb);
 1525   
 1526  1 VariableData vd1 = new VariableData("j", _packageMav, SymbolData.INT_TYPE, true, null);
 1527  1 VariableData vd2 = new VariableData("i", _packageMav, SymbolData.INT_TYPE, false, null);
 1528  1 MethodData md1 = new MethodData("myMethod", _publicMav, new TypeParameter[0], SymbolData.INT_TYPE,
 1529    new VariableData[] {vd1}, new String[0], _sd1, cmd1);
 1530   
 1531  1 vd1.setEnclosingData(md1);
 1532  1 vd2.setEnclosingData(md1);
 1533   
 1534  1 md1.addVar(vd1);
 1535  1 md1.addVar(vd2);
 1536   
 1537  1 LinkedList<VariableData> vars = new LinkedList<VariableData>();
 1538  1 vars.addLast(vd1);
 1539  1 vars.addLast(vd2);
 1540  1 _bbtc = new BodyTypeChecker(md1, _bbtc._file, _bbtc._package, _bbtc._importedFiles, _bbtc._importedPackages, vars, new LinkedList<Pair<SymbolData, JExpression>>());
 1541  1 _bbtc._bodyData = md1;
 1542  1 _bbtc._data = md1;
 1543   
 1544  1 ift.visit(_bbtc);
 1545  1 assertTrue("vd1 should be assigned", vd1.hasValue());
 1546  1 assertFalse("vd2 should not be assigned", vd2.hasValue());
 1547   
 1548    //test that if a variable is only assigned in the else case that it is not assigned afterwards
 1549  1 te = new LessThanExpression(SourceInfo.NONE, new SimpleNameReference(SourceInfo.NONE, new Word(SourceInfo.NONE, "j")),
 1550    new IntegerLiteral(SourceInfo.NONE, 5));
 1551  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)));
 1552  1 ts = new Block(SourceInfo.NONE, new BracedBody(SourceInfo.NONE, new BodyItemI[] {assignStatement}));
 1553  1 ift = new IfThenElseStatement(SourceInfo.NONE, te, new EmptyStatement(SourceInfo.NONE), ts);
 1554   
 1555  1 bb = new BracedBody(SourceInfo.NONE, new BodyItemI[] {new VariableDeclaration(SourceInfo.NONE, _packageMav, new UninitializedVariableDeclarator[]{uvd}), ift});
 1556   
 1557  1 cmd1 = new ConcreteMethodDef(SourceInfo.NONE, _publicMav, new TypeParameter[0],
 1558    intt, new Word(SourceInfo.NONE, "myMethod"), new FormalParameter[] {param},
 1559    new ReferenceType[0], bb);
 1560   
 1561  1 vd1 = new VariableData("j", _packageMav, SymbolData.INT_TYPE, true, null);
 1562  1 vd2 = new VariableData("i", _packageMav, SymbolData.INT_TYPE, false, null);
 1563  1 md1 = new MethodData("myMethod", _publicMav, new TypeParameter[0], SymbolData.INT_TYPE,
 1564    new VariableData[] {vd1}, new String[0], _sd1, cmd1);
 1565   
 1566  1 vd1.setEnclosingData(md1);
 1567  1 vd2.setEnclosingData(md1);
 1568   
 1569  1 md1.addVar(vd1);
 1570  1 md1.addVar(vd2);
 1571   
 1572  1 vars = new LinkedList<VariableData>();
 1573  1 vars.addLast(vd1);
 1574  1 vars.addLast(vd2);
 1575  1 _bbtc = new BodyTypeChecker(md1, _bbtc._file, _bbtc._package, _bbtc._importedFiles, _bbtc._importedPackages, vars, new LinkedList<Pair<SymbolData, JExpression>>());
 1576  1 _bbtc._bodyData = md1;
 1577  1 _bbtc._data = md1;
 1578  1 _bbtc._bodyData.addBlock(new BlockData(_bbtc._bodyData));
 1579   
 1580  1 ift.visit(_bbtc);
 1581  1 assertTrue("vd1 should be assigned", vd1.hasValue());
 1582  1 assertFalse("vd2 should not be assigned", vd2.hasValue());
 1583  1 assertEquals("There should be no errors", 0, errors.size());
 1584   
 1585    //Here, a variable is assigned before the if, so it should still have a value after the if.
 1586   
 1587  1 vd1 = new VariableData("j", _packageMav, SymbolData.INT_TYPE, true, null);
 1588  1 vd2 = new VariableData("i", _packageMav, SymbolData.INT_TYPE, true, null);
 1589  1 md1 = new MethodData("myMethod", _publicMav, new TypeParameter[0], SymbolData.INT_TYPE,
 1590    new VariableData[] {vd1}, new String[0], _sd1, cmd1);
 1591   
 1592  1 vd1.setEnclosingData(md1);
 1593  1 vd2.setEnclosingData(md1);
 1594   
 1595  1 md1.addVar(vd1);
 1596  1 md1.addVar(vd2);
 1597   
 1598  1 vars = new LinkedList<VariableData>();
 1599  1 vars.addLast(vd1);
 1600  1 vars.addLast(vd2);
 1601  1 _bbtc = new BodyTypeChecker(md1, _bbtc._file, _bbtc._package, _bbtc._importedFiles, _bbtc._importedPackages, vars, new LinkedList<Pair<SymbolData, JExpression>>());
 1602  1 _bbtc._bodyData = md1;
 1603  1 _bbtc._data = md1;
 1604  1 _bbtc._bodyData.addBlock(new BlockData(_bbtc._bodyData));
 1605   
 1606  1 ift.visit(_bbtc);
 1607  1 assertTrue("vd1 should be assigned", vd1.hasValue());
 1608  1 assertTrue("vd2 should also be assigned", vd2.hasValue());
 1609   
 1610   
 1611    //test that if a variable is assigned in a branch of the if, and then returned, it is okay.
 1612  1 te = new LessThanExpression(SourceInfo.NONE, new SimpleNameReference(SourceInfo.NONE, new Word(SourceInfo.NONE, "j")),
 1613    new IntegerLiteral(SourceInfo.NONE, 5));
 1614  1 assignStatement = new ExpressionStatement(SourceInfo.NONE, new SimpleAssignmentExpression(SourceInfo.NONE, new SimpleNameReference(SourceInfo.NONE, new Word(SourceInfo.NONE, "i")), new IntegerLiteral(SourceInfo.NONE, 10)));
 1615  1 Statement returnStatement = new ValueReturnStatement(SourceInfo.NONE, new SimpleNameReference(SourceInfo.NONE, new Word(SourceInfo.NONE, "i")));
 1616  1 ts = new Block(SourceInfo.NONE, new BracedBody(SourceInfo.NONE, new BodyItemI[] {assignStatement, returnStatement}));
 1617  1 ift = new IfThenElseStatement(SourceInfo.NONE, te, ts, new EmptyStatement(SourceInfo.NONE));
 1618   
 1619  1 bb = new BracedBody(SourceInfo.NONE, new BodyItemI[] {new VariableDeclaration(SourceInfo.NONE, _packageMav, new UninitializedVariableDeclarator[]{uvd}), ift});
 1620   
 1621  1 cmd1 = new ConcreteMethodDef(SourceInfo.NONE, _publicMav, new TypeParameter[0],
 1622    intt, new Word(SourceInfo.NONE, "myMethod"), new FormalParameter[] {param},
 1623    new ReferenceType[0], bb);
 1624   
 1625  1 vd1 = new VariableData("j", _packageMav, SymbolData.INT_TYPE, true, null);
 1626  1 vd2 = new VariableData("i", _packageMav, SymbolData.INT_TYPE, false, null);
 1627  1 md1 = new MethodData("myMethod", _publicMav, new TypeParameter[0], SymbolData.INT_TYPE,
 1628    new VariableData[] {vd1}, new String[0], _sd1, cmd1);
 1629   
 1630  1 vd1.setEnclosingData(md1);
 1631  1 vd2.setEnclosingData(md1);
 1632   
 1633  1 md1.addVar(vd1);
 1634  1 md1.addVar(vd2);
 1635   
 1636  1 vars = new LinkedList<VariableData>();
 1637  1 vars.addLast(vd1);
 1638  1 vars.addLast(vd2);
 1639  1 _bbtc = new BodyTypeChecker(md1, _bbtc._file, _bbtc._package, _bbtc._importedFiles, _bbtc._importedPackages, vars, new LinkedList<Pair<SymbolData, JExpression>>());
 1640  1 _bbtc._bodyData = md1;
 1641  1 _bbtc._data = md1;
 1642  1 _bbtc._bodyData.addBlock(new BlockData(_bbtc._bodyData));
 1643   
 1644   
 1645  1 ift.visit(_bbtc);
 1646  1 assertTrue("vd1 should be assigned", vd1.hasValue());
 1647  1 assertFalse("vd2 should not be assigned", vd2.hasValue());
 1648  1 assertEquals("There should be no errors", 0, errors.size());
 1649  1 errors = new LinkedList<Pair<String, JExpressionIF>>();
 1650   
 1651   
 1652    //test that if a variable is assigned in the then case that it cannot be used in the else case.
 1653  1 te = new LessThanExpression(SourceInfo.NONE, new SimpleNameReference(SourceInfo.NONE, new Word(SourceInfo.NONE, "j")),
 1654    new IntegerLiteral(SourceInfo.NONE, 5));
 1655  1 assignStatement = new ExpressionStatement(SourceInfo.NONE, new SimpleAssignmentExpression(SourceInfo.NONE, new SimpleNameReference(SourceInfo.NONE, new Word(SourceInfo.NONE, "i")), new IntegerLiteral(SourceInfo.NONE, 10)));
 1656  1 ts = new Block(SourceInfo.NONE, new BracedBody(SourceInfo.NONE, new BodyItemI[] {assignStatement}));
 1657  1 ift = new IfThenElseStatement(SourceInfo.NONE, te, ts, new ExpressionStatement(SourceInfo.NONE, new EqualsExpression(SourceInfo.NONE, new SimpleNameReference(SourceInfo.NONE, new Word (SourceInfo.NONE, "i")), new IntegerLiteral(SourceInfo.NONE, 32))));
 1658   
 1659  1 bb = new BracedBody(SourceInfo.NONE, new BodyItemI[] {new VariableDeclaration(SourceInfo.NONE, _packageMav, new UninitializedVariableDeclarator[]{uvd}), ift});
 1660   
 1661  1 cmd1 = new ConcreteMethodDef(SourceInfo.NONE, _publicMav, new TypeParameter[0],
 1662    intt, new Word(SourceInfo.NONE, "myMethod"), new FormalParameter[] {param},
 1663    new ReferenceType[0], bb);
 1664   
 1665  1 vd1 = new VariableData("j", _packageMav, SymbolData.INT_TYPE, true, null);
 1666  1 vd2 = new VariableData("i", _packageMav, SymbolData.INT_TYPE, false, null);
 1667  1 md1 = new MethodData("myMethod", _publicMav, new TypeParameter[0], SymbolData.INT_TYPE,
 1668    new VariableData[] {vd1}, new String[0], _sd1, cmd1);
 1669   
 1670  1 vd1.setEnclosingData(md1);
 1671  1 vd2.setEnclosingData(md1);
 1672   
 1673  1 md1.addVar(vd1);
 1674  1 md1.addVar(vd2);
 1675   
 1676  1 vars = new LinkedList<VariableData>();
 1677  1 vars.addLast(vd1);
 1678  1 vars.addLast(vd2);
 1679  1 _bbtc = new BodyTypeChecker(md1, _bbtc._file, _bbtc._package, _bbtc._importedFiles, _bbtc._importedPackages, vars, new LinkedList<Pair<SymbolData, JExpression>>());
 1680  1 _bbtc._bodyData = md1;
 1681  1 _bbtc._data = md1;
 1682  1 _bbtc._bodyData.addBlock(new BlockData(_bbtc._bodyData));
 1683   
 1684   
 1685  1 ift.visit(_bbtc);
 1686  1 assertTrue("vd1 should be assigned", vd1.hasValue());
 1687  1 assertFalse("vd2 should not be assigned", vd2.hasValue());
 1688  1 assertEquals("There should be one error", 1, errors.size());
 1689  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());
 1690   
 1691    //test that if a variable is assigned in both cases that it is assigned afterwards
 1692  1 te = new LessThanExpression(SourceInfo.NONE, new SimpleNameReference(SourceInfo.NONE, new Word(SourceInfo.NONE, "j")),
 1693    new IntegerLiteral(SourceInfo.NONE, 5));
 1694  1 assignStatement = new ExpressionStatement(SourceInfo.NONE, new SimpleAssignmentExpression(SourceInfo.NONE, new SimpleNameReference(SourceInfo.NONE, new Word(SourceInfo.NONE, "i")), new IntegerLiteral(SourceInfo.NONE, 10)));
 1695  1 ts = new Block(SourceInfo.NONE, new BracedBody(SourceInfo.NONE, new BodyItemI[] {assignStatement}));
 1696  1 ift = new IfThenElseStatement(SourceInfo.NONE, te, ts, ts);
 1697   
 1698  1 bb = new BracedBody(SourceInfo.NONE, new BodyItemI[] {new VariableDeclaration(SourceInfo.NONE, _packageMav, new UninitializedVariableDeclarator[]{uvd}), ift});
 1699   
 1700  1 cmd1 = new ConcreteMethodDef(SourceInfo.NONE, _publicMav, new TypeParameter[0],
 1701    intt, new Word(SourceInfo.NONE, "myMethod"), new FormalParameter[] {param},
 1702    new ReferenceType[0], bb);
 1703   
 1704  1 vd1 = new VariableData("j", _packageMav, SymbolData.INT_TYPE, true, null);
 1705  1 vd2 = new VariableData("i", _packageMav, SymbolData.INT_TYPE, false, null);
 1706  1 md1 = new MethodData("myMethod", _publicMav, new TypeParameter[0], SymbolData.INT_TYPE,
 1707    new VariableData[] {vd1}, new String[0], _sd1, cmd1);
 1708   
 1709  1 vd1.setEnclosingData(md1);
 1710  1 vd2.setEnclosingData(md1);
 1711   
 1712  1 md1.addVar(vd1);
 1713  1 md1.addVar(vd2);
 1714   
 1715  1 vars = new LinkedList<VariableData>();
 1716  1 vars.addLast(vd1);
 1717  1 vars.addLast(vd2);
 1718  1 _bbtc = new BodyTypeChecker(md1, _bbtc._file, _bbtc._package, _bbtc._importedFiles, _bbtc._importedPackages, vars, new LinkedList<Pair<SymbolData, JExpression>>());
 1719  1 _bbtc._bodyData = md1;
 1720  1 _bbtc._data = md1;
 1721  1 _bbtc._bodyData.addBlock(new BlockData(_bbtc._bodyData));
 1722  1 _bbtc._bodyData.addBlock(new BlockData(_bbtc._bodyData));
 1723   
 1724   
 1725  1 ift.visit(_bbtc);
 1726  1 assertTrue("vd1 should be assigned", vd1.hasValue());
 1727  1 assertTrue("vd2 should be assigned", vd2.hasValue());
 1728  1 assertEquals("There should be one error", 1, errors.size());
 1729   
 1730   
 1731    //Test that if assignment is used in the conditional expression, an error is thrown
 1732  1 te = new PlusAssignmentExpression(SourceInfo.NONE, new SimpleNameReference(SourceInfo.NONE, new Word(SourceInfo.NONE, "i")), new IntegerLiteral(SourceInfo.NONE, 5));
 1733  1 assignStatement = new ExpressionStatement(SourceInfo.NONE, new SimpleAssignmentExpression(SourceInfo.NONE, new SimpleNameReference(SourceInfo.NONE, new Word(SourceInfo.NONE, "i")), new IntegerLiteral(SourceInfo.NONE, 10)));
 1734  1 ts = new Block(SourceInfo.NONE, new BracedBody(SourceInfo.NONE, new BodyItemI[] {assignStatement}));
 1735  1 ift = new IfThenElseStatement(SourceInfo.NONE, te, new EmptyStatement(SourceInfo.NONE), ts);
 1736   
 1737  1 bb = new BracedBody(SourceInfo.NONE, new BodyItemI[] {new VariableDeclaration(SourceInfo.NONE, _packageMav, new UninitializedVariableDeclarator[]{uvd}), ift});
 1738   
 1739  1 cmd1 = new ConcreteMethodDef(SourceInfo.NONE, _publicMav, new TypeParameter[0],
 1740    intt, new Word(SourceInfo.NONE, "myMethod"), new FormalParameter[] {param},
 1741    new ReferenceType[0], bb);
 1742   
 1743  1 vd1 = new VariableData("j", _packageMav, SymbolData.INT_TYPE, true, null);
 1744  1 vd2 = new VariableData("i", _packageMav, SymbolData.INT_TYPE, true, null);
 1745  1 md1 = new MethodData("myMethod", _publicMav, new TypeParameter[0], SymbolData.INT_TYPE,
 1746    new VariableData[] {vd1}, new String[0], _sd1, cmd1);
 1747   
 1748  1 vd1.setEnclosingData(md1);
 1749  1 vd2.setEnclosingData(md1);
 1750   
 1751  1 md1.addVar(vd1);
 1752  1 md1.addVar(vd2);
 1753   
 1754  1 vars = new LinkedList<VariableData>();
 1755  1 vars.addLast(vd1);
 1756  1 vars.addLast(vd2);
 1757  1 _bbtc = new BodyTypeChecker(md1, _bbtc._file, _bbtc._package, _bbtc._importedFiles, _bbtc._importedPackages, vars, new LinkedList<Pair<SymbolData, JExpression>>());
 1758  1 _bbtc._bodyData = md1;
 1759  1 _bbtc._data = md1;
 1760  1 _bbtc._bodyData.addBlock(new BlockData(_bbtc._bodyData));
 1761   
 1762   
 1763  1 ift.visit(_bbtc);
 1764  1 assertEquals("There should now be two errors", 2, errors.size());
 1765  1 assertEquals("The error message should be correct", "You cannot use an assignment expression in the conditional expression of an if-then-else statement at any language level", errors.get(1).getFirst());
 1766   
 1767    //test that if one branch returns a value but the other is a break or continue that SymbolData.NOT_FOUND is returned.
 1768  1 te = new LessThanExpression(SourceInfo.NONE, new SimpleNameReference(SourceInfo.NONE, new Word(SourceInfo.NONE, "j")),
 1769    new IntegerLiteral(SourceInfo.NONE, 5));
 1770  1 returnStatement = new ValueReturnStatement(SourceInfo.NONE, new SimpleNameReference(SourceInfo.NONE, new Word(SourceInfo.NONE, "i")));
 1771  1 ts = new Block(SourceInfo.NONE, new BracedBody(SourceInfo.NONE, new BodyItemI[] {returnStatement}));
 1772  1 BreakStatement bs = new UnlabeledBreakStatement(SourceInfo.NONE);
 1773  1 ift = new IfThenElseStatement(SourceInfo.NONE, te, ts, bs);
 1774   
 1775  1 bb = new BracedBody(SourceInfo.NONE, new BodyItemI[] {new VariableDeclaration(SourceInfo.NONE, _packageMav, new UninitializedVariableDeclarator[]{uvd}), ift});
 1776   
 1777  1 cmd1 = new ConcreteMethodDef(SourceInfo.NONE, _publicMav, new TypeParameter[0],
 1778    intt, new Word(SourceInfo.NONE, "myMethod"), new FormalParameter[] {param},
 1779    new ReferenceType[0], bb);
 1780   
 1781  1 vd1 = new VariableData("j", _packageMav, SymbolData.INT_TYPE, true, null);
 1782  1 vd2 = new VariableData("i", _packageMav, SymbolData.INT_TYPE, true, null);
 1783  1 md1 = new MethodData("myMethod", _publicMav, new TypeParameter[0], SymbolData.INT_TYPE,
 1784    new VariableData[] {vd1}, new String[0], _sd1, cmd1);
 1785   
 1786  1 vd1.setEnclosingData(md1);
 1787  1 vd2.setEnclosingData(md1);
 1788   
 1789  1 md1.addVar(vd1);
 1790  1 md1.addVar(vd2);
 1791   
 1792  1 vars = new LinkedList<VariableData>();
 1793  1 vars.addLast(vd1);
 1794  1 vars.addLast(vd2);
 1795  1 _bbtc = new BodyTypeChecker(md1, _bbtc._file, _bbtc._package, _bbtc._importedFiles, _bbtc._importedPackages, vars, new LinkedList<Pair<SymbolData, JExpression>>());
 1796  1 _bbtc._bodyData = md1;
 1797  1 _bbtc._data = md1;
 1798  1 _bbtc._bodyData.addBlock(new BlockData(_bbtc._bodyData));
 1799   
 1800  1 assertEquals("Should return SymbolData.NOT_FOUND", SymbolData.NOT_FOUND.getInstanceData(), ift.visit(_bbtc));
 1801   
 1802  1 assertEquals("There should still be two errors", 2, errors.size());
 1803    }
 1804   
 1805  1 public void testForForStatement() {
 1806    //Test that the proper variable assignment happens.
 1807    //here, a variable is only assigned in the for init, so it should not be set after it returns.
 1808  1 Expression te = new LessThanExpression(SourceInfo.NONE, new SimpleNameReference(SourceInfo.NONE, new Word(SourceInfo.NONE, "j")),
 1809    new IntegerLiteral(SourceInfo.NONE, 5));
 1810   
 1811  1 UnparenthesizedExpressionList sel = new UnparenthesizedExpressionList(SourceInfo.NONE, new Expression[] {new SimpleAssignmentExpression(SourceInfo.NONE, new SimpleNameReference(SourceInfo.NONE, new Word(SourceInfo.NONE, "i")), new IntegerLiteral(SourceInfo.NONE, 10))});
 1812  1 ForStatement fs = new ForStatement(SourceInfo.NONE, sel, te, new UnparenthesizedExpressionList(SourceInfo.NONE, new Expression[0]), new EmptyStatement(SourceInfo.NONE));
 1813    // IfThenElseStatement ift = new IfThenElseStatement(SourceInfo.NONE, te, ts, new EmptyStatement(SourceInfo.NONE));
 1814   
 1815  1 PrimitiveType intt = new PrimitiveType(SourceInfo.NONE, "int");
 1816  1 UninitializedVariableDeclarator uvd = new UninitializedVariableDeclarator(SourceInfo.NONE, intt, new Word(SourceInfo.NONE, "i"));
 1817  1 FormalParameter param = new FormalParameter(SourceInfo.NONE, new UninitializedVariableDeclarator(SourceInfo.NONE, intt, new Word(SourceInfo.NONE, "j")), false);
 1818  1 BracedBody bb = new BracedBody(SourceInfo.NONE, new BodyItemI[] {new VariableDeclaration(SourceInfo.NONE, _packageMav, new UninitializedVariableDeclarator[]{uvd}), fs});
 1819   
 1820  1 ConcreteMethodDef cmd1 = new ConcreteMethodDef(SourceInfo.NONE, _publicMav, new TypeParameter[0],
 1821    intt, new Word(SourceInfo.NONE, "myMethod"), new FormalParameter[] {param},
 1822    new ReferenceType[0], bb);
 1823   
 1824  1 VariableData vd1 = new VariableData("j", _packageMav, SymbolData.INT_TYPE, true, null);
 1825  1 VariableData vd2 = new VariableData("i", _packageMav, SymbolData.INT_TYPE, false, null);
 1826  1 MethodData md1 = new MethodData("myMethod", _publicMav, new TypeParameter[0], SymbolData.INT_TYPE,
 1827    new VariableData[] {vd1}, new String[0], _sd1, cmd1);
 1828   
 1829  1 vd1.setEnclosingData(md1);
 1830  1 vd2.setEnclosingData(md1);
 1831   
 1832  1 md1.addVar(vd1);
 1833  1 md1.addVar(vd2);
 1834   
 1835  1 LinkedList<VariableData> vars = new LinkedList<VariableData>();
 1836  1 vars.addLast(vd1);
 1837  1 vars.addLast(vd2);
 1838  1 _bbtc = new BodyTypeChecker(md1, _bbtc._file, _bbtc._package, _bbtc._importedFiles, _bbtc._importedPackages, vars, new LinkedList<Pair<SymbolData, JExpression>>());
 1839  1 _bbtc._bodyData = md1;
 1840  1 _bbtc._data = md1;
 1841   
 1842  1 fs.visit(_bbtc);
 1843  1 assertTrue("vd1 should be assigned", vd1.hasValue());
 1844  1 assertFalse("vd2 should not be assigned", vd2.hasValue());
 1845  1 assertEquals("There should be no errors", 0, errors.size());
 1846   
 1847    //test that if a variable is testForForStdeclared in the for init that it has a value in the scope of the for statement, but not afterwards
 1848  1 te = new LessThanExpression(SourceInfo.NONE, new SimpleNameReference(SourceInfo.NONE, new Word(SourceInfo.NONE, "j")),
 1849    new IntegerLiteral(SourceInfo.NONE, 5));
 1850  1 VariableDeclaration vd = new VariableDeclaration (SourceInfo.NONE, _publicMav, new VariableDeclarator[] { new InitializedVariableDeclarator(SourceInfo.NONE, new PrimitiveType(SourceInfo.NONE, "int"), new Word(SourceInfo.NONE, "i"), new IntegerLiteral(SourceInfo.NONE, 10))});
 1851  1 UnparenthesizedExpressionList sel2 = new UnparenthesizedExpressionList(SourceInfo.NONE, new Expression[] {te});
 1852  1 fs = new ForStatement(SourceInfo.NONE, sel, te, sel2, new ExpressionStatement(SourceInfo.NONE, te));
 1853   
 1854  1 bb = new BracedBody(SourceInfo.NONE, new BodyItemI[] {fs});
 1855   
 1856  1 cmd1 = new ConcreteMethodDef(SourceInfo.NONE, _publicMav, new TypeParameter[0],
 1857    intt, new Word(SourceInfo.NONE, "myMethod"), new FormalParameter[] {param},
 1858    new ReferenceType[0], bb);
 1859   
 1860  1 vd1 = new VariableData("j", _packageMav, SymbolData.INT_TYPE, true, null);
 1861  1 vd2 = new VariableData("i", _packageMav, SymbolData.INT_TYPE, false, null);
 1862  1 md1 = new MethodData("myMethod", _publicMav, new TypeParameter[0], SymbolData.INT_TYPE,
 1863    new VariableData[] {vd1}, new String[0], _sd1, cmd1);
 1864   
 1865  1 vd1.setEnclosingData(md1);
 1866  1 vd2.setEnclosingData(md1);
 1867   
 1868  1 md1.addVar(vd1);
 1869  1 md1.addVar(vd2);
 1870   
 1871  1 vars = new LinkedList<VariableData>();
 1872  1 vars.addLast(vd1);
 1873  1 vars.addLast(vd2);
 1874  1 _bbtc = new BodyTypeChecker(md1, _bbtc._file, _bbtc._package, _bbtc._importedFiles, _bbtc._importedPackages, vars, new LinkedList<Pair<SymbolData, JExpression>>());
 1875  1 _bbtc._bodyData = md1;
 1876  1 _bbtc._data = md1;
 1877   
 1878  1 fs.visit(_bbtc);
 1879  1 assertTrue("vd1 should be assigned", vd1.hasValue());
 1880  1 assertFalse("vd2 should not be assigned", vd2.hasValue());
 1881  1 assertEquals("There should be no errors", 0, errors.size());
 1882   
 1883    //here, a variable is only assigned in the for init and the for body, so it should not be set after it returns.
 1884  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)));
 1885    // te = new Expression(SourceInfo.NONE, new ExpressionPiece[] { new Word(SourceInfo.NONE, "j"),
 1886    // new Operator(SourceInfo.NONE, "<"), new IntegerLiteral(SourceInfo.NONE, 5)});
 1887  1 sel = new UnparenthesizedExpressionList(SourceInfo.NONE, new Expression[] {new SimpleAssignmentExpression(SourceInfo.NONE, new SimpleNameReference(SourceInfo.NONE, new Word(SourceInfo.NONE, "i")), new IntegerLiteral(SourceInfo.NONE, 10))});
 1888  1 fs = new ForStatement(SourceInfo.NONE, sel, new EmptyForCondition(SourceInfo.NONE), new UnparenthesizedExpressionList(SourceInfo.NONE, new Expression[0]), new Block(SourceInfo.NONE, new BracedBody(SourceInfo.NONE, new BodyItemI[] {ts})));
 1889    // IfThenElseStatement ift = new IfThenElseStatement(SourceInfo.NONE, te, ts, new EmptyStatement(SourceInfo.NONE));
 1890   
 1891  1 bb = new BracedBody(SourceInfo.NONE, new BodyItemI[] {new VariableDeclaration(SourceInfo.NONE, _packageMav, new UninitializedVariableDeclarator[]{uvd}), fs});
 1892   
 1893  1 cmd1 = new ConcreteMethodDef(SourceInfo.NONE, _publicMav, new TypeParameter[0],
 1894    intt, new Word(SourceInfo.NONE, "myMethod"), new FormalParameter[] {param},
 1895    new ReferenceType[0], bb);
 1896   
 1897  1 vd1 = new VariableData("j", _packageMav, SymbolData.INT_TYPE, true, null);
 1898  1 vd2 = new VariableData("i", _packageMav, SymbolData.INT_TYPE, false, null);
 1899  1 md1 = new MethodData("myMethod", _publicMav, new TypeParameter[0], SymbolData.INT_TYPE,
 1900    new VariableData[] {vd1}, new String[0], _sd1, cmd1);
 1901   
 1902  1 vd1.setEnclosingData(md1);
 1903  1 vd2.setEnclosingData(md1);
 1904   
 1905  1 md1.addVar(vd1);
 1906  1 md1.addVar(vd2);
 1907   
 1908  1 vars = new LinkedList<VariableData>();
 1909  1 vars.addLast(vd1);
 1910  1 vars.addLast(vd2);
 1911  1 _bbtc = new BodyTypeChecker(md1, _bbtc._file, _bbtc._package, _bbtc._importedFiles, _bbtc._importedPackages, vars, new LinkedList<Pair<SymbolData, JExpression>>());
 1912  1 _bbtc._bodyData = md1;
 1913  1 _bbtc._data = md1;
 1914  1 _bbtc._bodyData.addBlock(new BlockData(_bbtc._bodyData));
 1915   
 1916  1 fs.visit(_bbtc);
 1917  1 assertTrue("vd1 should be assigned", vd1.hasValue());
 1918  1 assertFalse("vd2 should not be assigned", vd2.hasValue());
 1919  1 assertEquals("There should be no errors", 0, errors.size());
 1920   
 1921    //here, a variable is assigned before the for init, so it should still be set after it returns.
 1922    // te = new Expression(SourceInfo.NONE, new ExpressionPiece[] { new Word(SourceInfo.NONE, "j"),
 1923    // new Operator(SourceInfo.NONE, "<"), new IntegerLiteral(SourceInfo.NONE, 5)});
 1924  1 sel = new UnparenthesizedExpressionList(SourceInfo.NONE, new Expression[] {new SimpleAssignmentExpression(SourceInfo.NONE, new SimpleNameReference(SourceInfo.NONE, new Word(SourceInfo.NONE, "i")), new IntegerLiteral(SourceInfo.NONE, 10))});
 1925  1 fs = new ForStatement(SourceInfo.NONE, sel, new EmptyForCondition(SourceInfo.NONE), new UnparenthesizedExpressionList(SourceInfo.NONE, new Expression[0]), new EmptyStatement(SourceInfo.NONE));
 1926    // IfThenElseStatement ift = new IfThenElseStatement(SourceInfo.NONE, te, ts, new EmptyStatement(SourceInfo.NONE));
 1927   
 1928  1 bb = new BracedBody(SourceInfo.NONE, new BodyItemI[] {new VariableDeclaration(SourceInfo.NONE, _packageMav, new UninitializedVariableDeclarator[]{uvd}), fs});
 1929   
 1930  1 cmd1 = new ConcreteMethodDef(SourceInfo.NONE, _publicMav, new TypeParameter[0],
 1931    intt, new Word(SourceInfo.NONE, "myMethod"), new FormalParameter[] {param},
 1932    new ReferenceType[0], bb);
 1933   
 1934  1 vd1 = new VariableData("j", _packageMav, SymbolData.INT_TYPE, true, null);
 1935  1 vd2 = new VariableData("i", _packageMav, SymbolData.INT_TYPE, true, null);
 1936  1 md1 = new MethodData("myMethod", _publicMav, new TypeParameter[0], SymbolData.INT_TYPE,
 1937    new VariableData[] {vd1}, new String[0], _sd1, cmd1);
 1938   
 1939  1 vd1.setEnclosingData(md1);
 1940  1 vd2.setEnclosingData(md1);
 1941   
 1942  1 md1.addVar(vd1);
 1943  1 md1.addVar(vd2);
 1944   
 1945  1 vars = new LinkedList<VariableData>();
 1946  1 vars.addLast(vd1);
 1947  1 vars.addLast(vd2);
 1948  1 _bbtc = new BodyTypeChecker(md1, _bbtc._file, _bbtc._package, _bbtc._importedFiles, _bbtc._importedPackages, vars, new LinkedList<Pair<SymbolData, JExpression>>());
 1949  1 _bbtc._bodyData = md1;
 1950  1 _bbtc._data = md1;
 1951   
 1952  1 fs.visit(_bbtc);
 1953  1 assertTrue("vd1 should be assigned", vd1.hasValue());
 1954  1 assertTrue("vd2 should be assigned", vd2.hasValue());
 1955  1 assertEquals("Should be 0 errors", 0, errors.size());
 1956   
 1957    // make sure that assignment is not allowed in the conditional of the for statement
 1958  1 te = new PlusAssignmentExpression(SourceInfo.NONE, new SimpleNameReference(SourceInfo.NONE, new Word(SourceInfo.NONE, "j")), new IntegerLiteral(SourceInfo.NONE, 5));
 1959  1 vd = new VariableDeclaration (SourceInfo.NONE, _publicMav, new VariableDeclarator[] { new InitializedVariableDeclarator(SourceInfo.NONE, new PrimitiveType(SourceInfo.NONE, "int"), new Word(SourceInfo.NONE, "i"), new IntegerLiteral(SourceInfo.NONE, 10))});
 1960  1 sel2 = new UnparenthesizedExpressionList(SourceInfo.NONE, new Expression[] {te});
 1961  1 fs = new ForStatement(SourceInfo.NONE, sel, te, sel2, new EmptyStatement(SourceInfo.NONE));
 1962   
 1963  1 bb = new BracedBody(SourceInfo.NONE, new BodyItemI[] {fs});
 1964   
 1965  1 cmd1 = new ConcreteMethodDef(SourceInfo.NONE, _publicMav, new TypeParameter[0],
 1966    intt, new Word(SourceInfo.NONE, "myMethod"), new FormalParameter[] {param},
 1967    new ReferenceType[0], bb);
 1968   
 1969  1 vd1 = new VariableData("j", _packageMav, SymbolData.INT_TYPE, true, null);
 1970  1 vd2 = new VariableData("i", _packageMav, SymbolData.INT_TYPE, false, null);
 1971  1 md1 = new MethodData("myMethod", _publicMav, new TypeParameter[0], SymbolData.INT_TYPE,
 1972    new VariableData[] {vd1}, new String[0], _sd1, cmd1);
 1973   
 1974  1 vd1.setEnclosingData(md1);
 1975  1 vd2.setEnclosingData(md1);
 1976   
 1977  1 md1.addVar(vd1);
 1978  1 md1.addVar(vd2);
 1979   
 1980  1 vars = new LinkedList<VariableData>();
 1981  1 vars.addLast(vd1);
 1982  1 vars.addLast(vd2);
 1983  1 _bbtc = new BodyTypeChecker(md1, _bbtc._file, _bbtc._package, _bbtc._importedFiles, _bbtc._importedPackages, vars, new LinkedList<Pair<SymbolData, JExpression>>());
 1984  1 _bbtc._bodyData = md1;
 1985  1 _bbtc._data = md1;
 1986   
 1987  1 te = new PositivePrefixIncrementExpression(SourceInfo.NONE, new SimpleNameReference(SourceInfo.NONE, new Word(SourceInfo.NONE, "j")));
 1988  1 vd = new VariableDeclaration (SourceInfo.NONE, _publicMav, new VariableDeclarator[] { new InitializedVariableDeclarator(SourceInfo.NONE, new PrimitiveType(SourceInfo.NONE, "int"), new Word(SourceInfo.NONE, "i"), new IntegerLiteral(SourceInfo.NONE, 10))});
 1989  1 sel2 = new UnparenthesizedExpressionList(SourceInfo.NONE, new Expression[] {te});
 1990  1 fs = new ForStatement(SourceInfo.NONE, sel, te, sel2, new EmptyStatement(SourceInfo.NONE));
 1991   
 1992  1 fs.visit(_bbtc);
 1993  1 assertEquals("There should be 1 error", 1, errors.size());
 1994  1 assertEquals("The error message should be correct", "You cannot use an increment or decrement expression in the conditional expression of a for-statement at any language level", errors.get(0).getFirst());
 1995   
 1996   
 1997    }
 1998   
 1999  1 public void testForWhileStatement() {
 2000    //Test that a variable without a value before the while statement, that is given a value in the body of the while statement, still doesn't have a value afterwards
 2001  1 Expression te = new LessThanExpression(SourceInfo.NONE, new SimpleNameReference(SourceInfo.NONE, new Word(SourceInfo.NONE, "j")),
 2002    new IntegerLiteral(SourceInfo.NONE, 5));
 2003   
 2004   
 2005  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)));
 2006   
 2007  1 Statement ts = new Block(SourceInfo.NONE, new BracedBody(SourceInfo.NONE, new BodyItemI[] {assignStatement}));
 2008  1 WhileStatement ws = new WhileStatement(SourceInfo.NONE, te, ts);
 2009   
 2010  1 VariableData vd1 = new VariableData("j", _packageMav, SymbolData.INT_TYPE, true, null);
 2011  1 VariableData vd2 = new VariableData("i", _packageMav, SymbolData.INT_TYPE, false, null);
 2012   
 2013  1 MethodData md1 = new MethodData("myMethod", _publicMav, new TypeParameter[0], SymbolData.INT_TYPE,
 2014    new VariableData[] {vd1}, new String[0], _sd1, null);
 2015   
 2016  1 vd1.setEnclosingData(md1);
 2017  1 vd2.setEnclosingData(md1);
 2018   
 2019  1 md1.addVar(vd1);
 2020  1 md1.addVar(vd2);
 2021   
 2022  1 LinkedList<VariableData> vars = new LinkedList<VariableData>();
 2023  1 vars.addLast(vd1);
 2024  1 vars.addLast(vd2);
 2025  1 _bbtc = new BodyTypeChecker(md1, _bbtc._file, _bbtc._package, _bbtc._importedFiles, _bbtc._importedPackages, vars, new LinkedList<Pair<SymbolData, JExpression>>());
 2026  1 _bbtc._bodyData = md1;
 2027  1 _bbtc._data = md1;
 2028  1 _bbtc._bodyData.addBlock(new BlockData(_bbtc._bodyData));
 2029   
 2030   
 2031  1 ws.visit(_bbtc);
 2032  1 assertTrue("vd1 should be assigned", vd1.hasValue());
 2033  1 assertFalse("vd2 should not be assigned", vd2.hasValue());
 2034   
 2035   
 2036    //Test that a variable with a value before the while statement, that is given a value in the body of the while statement, still has a value afterwards
 2037  1 vd1 = new VariableData("j", _packageMav, SymbolData.INT_TYPE, true, null);
 2038  1 vd2 = new VariableData("i", _packageMav, SymbolData.INT_TYPE, true, null);
 2039   
 2040  1 md1 = new MethodData("myMethod", _publicMav, new TypeParameter[0], SymbolData.INT_TYPE,
 2041    new VariableData[] {vd1}, new String[0], _sd1, null);
 2042   
 2043  1 vd1.setEnclosingData(md1);
 2044  1 vd2.setEnclosingData(md1);
 2045   
 2046  1 md1.addVar(vd1);
 2047  1 md1.addVar(vd2);
 2048   
 2049  1 vars = new LinkedList<VariableData>();
 2050  1 vars.addLast(vd1);
 2051  1 vars.addLast(vd2);
 2052  1 _bbtc = new BodyTypeChecker(md1, _bbtc._file, _bbtc._package, _bbtc._importedFiles, _bbtc._importedPackages, vars, new LinkedList<Pair<SymbolData, JExpression>>());
 2053  1 _bbtc._bodyData = md1;
 2054  1 _bbtc._data = md1;
 2055  1 _bbtc._bodyData.addBlock(new BlockData(_bbtc._bodyData));
 2056   
 2057   
 2058  1 ws.visit(_bbtc);
 2059  1 assertTrue("vd1 should be assigned", vd1.hasValue());
 2060  1 assertTrue("vd2 should be assigned", vd2.hasValue());
 2061   
 2062   
 2063    //Test that assignment is not allowed in the condition expression of the while
 2064  1 te = new SimpleAssignmentExpression(SourceInfo.NONE, new SimpleNameReference(SourceInfo.NONE, new Word(SourceInfo.NONE, "i")), new IntegerLiteral(SourceInfo.NONE, 5));
 2065  1 ws = new WhileStatement(SourceInfo.NONE, te, ts);
 2066   
 2067  1 vd1 = new VariableData("j", _packageMav, SymbolData.INT_TYPE, true, null);
 2068  1 vd2 = new VariableData("i", _packageMav, SymbolData.INT_TYPE, true, null);
 2069   
 2070  1 md1 = new MethodData("myMethod", _publicMav, new TypeParameter[0], SymbolData.INT_TYPE,
 2071    new VariableData[] {vd1}, new String[0], _sd1, null);
 2072   
 2073  1 vd1.setEnclosingData(md1);
 2074  1 vd2.setEnclosingData(md1);
 2075   
 2076  1 md1.addVar(vd1);
 2077  1 md1.addVar(vd2);
 2078   
 2079  1 vars = new LinkedList<VariableData>();
 2080  1 vars.addLast(vd1);
 2081  1 vars.addLast(vd2);
 2082  1 _bbtc = new BodyTypeChecker(md1, _bbtc._file, _bbtc._package, _bbtc._importedFiles, _bbtc._importedPackages, vars, new LinkedList<Pair<SymbolData, JExpression>>());
 2083  1 _bbtc._bodyData = md1;
 2084  1 _bbtc._data = md1;
 2085  1 _bbtc._bodyData.addBlock(new BlockData(_bbtc._bodyData));
 2086   
 2087   
 2088  1 ws.visit(_bbtc);
 2089  1 assertEquals("There should be 1 error", 1, errors.size());
 2090  1 assertEquals("The error message should be correct", "You cannot use an assignment expression in the condition expression of a while statement at any language level. Perhaps you meant to compare two values with '=='", errors.get(0).getFirst());
 2091   
 2092   
 2093   
 2094    }
 2095   
 2096  1 public void testForWhileStatementOnly() {
 2097    //Test that a boolean condition expression results in no error
 2098  1 Expression te = new LessThanExpression(SourceInfo.NONE, new SimpleNameReference(SourceInfo.NONE, new Word(SourceInfo.NONE, "j")),
 2099    new IntegerLiteral(SourceInfo.NONE, 5));
 2100   
 2101   
 2102  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)));
 2103   
 2104  1 Statement ts = new Block(SourceInfo.NONE, new BracedBody(SourceInfo.NONE, new BodyItemI[] {assignStatement}));
 2105  1 WhileStatement ws = new WhileStatement(SourceInfo.NONE, te, ts);
 2106  1 _bbtc._bodyData.addBlock(new BlockData(_bbtc._bodyData));
 2107   
 2108  1 assertEquals("Should return null", null, _bbtc.forWhileStatementOnly(ws, SymbolData.BOOLEAN_TYPE.getInstanceData(), SymbolData.INT_TYPE.getInstanceData()));
 2109  1 assertEquals("There should be no errors", 0, errors.size());
 2110   
 2111    //Test that a non-boolean condition expression throws an error
 2112  1 assertEquals("Should return null", null, _bbtc.forWhileStatementOnly(ws, SymbolData.INT_TYPE.getInstanceData(), SymbolData.DOUBLE_TYPE.getInstanceData()));
 2113  1 assertEquals("There should be 1 error", 1, errors.size());
 2114  1 assertEquals("Error message should be correct", "This while-statement's conditional expression must be a boolean value. Instead, its type is int", errors.get(0).getFirst());
 2115   
 2116    //Test "boolean" as a condition
 2117  1 assertEquals("Should return null", null, _bbtc.forWhileStatementOnly(ws, SymbolData.BOOLEAN_TYPE, SymbolData.DOUBLE_TYPE.getInstanceData()));
 2118  1 assertEquals("There should be 2 error", 2, errors.size());
 2119  1 assertEquals("Error message should be correct", "This while-statement's conditional expression must be a boolean value. Instead, it is a class or interface name", errors.getLast().getFirst());
 2120    }
 2121   
 2122  1 public void testForForStatementOnly() {
 2123   
 2124  1 Expression te = new LessThanExpression(SourceInfo.NONE, new SimpleNameReference(SourceInfo.NONE, new Word(SourceInfo.NONE, "j")),
 2125    new IntegerLiteral(SourceInfo.NONE, 5));
 2126   
 2127  1 UnparenthesizedExpressionList sel = new UnparenthesizedExpressionList(SourceInfo.NONE, new Expression[] {new SimpleAssignmentExpression(SourceInfo.NONE, new SimpleNameReference(SourceInfo.NONE, new Word(SourceInfo.NONE, "i")), new IntegerLiteral(SourceInfo.NONE, 10))});
 2128  1 ForStatement fs = new ForStatement(SourceInfo.NONE, sel, new NullLiteral(SourceInfo.NONE), new UnparenthesizedExpressionList(SourceInfo.NONE, new Expression[0]), new EmptyStatement(SourceInfo.NONE));
 2129   
 2130   
 2131    //Test that a boolean condition results in no error
 2132  1 assertEquals("Should return null", null, _bbtc.forForStatementOnly(fs, SymbolData.INT_TYPE, SymbolData.BOOLEAN_TYPE.getInstanceData(), SymbolData.INT_TYPE, SymbolData.INT_TYPE));
 2133  1 assertEquals("There should be no errors", 0, errors.size());
 2134   
 2135   
 2136    //Test that a non-boolean condition expression throws an error
 2137  1 assertEquals("Should return null", null, _bbtc.forForStatementOnly(fs, SymbolData.INT_TYPE, SymbolData.DOUBLE_TYPE.getInstanceData(), SymbolData.INT_TYPE, SymbolData.CHAR_TYPE));
 2138  1 assertEquals("Should be 1 error", 1, errors.size());
 2139  1 assertEquals("The error message should be correct", "This for-statement's conditional expression must be a boolean value. Instead, its type is double", errors.get(0).getFirst());
 2140   
 2141    //Test "boolean" as the condition
 2142  1 assertEquals("Should return null", null, _bbtc.forForStatementOnly(fs, SymbolData.INT_TYPE, SymbolData.BOOLEAN_TYPE, SymbolData.INT_TYPE, SymbolData.CHAR_TYPE));
 2143  1 assertEquals("Should be 2 error", 2, errors.size());
 2144  1 assertEquals("The error message should be correct", "This for-statement's conditional expression must be a boolean value. Instead, it is a class or interface name", errors.getLast().getFirst());
 2145    }
 2146   
 2147  1 public void testForDoStatement() {
 2148    //Test that a variable without a value before the do statement, that is given a value in the body of the while statement, still doesn't have a value afterwards
 2149  1 Expression te = new LessThanExpression(SourceInfo.NONE, new SimpleNameReference(SourceInfo.NONE, new Word(SourceInfo.NONE, "j")),
 2150    new IntegerLiteral(SourceInfo.NONE, 5));
 2151   
 2152   
 2153  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)));
 2154   
 2155  1 Statement ts = new Block(SourceInfo.NONE, new BracedBody(SourceInfo.NONE, new BodyItemI[] {assignStatement}));
 2156  1 DoStatement ds = new DoStatement(SourceInfo.NONE, ts, te);
 2157   
 2158  1 VariableData vd1 = new VariableData("j", _packageMav, SymbolData.INT_TYPE, true, null);
 2159  1 VariableData vd2 = new VariableData("i", _packageMav, SymbolData.INT_TYPE, false, null);
 2160   
 2161  1 MethodData md1 = new MethodData("myMethod", _publicMav, new TypeParameter[0], SymbolData.INT_TYPE,
 2162    new VariableData[] {vd1}, new String[0], _sd1, null);
 2163   
 2164  1 vd1.setEnclosingData(md1);
 2165  1 vd2.setEnclosingData(md1);
 2166   
 2167  1 md1.addVar(vd1);
 2168  1 md1.addVar(vd2);
 2169   
 2170  1 LinkedList<VariableData> vars = new LinkedList<VariableData>();
 2171  1 vars.addLast(vd1);
 2172  1 vars.addLast(vd2);
 2173  1 _bbtc = new BodyTypeChecker(md1, _bbtc._file, _bbtc._package, _bbtc._importedFiles, _bbtc._importedPackages, vars, new LinkedList<Pair<SymbolData, JExpression>>());
 2174  1 _bbtc._bodyData = md1;
 2175  1 _bbtc._data = md1;
 2176  1 _bbtc._bodyData.addBlock(new BlockData(_bbtc._bodyData));
 2177   
 2178   
 2179  1 ds.visit(_bbtc);
 2180  1 assertTrue("vd1 should be assigned", vd1.hasValue());
 2181  1 assertFalse("vd2 should not be assigned", vd2.hasValue());
 2182   
 2183   
 2184    //Test that a variable with a value before the do statement, that is given a value in the body of the do statement, still has a value afterwards
 2185  1 vd1 = new VariableData("j", _packageMav, SymbolData.INT_TYPE, true, null);
 2186  1 vd2 = new VariableData("i", _packageMav, SymbolData.INT_TYPE, true, null);
 2187   
 2188  1 md1 = new MethodData("myMethod", _publicMav, new TypeParameter[0], SymbolData.INT_TYPE,
 2189    new VariableData[] {vd1}, new String[0], _sd1, null);
 2190   
 2191  1 vd1.setEnclosingData(md1);
 2192  1 vd2.setEnclosingData(md1);
 2193   
 2194  1 md1.addVar(vd1);
 2195  1 md1.addVar(vd2);
 2196   
 2197  1 vars = new LinkedList<VariableData>();
 2198  1 vars.addLast(vd1);
 2199  1 vars.addLast(vd2);
 2200  1 _bbtc = new BodyTypeChecker(md1, _bbtc._file, _bbtc._package, _bbtc._importedFiles, _bbtc._importedPackages, vars, new LinkedList<Pair<SymbolData, JExpression>>());
 2201  1 _bbtc._bodyData = md1;
 2202  1 _bbtc._data = md1;
 2203  1 _bbtc._bodyData.addBlock(new BlockData(_bbtc._bodyData));
 2204   
 2205   
 2206  1 ds.visit(_bbtc);
 2207  1 assertTrue("vd1 should be assigned", vd1.hasValue());
 2208  1 assertTrue("vd2 should be assigned", vd2.hasValue());
 2209   
 2210   
 2211    //Test that assignment is not allowed in the condition expression of the do
 2212  1 te = new PlusAssignmentExpression(SourceInfo.NONE, new SimpleNameReference(SourceInfo.NONE, new Word(SourceInfo.NONE, "i")), new IntegerLiteral(SourceInfo.NONE, 5));
 2213  1 ds = new DoStatement(SourceInfo.NONE, ts, te);
 2214   
 2215  1 vd1 = new VariableData("j", _packageMav, SymbolData.INT_TYPE, true, null);
 2216  1 vd2 = new VariableData("i", _packageMav, SymbolData.INT_TYPE, true, null);
 2217   
 2218  1 md1 = new MethodData("myMethod", _publicMav, new TypeParameter[0], SymbolData.INT_TYPE,
 2219    new VariableData[] {vd1}, new String[0], _sd1, null);
 2220   
 2221  1 vd1.setEnclosingData(md1);
 2222  1 vd2.setEnclosingData(md1);
 2223   
 2224  1 md1.addVar(vd1);
 2225  1 md1.addVar(vd2);
 2226   
 2227  1 vars = new LinkedList<VariableData>();
 2228  1 vars.addLast(vd1);
 2229  1 vars.addLast(vd2);
 2230  1 _bbtc = new BodyTypeChecker(md1, _bbtc._file, _bbtc._package, _bbtc._importedFiles, _bbtc._importedPackages, vars, new LinkedList<Pair<SymbolData, JExpression>>());
 2231  1 _bbtc._bodyData = md1;
 2232  1 _bbtc._data = md1;
 2233  1 _bbtc._bodyData.addBlock(new BlockData(_bbtc._bodyData));
 2234   
 2235   
 2236  1 ds.visit(_bbtc);
 2237  1 assertEquals("There should be 1 error", 1, errors.size());
 2238  1 assertEquals("The error message should be correct", "You cannot use an assignment expression in the condition expression of a do statement at any language level", errors.get(0).getFirst());
 2239   
 2240    }
 2241   
 2242  1 public void testForDoStatementOnly() {
 2243  1 Expression te = new LessThanExpression(SourceInfo.NONE, new SimpleNameReference(SourceInfo.NONE, new Word(SourceInfo.NONE, "j")),
 2244    new IntegerLiteral(SourceInfo.NONE, 5));
 2245   
 2246   
 2247  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)));
 2248   
 2249  1 Statement ts = new Block(SourceInfo.NONE, new BracedBody(SourceInfo.NONE, new BodyItemI[] {assignStatement}));
 2250  1 DoStatement ds = new DoStatement(SourceInfo.NONE, ts, te);
 2251  1 _bbtc._bodyData.addBlock(new BlockData(_bbtc._bodyData));
 2252   
 2253    //Test that a boolean condition results in no error
 2254  1 assertEquals("Should return int", SymbolData.INT_TYPE.getInstanceData(), _bbtc.forDoStatementOnly(ds, SymbolData.INT_TYPE, SymbolData.BOOLEAN_TYPE.getInstanceData()));
 2255  1 assertEquals("There should be no errors", 0, errors.size());
 2256   
 2257    //test that a non-boolean condition expression throws an error
 2258  1 assertEquals("Should return int", SymbolData.INT_TYPE.getInstanceData(), _bbtc.forDoStatementOnly(ds, SymbolData.INT_TYPE, SymbolData.DOUBLE_TYPE.getInstanceData()));
 2259  1 assertEquals("Should be 1 error", 1, errors.size());
 2260  1 assertEquals("The error message should be correct", "This do-statement's conditional expression must be a boolean value. Instead, its type is double", errors.get(0).getFirst());
 2261   
 2262    //test "bool" as the condition
 2263  1 assertEquals("Should return double", SymbolData.DOUBLE_TYPE.getInstanceData(), _bbtc.forDoStatementOnly(ds, SymbolData.DOUBLE_TYPE.getInstanceData(), SymbolData.BOOLEAN_TYPE));
 2264  1 assertEquals("Should be 2 errors", 2, errors.size());
 2265  1 assertEquals("The error message should be correct", "This do-statement's conditional expression must be a boolean value. Instead, it is a class or interface name", errors.getLast().getFirst());
 2266    }
 2267   
 2268   
 2269  1 public void testForSwitchStatementOnly() {
 2270    //if we did not see a default block, should return null
 2271  1 SwitchStatement ss = new SwitchStatement(SourceInfo.NONE, new IntegerLiteral(SourceInfo.NONE, 1), new SwitchCase[0]);
 2272  1 assertEquals("Should return null--no default block", null, _bbtc.forSwitchStatementOnly(ss,
 2273    SymbolData.CHAR_TYPE.getInstanceData(),
 2274    new TypeData[] {SymbolData.INT_TYPE},
 2275    false));
 2276   
 2277    //if any of the blocks are NOT FOUND, should return null
 2278  1 assertEquals("Should return null--has a not-found block", null, _bbtc.forSwitchStatementOnly(ss,
 2279    SymbolData.CHAR_TYPE.getInstanceData(),
 2280    new TypeData[] {SymbolData.NOT_FOUND, SymbolData.INT_TYPE},
 2281    true));
 2282   
 2283  1 assertEquals("Should return null--has a not-found block", null, _bbtc.forSwitchStatementOnly(ss,
 2284    SymbolData.CHAR_TYPE.getInstanceData(),
 2285    new TypeData[] {SymbolData.INT_TYPE, SymbolData.NOT_FOUND},
 2286    true));
 2287   
 2288   
 2289    //if last block does not return, statement does not return
 2290  1 assertEquals("Should return null--last block is null", null, _bbtc.forSwitchStatementOnly(ss,
 2291    SymbolData.CHAR_TYPE.getInstanceData(),
 2292    new TypeData[] {SymbolData.INT_TYPE, SymbolData.CHAR_TYPE, null},
 2293    true));
 2294   
 2295   
 2296    //if all 3 conditions are false, statement does return
 2297  1 assertEquals("Should NOT return null", SymbolData.INT_TYPE.getInstanceData(), _bbtc.forSwitchStatementOnly(ss,
 2298    SymbolData.CHAR_TYPE.getInstanceData(),
 2299    new TypeData[] {SymbolData.INT_TYPE, SymbolData.CHAR_TYPE, null, SymbolData.CHAR_TYPE},
 2300    true));
 2301   
 2302    }
 2303   
 2304  1 public void testForSwitchStatement() {
 2305  1 _bbtc._vars.addLast(new VariableData("dan", _publicMav, SymbolData.INT_TYPE, true, _bbtc._bodyData));
 2306   
 2307    //assignment in switch expression should throw error
 2308  1 SwitchStatement ss = new SwitchStatement(SourceInfo.NONE, new SimpleAssignmentExpression(SourceInfo.NONE, new SimpleNameReference(SourceInfo.NONE, new Word(SourceInfo.NONE, "dan")), new IntegerLiteral(SourceInfo.NONE, 5)), new SwitchCase[0]);
 2309  1 assertEquals("Should return null", null, ss.visit(_bbtc));
 2310  1 assertEquals("Should be 1 error", 1, errors.size());
 2311  1 assertEquals("Error message should be correct", "You cannot use an assignment expression in the switch expression of a switch statement at any language level. Perhaps you meant to compare two values with '=='", errors.getLast().getFirst());
 2312   
 2313    //non int or char value in switch expression
 2314  1 ss = new SwitchStatement(SourceInfo.NONE, new DoubleLiteral(SourceInfo.NONE, 4.2), new SwitchCase[0]);
 2315  1 assertEquals("Should return null", null, ss.visit(_bbtc));
 2316  1 assertEquals("Should be 2 error", 2, errors.size());
 2317  1 assertEquals("Error message should be correct", "The switch expression must be either an int or a char. You have used a double", errors.getLast().getFirst());
 2318   
 2319    //two switch cases with the same label
 2320  1 UnbracedBody emptyBody = new UnbracedBody(SourceInfo.NONE, new BodyItemI[0]);
 2321   
 2322  1 LabeledCase l1 = new LabeledCase(SourceInfo.NONE, new IntegerLiteral(SourceInfo.NONE, 5), emptyBody);
 2323  1 LabeledCase l2 = new LabeledCase(SourceInfo.NONE, new IntegerLiteral(SourceInfo.NONE, 5), emptyBody);
 2324  1 LabeledCase l3 = new LabeledCase(SourceInfo.NONE, new IntegerLiteral(SourceInfo.NONE, 7), emptyBody);
 2325   
 2326  1 ss = new SwitchStatement(SourceInfo.NONE, new SimpleNameReference(SourceInfo.NONE, new Word(SourceInfo.NONE, "dan")), new SwitchCase[] {l1, l2, l3});
 2327  1 assertEquals("Should return null", null, ss.visit(_bbtc));
 2328  1 assertEquals("Should be 3 errors", 3, errors.size());
 2329  1 assertEquals("Error message should be correct", "You cannot have two switch cases with the same label 5", errors.getLast().getFirst());
 2330   
 2331    //two default cases
 2332  1 DefaultCase dc1 = new DefaultCase(SourceInfo.NONE, emptyBody);
 2333  1 ss = new SwitchStatement(SourceInfo.NONE, new SimpleNameReference(SourceInfo.NONE, new Word(SourceInfo.NONE, "dan")), new SwitchCase[] {dc1, dc1});
 2334  1 assertEquals("Should return null", null, ss.visit(_bbtc));
 2335  1 assertEquals("Should be 4 errors", 4, errors.size());
 2336  1 assertEquals("Error message should be correct", "A switch statement can only have one default case", errors.getLast().getFirst());
 2337   
 2338    //x is assigned
 2339  1 VariableData xData = new VariableData("x", _publicMav, SymbolData.INT_TYPE, false, _bbtc._bodyData);
 2340  1 _bbtc._vars.addLast(xData);
 2341   
 2342  1 ExpressionStatement assignX = new ExpressionStatement(SourceInfo.NONE, new SimpleAssignmentExpression(SourceInfo.NONE, new SimpleNameReference(SourceInfo.NONE, new Word(SourceInfo.NONE, "x")), new IntegerLiteral(SourceInfo.NONE, 5)));
 2343  1 UnbracedBody returnBody = new UnbracedBody(SourceInfo.NONE, new BodyItemI[] {assignX, new ValueReturnStatement(SourceInfo.NONE, new IntegerLiteral(SourceInfo.NONE, 5))});
 2344  1 UnbracedBody breakBody = new UnbracedBody(SourceInfo.NONE, new BodyItemI[] {assignX, new UnlabeledBreakStatement(SourceInfo.NONE)});
 2345  1 UnbracedBody breakNoAssignBody = new UnbracedBody(SourceInfo.NONE, new BodyItemI[] {new UnlabeledBreakStatement(SourceInfo.NONE)});
 2346  1 UnbracedBody fallThroughBody = new UnbracedBody(SourceInfo.NONE, new BodyItemI[] {assignX});
 2347  1 UnbracedBody fallThroughNoAssignBody = new UnbracedBody(SourceInfo.NONE, new BodyItemI[0]);
 2348   
 2349  1 SwitchCase c1 = new LabeledCase(SourceInfo.NONE, new IntegerLiteral(SourceInfo.NONE, 5), returnBody);
 2350  1 SwitchCase c2 = new LabeledCase(SourceInfo.NONE, new IntegerLiteral(SourceInfo.NONE, 6), breakBody);
 2351  1 SwitchCase c3 = new DefaultCase(SourceInfo.NONE, breakBody);
 2352   
 2353  1 ss = new SwitchStatement(SourceInfo.NONE, new SimpleNameReference(SourceInfo.NONE, new Word(SourceInfo.NONE, "dan")), new SwitchCase[] {c1, c2, c3});
 2354   
 2355  1 assertEquals("Should return null", null, ss.visit(_bbtc));
 2356  1 assertEquals("Should still be 4 errors", 4, errors.size());
 2357  1 assertTrue("x has been assigned", xData.hasValue());
 2358   
 2359    //x is assigned -- the first block falls through
 2360  1 xData.lostValue();
 2361   
 2362  1 c1 = new LabeledCase(SourceInfo.NONE, new IntegerLiteral(SourceInfo.NONE, 5), fallThroughNoAssignBody);
 2363  1 c2 = new DefaultCase(SourceInfo.NONE, breakBody);
 2364  1 c3 = new LabeledCase(SourceInfo.NONE, new IntegerLiteral(SourceInfo.NONE, 6), breakBody);
 2365  1 ss = new SwitchStatement(SourceInfo.NONE, new SimpleNameReference(SourceInfo.NONE, new Word(SourceInfo.NONE, "dan")), new SwitchCase[] {c1, c2, c3});
 2366   
 2367  1 assertEquals("Should return null", null, ss.visit(_bbtc));
 2368  1 assertEquals("Should still be 4 errors", 4, errors.size());
 2369  1 assertTrue("x has been assigned", xData.hasValue());
 2370   
 2371    //x is not assigned -- the second block does not fall through
 2372  1 xData.lostValue();
 2373   
 2374  1 c1 = new LabeledCase(SourceInfo.NONE, new IntegerLiteral(SourceInfo.NONE, 5), fallThroughNoAssignBody);
 2375  1 c2 = new LabeledCase(SourceInfo.NONE, new IntegerLiteral(SourceInfo.NONE, 6), breakNoAssignBody);
 2376  1 c3 = new DefaultCase(SourceInfo.NONE, breakBody);
 2377  1 ss = new SwitchStatement(SourceInfo.NONE, new SimpleNameReference(SourceInfo.NONE, new Word(SourceInfo.NONE, "dan")), new SwitchCase[] {c1, c2, c3});
 2378   
 2379  1 assertEquals("Should return null", null, ss.visit(_bbtc));
 2380  1 assertEquals("Should still be 4 errors", 4, errors.size());
 2381  1 assertFalse("x has not been assigned", xData.hasValue());
 2382   
 2383    //x is not assigned -- there is no default case
 2384  1 xData.lostValue();
 2385   
 2386  1 c1 = new LabeledCase(SourceInfo.NONE, new IntegerLiteral(SourceInfo.NONE, 5), fallThroughNoAssignBody);
 2387  1 c2 = new LabeledCase(SourceInfo.NONE, new IntegerLiteral(SourceInfo.NONE, 6), fallThroughNoAssignBody);
 2388  1 c3 = new LabeledCase(SourceInfo.NONE, new IntegerLiteral(SourceInfo.NONE, 7), breakBody);
 2389  1 ss = new SwitchStatement(SourceInfo.NONE, new SimpleNameReference(SourceInfo.NONE, new Word(SourceInfo.NONE, "dan")), new SwitchCase[] {c1, c2, c3});
 2390   
 2391  1 assertEquals("Should return null", null, ss.visit(_bbtc));
 2392  1 assertEquals("Should still be 4 errors", 4, errors.size());
 2393  1 assertFalse("x has not been assigned", xData.hasValue());
 2394   
 2395    //x is assigned -- the last case is always executed--but an error is added, because it falls through.
 2396  1 xData.lostValue();
 2397   
 2398  1 c1 = new LabeledCase(SourceInfo.NONE, new IntegerLiteral(SourceInfo.NONE, 5), fallThroughNoAssignBody);
 2399  1 c2 = new LabeledCase(SourceInfo.NONE, new IntegerLiteral(SourceInfo.NONE, 6), fallThroughNoAssignBody);
 2400  1 c3 = new DefaultCase(SourceInfo.NONE, fallThroughBody);
 2401  1 ss = new SwitchStatement(SourceInfo.NONE, new SimpleNameReference(SourceInfo.NONE, new Word(SourceInfo.NONE, "dan")), new SwitchCase[] {c1, c2, c3});
 2402   
 2403  1 assertEquals("Should return null", null, ss.visit(_bbtc));
 2404  1 assertEquals("Should be 5 errors", 5, errors.size());
 2405  1 assertEquals("The error message should be correct", "You must end a non-empty switch case with a break or return statement at the Advanced level", errors.getLast().getFirst());
 2406  1 assertTrue("x has been assigned", xData.hasValue());
 2407   
 2408    }
 2409   
 2410  1 public void testForLabeledCase() {
 2411  1 symbolTable.put("java.lang.String", new SymbolData("java.lang.String"));
 2412  1 UnbracedBody emptyBody = new UnbracedBody(SourceInfo.NONE, new BodyItemI[0]);
 2413    //Test a label that is okay
 2414  1 LabeledCase lc = new LabeledCase(SourceInfo.NONE, new CharLiteral(SourceInfo.NONE, 'e'), emptyBody);
 2415  1 assertEquals("Should return null", null, lc.visit(_bbtc));
 2416  1 assertEquals("There should be no errors", 0, errors.size());
 2417   
 2418  1 lc = new LabeledCase(SourceInfo.NONE, new IntegerLiteral(SourceInfo.NONE, 27), emptyBody);
 2419  1 assertEquals("Should return null", null, lc.visit(_bbtc));
 2420  1 assertEquals("There should be no errors", 0, errors.size());
 2421   
 2422    //Test that a braced body that returns something is handled correctly
 2423  1 UnbracedBody nonEmptyBody = new UnbracedBody(SourceInfo.NONE, new BodyItemI[] {new ValueReturnStatement(SourceInfo.NONE, new IntegerLiteral(SourceInfo.NONE, 5))});
 2424  1 lc = new LabeledCase(SourceInfo.NONE, new IntegerLiteral(SourceInfo.NONE, 27), nonEmptyBody);
 2425  1 TypeData result = lc.visit(_bbtc);
 2426  1 assertEquals("There should be no errors", 0, errors.size());
 2427  1 assertEquals("Should return int", SymbolData.INT_TYPE.getInstanceData(), result);
 2428  1 assertEquals("There should be no errors", 0, errors.size());
 2429   
 2430   
 2431    //Test some that are not:
 2432   
 2433    //label that is a more complex expression: length greater than 1
 2434  1 lc = new LabeledCase(SourceInfo.NONE, new PlusExpression(SourceInfo.NONE, new IntegerLiteral(SourceInfo.NONE, 5), new IntegerLiteral(SourceInfo.NONE, 42)), emptyBody);
 2435  1 assertEquals("Should return null", null, lc.visit(_bbtc));
 2436  1 assertEquals("There should be 1 error", 1, errors.size());
 2437  1 assertEquals("The error message should be correct", "The labels of a switch statement must be constants. You are using a more complicated expression of type int", errors.getLast().getFirst());
 2438   
 2439    //label that is a more complex expression: something other than a literal of length 1
 2440  1 _bbtc._vars.addLast(new VariableData("dan", _publicMav, SymbolData.INT_TYPE, true, _bbtc._bodyData));
 2441  1 lc = new LabeledCase(SourceInfo.NONE, new SimpleNameReference(SourceInfo.NONE, new Word(SourceInfo.NONE, "dan")), emptyBody);
 2442  1 assertEquals("Should return null", null, lc.visit(_bbtc));
 2443  1 assertEquals("There should now be 2 errors", 2, errors.size());
 2444  1 assertEquals("The error message should be correct", "The labels of a switch statement must be constants. You are using a more complicated expression of type int", errors.getLast().getFirst());
 2445   
 2446    //and a literal whose type is not int or char
 2447  1 lc = new LabeledCase(SourceInfo.NONE, new StringLiteral(SourceInfo.NONE, "hi!"), emptyBody);
 2448  1 assertEquals("Should return null", null, lc.visit(_bbtc));
 2449  1 assertEquals("There should now be 3 errors", 3, errors.size());
 2450  1 assertEquals("The error message should be correct", "The labels of a switch statement must be constants of int or char type. You specified a constant of type java.lang.String", errors.getLast().getFirst());
 2451   
 2452    }
 2453   
 2454  1 public void testForDefaultCase() {
 2455  1 UnbracedBody emptyBody = new UnbracedBody(SourceInfo.NONE, new BodyItemI[0]);
 2456  1 UnbracedBody returnBody = new UnbracedBody(SourceInfo.NONE, new BodyItemI[] {new ValueReturnStatement(SourceInfo.NONE, new IntegerLiteral(SourceInfo.NONE, 5))});
 2457  1 UnbracedBody breakBody = new UnbracedBody(SourceInfo.NONE, new BodyItemI[] {new UnlabeledBreakStatement(SourceInfo.NONE)});
 2458   
 2459    //an empty body
 2460  1 DefaultCase dc = new DefaultCase(SourceInfo.NONE, emptyBody);
 2461  1 assertEquals("Should return null", null, dc.visit(_bbtc));
 2462  1 assertEquals("There should be no errors", 0, errors.size());
 2463   
 2464    //a body with a return statement
 2465  1 dc = new DefaultCase(SourceInfo.NONE, returnBody);
 2466  1 assertEquals("Should return int", SymbolData.INT_TYPE.getInstanceData(), dc.visit(_bbtc));
 2467  1 assertEquals("There should be no errors", 0, errors.size());
 2468   
 2469    //a body with a break
 2470  1 dc = new DefaultCase(SourceInfo.NONE, breakBody);
 2471  1 assertEquals("Should return NOT_FOUND", SymbolData.NOT_FOUND, dc.visit(_bbtc));
 2472  1 assertEquals("There should be no errors", 0, errors.size());
 2473    }
 2474   
 2475  1 public void testForSwitchCase() {
 2476  1 UnbracedBody emptyBody = new UnbracedBody(SourceInfo.NONE, new BodyItemI[0]);
 2477  1 UnbracedBody returnBody = new UnbracedBody(SourceInfo.NONE, new BodyItemI[] {new ValueReturnStatement(SourceInfo.NONE, new IntegerLiteral(SourceInfo.NONE, 5))});
 2478  1 UnbracedBody breakBody = new UnbracedBody(SourceInfo.NONE, new BodyItemI[] {new UnlabeledBreakStatement(SourceInfo.NONE)});
 2479  1 UnbracedBody nonEmptyBody = new UnbracedBody(SourceInfo.NONE, new BodyItemI[] {new EmptyStatement(SourceInfo.NONE)});
 2480   
 2481    //empty body
 2482  1 DefaultCase dc = new DefaultCase(SourceInfo.NONE, emptyBody);
 2483  1 assertEquals("Should return null", null, _bbtc.forSwitchCase(dc));
 2484  1 assertEquals("There should be no errors", 0, errors.size());
 2485   
 2486    //return body
 2487  1 dc = new DefaultCase(SourceInfo.NONE, returnBody);
 2488  1 assertEquals("Should return int", SymbolData.INT_TYPE.getInstanceData(), _bbtc.forSwitchCase(dc));
 2489  1 assertEquals("There should be no errors", 0, errors.size());
 2490   
 2491    //break body
 2492  1 dc = new DefaultCase(SourceInfo.NONE, breakBody);
 2493  1 assertEquals("Should return NOT_FOUND", SymbolData.NOT_FOUND, _bbtc.forSwitchCase(dc));
 2494  1 assertEquals("There should be no errors", 0, errors.size());
 2495   
 2496    //non-empty body that does not return: fall-through
 2497  1 dc = new DefaultCase(SourceInfo.NONE, nonEmptyBody);
 2498  1 assertEquals("Should return null", null, _bbtc.forSwitchCase(dc));
 2499  1 assertEquals("There should be one error", 1, errors.size());
 2500  1 assertEquals("The error message should be correct", "You must end a non-empty switch case with a break or return statement at the Advanced level", errors.getLast().getFirst());
 2501   
 2502    }
 2503   
 2504  1 public void testCreateANewInstanceOfMe() {
 2505    //make sure that the correct type of visitor is returned
 2506  1 BodyTypeChecker btc = _bbtc.createANewInstanceOfMe(_bbtc._bodyData, _bbtc._file, _bbtc._package, _bbtc._importedFiles, _bbtc._importedPackages, _bbtc._vars, _bbtc._thrown);
 2507  1 assertTrue("Should be an instance of BodyTypeChecker", btc instanceof BodyTypeChecker);
 2508  1 assertFalse("Should not be an instance of ConstructorBodyTypeChecker", btc instanceof ConstructorBodyTypeChecker);
 2509   
 2510    }
 2511   
 2512  1 public void testCheckDuplicateExceptions() {
 2513  1 BracedBody emptyBody = new BracedBody(SourceInfo.NONE, new BodyItemI[0]);
 2514  1 Block b = new Block(SourceInfo.NONE, emptyBody);
 2515   
 2516  1 NormalTryCatchStatement ntcs = new NormalTryCatchStatement(SourceInfo.NONE, b, new CatchBlock[0]);
 2517  1 TryCatchFinallyStatement tcfs = new TryCatchFinallyStatement(SourceInfo.NONE, b, new CatchBlock[0], b);
 2518  1 _bbtc.checkDuplicateExceptions(ntcs);
 2519  1 _bbtc.checkDuplicateExceptions(tcfs);
 2520  1 assertEquals("Should be no errors", 0, errors.size());
 2521   
 2522  1 UninitializedVariableDeclarator uvd1 =
 2523    new UninitializedVariableDeclarator(SourceInfo.NONE,
 2524    new ClassOrInterfaceType(SourceInfo.NONE, "java.lang.Exception", new Type[0]),
 2525    new Word(SourceInfo.NONE, "e"));
 2526  1 UninitializedVariableDeclarator uvd2 =
 2527    new UninitializedVariableDeclarator(SourceInfo.NONE,
 2528    new ClassOrInterfaceType(SourceInfo.NONE, "RuntimeException", new Type[0]),
 2529    new Word(SourceInfo.NONE, "e"));
 2530  1 UninitializedVariableDeclarator uvd3 =
 2531    new UninitializedVariableDeclarator(SourceInfo.NONE,
 2532    new ClassOrInterfaceType(SourceInfo.NONE, "IOException", new Type[0]),
 2533    new Word(SourceInfo.NONE, "e"));
 2534   
 2535  1 FormalParameter fp1 = new FormalParameter(SourceInfo.NONE, uvd1, false);
 2536  1 FormalParameter fp2 = new FormalParameter(SourceInfo.NONE, uvd2, false);
 2537  1 FormalParameter fp3 = new FormalParameter(SourceInfo.NONE, uvd3, false);
 2538   
 2539  1 LanguageLevelVisitor llv =
 2540    new LanguageLevelVisitor(new File(""),
 2541    "",
 2542    null, // enclosingClassName for top level traversal
 2543    new LinkedList<String>(),
 2544    new LinkedList<String>(),
 2545    new HashSet<String>(),
 2546    new Hashtable<String, Triple<SourceInfo, LanguageLevelVisitor, SymbolData>>(),
 2547    new LinkedList<Command>());
 2548   
 2549  1 llv.errors = new LinkedList<Pair<String, JExpressionIF>>();
 2550  1 llv._errorAdded=false;
 2551    // LanguageLevelConverter.symbolTable = llv.symbolTable = new Symboltable();
 2552  1 llv.continuations = new Hashtable<String, Triple<SourceInfo, LanguageLevelVisitor, SymbolData>>();
 2553  1 llv.visitedFiles = new LinkedList<Pair<LanguageLevelVisitor, edu.rice.cs.javalanglevels.tree.SourceFile>>();
 2554    // llv._hierarchy = new Hashtable<String, TypeDefBase>();
 2555  1 llv._classesInThisFile = new HashSet<String>();
 2556   
 2557  1 llv._importedFiles.addLast("java.io.IOException");
 2558  1 SymbolData e = llv.getQualifiedSymbolData("java.lang.Exception", SourceInfo.NONE);
 2559  1 SymbolData re = llv.getQualifiedSymbolData("java.lang.RuntimeException", SourceInfo.NONE);
 2560  1 SymbolData ioe = llv.getQualifiedSymbolData("java.io.IOException", SourceInfo.NONE);
 2561   
 2562  1 assert symbolTable.containsKey("java.lang.Exception");
 2563  1 assert symbolTable.containsKey("java.lang.RuntimeException");
 2564  1 assert symbolTable.containsKey("java.io.IOException");
 2565  1 assert symbolTable.contains(e);
 2566  1 assert symbolTable.contains(re);
 2567  1 assert symbolTable.contains(ioe);
 2568   
 2569  1 CatchBlock c1 = new CatchBlock(SourceInfo.NONE, fp1, b);
 2570  1 CatchBlock c2 = new CatchBlock(SourceInfo.NONE, fp2, b);
 2571  1 CatchBlock c3 = new CatchBlock(SourceInfo.NONE, fp3, b);
 2572  1 _bbtc._importedFiles.addLast("java.io.IOException");
 2573   
 2574    // Just one exception, no error
 2575  1 ntcs = new NormalTryCatchStatement(SourceInfo.NONE, b, new CatchBlock[] {c1});
 2576  1 _bbtc.checkDuplicateExceptions(ntcs);
 2577  1 assertEquals("Should be no errors", 0, errors.size());
 2578   
 2579    // Second exception is subclass of 1st exception: should throw error
 2580  1 ntcs = new NormalTryCatchStatement(SourceInfo.NONE, b, new CatchBlock[]{c1, c2});
 2581  1 _bbtc.checkDuplicateExceptions(ntcs);
 2582    // System.out.println("First error is: " + errors.get(0));
 2583  1 assertEquals("Should be one error", 1, errors.size());
 2584  1 assertEquals("Error message should be correct", "Exception java.lang.RuntimeException has already been caught", errors.get(0).getFirst());
 2585   
 2586    // Two exceptions, unrelated. no error
 2587  1 ntcs = new NormalTryCatchStatement(SourceInfo.NONE, b, new CatchBlock[]{c2, c3});
 2588  1 _bbtc.checkDuplicateExceptions(ntcs);
 2589  1 assertEquals("Should still be one error", 1, errors.size());
 2590   
 2591    // 2nd and 3rd exceptions subclasses of 1st exception: should throw 2 errors, but one is a duplicate
 2592  1 ntcs = new NormalTryCatchStatement(SourceInfo.NONE, b, new CatchBlock[]{c1, c2, c3});
 2593  1 _bbtc.checkDuplicateExceptions(ntcs);
 2594   
 2595  1 assertEquals("Should be two errors", 2, errors.size());
 2596  1 assertEquals("2nd Error message should be correct", "Exception java.lang.RuntimeException has already been caught", errors.get(0).getFirst());
 2597  1 assertEquals("3rd Error message should be correct", "Exception java.io.IOException has already been caught", errors.get(1).getFirst());
 2598   
 2599    // 1st exception subclass of 2nd exception: should be no error
 2600  1 ntcs = new NormalTryCatchStatement(SourceInfo.NONE, b, new CatchBlock[]{c2, c1});
 2601  1 _bbtc.checkDuplicateExceptions(ntcs);
 2602  1 assertEquals("Should still be two errors", 2, errors.size());
 2603    }
 2604   
 2605  1 public void testTryCatchLeastRestrictiveType() {
 2606   
 2607  1 InstanceData[] sdArray = new InstanceData[] {SymbolData.BYTE_TYPE.getInstanceData(), SymbolData.INT_TYPE.getInstanceData(), SymbolData.SHORT_TYPE.getInstanceData()};
 2608  1 assertEquals("Should return long type", SymbolData.LONG_TYPE.getInstanceData(), _bbtc.tryCatchLeastRestrictiveType(SymbolData.LONG_TYPE.getInstanceData(), sdArray, null));
 2609  1 assertEquals("Should return Object", "java.lang.Object", _bbtc.tryCatchLeastRestrictiveType(SymbolData.SHORT_TYPE.getInstanceData(), sdArray, SymbolData.BOOLEAN_TYPE.getInstanceData()).getName());
 2610  1 assertEquals("Should return double type", SymbolData.DOUBLE_TYPE.getInstanceData(), _bbtc.tryCatchLeastRestrictiveType(SymbolData.SHORT_TYPE.getInstanceData(), sdArray, SymbolData.DOUBLE_TYPE.getInstanceData()));
 2611  1 assertEquals("Should return null", null, _bbtc.tryCatchLeastRestrictiveType(null, sdArray, null));
 2612  1 assertEquals("Should return int type", SymbolData.INT_TYPE.getInstanceData(), _bbtc.tryCatchLeastRestrictiveType(SymbolData.SHORT_TYPE.getInstanceData(), sdArray, null));
 2613  1 assertEquals("Should return long type", SymbolData.LONG_TYPE.getInstanceData(), _bbtc.tryCatchLeastRestrictiveType(null, sdArray, SymbolData.LONG_TYPE.getInstanceData()));
 2614   
 2615  1 sdArray = new InstanceData[] {null, SymbolData.INT_TYPE.getInstanceData()};
 2616  1 assertEquals("Should return null", null, _bbtc.tryCatchLeastRestrictiveType(SymbolData.INT_TYPE.getInstanceData(), sdArray, null));
 2617  1 assertEquals("Should return short", SymbolData.SHORT_TYPE.getInstanceData(), _bbtc.tryCatchLeastRestrictiveType(SymbolData.INT_TYPE.getInstanceData(), sdArray, SymbolData.SHORT_TYPE.getInstanceData()));
 2618   
 2619  1 SymbolData sd = new SymbolData("java.lang.Object");
 2620  1 SymbolData sd2 = new SymbolData("java.lang.String");
 2621    // sd.setIsContinuation(false);
 2622    // sd2.setIsContinuation(false);
 2623    // symbolTable.put("java.lang.Object", sd);
 2624    // symbolTable.put("java.lang.String", sd2);
 2625  1 sd2.setSuperClass(sd);
 2626   
 2627  1 assertEquals("Should return Object", sd.getInstanceData(), _bbtc.tryCatchLeastRestrictiveType(sd2.getInstanceData(), new InstanceData[]{sd.getInstanceData(), sd2.getInstanceData()}, null));
 2628    }
 2629   
 2630  1 public void testHandleMethodInvocation() {
 2631    //handleMethodInvocation(MethodData md, JExpression jexpr)
 2632  1 MethodData md = new MethodData("Fun", _publicMav, new TypeParameter[0], _sd1,
 2633    new VariableData[0],
 2634    new String[0],
 2635    _sd1,
 2636    null);
 2637   
 2638  1 MethodData md2 = new MethodData("InTheSun", _publicMav, new TypeParameter[0], _sd1,
 2639    new VariableData[0],
 2640    new String[] {"java.lang.RuntimeException", "java.io.IOException"},
 2641    _sd1,
 2642    null);
 2643   
 2644  1 NullLiteral nl = new NullLiteral(SourceInfo.NONE);
 2645   
 2646  1 _bbtc._importedFiles.addLast("java.io.IOException");
 2647    // TODO: create LL constructor specifically for testing that only takes file name.
 2648  1 LanguageLevelVisitor llv =
 2649    new LanguageLevelVisitor(new File(""), "",
 2650    null /* enclosingClassName */,
 2651    new LinkedList<String>(),
 2652    new LinkedList<String>(),
 2653    new HashSet<String>(),
 2654    new Hashtable<String, Triple<SourceInfo, LanguageLevelVisitor, SymbolData>>(),
 2655    new LinkedList<Command>());
 2656   
 2657  1 llv.errors = new LinkedList<Pair<String, JExpressionIF>>();
 2658  1 llv._errorAdded = false;
 2659    // LanguageLevelConverter.symbolTable.clear(); // done in setUp()
 2660  1 llv.continuations = new Hashtable<String, Triple<SourceInfo, LanguageLevelVisitor, SymbolData>>();
 2661  1 llv.visitedFiles = new LinkedList<Pair<LanguageLevelVisitor, edu.rice.cs.javalanglevels.tree.SourceFile>>();
 2662    // llv._hierarchy = new Hashtable<String, TypeDefBase>();
 2663  1 llv._classesInThisFile = new HashSet<String>();
 2664   
 2665  1 llv._importedFiles.addLast("java.io.IOException");
 2666   
 2667   
 2668  1 SymbolData re = llv.getSymbolData("java.lang.RuntimeException", SourceInfo.NONE, true);
 2669  1 SymbolData ioe = llv.getSymbolData("java.io.IOException", SourceInfo.NONE, true);
 2670   
 2671  1 assert symbolTable.containsKey("java.lang.RuntimeException");
 2672  1 assert symbolTable.containsKey("java.io.IOException");
 2673  1 assert symbolTable.contains(re);
 2674  1 assert symbolTable.contains(ioe);
 2675    // symbolTable.put("java.lang.RuntimeException", re);
 2676    // symbolTable.put("java.io.IOException", ioe);
 2677   
 2678   
 2679  1 _bbtc.handleMethodInvocation(md, nl);
 2680  1 assertEquals("There should be no exceptions in _thrown", 0, _bbtc._thrown.size());
 2681   
 2682  1 _bbtc.handleMethodInvocation(md2, nl);
 2683  1 assertEquals("There should be 2 exceptions in _thrown", 2, _bbtc._thrown.size());
 2684  1 assertEquals("The first exception should be java.lang.RuntimeException", re, _bbtc._thrown.get(0).getFirst());
 2685  1 assertEquals("The second exception should be java.lang.IOException", ioe, _bbtc._thrown.get(1).getFirst());
 2686    }
 2687   
 2688  1 public void testForThrowStatement() {
 2689  1 LanguageLevelVisitor llv =
 2690    new LanguageLevelVisitor(new File(""),
 2691    "",
 2692    null, // enclosingClassName for top level traversal
 2693    new LinkedList<String>(),
 2694    new LinkedList<String>(),
 2695    new HashSet<String>(),
 2696    new Hashtable<String, Triple<SourceInfo, LanguageLevelVisitor, SymbolData>>(),
 2697    new LinkedList<Command>());
 2698   
 2699  1 llv.errors = new LinkedList<Pair<String, JExpressionIF>>();
 2700  1 llv._errorAdded=false;
 2701    // LanguageLevelConverter.symbolTable = llv.symbolTable = new Symboltable();
 2702  1 llv.continuations = new Hashtable<String, Triple<SourceInfo, LanguageLevelVisitor, SymbolData>>();
 2703  1 llv.visitedFiles = new LinkedList<Pair<LanguageLevelVisitor, edu.rice.cs.javalanglevels.tree.SourceFile>>();
 2704    // llv._hierarchy = new Hashtable<String, TypeDefBase>();
 2705  1 llv._classesInThisFile = new HashSet<String>();
 2706   
 2707  1 SymbolData re = llv.getSymbolData("java.lang.RuntimeException", SourceInfo.NONE, true);
 2708  1 assert symbolTable.containsKey("java.lang.RuntimeException");
 2709  1 assert symbolTable.contains(re);
 2710   
 2711    // symbolTable.put("java.lang.RuntimeException", re);
 2712   
 2713  1 VariableData vd = new VariableData("myException", _publicMav, re, true, _bbtc._bodyData);
 2714  1 _bbtc._vars.addLast(vd);
 2715  1 Expression e = new SimpleNameReference(SourceInfo.NONE, new Word(SourceInfo.NONE, "myException"));
 2716  1 ThrowStatement ts = new ThrowStatement(SourceInfo.NONE, e);
 2717   
 2718  1 assertEquals("Should return EXCEPTION", SymbolData.EXCEPTION.getInstanceData(), ts.visit(_bbtc));
 2719   
 2720  1 assertEquals("There should be 1 exception in _thrown", 1, _bbtc._thrown.size());
 2721  1 assertEquals("The exception should be java.lang.RuntimeException", re, _bbtc._thrown.get(0).getFirst());
 2722   
 2723    }
 2724   
 2725  1 public void testMakeSureCaughtStuffWasThrown() {
 2726    //TryCatchStatement that, SymbolData[] caught_array, LinkedList<Pair<SymbolData, JExpression>> thrown) {
 2727  1 BracedBody emptyBody = new BracedBody(SourceInfo.NONE, new BodyItemI[0]);
 2728  1 Block b = new Block(SourceInfo.NONE, emptyBody);
 2729   
 2730  1 PrimitiveType intt = new PrimitiveType(SourceInfo.NONE, "int");
 2731  1 UninitializedVariableDeclarator uvd = new UninitializedVariableDeclarator(SourceInfo.NONE, intt, new Word(SourceInfo.NONE, "i"));
 2732  1 FormalParameter param = new FormalParameter(SourceInfo.NONE, new UninitializedVariableDeclarator(SourceInfo.NONE, intt, new Word(SourceInfo.NONE, "j")), false);
 2733   
 2734  1 NormalTryCatchStatement ntcs =
 2735    new NormalTryCatchStatement(SourceInfo.NONE, b,
 2736    new CatchBlock[] {new CatchBlock(SourceInfo.NONE, param, b)});
 2737  1 SymbolData javaLangThrowable = _bbtc.getSymbolData("java.lang.Throwable", ntcs, false, true);
 2738    // new SymbolData("java.lang.Throwable");
 2739  1 _bbtc.symbolTable.put("java.lang.Throwable", javaLangThrowable);
 2740  1 SymbolData exception = new SymbolData("my.crazy.exception");
 2741  1 exception.setSuperClass(javaLangThrowable);
 2742  1 SymbolData exception2 = new SymbolData("A&M.beat.Rice.in.BaseballException");
 2743  1 exception2.setSuperClass(javaLangThrowable);
 2744  1 SymbolData exception3 = new SymbolData("aegilha");
 2745  1 exception3.setSuperClass(javaLangThrowable);
 2746  1 LinkedList<Pair<SymbolData, JExpression>> thrown = new LinkedList<Pair<SymbolData, JExpression>>();
 2747   
 2748   
 2749  1 _bbtc.makeSureCaughtStuffWasThrown(ntcs, new SymbolData[0], thrown);
 2750  1 assertEquals("There should be no errors", 0, errors.size());
 2751   
 2752  1 Pair<SymbolData, JExpression> p = new Pair<SymbolData, JExpression>(exception, ntcs);
 2753  1 thrown.addLast(p);
 2754  1 _bbtc.makeSureCaughtStuffWasThrown(ntcs, new SymbolData[]{exception}, thrown);
 2755  1 assertEquals("There should still be no errors", 0, errors.size());
 2756   
 2757  1 thrown.remove(p);
 2758   
 2759  1 _bbtc.makeSureCaughtStuffWasThrown(ntcs, new SymbolData[] {exception2}, thrown);
 2760    // System.err.println("thrown = " + thrown);
 2761    // System.err.println("errors = " + errors);
 2762  1 assertEquals("There should be one error", 1, errors.size());
 2763  1 assertEquals("The error message should be correct", "The exception A&M.beat.Rice.in.BaseballException is never thrown in the body of the corresponding try block", errors.get(0).getFirst());
 2764    }
 2765   
 2766  1 public void testIsCheckedException() {
 2767  1 SymbolData th = new SymbolData("java.lang.Throwable");
 2768  1 th.setIsContinuation(false);
 2769  1 SymbolData r = new SymbolData("java.lang.Error");
 2770  1 r.setIsContinuation(false);
 2771  1 r.setSuperClass(th);
 2772  1 SymbolData ex = new SymbolData("java.lang.Exception");
 2773  1 ex.setIsContinuation(false);
 2774  1 ex.setSuperClass(th);
 2775  1 SymbolData re = new SymbolData("java.lang.RuntimeException");
 2776  1 re.setIsContinuation(false);
 2777  1 re.setSuperClass(ex);
 2778  1 symbolTable.put("java.lang.Throwable", th);
 2779  1 symbolTable.put("java.lang.RuntimeException", re);
 2780  1 symbolTable.put("java.lang.Error", r);
 2781  1 symbolTable.put("java.lang.Exception", ex);
 2782  1 SymbolData e1 = new SymbolData("exception1");
 2783  1 e1.setSuperClass(ex);
 2784  1 SymbolData e2 = new SymbolData("exception2");
 2785  1 e2.setSuperClass(re);
 2786  1 SymbolData e3 = new SymbolData("exception3");
 2787  1 e3.setSuperClass(r);
 2788   
 2789  1 NullLiteral nl = new NullLiteral(SourceInfo.NONE);
 2790   
 2791  1 assertTrue("Does not subclass RuntimeException or Error", _bbtc.isCheckedException(e1, nl));
 2792  1 assertFalse("Subclasses java.lang.RuntimeException", _bbtc.isCheckedException(e2, nl));
 2793  1 assertFalse("Subclasses java.lang.Error", _bbtc.isCheckedException(e3, nl));
 2794   
 2795    }
 2796   
 2797  1 public void testIsUncheckedException() {
 2798    //Check that extending RuntimeException or Error works as expected
 2799  1 SymbolData th = new SymbolData("java.lang.Throwable");
 2800  1 th.setIsContinuation(false);
 2801  1 SymbolData r = new SymbolData("java.lang.Error");
 2802  1 r.setIsContinuation(false);
 2803  1 r.setSuperClass(th);
 2804  1 SymbolData ex = new SymbolData("java.lang.Exception");
 2805  1 ex.setIsContinuation(false);
 2806  1 ex.setSuperClass(th);
 2807  1 SymbolData re = new SymbolData("java.lang.RuntimeException");
 2808  1 re.setIsContinuation(false);
 2809  1 re.setSuperClass(ex);
 2810  1 symbolTable.put("java.lang.Throwable", th);
 2811  1 symbolTable.put("java.lang.RuntimeException", re);
 2812  1 symbolTable.put("java.lang.Error", r);
 2813  1 symbolTable.put("java.lang.Exception", ex);
 2814   
 2815  1 SymbolData e1 = new SymbolData("exception1");
 2816  1 e1.setIsContinuation(false);
 2817  1 e1.setSuperClass(ex);
 2818  1 symbolTable.put("exception1", e1);
 2819  1 SymbolData e2 = new SymbolData("exception2");
 2820  1 e2.setSuperClass(re);
 2821  1 SymbolData e3 = new SymbolData("exception3");
 2822  1 e3.setSuperClass(r);
 2823  1 SymbolData e4 = new SymbolData("exception4");
 2824  1 e4.setSuperClass(e1);
 2825   
 2826  1 NullLiteral nl = new NullLiteral(SourceInfo.NONE);
 2827   
 2828  1 assertTrue("Does not subclass RuntimeException or Error or anything in the method data", _bbtc.isUncaughtCheckedException(e1, nl));
 2829  1 assertFalse("Subclasses java.lang.RuntimeException", _bbtc.isUncaughtCheckedException(e2, nl));
 2830  1 assertFalse("Subclasses java.lang.Error", _bbtc.isUncaughtCheckedException(e3, nl));
 2831   
 2832    //What if you throw something the method data announces that it throws?
 2833  1 _bbtc._bodyData.getMethodData().setThrown(new String[] {"exception1"});
 2834  1 assertFalse("Is in method data", _bbtc.isUncaughtCheckedException(e1, nl));
 2835   
 2836  1 assertFalse("Superclass is in method data", _bbtc.isUncaughtCheckedException(e4, nl));
 2837   
 2838   
 2839    }
 2840   
 2841  1 public void testHandleUncheckedException() {
 2842  1 JExpression j = new SimpleMethodInvocation(SourceInfo.NONE, new Word(SourceInfo.NONE, "myMethod"), new ParenthesizedExpressionList(SourceInfo.NONE, new Expression[] {new SimpleNameReference(SourceInfo.NONE, new Word(SourceInfo.NONE, "i"))}));
 2843   
 2844  1 _bbtc.handleUncheckedException(new SymbolData("i.have.a.shoe"), j);
 2845  1 assertEquals("There should be one error", 1, errors.size());
 2846  1 assertEquals("The error message should be correct", "The method myMethod is declared to throw the exception i.have.a.shoe which needs to be caught or declared to be thrown", errors.get(0).getFirst());
 2847  1 Expression e = new SimpleNameReference(SourceInfo.NONE, new Word(SourceInfo.NONE, "myException"));
 2848  1 j = new ThrowStatement(SourceInfo.NONE, e);
 2849  1 _bbtc.handleUncheckedException(new SymbolData("you.have.a.pot"), j);
 2850  1 assertEquals("There should be two errors", 2, errors.size());
 2851  1 assertEquals("The error message should be correct", "This statement throws the exception you.have.a.pot which needs to be caught or declared to be thrown", errors.get(1).getFirst());
 2852   
 2853    }
 2854   
 2855  1 public void testCompareThrownAndCaught() {
 2856   
 2857  1 JExpression j =
 2858    new SimpleMethodInvocation(SourceInfo.NONE,
 2859    new Word(SourceInfo.NONE, "myMethod"),
 2860    new ParenthesizedExpressionList(SourceInfo.NONE, new Expression[] {new SimpleNameReference(SourceInfo.NONE, new Word(SourceInfo.NONE, "i"))}));
 2861   
 2862  1 BracedBody emptyBody = new BracedBody(SourceInfo.NONE, new BodyItemI[0]);
 2863  1 Block b = new Block(SourceInfo.NONE, emptyBody);
 2864   
 2865  1 PrimitiveType intt = new PrimitiveType(SourceInfo.NONE, "int");
 2866  1 UninitializedVariableDeclarator uvd =
 2867    new UninitializedVariableDeclarator(SourceInfo.NONE, intt, new Word(SourceInfo.NONE, "i"));
 2868  1 FormalParameter param =
 2869    new FormalParameter(SourceInfo.NONE,
 2870    new UninitializedVariableDeclarator(SourceInfo.NONE, intt, new Word(SourceInfo.NONE, "j")), false);
 2871   
 2872  1 NormalTryCatchStatement ntcs =
 2873    new NormalTryCatchStatement(SourceInfo.NONE,
 2874    b,
 2875    new CatchBlock[] {new CatchBlock(SourceInfo.NONE, param, b)});
 2876   
 2877  1 SymbolData javaLangThrowable = _bbtc.getSymbolData("java.lang.Throwable", ntcs, false, true);
 2878    // System.err.println("**** In symbol table, java.lang.Throwable = " + symbolTable.get("java.lang.Throwable"));
 2879  1 assertEquals("There should be no errors", 0, errors.size());
 2880  1 javaLangThrowable.setPackage("java.lang"); // Don't know why it is not properly set already
 2881  1 _bbtc.symbolTable.put("java.lang.Throwable", javaLangThrowable);
 2882   
 2883    // System.err.println("***Name for java.lang.Throwable = " + javaLangThrowable.getName());
 2884    // System.err.println("***notRightPackage for java.lang.Throwable = " + _bbtc.notRightPackage(javaLangThrowable));
 2885    // System.err.println("***Package for java.lang.Throwable = " + javaLangThrowable.getPackage());
 2886   
 2887  1 SymbolData exception = new SymbolData("my.crazy.exception");
 2888  1 exception.setSuperClass(javaLangThrowable);
 2889  1 SymbolData exception2 = new SymbolData("A&M.beat.Rice.in.BaseballException");
 2890  1 exception2.setSuperClass(javaLangThrowable);
 2891  1 SymbolData exception3 = new SymbolData("aegilha");
 2892  1 exception3.setSuperClass(exception2);
 2893  1 SymbolData[] caught_array = new SymbolData[] { exception, exception2 };
 2894  1 LinkedList<Pair<SymbolData, JExpression>> thrown = new LinkedList<Pair<SymbolData, JExpression>>();
 2895  1 thrown.addLast(new Pair<SymbolData, JExpression>(exception, j));
 2896  1 thrown.addLast(new Pair<SymbolData, JExpression>(exception2, ntcs));
 2897  1 thrown.addLast(new Pair<SymbolData, JExpression>(exception3, ntcs));
 2898   
 2899  1 assertEquals("There should be no errors", 0, errors.size());
 2900  1 _bbtc.compareThrownAndCaught(ntcs, caught_array, thrown);
 2901  1 for (int i = 0; i < errors.size(); i++)
 2902    // System.err.println("Error " + i + ":\n" + errors.get(i).getFirst());
 2903  0 assertEquals("There should be no errors", 0, errors.size());
 2904   
 2905  1 _bbtc.compareThrownAndCaught(ntcs, new SymbolData[] {exception2}, thrown);
 2906  1 assertEquals("There should be one error", 1, errors.size());
 2907  1 assertEquals("The error message should be correct", "The method myMethod is declared to throw the exception my.crazy.exception which needs to be caught or declared to be thrown", errors.get(0).getFirst());
 2908   
 2909    }
 2910   
 2911  1 public void testForBracedBody() {
 2912  1 LanguageLevelVisitor llv =
 2913    new LanguageLevelVisitor(new File(""),
 2914    "",
 2915    null, // enclosingClassName for top level traversal
 2916    new LinkedList<String>(),
 2917    new LinkedList<String>(),
 2918    new HashSet<String>(),
 2919    new Hashtable<String, Triple<SourceInfo, LanguageLevelVisitor, SymbolData>>(),
 2920    new LinkedList<Command>());
 2921  1 llv.errors = new LinkedList<Pair<String, JExpressionIF>>();
 2922  1 llv._errorAdded=false;
 2923    // LanguageLevelConverter.symbolTable = llv.symbolTable = new Symboltable();
 2924  1 llv.continuations = new Hashtable<String, Triple<SourceInfo, LanguageLevelVisitor, SymbolData>>();
 2925  1 llv.visitedFiles = new LinkedList<Pair<LanguageLevelVisitor, edu.rice.cs.javalanglevels.tree.SourceFile>>();
 2926    // llv._hierarchy = new Hashtable<String, TypeDefBase>();
 2927  1 llv._classesInThisFile = new HashSet<String>();
 2928   
 2929    // preload symbolTable
 2930  1 SymbolData throwable = llv.getQualifiedSymbolData("java.lang.Throwable");
 2931  1 SymbolData exception = llv.getQualifiedSymbolData("java.lang.Exception");
 2932  1 SymbolData string = llv.getQualifiedSymbolData("java.lang.String");
 2933  1 SymbolData eb = llv.getQualifiedSymbolData("java.util.prefs.BackingStoreException");
 2934  1 SymbolData re = llv.getQualifiedSymbolData("java.lang.RuntimeException");
 2935   
 2936  1 assert symbolTable.contains(throwable);
 2937  1 assert symbolTable.contains(exception);
 2938  1 assert symbolTable.contains(string);
 2939   
 2940    // System.err.println("Interfaces for java.lang.RuntimeException = " + re.getInterfaces());
 2941    //Make sure it is okay to have something else other than an uncaught exception in a braced body.
 2942  1 BracedBody plainBody =
 2943    new BracedBody(SourceInfo.NONE, new BodyItemI[] {new UnlabeledBreakStatement(SourceInfo.NONE)});
 2944  1 plainBody.visit(_bbtc);
 2945  1 assertEquals("There should be no errors", 0, errors.size());
 2946   
 2947    //Make sure it is okay to throw a Runtime Exception in a braced body, without catching it.
 2948  1 BracedBody runtimeBB = new BracedBody(SourceInfo.NONE,
 2949    new BodyItemI[] {
 2950    new ThrowStatement(SourceInfo.NONE,
 2951    new SimpleNamedClassInstantiation(SourceInfo.NONE,
 2952    new ClassOrInterfaceType(SourceInfo.NONE,
 2953    "java.lang.RuntimeException",
 2954    new Type[0]),
 2955    new ParenthesizedExpressionList(SourceInfo.NONE, new Expression[0])))});
 2956  1 runtimeBB.visit(_bbtc);
 2957  1 assertEquals("There should be no errors", 0, errors.size());
 2958   
 2959    //Make sure it is okay to have a uncaught exception in a braced body, if the method is declared to throw it.
 2960  1 BracedBody bb = new BracedBody(SourceInfo.NONE,
 2961    new BodyItemI[] {
 2962    new ThrowStatement(SourceInfo.NONE,
 2963    new SimpleNamedClassInstantiation(SourceInfo.NONE,
 2964    new ClassOrInterfaceType(SourceInfo.NONE,
 2965    "java.util.prefs.BackingStoreException",
 2966    new Type[0]),
 2967    new ParenthesizedExpressionList(SourceInfo.NONE, new Expression[] {new StringLiteral(SourceInfo.NONE, "wee")})))});
 2968   
 2969  1 _bbtc._bodyData.getMethodData().setThrown(new String[]{"java.util.prefs.BackingStoreException"});
 2970  1 _bbtc._thrown = new LinkedList<Pair<SymbolData, JExpression>>();
 2971   
 2972  1 bb.visit(_bbtc);
 2973  1 assertEquals("There should still be no errors", 0, errors.size());
 2974   
 2975    //make sure it is not okay to have a unchecked exception in a braced body if the method is not declared to throw it.
 2976  1 _bbtc._bodyData.getMethodData().setThrown(new String[0]);
 2977  1 _bbtc._thrown = new LinkedList<Pair<SymbolData, JExpression>>();
 2978   
 2979  1 bb.visit(_bbtc);
 2980   
 2981  1 assertEquals("There should be one error", 1, errors.size());
 2982  1 assertEquals("The error message should be correct", "This statement throws the exception java.util.prefs.BackingStoreException which needs to be caught or declared to be thrown", errors.get(0).getFirst());
 2983   
 2984    //make sure that it is not okay to invoke a method that throws an exception if the enclosing method is not declared to throw it.
 2985  1 MethodData badMethod = new MethodData("throwsException",
 2986    _packageMav,
 2987    new TypeParameter[0],
 2988    SymbolData.INT_TYPE,
 2989    new VariableData[0],
 2990    new String[] {"java.util.prefs.BackingStoreException"},
 2991    _sd1,
 2992    null);
 2993  1 _bbtc._bodyData.getSymbolData().addMethod(badMethod);
 2994  1 _bbtc._thrown = new LinkedList<Pair<SymbolData, JExpression>>();
 2995  1 BracedBody bbMethod =
 2996    new BracedBody(SourceInfo.NONE,
 2997    new BodyItemI[] {
 2998    new ExpressionStatement(SourceInfo.NONE,
 2999    new SimpleMethodInvocation(SourceInfo.NONE,
 3000    new Word(SourceInfo.NONE, "throwsException"),
 3001    new ParenthesizedExpressionList(SourceInfo.NONE,
 3002    new Expression[0])))});
 3003  1 bbMethod.visit(_bbtc);
 3004  1 assertEquals("There should be two errors", 2, errors.size());
 3005  1 assertEquals("The error message should be correct",
 3006    "The method throwsException is declared to throw the exception java.util.prefs.BackingStoreException" +
 3007    " which needs to be caught or declared to be thrown", errors.getLast().getFirst());
 3008   
 3009    //if enclosing method is delared to throw it, should be okay:
 3010  1 _bbtc._bodyData.getMethodData().setThrown(new String[] {"java.util.prefs.BackingStoreException"});
 3011  1 bbMethod.visit(_bbtc);
 3012  1 assertEquals("There should still be two errors", 2, errors.size());
 3013   
 3014   
 3015    //make sure that it is not okay to invoke a constructor that throws an exception if the enclosing method is not declared to throw it
 3016  1 _bbtc._bodyData.getMethodData().setThrown(new String[0]);
 3017  1 _sd3.setMav(_publicMav);
 3018  1 _sd3.setIsContinuation(false);
 3019  1 _bbtc.symbolTable.put(_sd3.getName(), _sd3);
 3020  1 MethodData constructor = new MethodData("zebra", _publicMav, new TypeParameter[0], _sd3, new VariableData[0], new String[] {"java.util.prefs.BackingStoreException"}, _sd3, null);
 3021  1 _sd3.addMethod(constructor);
 3022  1 BracedBody bbConstr = new BracedBody(SourceInfo.NONE, new BodyItemI[]{new ExpressionStatement(SourceInfo.NONE, new SimpleNamedClassInstantiation(SourceInfo.NONE, new ClassOrInterfaceType(SourceInfo.NONE, _sd3.getName(), new Type[0]), new ParenthesizedExpressionList(SourceInfo.NONE, new Expression[0])))});
 3023  1 _bbtc._thrown = new LinkedList<Pair<SymbolData, JExpression>>();
 3024  1 bbConstr.visit(_bbtc);
 3025  1 assertEquals("There should be three errors", 3, errors.size());
 3026  1 assertEquals("The error message should be correct", "The constructor for the class zebra is declared to throw the exception java.util.prefs.BackingStoreException which needs to be caught or declared to be thrown.", errors.getLast().getFirst());
 3027   
 3028   
 3029    //if enclosing method is delared to throw it, should be okay:
 3030  1 _bbtc._bodyData.getMethodData().setThrown(new String[] {"java.util.prefs.BackingStoreException"});
 3031  1 bbConstr.visit(_bbtc);
 3032  1 assertEquals("There should still be three errors", 3, errors.size());
 3033   
 3034   
 3035    }
 3036   
 3037  1 public void testForTryCatchFinallyStatement() {
 3038  1 LanguageLevelVisitor llv =
 3039    new LanguageLevelVisitor(new File(""),
 3040    "",
 3041    null, // enclosingClassName for top level traversal
 3042    new LinkedList<String>(),
 3043    new LinkedList<String>(),
 3044    new HashSet<String>(),
 3045    new Hashtable<String, Triple<SourceInfo, LanguageLevelVisitor, SymbolData>>(),
 3046    new LinkedList<Command>());
 3047  1 llv.errors = new LinkedList<Pair<String, JExpressionIF>>();
 3048  1 llv._errorAdded = false;
 3049    // LanguageLevelConverter.symbolTable = llv.symbolTable = symbolTable;
 3050    // LanguageLevelConverter._newSDs = new Hashtable<SymbolData, LanguageLevelVisitor>();
 3051  1 llv.continuations = new Hashtable<String, Triple<SourceInfo, LanguageLevelVisitor, SymbolData>>();
 3052  1 llv.visitedFiles = new LinkedList<Pair<LanguageLevelVisitor, edu.rice.cs.javalanglevels.tree.SourceFile>>();
 3053    // llv._hierarchy = new Hashtable<String, TypeDefBase>();
 3054  1 llv._classesInThisFile = new HashSet<String>();
 3055   
 3056    // preload symbolTable
 3057  1 SymbolData throwable = llv.getQualifiedSymbolData("java.lang.Throwable");
 3058  1 SymbolData exception = llv.getQualifiedSymbolData("java.lang.Exception");
 3059  1 SymbolData string = llv.getQualifiedSymbolData("java.lang.String");
 3060  1 SymbolData eb = llv.getSymbolData("java.util.prefs.BackingStoreException", SourceInfo.NONE, true);
 3061  1 SymbolData re = llv.getSymbolData("java.lang.RuntimeException", SourceInfo.NONE, true);
 3062   
 3063  1 assert symbolTable.contains(throwable);
 3064  1 assert symbolTable.contains(exception);
 3065  1 assert symbolTable.contains(string);
 3066   
 3067  1 BracedBody emptyBody = new BracedBody(SourceInfo.NONE, new BodyItemI[0]);
 3068  1 BracedBody bb = new BracedBody(SourceInfo.NONE,
 3069    new BodyItemI[] {
 3070    new ThrowStatement(SourceInfo.NONE,
 3071    new SimpleNamedClassInstantiation(SourceInfo.NONE,
 3072    new ClassOrInterfaceType(SourceInfo.NONE,
 3073    "java.util.prefs.BackingStoreException",
 3074    new Type[0]),
 3075    new ParenthesizedExpressionList(SourceInfo.NONE, new Expression[]{new StringLiteral(SourceInfo.NONE, "arg")})))});
 3076   
 3077  1 Block b = new Block(SourceInfo.NONE, bb);
 3078  1 Block b2 = new Block(SourceInfo.NONE, emptyBody);
 3079   
 3080  1 _bbtc._bodyData.getMethodData().setThrown(new String[0]);
 3081  1 _bbtc._bodyData.addBlock(new BlockData(_bbtc._bodyData));
 3082  1 _bbtc._bodyData.addBlock(new BlockData(_bbtc._bodyData));
 3083   
 3084    //Test that an empty finally block behaves as expected
 3085  1 TryCatchFinallyStatement tcfs = new TryCatchFinallyStatement(SourceInfo.NONE, b, new CatchBlock[0], b2);
 3086  1 tcfs.visit(_bbtc);
 3087  1 assertEquals("Should be 1 error", 1, errors.size());
 3088  1 assertEquals("Error message should be correct",
 3089    "This statement throws the exception java.util.prefs.BackingStoreException which needs to be caught"
 3090    + " or declared to be thrown",
 3091    errors.getLast().getFirst());
 3092   
 3093    //Test that a finally block where only one branch ends abruptly acts as expected
 3094  1 IfThenElseStatement ites1 = new IfThenElseStatement(SourceInfo.NONE,
 3095    new BooleanLiteral(SourceInfo.NONE, true),
 3096    new ValueReturnStatement(SourceInfo.NONE, new IntegerLiteral(SourceInfo.NONE, 4)),
 3097    new EmptyStatement(SourceInfo.NONE));
 3098   
 3099  1 BracedBody bb2 = new BracedBody(SourceInfo.NONE, new BodyItemI[] {ites1});
 3100  1 TryCatchFinallyStatement tcfs2 = new TryCatchFinallyStatement(SourceInfo.NONE, b, new CatchBlock[0], new Block(SourceInfo.NONE, bb2));
 3101  1 _bbtc._bodyData.removeAllBlocks();
 3102  1 _bbtc._bodyData.addBlock(new BlockData(_bbtc._bodyData));
 3103  1 _bbtc._bodyData.addBlock(new BlockData(_bbtc._bodyData));
 3104  1 _bbtc._bodyData.resetBlockIterator();
 3105   
 3106  1 TypeData result = tcfs2.visit(_bbtc); // Duplicates previous error
 3107  1 assertEquals("Should return Exception", SymbolData.EXCEPTION.getInstanceData(), result);
 3108  1 assertEquals("Should still be 1 error", 1, errors.size());
 3109  1 assertEquals("Error message should be correct",
 3110    "This statement throws the exception java.util.prefs.BackingStoreException which needs to be caught"
 3111    + " or declared to be thrown",
 3112    errors.get(0).getFirst());
 3113   
 3114    //Test that a finally block where both branches end abruptly acts as expected (break)
 3115  1 IfThenElseStatement ites2 = new IfThenElseStatement(SourceInfo.NONE,
 3116    new BooleanLiteral(SourceInfo.NONE, false),
 3117    new ValueReturnStatement(SourceInfo.NONE, new IntegerLiteral(SourceInfo.NONE, 4)),
 3118    new UnlabeledBreakStatement(SourceInfo.NONE));
 3119   
 3120  1 BracedBody bb3 = new BracedBody(SourceInfo.NONE, new BodyItemI[] {ites2});
 3121  1 TryCatchFinallyStatement tcfs3 = new TryCatchFinallyStatement(SourceInfo.NONE, b, new CatchBlock[0], new Block(SourceInfo.NONE, bb3));
 3122   
 3123  1 _bbtc._bodyData.removeAllBlocks();
 3124  1 _bbtc._bodyData.addBlock(new BlockData(_bbtc._bodyData));
 3125  1 _bbtc._bodyData.addBlock(new BlockData(_bbtc._bodyData));
 3126  1 _bbtc._bodyData.resetBlockIterator();
 3127   
 3128  1 assertEquals("Should return Exception", SymbolData.EXCEPTION.getInstanceData(), tcfs3.visit(_bbtc));
 3129  1 assertEquals("Should still be 1 error", 1, errors.size());
 3130   
 3131   
 3132    //Test that a finally block where both branches end abruptly acts as expected (void return)
 3133  1 _bbtc._bodyData.getMethodData().setReturnType(SymbolData.VOID_TYPE);
 3134  1 IfThenElseStatement ites3 = new IfThenElseStatement(SourceInfo.NONE,
 3135    new BooleanLiteral(SourceInfo.NONE, true),
 3136    new VoidReturnStatement(SourceInfo.NONE),
 3137    new VoidReturnStatement(SourceInfo.NONE));
 3138   
 3139  1 BracedBody bb4 = new BracedBody(SourceInfo.NONE, new BodyItemI[] {ites3});
 3140  1 TryCatchFinallyStatement tcfs4 = new TryCatchFinallyStatement(SourceInfo.NONE, b, new CatchBlock[0], new Block(SourceInfo.NONE, bb4));
 3141  1 _bbtc._bodyData.removeAllBlocks();
 3142  1 _bbtc._bodyData.addBlock(new BlockData(_bbtc._bodyData));
 3143  1 _bbtc._bodyData.addBlock(new BlockData(_bbtc._bodyData));
 3144  1 _bbtc._bodyData.resetBlockIterator();
 3145   
 3146  1 result = tcfs4.visit(_bbtc);
 3147  1 assertEquals("Should return SymbolData.VOID_TYPE", SymbolData.VOID_TYPE.getInstanceData(), result);
 3148   
 3149  1 assertEquals("Should still still be 1 error", 1, errors.size());
 3150   
 3151  1 _bbtc._bodyData.getMethodData().setReturnType(SymbolData.INT_TYPE);
 3152   
 3153   
 3154    // try {
 3155    // try b
 3156    // finally b2 }
 3157    // finally b2
 3158   
 3159    //Test that an error is thrown if a try catch statement is nested, an error is thrown but not caught, and finally doesn't return
 3160  1 TryCatchFinallyStatement inner = new TryCatchFinallyStatement(SourceInfo.NONE, b, new CatchBlock[0], b2);
 3161  1 TryCatchFinallyStatement nested = new TryCatchFinallyStatement(SourceInfo.NONE,
 3162    new Block(SourceInfo.NONE, new BracedBody(SourceInfo.NONE, new BodyItemI[] {inner})),
 3163    new CatchBlock[0], b2);
 3164   
 3165  1 BlockData innerBD = new BlockData(_bbtc._bodyData);
 3166  1 innerBD.addBlock(new BlockData(innerBD));
 3167  1 innerBD.addBlock(new BlockData(innerBD));
 3168   
 3169  1 _bbtc._bodyData.removeAllBlocks();
 3170  1 _bbtc._bodyData.addBlock(innerBD);
 3171  1 _bbtc._bodyData.addBlock(new BlockData(_bbtc._bodyData));
 3172   
 3173  1 _bbtc._bodyData.resetBlockIterator();
 3174   
 3175  1 nested.visit(_bbtc); // Duplicates existing error
 3176  1 assertEquals("There should still be 1 errors", 1, errors.size());
 3177  1 assertEquals("Error message should be correct",
 3178    "This statement throws the exception java.util.prefs.BackingStoreException which needs to be caught"
 3179    + " or declared to be thrown",
 3180    errors.get(0).getFirst());
 3181   
 3182    //Test that no error is thrown if the exception is caught
 3183  1 UninitializedVariableDeclarator uvd1 = new UninitializedVariableDeclarator(SourceInfo.NONE, new ClassOrInterfaceType(SourceInfo.NONE, "java.util.prefs.BackingStoreException", new Type[0]), new Word(SourceInfo.NONE, "e"));
 3184  1 FormalParameter fp1 = new FormalParameter(SourceInfo.NONE, uvd1, false);
 3185  1 BlockData catchBD = new BlockData(_bbtc._bodyData);
 3186  1 VariableData fpData = new VariableData("e", null, eb, true, catchBD);
 3187  1 catchBD.addVar(fpData);
 3188   
 3189  1 CatchBlock cb = new CatchBlock(SourceInfo.NONE, fp1, b2);
 3190  1 TryCatchFinallyStatement nested2 = new TryCatchFinallyStatement(SourceInfo.NONE, new Block(SourceInfo.NONE, new BracedBody(SourceInfo.NONE, new BodyItemI[] {inner})), new CatchBlock[] {cb}, b2);
 3191  1 _bbtc._bodyData.removeAllBlocks();
 3192  1 innerBD.resetBlockIterator();
 3193  1 _bbtc._bodyData.addBlock(innerBD);
 3194  1 _bbtc._bodyData.addBlock(catchBD);
 3195  1 _bbtc._bodyData.addBlock(new BlockData(_bbtc._bodyData));
 3196  1 _bbtc._bodyData.resetBlockIterator();
 3197   
 3198  1 nested2.visit(_bbtc);
 3199  1 assertEquals("There should still be 1 error", 1, errors.size());
 3200   
 3201    //Test that no error is thrown if it is a runtime exception
 3202  1 BracedBody reb = new BracedBody(SourceInfo.NONE,
 3203    new BodyItemI[] {
 3204    new ThrowStatement(SourceInfo.NONE,
 3205    new SimpleNamedClassInstantiation(SourceInfo.NONE,
 3206    new ClassOrInterfaceType(SourceInfo.NONE,
 3207    "java.lang.RuntimeException",
 3208    new Type[0]),
 3209    new ParenthesizedExpressionList(SourceInfo.NONE, new Expression[0])))});
 3210   
 3211    // try {
 3212    // try {
 3213    // reb
 3214    // }
 3215    // finally b2
 3216    // }
 3217    // finally b2
 3218    // }
 3219   
 3220  1 TryCatchFinallyStatement inner3 = new TryCatchFinallyStatement(SourceInfo.NONE,
 3221    new Block(SourceInfo.NONE, reb), new CatchBlock[0], b2);
 3222  1 TryCatchFinallyStatement nested3 = new TryCatchFinallyStatement(SourceInfo.NONE,
 3223    new Block(SourceInfo.NONE,
 3224    new BracedBody(SourceInfo.NONE, new BodyItemI[] {inner3})),
 3225    new CatchBlock[0], b2);
 3226   
 3227  1 _bbtc._bodyData.removeAllBlocks();
 3228  1 innerBD.resetBlockIterator();
 3229  1 _bbtc._bodyData.addBlock(innerBD);
 3230  1 _bbtc._bodyData.addBlock(new BlockData(_bbtc._bodyData));
 3231  1 _bbtc._bodyData.resetBlockIterator();
 3232   
 3233  1 nested3.visit(_bbtc);
 3234    // System.err.println("Last error was " + errors.getLast().getFirst());
 3235  1 assertEquals("There should still be 1 error", 1, errors.size());
 3236   
 3237    //Test that no error is thrown if the method is declared to throw it
 3238  1 _bbtc._bodyData.getMethodData().setThrown(new String[]{"java.util.prefs.BackingStoreException"});
 3239  1 innerBD.resetBlockIterator();
 3240  1 _bbtc._bodyData.resetBlockIterator();
 3241  1 nested.visit(_bbtc);
 3242  1 assertEquals("There should still be 1 error!", 1, errors.size());
 3243    }
 3244   
 3245  1 public void testForNormalTryCatchStatement() {
 3246  1 LanguageLevelVisitor llv =
 3247    new LanguageLevelVisitor(new File(""),
 3248    "",
 3249    null, // enclosingClassName for top level traversal
 3250    new LinkedList<String>(),
 3251    new LinkedList<String>(),
 3252    new HashSet<String>(),
 3253    new Hashtable<String, Triple<SourceInfo, LanguageLevelVisitor, SymbolData>>(),
 3254    new LinkedList<Command>());
 3255  1 llv.errors = new LinkedList<Pair<String, JExpressionIF>>();
 3256  1 llv._errorAdded=false;
 3257    // LanguageLevelConverter.symbolTable = llv.symbolTable = symbolTable;
 3258    // LanguageLevelConverter._newSDs = new Hashtable<SymbolData, LanguageLevelVisitor>();
 3259  1 llv.continuations = new Hashtable<String, Triple<SourceInfo, LanguageLevelVisitor, SymbolData>>();
 3260  1 llv.visitedFiles = new LinkedList<Pair<LanguageLevelVisitor, edu.rice.cs.javalanglevels.tree.SourceFile>>();
 3261    // llv._hierarchy = new Hashtable<String, TypeDefBase>();
 3262  1 llv._classesInThisFile = new HashSet<String>();
 3263   
 3264    // preload symbolTable
 3265  1 SymbolData throwable = llv.getQualifiedSymbolData("java.lang.Throwable");
 3266  1 SymbolData exception = llv.getQualifiedSymbolData("java.lang.Exception");
 3267  1 SymbolData string = llv.getQualifiedSymbolData("java.lang.String");
 3268  1 SymbolData eb = llv.getQualifiedSymbolData("java.util.prefs.BackingStoreException");
 3269  1 SymbolData re = llv.getQualifiedSymbolData("java.lang.RuntimeException");
 3270   
 3271  1 assert symbolTable.contains(throwable);
 3272  1 assert symbolTable.contains(exception);
 3273  1 assert symbolTable.contains(string);
 3274   
 3275  1 BracedBody emptyBody = new BracedBody(SourceInfo.NONE, new BodyItemI[0]);
 3276  1 BracedBody bb = new BracedBody(SourceInfo.NONE,
 3277    new BodyItemI[] {
 3278    new ThrowStatement(SourceInfo.NONE,
 3279    new SimpleNamedClassInstantiation(SourceInfo.NONE,
 3280    new ClassOrInterfaceType(SourceInfo.NONE,
 3281    "java.util.prefs.BackingStoreException",
 3282    new Type[0]),
 3283    new ParenthesizedExpressionList(SourceInfo.NONE, new Expression[]{new StringLiteral(SourceInfo.NONE, "boo")})))});
 3284   
 3285  1 Block b = new Block(SourceInfo.NONE, bb);
 3286  1 Block b2 = new Block(SourceInfo.NONE, emptyBody);
 3287   
 3288  1 _bbtc._bodyData.getMethodData().setThrown(new String[0]);
 3289   
 3290   
 3291    // Test that an empty finally block behaves as expected
 3292  1 NormalTryCatchStatement tcfs = new NormalTryCatchStatement(SourceInfo.NONE, b, new CatchBlock[0]);
 3293  1 _bbtc._bodyData.addBlock(new BlockData(_bbtc._bodyData));
 3294  1 tcfs.visit(_bbtc);
 3295  1 assertEquals("Should be 1 error", 1, errors.size());
 3296  1 assertEquals("Error message should be correct",
 3297    "This statement throws the exception java.util.prefs.BackingStoreException " +
 3298    "which needs to be caught or declared to be thrown",
 3299    // "You are attempting to throw java.util.prefs.BackingStoreException, which does not implement the "
 3300    // + "Throwable interface",
 3301    errors.getLast().getFirst());
 3302   
 3303    // Test that an error is thrown if a try catch statement is nested, an error is thrown but not caught, and finally doesn't return
 3304  1 NormalTryCatchStatement inner = new NormalTryCatchStatement(SourceInfo.NONE, b, new CatchBlock[0]);
 3305  1 NormalTryCatchStatement nested = new NormalTryCatchStatement(SourceInfo.NONE, new Block(SourceInfo.NONE, new BracedBody(SourceInfo.NONE, new BodyItemI[] {inner})), new CatchBlock[0]);
 3306   
 3307  1 BlockData innerBD = new BlockData(_bbtc._bodyData);
 3308  1 innerBD.addBlock(new BlockData(innerBD));
 3309  1 innerBD.addBlock(new BlockData(innerBD));
 3310   
 3311  1 _bbtc._bodyData.removeAllBlocks();
 3312  1 _bbtc._bodyData.addBlock(innerBD);
 3313  1 _bbtc._bodyData.addBlock(new BlockData(_bbtc._bodyData));
 3314   
 3315  1 _bbtc._bodyData.resetBlockIterator();
 3316   
 3317  1 nested.visit(_bbtc);
 3318  1 assertEquals("There should still be be 1 error", 1, errors.size()); // Generated error is a duplicate!
 3319  1 assertEquals("Error message should be correct",
 3320    // "You are attempting to throw java.util.prefs.BackingStoreException, which does not implement the"
 3321    // + " Throwable interface",
 3322    "This statement throws the exception java.util.prefs.BackingStoreException " +
 3323    "which needs to be caught or declared to be thrown",
 3324    errors.get(0).getFirst());
 3325   
 3326    // Test that no error is thrown if the exception is caught
 3327  1 UninitializedVariableDeclarator uvd1 = new UninitializedVariableDeclarator(SourceInfo.NONE, new ClassOrInterfaceType(SourceInfo.NONE, "java.util.prefs.BackingStoreException", new Type[0]), new Word(SourceInfo.NONE, "e"));
 3328  1 FormalParameter fp1 = new FormalParameter(SourceInfo.NONE, uvd1, false);
 3329  1 BlockData catchBD = new BlockData(_bbtc._bodyData);
 3330  1 VariableData fpData = new VariableData("e", null, eb, true, catchBD);
 3331  1 catchBD.addVar(fpData);
 3332   
 3333   
 3334  1 CatchBlock cb = new CatchBlock(SourceInfo.NONE, fp1, b2);
 3335  1 NormalTryCatchStatement nested2 = new NormalTryCatchStatement(SourceInfo.NONE, new Block(SourceInfo.NONE, new BracedBody(SourceInfo.NONE, new BodyItemI[] {inner})), new CatchBlock[] {cb});
 3336   
 3337  1 _bbtc._bodyData.removeAllBlocks();
 3338  1 innerBD.resetBlockIterator();
 3339  1 _bbtc._bodyData.addBlock(innerBD);
 3340  1 _bbtc._bodyData.addBlock(catchBD);
 3341  1 _bbtc._bodyData.addBlock(new BlockData(_bbtc._bodyData));
 3342  1 _bbtc._bodyData.resetBlockIterator();
 3343   
 3344  1 nested2.visit(_bbtc);
 3345  1 assertEquals("There should still be 1 error", 1, errors.size());
 3346   
 3347    // Test that no error is thrown if it is a runtime exception
 3348  1 BracedBody reb = new BracedBody(SourceInfo.NONE,
 3349    new BodyItemI[] {
 3350    new ThrowStatement(SourceInfo.NONE,
 3351    new SimpleNamedClassInstantiation(SourceInfo.NONE,
 3352    new ClassOrInterfaceType(SourceInfo.NONE,
 3353    "java.lang.RuntimeException",
 3354    new Type[0]),
 3355    new ParenthesizedExpressionList(SourceInfo.NONE, new Expression[0])))});
 3356   
 3357  1 NormalTryCatchStatement inner3 = new NormalTryCatchStatement(SourceInfo.NONE, new Block(SourceInfo.NONE, reb), new CatchBlock[0]);
 3358  1 NormalTryCatchStatement nested3 = new NormalTryCatchStatement(SourceInfo.NONE, new Block(SourceInfo.NONE, new BracedBody(SourceInfo.NONE, new BodyItemI[] {inner3})), new CatchBlock[0]);
 3359   
 3360  1 _bbtc._bodyData.removeAllBlocks();
 3361  1 innerBD.resetBlockIterator();
 3362  1 _bbtc._bodyData.addBlock(innerBD);
 3363  1 _bbtc._bodyData.addBlock(new BlockData(_bbtc._bodyData));
 3364  1 _bbtc._bodyData.addBlock(new BlockData(_bbtc._bodyData));
 3365  1 _bbtc._bodyData.resetBlockIterator();
 3366   
 3367   
 3368  1 nested3.visit(_bbtc);
 3369    // System.err.println("Last error is: " + errors.getLast().getFirst());
 3370  1 assertEquals("There should still be 1 error", 1, errors.size());
 3371   
 3372    // Test that no error is thrown if the method is declared to throw it
 3373  1 _bbtc._bodyData.getMethodData().setThrown(new String[]{"java.util.prefs.BackingStoreException"});
 3374  1 _bbtc._bodyData.removeAllBlocks();
 3375  1 innerBD.resetBlockIterator();
 3376  1 _bbtc._bodyData.addBlock(innerBD);
 3377  1 _bbtc._bodyData.addBlock(new BlockData(_bbtc._bodyData));
 3378  1 _bbtc._bodyData.addBlock(new BlockData(_bbtc._bodyData));
 3379  1 _bbtc._bodyData.resetBlockIterator();
 3380   
 3381  1 nested.visit(_bbtc);
 3382  1 assertEquals("There should still be 1 error!", 1, errors.size());
 3383    }
 3384    }
 3385    }