Clover coverage report - Java Language Levels Test Coverage (javalanglevels-20120305-r5436)
Coverage timestamp: Sun Mar 4 2012 22:02:46 CST
file stats: LOC: 782   Methods: 22
NCLOC: 526   Classes: 2
 
 Source file Conditionals Statements Methods TOTAL
ConstructorBodyTypeChecker.java 85% 97.1% 95.5% 94.9%
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   
 44    import junit.framework.TestCase;
 45   
 46    /** Do the TypeChecking appropriate to the context of a constructor body. Common to all Language Levels. */
 47    public class ConstructorBodyTypeChecker extends BodyTypeChecker {
 48   
 49    /** Constructor for ConstructorBodyTypeChecker.
 50    * @param bodyData The bodyData corresponding to the constructor we are visiting
 51    * @param file The File corresponding to the source file we are checking.
 52    * @param packageName The package of the source file.
 53    * @param importedFiles A list of the names of the classes that are specifically imported in the source file
 54    * @param importedPackages A list of the names of the packages that are imported in the source file.
 55    * @param vars A list of the variable datas that can be seen and have been given a value before this context
 56    * @param thrown The exceptions that are thrown
 57    */
 58  29 public ConstructorBodyTypeChecker(BodyData bodyData, File file, String packageName, LinkedList<String> importedFiles,
 59    LinkedList<String> importedPackages, LinkedList<VariableData> vars,
 60    LinkedList<Pair<SymbolData, JExpression>> thrown) {
 61  29 super(bodyData, file, packageName, importedFiles, importedPackages, vars, thrown);
 62    }
 63   
 64   
 65    /** Creates a new instance of this class for visiting inner bodies. */
 66  1 protected BodyTypeChecker
 67    createANewInstanceOfMe(BodyData bodyData, File file, String pakage, LinkedList<String> importedFiles,
 68    LinkedList<String> importedPackages, LinkedList<VariableData> vars,
 69    LinkedList<Pair<SymbolData, JExpression>> thrown) {
 70  1 return new ConstructorBodyTypeChecker(bodyData, file, pakage, importedFiles, importedPackages, vars, thrown);
 71    }
 72   
 73   
 74    /** This is used in the case where a simple this constructor invocation is allowed. i.e. when it is the first
 75    * statement of a constructor body.
 76    */
 77  6 public TypeData simpleThisConstructorInvocationAllowed(SimpleThisConstructorInvocation that) {
 78    //Verify that a constructor of this form is in this--if not, an error will be thrown by this method invocation.
 79    //we continue with this method regardless.
 80  6 String name = LanguageLevelVisitor.getUnqualifiedClassName(_data.getSymbolData().getName());
 81  6 InstanceData[] args = getArgTypesForInvocation(that.getArguments());
 82  0 if (args == null) {return null;}
 83  6 MethodData cd = _lookupMethod(name, _data.getSymbolData(), args, that,
 84    "No constructor found in class " + _data.getSymbolData().getName() + " with signature: ",
 85    true, _data.getSymbolData());
 86   
 87  1 if (cd==null) {return null;}
 88   
 89    //set all final fields to have a value--they should have gotten caught.
 90  5 LinkedList<VariableData> myFields = _data.getSymbolData().getVars();
 91  5 for (int i = 0; i<myFields.size(); i++) {
 92  7 if (myFields.get(i).hasModifier("final")) {
 93  5 _vars.get(_vars.indexOf(myFields.get(i))).gotValue();
 94  5 thingsThatHaveBeenAssigned.addLast(_vars.get(_vars.indexOf(myFields.get(i))));
 95    }
 96    }
 97   
 98    // if constructor is declared to throw exceptions, add them to thrown list:
 99  5 String[] thrown = cd.getThrown();
 100  5 for (int i = 0; i < thrown.length; i++) {
 101  3 _thrown.addLast(new Pair<SymbolData, JExpression>(getSymbolData(thrown[i], _getData(), that), that));
 102    }
 103  5 return null;
 104    }
 105   
 106    /** ComplexThisConstructorInvocations are not ever allowed--throw an appropriate error. */
 107  1 public TypeData complexThisConstructorInvocationNotAllowed(ComplexThisConstructorInvocation that) {
 108  1 _addError("Constructor Invocations of this form are never allowed. A constructor invocation can appear here, "
 109    + "but it must either be a super constructor invocation or have the form this(...)", that);
 110  1 return null;
 111    }
 112   
 113    /** This is used in the case where a simple super constructor invocation is allowed i.e. when it is the first statement
 114    * of a constructor body.
 115    */
 116  10 public TypeData simpleSuperConstructorInvocationAllowed(SimpleSuperConstructorInvocation that) {
 117   
 118  10 SymbolData superClass = _data.getSymbolData().getSuperClass();
 119   
 120  10 if (superClass == null) { //This should never happen.
 121  1 _addError("The class " + _data.getSymbolData().getName() + " does not have a super class", that);
 122  1 return null;
 123    }
 124   
 125    //If the super class is an inner class, a constructor of this form can only be used if it is static.
 126  9 if (superClass.getOuterData() != null && !(superClass.hasModifier("static"))) {
 127  1 _addError(superClass.getName() + " is a non-static inner class of " + superClass.getOuterData().getName() + ". Its constructor must be invoked from an instance of its outer class", that);
 128  1 return null;
 129    }
 130   
 131   
 132    //Look in this's super class and try to match the invocation. If no match is found, the method invocation will add an error.
 133  8 String name = LanguageLevelVisitor.getUnqualifiedClassName(superClass.getName());
 134  8 InstanceData[] args = getArgTypesForInvocation(that.getArguments());
 135  0 if (args == null) return null;
 136  8 MethodData cd = _lookupMethod(name, superClass, args, that,
 137    "No constructor found in class " + superClass.getName() + " with signature: ",
 138    true, superClass);
 139   
 140  1 if (cd == null) return null;
 141   
 142    // if constructor is declared to throw exceptions, add them to thrown list:
 143  7 String[] thrown = cd.getThrown();
 144  7 for (int i = 0; i < thrown.length; i++) {
 145  3 _thrown.addLast(new Pair<SymbolData, JExpression>(getSymbolData(thrown[i], _getData(), that), that));
 146    }
 147  7 return null;
 148    }
 149   
 150    /** This is used in the case where a complex super constructor invocation is allowed i.e. when it is the first
 151    * statement of a constructor body.
 152    */
 153  10 public TypeData complexSuperConstructorInvocationAllowed(ComplexSuperConstructorInvocation that) {
 154    //resolve the first part of the super invocation using an ETC and super class and try to match the invocation.
 155  10 ExpressionTypeChecker etc = new ExpressionTypeChecker(_data, _file, _package, _importedFiles, _importedPackages,
 156    _vars, _thrown);
 157  10 TypeData enclosingResult = that.getEnclosing().visit(etc);
 158  10 thingsThatHaveBeenAssigned.addAll(etc.thingsThatHaveBeenAssigned);
 159   
 160  1 if (! assertFound(enclosingResult, that)) return null;
 161  9 SymbolData superClass = _data.getSymbolData().getSuperClass();
 162   
 163    //enclosingResult must be the outerclass of the super class of this class.
 164  9 if (superClass == null) {
 165  1 _addError("A qualified super constructor invocation can only be used to invoke the constructor of your super "
 166    + "class from the context of its outer class. The class " + _data.getSymbolData().getName() +
 167    " does not have a super class, so you cannot do this here",
 168    that);
 169  1 return null;
 170    }
 171  8 else if (superClass.getOuterData() == null) {
 172  1 _addError("A qualified super constructor invocation can only be used to invoke the constructor of your super "
 173    + "class from the context of its outer class. The super class " + superClass.getName()
 174    + " does not have an outer class, so you cannot do this here",
 175    that);
 176  1 return null;
 177    }
 178  7 else if (enclosingResult == null) {
 179  0 _addError("A qualified super constructor invocation can only be used to invoke the constructor of your super "
 180    + "class from the context of its outer class.",
 181    that);
 182  0 return null;
 183    }
 184  7 else if (superClass.getOuterData() != enclosingResult.getSymbolData()) {
 185  1 _addError("A qualified super constructor invocation can only be used to invoke the constructor of your super "
 186    + "class from the context of its outer class. The class or interface "
 187    + enclosingResult.getSymbolData().getName() + " is not the outer class of the super class "
 188    + superClass.getName(),
 189    that);
 190  1 return null;
 191    }
 192  6 else if (!enclosingResult.isInstanceType()) {
 193  1 _addError("A qualified super constructor invocation can only be made from the context of an instance of the "
 194    + "outer class of the super class. You have specified a type name",
 195    that);
 196  1 return null;
 197    }
 198  5 else if (superClass.hasModifier("static")) {
 199  1 _addError("A qualified super constructor invocation can only be used to invoke the constructor of a non-static "
 200    + "super class from the context of its outer class. The super class " + superClass.getName()
 201    + " is a static inner class",
 202    that);
 203  1 return null;
 204    }
 205  4 String name = LanguageLevelVisitor.getUnqualifiedClassName(superClass.getName());
 206  4 InstanceData[] args = getArgTypesForInvocation(that.getArguments());
 207  0 if (args == null) {return null;}
 208  4 MethodData cd = _lookupMethod(name, superClass, args, that,
 209    "No constructor found in class " + superClass.getName() + " with signature: ",
 210    true, superClass);
 211  1 if (cd == null) {return null;}
 212    //if constructor is declared to throw exceptions, add them to thrown list:
 213  3 String[] thrown = cd.getThrown();
 214  3 for (int i = 0; i<thrown.length; i++) {
 215  3 _thrown.addLast(new Pair<SymbolData, JExpression>(getSymbolData(thrown[i], _getData(), that), that));
 216    }
 217  3 return null;
 218    }
 219   
 220    /** Called when the first line of a constructor is not an explicit constructor invocation.
 221    * In this case, if the class has a super class (which it should), we assume there is an implicit call
 222    * to the super constructor, passing no arguments.
 223    */
 224  25 private void implicitSuperConstructor(BracedBody that) {
 225    // System.err.println("implicitSuperConstructor called for " + _data.getSymbolData());
 226  25 SymbolData superClass = _data.getSymbolData().getSuperClass();
 227   
 228  25 if (superClass == null) { //This should never happen, but if it does, no reason to throw an error.
 229  2 return;
 230    }
 231   
 232    //If the super class is an inner class, there cannot be an implicit constructor call
 233  23 if (superClass.getOuterData() != null && !(superClass.hasModifier("static"))) {
 234  1 _addError("There is an implicit call to the constructor of " + superClass.getName() + " here, but " +
 235    superClass.getName() + " is a non-static inner class of " + superClass.getOuterData().getName() +
 236    ". Thus, you must explicitly invoke its constructor from an instance of its outer class",
 237    that);
 238  1 return;
 239    }
 240   
 241   
 242    // Look in this's super class and try to match the invocation. If no match is found, the method invocation will
 243    // add an error.
 244  22 String name = LanguageLevelVisitor.getUnqualifiedClassName(superClass.getName());
 245   
 246    // There must be a default constructor with no arguments, or an error is thrown.
 247    // (Note--if there were no constructors in the super class at all, the default no arguments constructor would exist.
 248    // However, a constructor is always generated for a LanguageLevel file, and any class file that relied on the
 249    // default constructor would already have it. Therefore, we can assume that all classes have at least one constructor).
 250   
 251  22 MethodData cd =
 252    _lookupMethod(name,
 253    superClass,
 254    new InstanceData[0],
 255    that,
 256    "You must invoke one of " + superClass.getName() +
 257    "'s constructors here. You can either explicitly invoke one of its exisitng constructors or "
 258    + "add a constructor with signature: ",
 259    true, superClass);
 260   
 261  4 if (cd == null) return;
 262    // if constructor is declared to throw exceptions, add them to thrown list:
 263    // add BracedBody as the JExpression corresponding to the error
 264  18 String[] thrown = cd.getThrown();
 265  18 for (int i = 0; i<thrown.length; i++) {
 266  3 _thrown.addLast(new Pair<SymbolData, JExpression>(getSymbolData(thrown[i], _getData(), that), that));
 267    }
 268  18 return;
 269    }
 270   
 271    /** Void return statements are allowed in constructor bodies, since according to java, constructors are
 272    * void return methods. However, we treat them as if they returned an instance of the class they
 273    * are a constructor for, so we will return that symbol data here.
 274    */
 275  1 public TypeData forVoidReturnStatementOnly(VoidReturnStatement that) {
 276    // Just return the type the constructor would return.
 277  1 return _bodyData.getSymbolData().getInstanceData();
 278    }
 279   
 280    /** Throw an error and return null, becuase constructors cannot have value return statements in their bodies. */
 281  1 public TypeData forValueReturnStatementOnly(ValueReturnStatement that, TypeData valueRes) {
 282  1 _addError("You cannot return a value from a class's constructor", that);
 283  1 return _bodyData.getSymbolData().getInstanceData();
 284    }
 285   
 286    /** Walk over the statements in the BracedBody, treating the first line specially. A super constructor
 287    * invocation can only appear on the first line of a constructor, so see if there is one on the
 288    * first line, and if so, call the appropriate method. If there is no super constructor invocation,
 289    * then assume there is an implicit one. Then visit the rest of the statements in the body like normal.
 290    * Make sure errors are thrown for any uncaught exceptions.
 291    */
 292  29 public TypeData forBracedBody(BracedBody that) {
 293    // System.err.println("forBracedBody called in " + _data.getSymbolData() + " for " + that);
 294  29 int startIndex = 0;
 295  29 final TypeData[] items_result = makeArrayOfRetType(that.getStatements().length);
 296  29 if (items_result.length > 0) {
 297    // The first line of a constructor is treated specially:
 298  22 if (that.getStatements()[0] instanceof ExpressionStatement) {
 299  20 Expression firstExpression = ((ExpressionStatement) that.getStatements()[0]).getExpression();
 300  20 if (firstExpression instanceof SimpleThisConstructorInvocation) {
 301  3 items_result[0] = simpleThisConstructorInvocationAllowed((SimpleThisConstructorInvocation) firstExpression);
 302  3 startIndex ++;
 303    }
 304   
 305  17 else if (firstExpression instanceof ComplexThisConstructorInvocation) {
 306  0 items_result[0] = complexThisConstructorInvocationNotAllowed((ComplexThisConstructorInvocation) firstExpression);
 307  0 startIndex++;
 308    }
 309  17 else if (firstExpression instanceof SimpleSuperConstructorInvocation) {
 310  4 items_result[0] = simpleSuperConstructorInvocationAllowed((SimpleSuperConstructorInvocation) firstExpression);
 311  4 startIndex++;
 312    }
 313  13 else if (firstExpression instanceof ComplexSuperConstructorInvocation) {
 314  2 items_result[0] = complexSuperConstructorInvocationAllowed((ComplexSuperConstructorInvocation) firstExpression);
 315  2 startIndex++;
 316    }
 317    }
 318    }
 319  20 if (startIndex == 0) implicitSuperConstructor(that);
 320   
 321  29 int thrownSize = _thrown.size();
 322    // System.err.println("_thrown.size() in " + _data + " = " + thrownSize);
 323  29 for (int j = 0; j < thrownSize; j++) {
 324  9 if (isUncaughtCheckedException(_thrown.get(j).getFirst(), that)) {
 325  4 handleUncheckedException(_thrown.get(j).getFirst(), _thrown.get(j).getSecond());
 326    }
 327    }
 328    // TODO: ???? Provision for field initialization?
 329    /** The following is supposed to be equivalent to calling SpecialTypeChecker.forBody(that, items_result) */
 330  29 for (int i = startIndex; i < that.getStatements().length; i++) {
 331  18 items_result[i] = that.getStatements()[i].visit(this);
 332    // Walk over what has been thrown and throw an error if it contains an unchecked exception
 333  18 for (int j = thrownSize; j < _thrown.size(); j++) {
 334  0 if (isUncaughtCheckedException(_thrown.get(j).getFirst(), that)) {
 335  0 handleUncheckedException(_thrown.get(j).getFirst(), _thrown.get(j).getSecond());
 336    }
 337    }
 338    }
 339   
 340  29 return forBracedBodyOnly(that, items_result);
 341    }
 342   
 343    /** Tests the methods in the above class. */
 344    public static class ConstructorBodyTypeCheckerTest extends TestCase {
 345   
 346    private ConstructorBodyTypeChecker _cbtc;
 347   
 348    private MethodData _bd1;
 349    // private MethodData _bd2;
 350   
 351    private SymbolData _sd1;
 352    private SymbolData _sd2;
 353    private SymbolData _sd3;
 354    private SymbolData _sd4;
 355    private SymbolData _sd5;
 356    private SymbolData _sd6;
 357    private ModifiersAndVisibility _publicMav = new ModifiersAndVisibility(SourceInfo.NONE, new String[] {"public"});
 358    private ModifiersAndVisibility _protectedMav =
 359    new ModifiersAndVisibility(SourceInfo.NONE, new String[] {"protected"});
 360    private ModifiersAndVisibility _privateMav =
 361    new ModifiersAndVisibility(SourceInfo.NONE, new String[] {"private"});
 362    private ModifiersAndVisibility _packageMav = new ModifiersAndVisibility(SourceInfo.NONE, new String[0]);
 363    private ModifiersAndVisibility _abstractMav =
 364    new ModifiersAndVisibility(SourceInfo.NONE, new String[] {"abstract"});
 365    private ModifiersAndVisibility _finalMav = new ModifiersAndVisibility(SourceInfo.NONE, new String[] {"final"});
 366   
 367  0 public ConstructorBodyTypeCheckerTest() { this(""); }
 368  9 public ConstructorBodyTypeCheckerTest(String name) { super(name); }
 369   
 370  9 public void setUp() {
 371  9 _sd1 = new SymbolData("i.like.monkey");
 372  9 _sd2 = new SymbolData("i.like.giraffe");
 373  9 _sd3 = new SymbolData("zebra");
 374  9 _sd4 = new SymbolData("u.like.emu");
 375  9 _sd5 = new SymbolData("elephant");
 376  9 _sd6 = new SymbolData("cebu");
 377   
 378  9 VariableData[] vds = new VariableData[] { new VariableData("i", _publicMav, SymbolData.INT_TYPE, true, null),
 379    new VariableData(SymbolData.BOOLEAN_TYPE) };
 380  9 _bd1 = new MethodData("monkey",
 381    _packageMav,
 382    new TypeParameter[0],
 383    _sd1,
 384    vds,
 385    new String[0],
 386    _sd1,
 387    null); // no SourceInfo
 388   
 389  9 _bd1.getParams()[0].setEnclosingData(_bd1);
 390  9 _bd1.getParams()[1].setEnclosingData(_bd1);
 391   
 392  9 errors = new LinkedList<Pair<String, JExpressionIF>>();
 393  9 LanguageLevelConverter.symbolTable.clear();
 394  9 LanguageLevelConverter._newSDs.clear();
 395  9 _bd1.addEnclosingData(_sd1);
 396  9 _bd1.addVars(_bd1.getParams());
 397  9 _cbtc = new ConstructorBodyTypeChecker(_bd1,
 398    new File(""),
 399    "",
 400    new LinkedList<String>(),
 401    new LinkedList<String>(),
 402    new LinkedList<VariableData>(),
 403    new LinkedList<Pair<SymbolData, JExpression>>());
 404  9 _cbtc._importedPackages.addFirst("java.lang");
 405    }
 406   
 407   
 408  1 public void testForVoidReturnStatementOnly() {
 409  1 _cbtc._bodyData = _bd1; // this body data returns _sd1 (yeah, it's a constructor)
 410   
 411    //test one that works
 412  1 BracedBody bb1 = new BracedBody(SourceInfo.NONE,
 413    new BodyItemI[] { new VoidReturnStatement(SourceInfo.NONE)});
 414   
 415  1 TypeData sd = bb1.visit(_cbtc);
 416   
 417  1 assertEquals("There should be no errors.", 0, errors.size());
 418  1 assertEquals("Should return i.like.monkey type.", _sd1.getInstanceData(), sd);
 419   
 420    }
 421   
 422  1 public void testforValueReturnStatementOnly() {
 423    //value return statement should always throw an error.
 424  1 BodyItemI[] bis =
 425    new BodyItemI[] { new ValueReturnStatement(SourceInfo.NONE,
 426    new BooleanLiteral(SourceInfo.NONE, true))};
 427  1 BracedBody bb1 = new BracedBody(SourceInfo.NONE, bis);
 428  1 TypeData sd = bb1.visit(_cbtc);
 429  1 assertEquals("There should be one error", 1, errors.size());
 430  1 assertEquals("Should return i.like.monkey type", _sd1.getInstanceData(), sd);
 431  1 assertEquals("Error message should be correct", "You cannot return a value from a class's constructor",
 432    errors.get(0).getFirst());
 433   
 434    }
 435   
 436  1 public void testCreateANewInstanceOfMe() {
 437    //make sure that the correct visitor is returned from createANewInstanceOfMe
 438  1 BodyTypeChecker btc =
 439    _cbtc.createANewInstanceOfMe(_cbtc._bodyData, _cbtc._file, _cbtc._package, _cbtc._importedFiles,
 440    _cbtc._importedPackages, _cbtc._vars, _cbtc._thrown);
 441  1 assertTrue("Should be an instance of ConstructorBodyTypeChecker", btc instanceof ConstructorBodyTypeChecker);
 442    }
 443   
 444  1 public void testForBracedBody() {
 445  1 LanguageLevelVisitor llv =
 446    new LanguageLevelVisitor(new File(""),
 447    "",
 448    null, // enclosingClassName for top level traversal
 449    new LinkedList<String>(),
 450    new LinkedList<String>(),
 451    new HashSet<String>(),
 452    new Hashtable<String, Triple<SourceInfo, LanguageLevelVisitor, SymbolData>>(),
 453    new LinkedList<Command>());
 454  1 llv.errors = new LinkedList<Pair<String, JExpressionIF>>();
 455  1 llv._errorAdded=false;
 456    // LanguageLevelConverter.symbolTable = llv.symbolTable = new Symboltable();
 457  1 llv.continuations = new Hashtable<String, Triple<SourceInfo, LanguageLevelVisitor, SymbolData>>();
 458  1 llv.visitedFiles = new LinkedList<Pair<LanguageLevelVisitor, edu.rice.cs.javalanglevels.tree.SourceFile>>();
 459    // llv._hierarchy = new Hashtable<String, TypeDefBase>();
 460  1 llv._classesInThisFile = new HashSet<String>();
 461   
 462    // TODO: The next line should be unnecessary because the subsequent two lines should force its loading
 463  1 SymbolData throwable = llv.getSymbolData("java.lang.Exception", SourceInfo.NONE, true);
 464  1 SymbolData eb = llv.getSymbolData("java.util.prefs.BackingStoreException", SourceInfo.NONE, true);
 465  1 SymbolData re = llv.getSymbolData("java.lang.RuntimeException", SourceInfo.NONE, true);
 466    // LanguageLevelConverter.symbolTable = symbolTable = llv.symbolTable;
 467   
 468  1 assert symbolTable.contains(eb);
 469  1 assert symbolTable.contains(re);
 470  1 assert symbolTable.containsKey("java.lang.Throwable");
 471  1 assert symbolTable.containsKey("java.lang.Exception");
 472   
 473  1 _sd3.setIsContinuation(false);
 474  1 _sd3.setMav(_publicMav);
 475  1 _sd1.setSuperClass(_sd3);
 476    // Make sure that it is not okay to invoke a super constructor that throws an exception if the enclosing method
 477    // is not declared to throw it
 478  1 _cbtc._bodyData.getMethodData().setThrown(new String[0]);
 479  1 _sd3.setMav(_publicMav);
 480  1 _sd3.setIsContinuation(false);
 481  1 _cbtc.symbolTable.put(_sd3.getName(), _sd3);
 482  1 MethodData constructor = new MethodData("zebra",
 483    _publicMav,
 484    new TypeParameter[0],
 485    _sd3,
 486    new VariableData[0],
 487    new String[] {"java.util.prefs.BackingStoreException"},
 488    _sd3,
 489    null);
 490  1 _sd3.addMethod(constructor);
 491   
 492  1 SimpleSuperConstructorInvocation ssci =
 493    new SimpleSuperConstructorInvocation(SourceInfo.NONE,
 494    new ParenthesizedExpressionList(SourceInfo.NONE, new Expression[0]));
 495  1 BracedBody supConstr =
 496    new BracedBody(SourceInfo.NONE, new BodyItemI[]{new ExpressionStatement(SourceInfo.NONE, ssci)});
 497  1 _cbtc._thrown = new LinkedList<Pair<SymbolData, JExpression>>();
 498  1 supConstr.visit(_cbtc);
 499  1 assertEquals("There should be one error", 1, errors.size());
 500  1 assertEquals("The error message should be correct",
 501    "The constructor of this class's super class could throw the exception " +
 502    "java.util.prefs.BackingStoreException, so the enclosing constructor needs to be declared to throw it",
 503    errors.getLast().getFirst());
 504   
 505   
 506    //if enclosing method is delared to throw it, should be okay:
 507  1 _cbtc._thrown = new LinkedList<Pair<SymbolData, JExpression>>();
 508  1 _cbtc._bodyData.getMethodData().setThrown(new String[] {"java.util.prefs.BackingStoreException"});
 509  1 supConstr.visit(_cbtc);
 510  1 assertEquals("There should still be one error", 1, errors.size());
 511   
 512    // //if implicit reference, still give error.
 513  1 _cbtc._thrown = new LinkedList<Pair<SymbolData, JExpression>>();
 514  1 _cbtc._bodyData.getMethodData().setThrown(new String[0]);
 515  1 BracedBody emptyBody = new BracedBody(SourceInfo.NONE, new BodyItemI[0]);
 516  1 emptyBody.visit(_cbtc);
 517  1 assertEquals("There should be 2 errors", 2, errors.size());
 518  1 assertEquals("The error message should be correct", "There is an implicit call to the superclass's constructor here. That constructor could throw the exception java.util.prefs.BackingStoreException, so the enclosing constructor needs to be declared to throw it", errors.getLast().getFirst());
 519   
 520    //if enclosing method is delared to throw it, should be okay:
 521  1 _cbtc._bodyData.getMethodData().setThrown(new String[] {"java.util.prefs.BackingStoreException"});
 522  1 emptyBody.visit(_cbtc);
 523  1 assertEquals("There should still be two errors", 2, errors.size());
 524   
 525    //make sure that it is not okay to invoke a this constructor that throws an exception if the enclosing constructor is not declared to throw it
 526  1 _cbtc._thrown = new LinkedList<Pair<SymbolData, JExpression>>();
 527  1 BracedBody thisConstr = new BracedBody(SourceInfo.NONE, new BodyItemI[]{new ExpressionStatement(SourceInfo.NONE, new SimpleThisConstructorInvocation(SourceInfo.NONE, new ParenthesizedExpressionList(SourceInfo.NONE, new Expression[0])))});
 528   
 529  1 MethodData thisConstructor = new MethodData("cebu", _publicMav, new TypeParameter[0], _sd6, new VariableData[0], new String[] {"java.util.prefs.BackingStoreException"}, _sd6, null);
 530  1 MethodData thisConstructorNoThrown = new MethodData("cebu", _publicMav, new TypeParameter[0], _sd6, new VariableData[0], new String[0], _sd6, null);
 531  1 _sd6.addMethod(thisConstructor);
 532  1 BodyData oldData = _cbtc._bodyData;
 533  1 _cbtc._data = thisConstructorNoThrown;
 534  1 _cbtc._bodyData = thisConstructorNoThrown;
 535   
 536  1 thisConstr.visit(_cbtc);
 537  1 assertEquals("There should be 3 errors", 3, errors.size());
 538  1 assertEquals("The error message should be correct", "This constructor could throw the exception java.util.prefs.BackingStoreException, so this enclosing constructor needs to be declared to throw it", errors.getLast().getFirst());
 539   
 540    //if enclosing method is delared to throw it, should be okay:
 541  1 _cbtc._thrown = new LinkedList<Pair<SymbolData, JExpression>>();
 542  1 _cbtc._bodyData.getMethodData().setThrown(new String[] {"java.util.prefs.BackingStoreException"});
 543  1 thisConstr.visit(_cbtc);
 544  1 assertEquals("There should still be 3 errors", 3, errors.size());
 545   
 546   
 547    //make sure that it is not okay to invoke a complex super constructor that throws an exception if the enlcosing constructor is not declared to throw it.
 548  1 _cbtc._thrown = new LinkedList<Pair<SymbolData, JExpression>>();
 549   
 550  1 _sd5.setIsContinuation(false);
 551  1 _sd5.addInnerClass(_sd3);
 552  1 _sd3.setOuterData(_sd5);
 553   
 554  1 _sd5.setMav(_publicMav);
 555  1 _sd5.setIsContinuation(false);
 556  1 symbolTable.put("elephant", _sd5);
 557   
 558  1 BracedBody complexSC = new BracedBody(SourceInfo.NONE, new BodyItemI[] {new ExpressionStatement(SourceInfo.NONE, new ComplexSuperConstructorInvocation(SourceInfo.NONE, new SimpleNameReference(SourceInfo.NONE, new Word(SourceInfo.NONE, "e")), new ParenthesizedExpressionList(SourceInfo.NONE, new Expression[0])))});
 559  1 oldData.getMethodData().setThrown(new String[0]);
 560  1 _cbtc._vars.add(new VariableData("e", _publicMav, _sd5, true, _sd3));
 561  1 _cbtc._data = oldData;
 562  1 _cbtc._bodyData = oldData;
 563   
 564  1 complexSC.visit(_cbtc);
 565  1 assertEquals("There should be 4 errors", 4, errors.size());
 566  1 assertEquals("Error message should be correct", "The constructor of this class's super class could throw the exception java.util.prefs.BackingStoreException, so the enclosing constructor needs to be declared to throw it", errors.getLast().getFirst());
 567   
 568    //if enclosing method is delared to throw it, should be okay:
 569  1 _cbtc._thrown = new LinkedList<Pair<SymbolData, JExpression>>();
 570   
 571  1 _cbtc._bodyData.getMethodData().setThrown(new String[] {"java.util.prefs.BackingStoreException"});
 572  1 complexSC.visit(_cbtc);
 573  1 assertEquals("There should still be 4 errors", 4, errors.size());
 574   
 575    }
 576   
 577  1 public void testSimpleThisConstructorInvocationAllowed() {
 578    // if there is a constructor of the right form, all variable datas will be given a value
 579  1 MethodData constructor =
 580    new MethodData("zebra", _publicMav, new TypeParameter[0], _sd3,
 581    new VariableData[] {new VariableData(SymbolData.INT_TYPE)}, new String[0], _sd3, null);
 582  1 _sd3.addMethod(constructor);
 583  1 _cbtc._bodyData = constructor;
 584  1 _cbtc._data = constructor;
 585   
 586  1 VariableData vd1 = new VariableData("i", _finalMav, SymbolData.INT_TYPE, false, _sd3);
 587  1 VariableData vd2 = new VariableData("d", _finalMav, SymbolData.DOUBLE_TYPE, false, _sd3);
 588  1 VariableData vd3 = new VariableData("notFinal", _publicMav, SymbolData.BOOLEAN_TYPE, false, _sd3);
 589  1 _cbtc._vars.add(vd1);
 590  1 _cbtc._vars.add(vd2);
 591  1 _cbtc._vars.add(vd3);
 592  1 _sd3.addVar(vd1);
 593  1 _sd3.addVar(vd2);
 594  1 _sd3.addVar(vd3);
 595   
 596  1 SimpleThisConstructorInvocation constr =
 597    new SimpleThisConstructorInvocation(SourceInfo.NONE,
 598    new ParenthesizedExpressionList(SourceInfo.NONE, new Expression[] {
 599    new IntegerLiteral(SourceInfo.NONE, 5)}));
 600  1 _cbtc.simpleThisConstructorInvocationAllowed(constr);
 601  1 assertEquals("Should be no errors", 0, errors.size());
 602  1 assertEquals("vd1 should have value", true, vd1.hasValue());
 603  1 assertEquals("vd2 should have value", true, vd2.hasValue());
 604  1 assertEquals("vd3 is not final, and thus should not have a value", false, vd3.hasValue());
 605  1 assertEquals("thrown should have 0 elements", 0, _cbtc._thrown.size());
 606   
 607    //if there is not a constructor of the right form, an error will be given
 608  1 vd1.lostValue();
 609  1 vd2.lostValue();
 610   
 611  1 SimpleThisConstructorInvocation constr2 = new SimpleThisConstructorInvocation(SourceInfo.NONE, new ParenthesizedExpressionList(SourceInfo.NONE, new Expression[0]));
 612  1 _cbtc.simpleThisConstructorInvocationAllowed(constr2);
 613  1 assertEquals("Should be one error", 1, errors.size());
 614  1 assertEquals("Error message should be correct", "No constructor found in class zebra with signature: zebra().", errors.getLast().getFirst());
 615  1 assertFalse("vd1 should not have value", vd1.hasValue());
 616  1 assertFalse("vd2 should not have value", vd2.hasValue());
 617  1 assertFalse("vd3 should not have a value", vd3.hasValue());
 618  1 assertEquals("thrown should have 0 elements", 0, _cbtc._thrown.size());
 619   
 620   
 621    //if there is a constructor of the right form, but it throws an exception, the exception will be added to the _thrown list.
 622  1 constructor.setThrown(new String[] {"java.util.prefs.BackingStoreException"});
 623  1 _cbtc.simpleThisConstructorInvocationAllowed(constr);
 624  1 assertEquals("Should still be 1 error", 1, errors.size());
 625  1 assertTrue("vd1 should have a value", vd1.hasValue());
 626  1 assertTrue("vd2 should have a value", vd2.hasValue());
 627  1 assertFalse("vd3 is not final, and thus should not have a value", vd3.hasValue());
 628  1 assertEquals("thrown should have 1 element", 1, _cbtc._thrown.size());
 629   
 630    }
 631   
 632   
 633  1 public void testComplexThisConstructorInvocationNotAllowed() {
 634  1 ComplexThisConstructorInvocation constr = new ComplexThisConstructorInvocation(SourceInfo.NONE, new NullLiteral(SourceInfo.NONE), new ParenthesizedExpressionList(SourceInfo.NONE, new Expression[0]));
 635  1 _cbtc.complexThisConstructorInvocationNotAllowed(constr);
 636  1 assertEquals("There should be 1 error", 1, errors.size());
 637  1 assertEquals("Error message should be correct", "Constructor Invocations of this form are never allowed. A constructor invocation can appear here, but it must either be a super constructor invocation or have the form this(...)", errors.getLast().getFirst());
 638    }
 639   
 640   
 641  1 public void testSimpleSuperConstructorInvocationAllowed() {
 642    //if current class does not have a super class, give an error
 643  1 SimpleSuperConstructorInvocation constr = new SimpleSuperConstructorInvocation(SourceInfo.NONE, new ParenthesizedExpressionList(SourceInfo.NONE, new Expression[] {new IntegerLiteral(SourceInfo.NONE, 5)}));
 644  1 _cbtc.simpleSuperConstructorInvocationAllowed(constr);
 645  1 assertEquals("Should be 1 error", 1, errors.size());
 646  1 assertEquals("Error message should be correct", "The class i.like.monkey does not have a super class", errors.getLast().getFirst());
 647   
 648    //if current class has a super class, but there isn't a constructor of the right form, give an error
 649  1 _sd1.setSuperClass(_sd3);
 650  1 _cbtc.simpleSuperConstructorInvocationAllowed(constr);
 651  1 assertEquals("Should be 2 errors", 2, errors.size());
 652  1 assertEquals("Error message should be correct", "No constructor found in class zebra with signature: zebra(int).", errors.getLast().getFirst());
 653   
 654    //if everything is right, should work with no errors
 655  1 MethodData constructor = new MethodData("zebra", _publicMav, new TypeParameter[0], _sd3, new VariableData[] {new VariableData(SymbolData.INT_TYPE)}, new String[0], _sd3, null);
 656  1 _sd3.addMethod(constructor);
 657  1 _cbtc.simpleSuperConstructorInvocationAllowed(constr);
 658  1 assertEquals("Should still be 2 errors", 2, errors.size());
 659   
 660    //if there is a constructor of the right form, but it throws an exception, the exception will be added to the _thrown list.
 661  1 constructor.setThrown(new String[] {"java.util.prefs.BackingStoreException"});
 662  1 _cbtc.simpleSuperConstructorInvocationAllowed(constr);
 663  1 assertEquals("Should still be 2 errors", 2, errors.size());
 664  1 assertEquals("thrown should have 1 element", 1, _cbtc._thrown.size());
 665   
 666    //if super class is an inner class, it must be static--if not, throw an error
 667  1 constructor.setThrown(new String[0]);
 668  1 _sd3.setOuterData(_sd5);
 669  1 _cbtc.simpleSuperConstructorInvocationAllowed(constr);
 670  1 assertEquals("Should be 3 errors", 3, errors.size());
 671  1 assertEquals("Error message should be correct", "zebra is a non-static inner class of elephant. Its constructor must be invoked from an instance of its outer class", errors.getLast().getFirst());
 672   
 673   
 674    //if super class is a static inner class, no error
 675  1 _sd3.addModifier("static");
 676  1 _cbtc.simpleSuperConstructorInvocationAllowed(constr);
 677  1 assertEquals("Should still be 3 errors", 3, errors.size());
 678   
 679    }
 680   
 681  1 public void testComplexSuperConstructorInvocationAllowed() {
 682   
 683    //if enclosingResult is a PackageData, return null and add an error
 684  1 ComplexSuperConstructorInvocation constr1 = new ComplexSuperConstructorInvocation(SourceInfo.NONE, new SimpleNameReference(SourceInfo.NONE, new Word(SourceInfo.NONE, "nonExistant")), new ParenthesizedExpressionList(SourceInfo.NONE, new Expression[0]));
 685  1 _cbtc.complexSuperConstructorInvocationAllowed(constr1);
 686  1 assertEquals("Should be 1 error", 1, errors.size());
 687  1 assertEquals("Error message should be correct", "Could not resolve symbol nonExistant", errors.getLast().getFirst());
 688   
 689    //if the superclass is null, add error
 690  1 ComplexSuperConstructorInvocation constr2 = new ComplexSuperConstructorInvocation(SourceInfo.NONE, new SimpleNameReference(SourceInfo.NONE, new Word(SourceInfo.NONE, "zebra")), new ParenthesizedExpressionList(SourceInfo.NONE, new Expression[0]));
 691  1 symbolTable.put("zebra", _sd3);
 692  1 _sd3.setIsContinuation(false);
 693  1 _sd3.setMav(_publicMav);
 694  1 _cbtc.complexSuperConstructorInvocationAllowed(constr2);
 695  1 assertEquals("Should be 2 errors", 2, errors.size());
 696  1 assertEquals("Error message should be correct", "A qualified super constructor invocation can only be used to invoke the constructor of your super class from the context of its outer class. The class i.like.monkey does not have a super class, so you cannot do this here", errors.getLast().getFirst());
 697   
 698    //if the superclass exists, but the outer data is null, throw error
 699  1 _sd1.setSuperClass(_sd5);
 700  1 _cbtc.complexSuperConstructorInvocationAllowed(constr2);
 701  1 assertEquals("Should be 3 errors", 3, errors.size());
 702  1 assertEquals("Error message should be correct", "A qualified super constructor invocation can only be used to invoke the constructor of your super class from the context of its outer class. The super class elephant does not have an outer class, so you cannot do this here", errors.getLast().getFirst());
 703   
 704    //if the outer data of the super class does not match the name specified in the constructor, give error
 705  1 _sd5.setOuterData(_sd3);
 706  1 ComplexSuperConstructorInvocation constr3 = new ComplexSuperConstructorInvocation(SourceInfo.NONE, new SimpleNameReference(SourceInfo.NONE, new Word(SourceInfo.NONE, "u.like.emu")), new ParenthesizedExpressionList(SourceInfo.NONE, new Expression[0]));
 707  1 symbolTable.put("u.like.emu", _sd4);
 708  1 _sd4.setPackage("u.like");
 709  1 _sd4.setIsContinuation(false);
 710  1 _sd4.setMav(_publicMav);
 711  1 _cbtc.complexSuperConstructorInvocationAllowed(constr3);
 712  1 assertEquals("Should be 4 errors", 4, errors.size());
 713  1 assertEquals("Error message should be correct", "A qualified super constructor invocation can only be used to invoke the constructor of your super class from the context of its outer class. The class or interface u.like.emu is not the outer class of the super class elephant", errors.getLast().getFirst());
 714   
 715    //if the enclosing is not an instance type, give an error
 716  1 _cbtc.complexSuperConstructorInvocationAllowed(constr2);
 717  1 assertEquals("Should be 5 errors", 5, errors.size());
 718  1 assertEquals("Error message should be correct", "A qualified super constructor invocation can only be made from the context of an instance of the outer class of the super class. You have specified a type name", errors.getLast().getFirst());
 719   
 720    //if it is an instance type but can't find constructor, give error
 721  1 ComplexSuperConstructorInvocation constr4 = new ComplexSuperConstructorInvocation(SourceInfo.NONE, new SimpleNameReference(SourceInfo.NONE, new Word(SourceInfo.NONE, "var")), new ParenthesizedExpressionList(SourceInfo.NONE, new Expression[0]));
 722  1 _cbtc._vars.add(new VariableData("var", _publicMav, _sd3, true, _sd1));
 723  1 _cbtc.complexSuperConstructorInvocationAllowed(constr4);
 724  1 assertEquals("Should be 6 errors", 6, errors.size());
 725  1 assertEquals("Error message should be correct", "No constructor found in class elephant with signature: elephant().", errors.getLast().getFirst());
 726   
 727    //if it is an instance type and can match constructor, no problems--should add anything thrown to throws list
 728  1 MethodData constructor = new MethodData("elephant", _publicMav, new TypeParameter[0], _sd5, new VariableData[0], new String[] {"java.util.prefs.BackingStoreException"}, _sd5, null);
 729  1 _sd5.addMethod(constructor);
 730  1 _cbtc.complexSuperConstructorInvocationAllowed(constr4);
 731  1 assertEquals("Should still be 6 errors", 6, errors.size());
 732  1 assertEquals("_thrown should now have 1 element", 1, _cbtc._thrown.size());
 733   
 734    //if it is an instance type, but the super class is static, give an error
 735  1 _sd5.addModifier("static");
 736  1 _cbtc.complexSuperConstructorInvocationAllowed(constr4);
 737  1 assertEquals("Should be 7 errors", 7, errors.size());
 738  1 assertEquals("Error message should be correct", "A qualified super constructor invocation can only be used to invoke the constructor of a non-static super class from the context of its outer class. The super class elephant is a static inner class", errors.getLast().getFirst());
 739    }
 740   
 741   
 742  1 public void testImplicitSuperConstructor() {
 743  1 BracedBody constr = new BracedBody(SourceInfo.NONE, new BodyItemI[0]);
 744    //if current class has a super class, but there isn't a constructor of the right form, give an error
 745  1 _sd1.setSuperClass(_sd3);
 746  1 _cbtc.implicitSuperConstructor(constr);
 747  1 assertEquals("Should be 1 error", 1, errors.size());
 748  1 assertEquals("Error message should be correct", "You must invoke one of zebra's constructors here. You can either explicitly invoke one of its exisitng constructors or add a constructor with signature: zebra().",
 749    errors.getLast().getFirst());
 750   
 751    //if everything is right, should work with no errors
 752  1 MethodData constructor = new MethodData("zebra", _publicMav, new TypeParameter[0], _sd3, new VariableData[0], new String[0], _sd3, null);
 753  1 _sd3.addMethod(constructor);
 754  1 _cbtc.implicitSuperConstructor(constr);
 755  1 assertEquals("Should still be 1 error", 1, errors.size());
 756   
 757    //if there is a constructor of the right form, but it throws an exception, the exception will be added to the _thrown list.
 758  1 constructor.setThrown(new String[] {"java.util.prefs.BackingStoreException"});
 759  1 _cbtc.implicitSuperConstructor(constr);
 760  1 assertEquals("Should still be 1 error", 1, errors.size());
 761  1 assertEquals("thrown should have 1 element", 1, _cbtc._thrown.size());
 762   
 763    //if super class is an inner class, it must be static--if not, throw an error
 764  1 constructor.setThrown(new String[0]);
 765  1 _sd3.setOuterData(_sd5);
 766  1 _cbtc.implicitSuperConstructor(constr);
 767  1 assertEquals("Should be 2 errors", 2, errors.size());
 768  1 assertEquals("Error message should be correct", "There is an implicit call to the constructor of zebra here, but zebra is a non-static inner class of elephant. Thus, you must explicitly invoke its constructor from an instance of its outer class", errors.getLast().getFirst());
 769   
 770   
 771    //if super class is a static inner class, no error
 772  1 _sd3.addModifier("static");
 773  1 _cbtc.implicitSuperConstructor(constr);
 774  1 assertEquals("Should still be 2 errors", 2, errors.size());
 775    }
 776    }
 777    }
 778   
 779   
 780   
 781   
 782