Clover coverage report - Java Language Levels Test Coverage (javalanglevels-20120305-r5436)
Coverage timestamp: Sun Mar 4 2012 22:02:46 CST
file stats: LOC: 767   Methods: 48
NCLOC: 445   Classes: 2
 
 Source file Conditionals Statements Methods TOTAL
Data.java 80.9% 93.9% 91.7% 91.1%
coverage coverage
 1    /*BEGIN_COPYRIGHT_BLOCK
 2    *
 3    * Copyright (c) 2001-2008, 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 java.util.*;
 41    import junit.framework.TestCase;
 42    import edu.rice.cs.javalanglevels.parser.JExprParser;
 43   
 44    /** Abstract class epresenting the data for a given braced body: a class, interface, method, or just a body. */
 45    public abstract class Data {
 46   
 47    /** The fully qualified name of this data. */
 48    protected String _name;
 49   
 50    /** The vars defined in the lexical scope of this data.*/
 51    protected LinkedList<VariableData> _vars;
 52   
 53    /** All enclosing data are in this list. */
 54    protected LinkedList<Data> _enclosingData;
 55   
 56    /** The modifiers and visibility of this data.*/
 57    protected ModifiersAndVisibility _modifiersAndVisibility;
 58   
 59    /** The outer data--what directly encloses this data.*/
 60    protected Data _outerData;
 61   
 62    /** Any inner classes that are defined in this data.*/
 63    protected LinkedList<SymbolData> _innerClasses;
 64   
 65    /** All blocks defined within this data, in lexical order.*/
 66    protected LinkedList<BlockData> _blocks;
 67   
 68    /** Iterator over _blocks*/
 69    protected Iterator<BlockData> _blockIterator;
 70   
 71    /** The default constructor for a Data. It takes in the outerData, and sets all lists and the name to empty, except
 72    * that the outer data is asdded to the enclosing data list. */
 73  935432 public Data(Data outerData) {
 74  935432 _name = "";
 75  935432 _modifiersAndVisibility = null;
 76  935432 _vars = new LinkedList<VariableData>();
 77  935432 _enclosingData = new LinkedList<Data>();
 78  935432 _outerData = outerData;
 79  935432 if (outerData != null) {
 80  803937 _enclosingData.addLast(_outerData); // We add superclasses and interfaces to the front of this _enclosingData.
 81    }
 82  935432 _innerClasses = new LinkedList<SymbolData>();
 83  935432 _blocks = new LinkedList<BlockData>();
 84  935432 _blockIterator = null;
 85    }
 86   
 87    /** @return the name of this data.*/
 88  261181 public String getName() { return _name; }
 89   
 90    /** Set the fully qualified name of this data.
 91    * @param name The new fully qualified name of this data.
 92    */
 93  1 void setName(String name) { _name = name; }
 94   
 95  19 public Boolean isAnonymousClass() {
 96  19 int lastIndex = _name.lastIndexOf('$');
 97  19 try { return (lastIndex < 0) && Integer.parseInt(_name.substring(lastIndex+1)) >= 0; }
 98  19 catch(NumberFormatException e) { return false; /* suffix is not an anonymous class index */ }
 99    }
 100   
 101  19 public Boolean isDoublyAnonymous() {
 102  19 if (! isAnonymousClass()) return false;
 103  0 for (Data d: getEnclosingData()) {
 104  0 if (d.isAnonymousClass()) return true;
 105    }
 106  0 return false;
 107    }
 108   
 109    /** Set vars to the specified linked list of vars, the variables that are defined in the scope of this data. */
 110  114 void setVars(LinkedList<VariableData> vars) { _vars = vars; }
 111   
 112    /** Finds and returns the particular VariableData declared in this Data's context.
 113    * @param name Name of the variable
 114    * @return The VariableData with the matching name or null if it was not found.
 115    */
 116  67 public VariableData getVar(String name) {
 117  67 Iterator<VariableData> iter = _vars.iterator();
 118  67 while (iter.hasNext()) {
 119  82 VariableData vd = iter.next();
 120  82 if (vd.getName().equals(name)) {
 121  53 return vd;
 122    }
 123    }
 124  14 return null;
 125    }
 126   
 127    /**@return the list of variables declared in the scope of this data.*/
 128  2466 public LinkedList<VariableData> getVars() { return _vars; }
 129   
 130    /** @return the list of enclosing data. */
 131  355 public LinkedList<Data> getEnclosingData() { return _enclosingData; }
 132   
 133    /** Add to the front because we want the outer data to be the last thing in the list. */
 134  104119 public void addEnclosingData(Data enclosingData) {
 135  104119 assert enclosingData != null;
 136  104119 if (!_enclosingData.contains(enclosingData)) {
 137  104044 _enclosingData.addFirst(enclosingData);
 138    }
 139    }
 140   
 141    //Used during testing
 142  1 public void setEnclosingData(LinkedList<Data> d) { _enclosingData = d; }
 143   
 144    /** Check to see if a variable with the same name as vr has already been defined in the scope of this data. If so,
 145    * return true. Otherwise, return false.
 146    * @param vr The VariableData whose name we are searching for.
 147    * @return true if that name has already been used in this scope, false otherwise.
 148    */
 149  293638 private boolean _repeatedName (VariableData vr) {
 150  293638 Iterator<VariableData> iter = _vars.iterator();
 151  293638 while (iter.hasNext()) {
 152  4374925 VariableData next = iter.next();
 153  4374925 if (vr.getName().equals(next.getName())) {
 154  17 return true;
 155    }
 156    }
 157  293621 return false;
 158    }
 159   
 160    /** Add the specified Variable Data to the list of variables defined in this scope, unless its name has already been
 161    * used. Return true if it was successfully added, and false otherwise.
 162    * @param var The variable we want to add to this scope.
 163    * @return true if it was successfully added, false otherwise.
 164    */
 165  293384 public boolean addVar(VariableData var) {
 166  293384 if (! _repeatedName(var)) {
 167  293373 _vars.addLast(var);
 168  293373 return true;
 169    }
 170  11 else return false;
 171    }
 172   
 173    /** Add the array of variable datas to the list of variables defined in this scope, unless a name has already been
 174    * used. Return true if all variables were added successfully, false otherwise.
 175    * @param vars The VariableData[] that we want to add.
 176    * @return true if all VariableDatas were added successfully, false otherwise.
 177    */
 178  298 public boolean addVars(VariableData[] vars) {
 179  298 boolean success = true;
 180  298 for (int i = 0; i < vars.length; i++) {
 181    // if (vars[i] == null) { System.out.println("Var " + i + " was null!"); }
 182  211 if (! _repeatedName(vars[i])) {
 183  208 _vars.addLast(vars[i]);
 184    }
 185  3 else success = false;
 186    }
 187  298 return success;
 188    }
 189   
 190    /** Add the array of variable datas to the list of variables defined in this scope, unless a name has already been
 191    * used. Return true if all variables were added successfully, false otherwise. Set each of the variable datas in
 192    * the array to be final before adding them.
 193    * @param vars the VariableData[] that we want to add.
 194    * @return true if all VariableDatas were added successfully, false otherwise.
 195    */
 196  40 public boolean addFinalVars(VariableData[] vars) {
 197  40 boolean success = true;
 198  40 for (int i = 0; i < vars.length; i++) {
 199  40 if (! _repeatedName(vars[i])) {
 200  6 if (! vars[i].isFinal()) vars[i].setFinal();
 201  38 _vars.addLast(vars[i]);
 202    }
 203  2 else { success = false; }
 204    }
 205  40 return success;
 206    }
 207   
 208    /** @return the modifiersAndVisibility for this data. */
 209  286679 public ModifiersAndVisibility getMav() { return _modifiersAndVisibility; }
 210   
 211    /** Assigns the specified modifiersAndVisiblity to this data.
 212    * @param modifiersAndVisibility The ModifiersAndVisibility to assign to this data.
 213    */
 214  64030 public void setMav(ModifiersAndVisibility modifiersAndVisibility) {
 215  64030 _modifiersAndVisibility = modifiersAndVisibility;
 216    }
 217   
 218    /**Return the enclosing getSymbolData()*/
 219    public abstract SymbolData getSymbolData();
 220   
 221    /** @return the directly enclosing outer data. */
 222  155624 public Data getOuterData() { return _outerData; }
 223   
 224    /** Sets the outer data to the specified value--throw an exception if the data already has an outer data.
 225    * @param outerData The Data that encloses this data.
 226    */
 227  106 public void setOuterData(Data outerData) {
 228  106 if (outerData == null) {
 229  0 assert _outerData == null; // Client code should not try to nullify a defined outerData value
 230  0 return;
 231    }
 232  106 if (_outerData == null || _outerData.equals(outerData)) {
 233  106 _outerData = outerData;
 234  106 if (! _enclosingData.contains(outerData)) _enclosingData.addLast(outerData);
 235    }
 236    else {
 237  0 throw new RuntimeException("Internal Program Error: Trying to reset an outer data to " + outerData.getName() +
 238    " for " + getName() + " that has already been set to " + _outerData.getName() +
 239    ". Please report this bug.");
 240    }
 241    }
 242   
 243    /** @return true if d is an outer data of this data. TODO: What if d is a library class? */
 244  3778 public boolean isOuterData(Data d) {
 245  3778 Data outerData = _outerData;
 246  3778 while ((outerData != null) && ! LanguageLevelVisitor.isJavaLibraryClass(outerData.getName())) {
 247  91 if (outerData == d) return true;
 248  197 outerData = outerData.getOuterData();
 249    }
 250  3687 return false;
 251    }
 252   
 253    /** @return the enclosing class of this. */
 254  0 public SymbolData getEnclosingClass() {
 255  0 Data next = _outerData;
 256   
 257  0 while (next != null) {
 258  0 if (next instanceof SymbolData) return (SymbolData) next;
 259  0 next = next.getOuterData();
 260    }
 261  0 return null;
 262    }
 263   
 264    /** Loop over the specified string, and replace any '$' with '.' This is used to change an inner class name to a
 265    * standard format. It fails if the inner class is local or anonymous!
 266    * @param s The String to change.
 267    * @return The converted string.
 268    */
 269  341 public static String dollarSignsToDots(String s) { return s.replace('$', '.'); }
 270   
 271    /** Loop over the specified string, and replace any '.' with '$' This is used to change an inner class name from
 272    * external (as in Java source) to internal (as in class files) format.
 273    * @param s The String to change.
 274    * @return The converted string.
 275    */
 276  0 public static String dotsToDollarSigns(String s) { return s.replace('.', '$'); }
 277   
 278    /** Determines the name of the next anonymous inner class (enclosing class name + '$' + sequence number). Looks
 279    * through the list of inner classes of this data to see if there is a match. (It should succeed).
 280    * @return the SymbolData for next anonymous inner class of this data; null if it cannot be found
 281    */
 282  24 public SymbolData getNextAnonymousInnerClass() {
 283  24 String name = getSymbolData().getName() + '$' + getSymbolData().preincrementAnonymousInnerClassNum();
 284    // System.err.println("**** Looking up anonymous inner class " + name);
 285  24 LinkedList<SymbolData> myDatas = getInnerClasses();
 286  24 SymbolData myData = null;
 287    //look through the inner classes for the data
 288  24 for (int i = 0; i < myDatas.size(); i++) {
 289  46 if (myDatas.get(i).getName().equals(name)) {
 290  22 myData = myDatas.get(i);
 291  22 break;
 292    }
 293    }
 294  24 return myData;
 295    }
 296   
 297    /** Reset the block iterator to the beginning of the list of blocks. */
 298  17 public void resetBlockIterator() { _blockIterator = null; }
 299   
 300    /** Returns the next block contained within this data.
 301    * @return a BlockData, or null if none exists.
 302    */
 303  93 public BlockData getNextBlock() {
 304  56 if (_blockIterator == null) { _blockIterator = _blocks.iterator(); }
 305   
 306  93 if (_blockIterator.hasNext()) { return _blockIterator.next(); }
 307  0 else { return null; }
 308    }
 309   
 310    /** Add a BlockData to this Data's list of blocks. */
 311  111 public void addBlock(BlockData b) { _blocks.add(b); }
 312   
 313    /** Remove all blocks from this data's list of enclosed blocks. (Used to simplify testing.) */
 314  10 public void removeAllBlocks() { _blocks.clear(); }
 315   
 316    /** Takes in a relative name and tries to match it with one of this Data's inner classes or inner interfaces. The
 317    * relName argument is a name relative to this SymbolData (such as B to request the the class with this
 318    * relative name within some enclosing symbol data or B$C to request the class A.B.C from class A) and
 319    * may be delimited by '.' or '$' (??). If the name is not found in this Data, checks the outer data (if there is
 320    * one), which will recursively search up the chain of enclosing Datas. If no matching visible inner classes or
 321    * interfaces are found, but one or more that are not visible are found, one of the non-visible ones will be
 322    * returned. This means that checkAccess should be called after this method.
 323    * TODO: Is support for '$' delimiter required to process inner classes in class files? Yes.
 324    * !!! Eliminate the kludge in this method.
 325    * @param relName The name of the inner class or interface to find RELATIVE to this SymbolData
 326    * @return The SymbolData for the matching inner class or interface is null if there isn't one.
 327    */
 328  3234 public SymbolData getInnerClassOrInterface(String relName) {
 329    // if (relName.equals("MyInner")) System.err.println("getInnerClass('" + relName + "') called on '" + this + "'");
 330  3234 int firstIndexOfDot = relName.indexOf('.');
 331  3234 int firstIndexOfDollar = relName.indexOf("$");
 332  1714 if (firstIndexOfDot == -1) firstIndexOfDot = firstIndexOfDollar;
 333  3 else if (firstIndexOfDollar >= 0 && firstIndexOfDollar < firstIndexOfDot) firstIndexOfDot = firstIndexOfDollar;
 334   
 335    // First, look through the inner classes/interfaces of this class
 336  3234 SymbolData privateResult = null;
 337  3234 SymbolData result = getInnerClassOrInterfaceHelper(relName, firstIndexOfDot);
 338  3234 if (relName.equals("MyInner")) {
 339    // System.err.println("getInnerClassOrInterfaceHelper('" + relName + "', " + firstIndexOfDot + ")");
 340    // System.err.println("_innerClasses = " + _innerClasses);
 341    // System.err.println("Result is: '" + result + "'");
 342    }
 343  3234 if (result != null) {
 344    // System.err.println("Result is: '" + result + "'");
 345  103 SymbolData outerPiece;
 346  103 if (firstIndexOfDot > 0) {
 347  7 outerPiece = getInnerClassOrInterfaceHelper(relName.substring(0, firstIndexOfDot), -1);
 348    }
 349  96 else { outerPiece = result; }
 350  95 if (TypeChecker.checkAccess(outerPiece.getMav(), outerPiece, getSymbolData())) return result;
 351    else {
 352  8 privateResult = result;
 353  8 result = null;
 354    }
 355    }
 356   
 357    // Call this method recursively on the outer data; anything our outer class can see we can see, so there is no
 358    // eason to check accessibility here
 359  3139 if (_outerData != null) {
 360  1352 result = _outerData.getInnerClassOrInterface(relName);
 361    // if (relName.equals("MyInner")) System.err.println("outerResult = " + result);
 362  7 if (result != null) return result;
 363    }
 364   
 365  3132 return privateResult;
 366    }
 367   
 368    /** Takes in a relative name and tries to match it with one of this Data's inner classes or inner interfaces. The
 369    * relName argument is a name relative to this SymbolData (such as B.C to request the class A.B.C from class A) and
 370    * may be delimited by '.' or '$'. This method is overridden in SymbolData (but not other concrete Data classes) to
 371    * handle the fact that classes must check their super classes and interfaces and interfaces must check their super
 372    * interfaces.
 373    * TODO: Kludge! Only use dots to separate segments!!!
 374    * @return The SymbolData for the matching inner class or interface or null if there isn't one.
 375    */
 376  1270 protected SymbolData getInnerClassOrInterfaceHelper(String relName, int firstIndexOfDot) {
 377  1270 Iterator<SymbolData> iter = innerClassesAndInterfacesIterator();
 378  1270 while (iter.hasNext()) {
 379  11 SymbolData sd = iter.next();
 380  11 String sdName = sd.getName();
 381   
 382  11 sdName = LanguageLevelVisitor.getUnqualifiedClassName(sdName);
 383    // if (sdName.equals("MyInner")) System.err.println("In getInnerClass, sdName = '" + sdName + "'; relName = '"
 384    // + relName +"'");
 385  11 if (firstIndexOfDot == -1) {
 386  5 if (sdName.equals(relName)) return sd;
 387    }
 388    else {
 389  1 if (sdName.equals(relName.substring(0, firstIndexOfDot))) {
 390  0 return sd.getInnerClassOrInterface(relName.substring(firstIndexOfDot + 1));
 391    }
 392    }
 393    }
 394  1265 return null;
 395    }
 396   
 397  1270 public Iterator<SymbolData> innerClassesAndInterfacesIterator() { return _innerClasses.iterator(); }
 398   
 399    /** @return The inner classes of this Data. */
 400  150403 public LinkedList<SymbolData> getInnerClasses() { return _innerClasses; }
 401   
 402    /** Sets the inner classes of this Data. */
 403  0 public void setInnerClasses(LinkedList<SymbolData> innerClasses) { _innerClasses = innerClasses; }
 404   
 405    /** Add the specified SymbolData to the end of the list of inner classes.
 406    * @param innerClass The SymbolData to add.
 407    */
 408  122 public void addInnerClass(SymbolData innerClass) { _innerClasses.addLast(innerClass); }
 409   
 410    /** @return true if this data has the specified String modifier, and false otherwise. */
 411  2592 public boolean hasModifier(String modifier) {
 412  0 if (getMav() == null) {return false;}
 413  2592 String[] mavStrings = _modifiersAndVisibility.getModifiers();
 414  2592 for (int i = 0; i < mavStrings.length; i++) {
 415  2309 if (mavStrings[i].equals(modifier)) {
 416  289 return true;
 417    }
 418    }
 419  2303 return false;
 420    }
 421   
 422    //TODO: now that we have this, can we factor out some code in VariableData?
 423    /** Add the specified modifier to the modifiers and visibility for this data, if it is not already present.
 424    * @param modifier The String to add.
 425    */
 426  176 public void addModifier(String modifier) {
 427  176 if (! hasModifier(modifier)) {
 428  0 if (_modifiersAndVisibility == null) { setMav(new ModifiersAndVisibility(SourceInfo.NONE, new String[0])); }
 429  156 String[] modifiers = _modifiersAndVisibility.getModifiers();
 430  156 String[] newModifiers = new String[modifiers.length + 1];
 431  156 newModifiers[0] = modifier;
 432  156 for (int i = 1; i <= modifiers.length; i++) {
 433  55 newModifiers[i] = modifiers[i-1];
 434    }
 435  156 _modifiersAndVisibility = new ModifiersAndVisibility(_modifiersAndVisibility.getSourceInfo(), newModifiers);
 436    }
 437    }
 438   
 439    /** Check if varName is used in this Data's scope. If so, find a new name for the variable by appending a counter to
 440    * its name until an unused variable name results. Return the new name.
 441    * @param varName The initial String name of the variable we are creating.
 442    * @return The new variable name which does not shadow anything in vars.
 443    */
 444  15 public String createUniqueName(String varName) {
 445  15 VariableData vd =
 446    TypeChecker.getFieldOrVariable(varName, this, getSymbolData(), new NullLiteral(SourceInfo.NONE), getVars(),
 447    true, false);
 448  15 String newName = varName;
 449  15 int counter = 0; // Note: counter overflow is effectively impossible; 2G anonymous classes would blow memory
 450  15 while (vd != null && counter != -1) {
 451  7 newName = varName + counter; counter++;
 452  7 vd = TypeChecker.getFieldOrVariable(newName, this, getSymbolData(), new NullLiteral(SourceInfo.NONE),
 453    getVars(), true, false);
 454    }
 455  0 if (counter == -1) { throw new RuntimeException("Internal Program Error: Unable to rename variable " + varName
 456    + ". All possible names were taken. Please report this bug");}
 457  15 return newName;
 458    }
 459   
 460   
 461    /** Test the methods in the above class. */
 462    public static class DataTest extends TestCase {
 463   
 464    private Data _d;
 465   
 466    private ModifiersAndVisibility _publicMav =
 467    new ModifiersAndVisibility(SourceInfo.NONE, new String[] { "public" });
 468    private ModifiersAndVisibility _staticMav =
 469    new ModifiersAndVisibility(SourceInfo.NONE, new String[] { "static" });
 470    private ModifiersAndVisibility _lotsaMav =
 471    new ModifiersAndVisibility(SourceInfo.NONE, new String[] { "public", "final", "abstract" });
 472    private ModifiersAndVisibility _protectedMav =
 473    new ModifiersAndVisibility(SourceInfo.NONE, new String[] { "protected" });
 474    private ModifiersAndVisibility _privateMav =
 475    new ModifiersAndVisibility(SourceInfo.NONE, new String[] { "private" });
 476   
 477  0 public DataTest() { this("");}
 478  9 public DataTest(String name) { super(name); }
 479   
 480  1 public void testRepeatedName() {
 481  1 _d = new SymbolData("myname");
 482   
 483  1 VariableData vd = new VariableData("v1", _publicMav, SymbolData.INT_TYPE, false, _d);
 484   
 485    // Compare a vd to an symbol data with no vars
 486  1 assertFalse("No variables to repeat name", _d._repeatedName(vd));
 487   
 488    // Compare a vd to a symbol data with 1 var with a different name
 489  1 _d.addVar(new VariableData("v2", _protectedMav, SymbolData.BOOLEAN_TYPE, true, _d));
 490  1 assertFalse("No repeated name", _d._repeatedName(vd));
 491   
 492    // Compare a vd to a symbol data who has a var with the same name
 493  1 _d.addVar(vd);
 494  1 assertTrue("Should be repeated name", _d._repeatedName(vd));
 495    // System.err.println("testRepeatedName finished");
 496    }
 497   
 498  1 public void testIsAbstract() {
 499  1 _d = new SymbolData("myName");
 500  1 _d.setMav(_publicMav);
 501   
 502    // not abstract
 503  1 assertFalse("Should not be abstract", _d.hasModifier("abstract"));
 504   
 505  1 _d.setMav(_lotsaMav);
 506   
 507    // abstract
 508  1 assertTrue("Should be abstract", _d.hasModifier("abstract"));
 509   
 510    // System.err.println("testIsAbstract finished");
 511    }
 512   
 513  1 public void testAddVar() {
 514  1 _d = new SymbolData("myName");
 515  1 VariableData vd = new VariableData("v1", _publicMav, SymbolData.INT_TYPE, true, _d);
 516  1 VariableData vd2 = new VariableData("v2", _publicMav, SymbolData.CHAR_TYPE, true, _d);
 517  1 LinkedList<VariableData> myVds = new LinkedList<VariableData>();
 518  1 myVds.addLast(vd);
 519   
 520    //first variable added
 521  1 assertTrue("Should be able to add first variable", _d.addVar(vd));
 522  1 assertEquals("Variable list should have 1 variable, vd", myVds, _d.getVars());
 523   
 524    //duplicate variable
 525  1 assertFalse("Should not be able to add same variable again", _d.addVar(vd));
 526  1 assertEquals("Variable list should not have changed", myVds, _d.getVars());
 527   
 528    //different variable
 529  1 myVds.addLast(vd2);
 530  1 assertTrue("Should be able to add a different variable", _d.addVar(vd2));
 531  1 assertEquals("Variable list should have 2 variables, vd, vd2", myVds, _d.getVars());
 532   
 533    // System.err.println("testAddVar finished");
 534   
 535    }
 536   
 537  1 public void testAddVars() {
 538  1 _d = new SymbolData("genius");
 539  1 VariableData vd = new VariableData("v1", _publicMav, SymbolData.INT_TYPE, true, _d);
 540  1 VariableData vd2 = new VariableData("v2", _publicMav, SymbolData.CHAR_TYPE, true, _d);
 541  1 VariableData[] toAdd = new VariableData[] {vd, vd2};
 542  1 LinkedList<VariableData> myVds = new LinkedList<VariableData>();
 543   
 544    //first adding array
 545  1 myVds.addLast(vd);
 546  1 myVds.addLast(vd2);
 547  1 assertTrue("Should be able to add new vars array", _d.addVars(toAdd));
 548  1 assertEquals("Variable list should have 2 variables", myVds, _d.getVars());
 549   
 550    //trying to read array whose variables are already there.
 551  1 assertFalse("Should not be able to add same variables again", _d.addVars(toAdd));
 552  1 assertEquals("Variable list should not have changed", myVds, _d.getVars());
 553   
 554    //trying to add a different array
 555  1 VariableData vd3 = new VariableData("v3", _publicMav, SymbolData.INT_TYPE, true, _d);
 556  1 VariableData[] toAdd2 = new VariableData[] {vd3};
 557  1 myVds.addLast(vd3);
 558   
 559  1 assertTrue("Should be able to add new variable array", _d.addVars(toAdd2));
 560  1 assertEquals("Variable list should now have 3 variables", myVds, _d.getVars());
 561   
 562    //try adding an empty array of variable datas
 563  1 assertTrue("Should be able to add an empty array", _d.addVars(new VariableData[0]));
 564  1 assertEquals("Variable list should not have changed by adding empty array", myVds, _d.getVars());
 565   
 566    // System.err.println("testAddVars finished");
 567    }
 568   
 569  1 public void testGetVar() {
 570  1 _d = new SymbolData("woah");
 571  1 VariableData vd = new VariableData("v1", _publicMav, SymbolData.INT_TYPE, false, _d);
 572  1 VariableData vd2 = new VariableData("v2", _publicMav, SymbolData.CHAR_TYPE, true, _d);
 573  1 VariableData[] toAdd = new VariableData[] {vd, vd2};
 574  1 _d.addVars(toAdd);
 575   
 576    // Lookup a name that should be there
 577  1 assertEquals("Should return vd", vd, _d.getVar("v1"));
 578   
 579    // Lookup a name that should not be there
 580  1 assertEquals("Should return null--no variable with that name", null, _d.getVar("whatever"));
 581    // System.err.println("testGetVar finished");
 582    }
 583   
 584  1 public void testIsOuterData() {
 585  1 _d = new SymbolData("asdf");
 586  1 SymbolData d2 = new SymbolData("qwer");
 587  1 SymbolData d246 = new SymbolData("fdsa");
 588  1 d2.setOuterData(_d);
 589  1 _d.setOuterData(d246);
 590  1 assertTrue("d246 should be outer data of d2", d2.isOuterData(d246));
 591  1 assertTrue("d246 should be outer data of _d", _d.isOuterData(d246));
 592  1 assertFalse("d2 should not be outer data of d246", d246.isOuterData(d2));
 593    // System.err.println("testIsOuterData finished");
 594    }
 595   
 596  1 public void testGetInnerClassOrInterface() {
 597  1 SymbolData sd1 = new SymbolData("testing");
 598  1 SymbolData sd2 = new SymbolData("testing$test123");
 599  1 SymbolData sd3 = new SymbolData("testing$test123$test1234");
 600  1 sd1.addInnerClass(sd2);
 601  1 sd2.addInnerClass(sd3);
 602   
 603    // One level can be found
 604  1 SymbolData result = sd1.getInnerClassOrInterface("test123");
 605  1 assertEquals("The correct inner SymbolData should be returned", sd2, result);
 606   
 607    // Dollars or dots are okay, and nested inner classes can be found
 608  1 result = sd2.getInnerClassOrInterface("test1234");
 609  1 assertEquals("The correct nested inner SymbolData should be returned", sd3, result);
 610   
 611    //dollars or dots are okay, and nested inner classes can be found
 612  1 result = sd1.getInnerClassOrInterface("test123.test1234");
 613  1 assertEquals("The correct nested inner SymbolData should be returned", sd3, result);
 614   
 615    // Dollars or dots are okay, and nested inner classes can be found
 616  1 result = sd1.getInnerClassOrInterface("test123$test1234");
 617  1 assertEquals("The correct nested inner SymbolData should be returned", sd3, result);
 618   
 619    // null is returned when a non-present inner class is looked for.
 620  1 result = sd1.getInnerClassOrInterface("testing.notYourInnerClass");
 621  1 assertEquals("null should be returned", null, result);
 622   
 623  1 SymbolData sd4 = new SymbolData("testing");
 624  1 SymbolData sd5 = new SymbolData("testing$test123");
 625  1 sd5.setInterface(true);
 626  1 SymbolData sd6 = new SymbolData("testing$test123$2test1234");
 627  1 sd4.addInnerInterface(sd5);
 628  1 sd5.addInnerClass(sd6);
 629   
 630    // One level can be found
 631  1 result = sd4.getInnerClassOrInterface("test123");
 632  1 assertEquals("The correct inner SymbolData should be returned", sd5, result);
 633   
 634    //dollars or dots are okay, and nested inner classes can be found
 635  1 result = sd5.getInnerClassOrInterface("test1234");
 636  1 assertEquals("The correct nested inner SymbolData should be returned", sd6, result);
 637   
 638    //dollars or dots are okay, and nested inner classes can be found
 639  1 result = sd4.getInnerClassOrInterface("test123.test1234");
 640  1 assertEquals("The correct nested inner SymbolData should be returned", sd6, result);
 641   
 642    //null is returned when a non-present inner class is looked for.
 643  1 result = sd4.getInnerClassOrInterface("testing.notYourInnerClass");
 644  1 assertEquals("null should be returned", null, result);
 645   
 646    //Test a class defined in the context of a method
 647  1 SymbolData sd7 = new SymbolData("test123.myMethod$bob");
 648  1 sd7.setIsContinuation(false);
 649  1 MethodData md = new MethodData("myMethod", _publicMav, new TypeParameter[0],
 650    SymbolData.INT_TYPE, new VariableData[0], new String[0], sd1,
 651    new NullLiteral(SourceInfo.NONE));
 652  1 md.addInnerClass(sd7);
 653  1 assertEquals("Should return sd7", sd7, md.getInnerClassOrInterface("bob"));
 654   
 655    //Test an ambiguous case, where the inner class is in both the super interface and the super class.
 656  1 SymbolData interfaceInner = new SymbolData("MyInterface$MyInner");
 657  1 interfaceInner.setIsContinuation(false);
 658  1 interfaceInner.setInterface(true);
 659   
 660  1 SymbolData superInner = new SymbolData("MySuper$MyInner");
 661  1 superInner.setIsContinuation(false);
 662   
 663  1 SymbolData myInterface = new SymbolData("MyInterface");
 664  1 myInterface.setInterface(true);
 665  1 myInterface.setIsContinuation(false);
 666  1 myInterface.addInnerClass(interfaceInner);
 667  1 interfaceInner.setOuterData(myInterface);
 668   
 669  1 SymbolData mySuper = new SymbolData("MySuper");
 670  1 mySuper.addInnerClass(superInner);
 671  1 superInner.setOuterData(mySuper);
 672   
 673  1 SymbolData me = new SymbolData("Me");
 674  1 me.setSuperClass(mySuper);
 675  1 me.addInterface(myInterface);
 676   
 677  1 assertEquals("Should return SymbolData.AMBIGUOUS_REFERENCE", SymbolData.AMBIGUOUS_REFERENCE,
 678    me.getInnerClassOrInterface("MyInner"));
 679   
 680    // Test a case where the inner class is private in one, but not the other
 681  1 superInner.setMav(_privateMav);
 682  1 assertEquals("Should return interfaceInner", interfaceInner, me.getInnerClassOrInterface("MyInner"));
 683   
 684    // Test a case where the inner class is private in both--returns one of them
 685  1 interfaceInner.setMav(_privateMav);
 686  1 assertEquals("Should return interfaceInner", interfaceInner, me.getInnerClassOrInterface("MyInner"));
 687   
 688    // Test a case where the inner most class is private, but one layer is public
 689  1 interfaceInner.setMav(_publicMav);
 690  1 SymbolData innerInterfaceInner = new SymbolData("MyInterface$MyInner$Inner");
 691  1 innerInterfaceInner.setMav(_privateMav);
 692  1 interfaceInner.addInnerClass(innerInterfaceInner);
 693  1 innerInterfaceInner.setOuterData(interfaceInner);
 694  1 assertEquals("Should return innerInterfaceInner", innerInterfaceInner,
 695    me.getInnerClassOrInterface("MyInner.Inner"));
 696   
 697    // System.err.println("testGetInnerClassOrInterface finished");
 698    }
 699   
 700  1 public void testCreateUniqueName() {
 701    // where varName is not defined
 702  1 MethodData md = new MethodData("foozle", new VariableData[0]);
 703  1 md.addVars(md.getParams());
 704  1 md.setOuterData(new SymbolData("Fooz"));
 705  1 String result = md.createUniqueName("avar");
 706  1 assertEquals("the result is correct", "avar", result);
 707   
 708    // where varName is defined in a method signature
 709  1 VariableData vd = new VariableData("avar", _publicMav, SymbolData.INT_TYPE, true, null);
 710  1 md = new MethodData("foozleWithAvar", new VariableData[] {vd});
 711  1 vd.setEnclosingData(md);
 712  1 md.addVars(md.getParams());
 713  1 md.setOuterData(new SymbolData("Fooz"));
 714  1 result = md.createUniqueName("avar");
 715  1 assertEquals("the result is correct", "avar0", result);
 716   
 717    // where varName & varName0 are defined in the class
 718  1 SymbolData sd = new SymbolData("RandomClass");
 719  1 VariableData vd0 = new VariableData("avar0", _publicMav, SymbolData.DOUBLE_TYPE, true, sd);
 720  1 vd.setEnclosingData(sd);
 721  1 sd.addVars(new VariableData[] {vd, vd0});
 722  1 result = sd.createUniqueName("avar");
 723  1 assertEquals("the result is correct", "avar1", result);
 724   
 725    // where varName is defined in an enclosing class
 726  1 sd = new SymbolData("RandomClass");
 727  1 sd.setMav(_staticMav);
 728  1 SymbolData sd2 = new SymbolData("IAteRandomClass");
 729  1 sd2.addInnerClass(sd);
 730  1 sd.setOuterData(sd2);
 731  1 sd.addVar(vd);
 732  1 result = sd.createUniqueName("avar");
 733  1 assertEquals("the result is correct", "avar0", result);
 734   
 735    // where varName is defined in a super class and enclosing class
 736  1 SymbolData sd3 = new SymbolData("RandomsMama");
 737  1 sd.setSuperClass(sd3);
 738  1 sd3.addVar(vd0);
 739  1 result = sd.createUniqueName("avar");
 740  1 assertEquals("the result is correct", "avar1", result);
 741    // System.err.println("testCreateName finished");
 742    }
 743   
 744  1 public void testGetNextAnonymousInnerClass() {
 745  1 SymbolData sd1 = new SymbolData("silly");
 746  1 sd1.setIsContinuation(false);
 747   
 748  1 _d = new BlockData(sd1);
 749   
 750  1 SymbolData anon1 = new SymbolData("silly$1");
 751  1 anon1.setIsContinuation(false);
 752  1 SymbolData anon2 = new SymbolData("silly$2");
 753  1 anon2.setIsContinuation(false);
 754  1 sd1.addInnerClass(anon1);
 755  1 anon1.setOuterData(sd1);
 756  1 _d.addInnerClass(anon2);
 757  1 anon2.setOuterData(_d);
 758   
 759  1 assertEquals("Should return anon1", anon1, sd1.getNextAnonymousInnerClass());
 760  1 assertEquals("Should return anon2", anon2, _d.getNextAnonymousInnerClass());
 761  1 assertEquals("Should return null", null, _d.getNextAnonymousInnerClass());
 762  1 assertEquals("Should return null", null, sd1.getNextAnonymousInnerClass());
 763   
 764    // System.err.println("testGetNextAnonymousInnerClass finished");
 765    }
 766    }
 767    }