Code Search for Developers
 
 
  

BodyBodyAdvancedVisitor.java from DrJava at Krugle


Show BodyBodyAdvancedVisitor.java syntax highlighted

/*BEGIN_COPYRIGHT_BLOCK
 *
 * Copyright (c) 2001-2007, JavaPLT group at Rice University (javaplt@rice.edu)
 * All rights reserved.
 * 
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *    * Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 *    * Redistributions in binary form must reproduce the above copyright
 *      notice, this list of conditions and the following disclaimer in the
 *      documentation and/or other materials provided with the distribution.
 *    * Neither the names of DrJava, the JavaPLT group, Rice University, nor the
 *      names of its contributors may be used to endorse or promote products
 *      derived from this software without specific prior written permission.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * This software is Open Source Initiative approved Open Source Software.
 * Open Source Initative Approved is a trademark of the Open Source Initiative.
 * 
 * This file is part of DrJava.  Download the current version of this project
 * from http://www.drjava.org/ or http://sourceforge.net/projects/drjava/
 * 
 * END_COPYRIGHT_BLOCK*/

package edu.rice.cs.javalanglevels;

import edu.rice.cs.javalanglevels.tree.*;
import edu.rice.cs.javalanglevels.parser.*;
import java.util.*;
import java.io.*;

import junit.framework.TestCase;



/*
 * Language Level Visitor that represents the Advanced Language Level.  Enforces constraints during the
 * first walk of the AST (checking for langauge specific errors and building the symbol table).
 * This class enforces things that are common to all contexts reachable within a method body or other body 
 * (not class or interface body)the Advanced Language Level). 
 */
public class BodyBodyAdvancedVisitor extends AdvancedVisitor {

  /**The MethodData of this method.*/
  private BodyData _bodyData;
  
  /*
   * Constructor for BodyBodyAdvancedVisitor.
   * @param bodyData  The BodyData that encloses the context we are visiting.
   * @param file  The source file this came from.
   * @param packageName  The package the source file is in
   * @importedFiles  A list of classes that were specifically imported
   * @param importedPackages  A list of package names that were specifically imported
   * @param classDefsInThisFile  A list of the classes that are defined in the source file
   * @param continuations  A hashtable corresponding to the continuations (unresolved Symbol Datas) that will need to be resolved
   */
  public BodyBodyAdvancedVisitor(BodyData bodyData, File file, String packageName, LinkedList<String> importedFiles, 
                             LinkedList<String> importedPackages, LinkedList<String> classDefsInThisFile, Hashtable<String, Pair<SourceInfo, LanguageLevelVisitor>> continuations) {
    super(file, packageName, importedFiles, importedPackages, classDefsInThisFile, continuations);
    _bodyData = bodyData;
  }
  
  /*Give an appropriate error*/
  public void forMethodDefDoFirst(MethodDef that) {
    _addError("Methods definitions cannot appear within the body of another method or block.", that);
  }
  
  /* There is currently no way to differentiate between a block statement and
   * an instance initializer in a braced body given the general nature of a 
   * braced body.  Whenever an instance initialization is visited in a method
   * body, we must assume that it is a block statement.
   */
  public void forInstanceInitializer(InstanceInitializer that) {
    forBlock(that.getCode());
  }

  /*
   * Visit this BlockData with a new BodyBodyAdvanced visitor after making sure no errors need to be thrown.
   */
  public void forBlock(Block that) {
    forBlockDoFirst(that);
    if (prune(that)) { return; }
    BlockData bd = new BlockData(_bodyData);
    _bodyData.addBlock(bd);
    that.getStatements().visit(new BodyBodyAdvancedVisitor(bd, _file, _package, _importedFiles, _importedPackages, _classNamesInThisFile, continuations));
    forBlockOnly(that);
  }
  
  /** 
   * Visit the block as in forBlock(), but first add the exception parameter as a variable in 
   * that block.
   */
  public void forCatchBlock(CatchBlock that) {
    forCatchBlockDoFirst(that);
    if (prune(that)) { return; }
    
    Block b = that.getBlock();
    forBlockDoFirst(b);
    if (prune(b)) { return; }
    BlockData bd = new BlockData(_bodyData);
    _bodyData.addBlock(bd);
    
    VariableData exceptionVar = formalParameters2VariableData(new FormalParameter[]{ that.getException() }, bd)[0];
    if (prune(that.getException())) { return; }
    bd.addVar(exceptionVar);
    
    b.getStatements().visit(new BodyBodyIntermediateVisitor(bd, _file, _package, _importedFiles, _importedPackages, _classNamesInThisFile, continuations));
    forBlockOnly(b);
    forCatchBlockOnly(that);
  }
  
  /*Add the variables that were declared to the body data and make sure that no two
   * variables have the same name.*/
  public void forVariableDeclarationOnly(VariableDeclaration that) {
    if (!_bodyData.addVars(_variableDeclaration2VariableData(that, _bodyData))) {
      _addAndIgnoreError("You cannot have two variables with the same name.", that);
    }
  }
  
  /**
   * Call the super method to convert these to a VariableData array.
   * Do some special handling of the modifier "final" in the error message, since final can be used to declare a local variable.
   * @param enclosingData  The Data which contains the variables
   */
  protected VariableData[] _variableDeclaration2VariableData(VariableDeclaration vd, Data enclosingData) {
    VariableData[] vds = super._variableDeclaration2VariableData(vd, enclosingData);
    for (int i = 0; i < vds.length; i++) {
      if ((vds[i].hasModifier("final") && vds[i].getMav().getModifiers().length > 1) || (!vds[i].hasModifier("final") && vds[i].getMav().getModifiers().length > 0)) {
        StringBuffer sbuff = new StringBuffer("the keyword(s) ");
        String[] modifiers = vds[i].getMav().getModifiers();
        for (int j = 0; j<modifiers.length; j++) {
          if (!modifiers[j].equals("final")) {sbuff.append("\"" + modifiers[j] + "\" ");}
        }
        _addAndIgnoreError("You cannot use " + sbuff.toString() + "to declare a local variable", vd);
      }
    }
    return vds;
  }
  
  
  
  /**Override method in AdvancedVisitor that throws an error here.*/
  public void forTryCatchStatementDoFirst(TryCatchStatement that) {
    //do nothing!  No errors to throw here.
  }

  /*
   * Make sure that no modifiers appear before the InnerClassDef, and then delegate.
   */
  public void forInnerClassDef(InnerClassDef that) {
    if (that.getMav().getModifiers().length > 0) {_addAndIgnoreError("No modifiers may appear before a class declaration here", that.getMav());}
    handleInnerClassDef(that, _bodyData, getQualifiedClassName(_bodyData.getSymbolData().getName()) + "$" + _bodyData.getSymbolData().preincrementLocalClassNum() + that.getName().getText());
  }
  
  /**
   * Give an error, since InnerInterfaces cannot appear here.
   */
  public void forInnerInterfaceDef(InnerInterfaceDef that) {
    _addError("Inner interface declarations cannot appear here", that);
  }
  
  /**
   * Delegate to method in LLV
   */
  public void forComplexAnonymousClassInstantiation(ComplexAnonymousClassInstantiation that) {
    complexAnonymousClassInstantiationHelper(that, _bodyData);
  }

  /**
   * Delegate to method in LLV
   */
  public void forSimpleAnonymousClassInstantiation(SimpleAnonymousClassInstantiation that) {
    simpleAnonymousClassInstantiationHelper(that, _bodyData);
  }

    
   /**
    * Test most of the methods declared above right here:
    */
  public static class BodyBodyAdvancedVisitorTest extends TestCase {
    
    private BodyBodyAdvancedVisitor _bav;
    
    private SymbolData _sd1;
    private MethodData _md1;
    private ModifiersAndVisibility _publicMav = new ModifiersAndVisibility(JExprParser.NO_SOURCE_INFO, new String[] {"public"});
    private ModifiersAndVisibility _protectedMav = new ModifiersAndVisibility(JExprParser.NO_SOURCE_INFO, new String[] {"protected"});
    private ModifiersAndVisibility _privateMav = new ModifiersAndVisibility(JExprParser.NO_SOURCE_INFO, new String[] {"private"});
    private ModifiersAndVisibility _packageMav = new ModifiersAndVisibility(JExprParser.NO_SOURCE_INFO, new String[0]);
    private ModifiersAndVisibility _abstractMav = new ModifiersAndVisibility(JExprParser.NO_SOURCE_INFO, new String[] {"abstract"});
    private ModifiersAndVisibility _finalMav = new ModifiersAndVisibility(JExprParser.NO_SOURCE_INFO, new String[] {"final"});
    private ModifiersAndVisibility _staticMav = new ModifiersAndVisibility(JExprParser.NO_SOURCE_INFO, new String[] {"static"});
    
    
    public BodyBodyAdvancedVisitorTest() {
      this("");
    }
    
    public BodyBodyAdvancedVisitorTest(String name) {
      super(name);
    }
    
    public void setUp() {
      _sd1 = new SymbolData("i.like.monkey");
      _md1 = new MethodData("methodName", _publicMav, new TypeParameter[0], SymbolData.INT_TYPE, 
                                   new VariableData[0], 
                                   new String[0],
                                   _sd1,
                                   null);

      errors = new LinkedList<Pair<String, JExpressionIF>>();
      symbolTable = new Symboltable();
      visitedFiles = new LinkedList<Pair<LanguageLevelVisitor, edu.rice.cs.javalanglevels.tree.SourceFile>>();      
      _hierarchy = new Hashtable<String, TypeDefBase>();
      _classesToBeParsed = new Hashtable<String, Pair<TypeDefBase, LanguageLevelVisitor>>();
      _bav = new BodyBodyAdvancedVisitor(_md1, new File(""), "", new LinkedList<String>(), new LinkedList<String>(), new LinkedList<String>(), new Hashtable<String, Pair<SourceInfo, LanguageLevelVisitor>>());
      
      _bav.continuations = new Hashtable<String, Pair<SourceInfo, LanguageLevelVisitor>>();
      _bav._resetNonStaticFields();
      _bav._importedPackages.addFirst("java.lang");
      _bav._newSDs = new Hashtable<SymbolData, LanguageLevelVisitor>();
      _errorAdded = false;
    }
    
    public void testForMethodDefDoFirst() {
      ConcreteMethodDef cmd = new ConcreteMethodDef(JExprParser.NO_SOURCE_INFO, 
                                                    _packageMav, 
                                                    new TypeParameter[0], 
                                                    new PrimitiveType(JExprParser.NO_SOURCE_INFO, "int"), 
                                                    new Word(JExprParser.NO_SOURCE_INFO, "methodName"),
                                                    new FormalParameter[0],
                                                    new ReferenceType[0], 
                                                    new BracedBody(JExprParser.NO_SOURCE_INFO, new BodyItemI[0]));
      cmd.visit(_bav);
      assertEquals("There should be one error.", 1, errors.size());
      assertEquals("The error message should be correct.", 
                   "Methods definitions cannot appear within the body of another method or block.",
                   errors.get(0).getFirst());
    }
    
    /* These last two tests are shared with ClassBodyIntermediateVisitor,
     * perhaps we could factor them out. */
    
    public void testForVariableDeclarationOnly() {
      // Check one that works
      VariableDeclaration vdecl = new VariableDeclaration(JExprParser.NO_SOURCE_INFO,
                                                       _packageMav,
                                                       new VariableDeclarator[] {
        new UninitializedVariableDeclarator(JExprParser.NO_SOURCE_INFO, 
                               new PrimitiveType(JExprParser.NO_SOURCE_INFO, "double"), 
                               new Word (JExprParser.NO_SOURCE_INFO, "field1")),
        new UninitializedVariableDeclarator(JExprParser.NO_SOURCE_INFO, 
                               new PrimitiveType(JExprParser.NO_SOURCE_INFO, "boolean"), 
                               new Word (JExprParser.NO_SOURCE_INFO, "field2"))});
      VariableData vd1 = new VariableData("field1", _packageMav, SymbolData.DOUBLE_TYPE, false, _bav._bodyData);
      VariableData vd2 = new VariableData("field2", _packageMav, SymbolData.BOOLEAN_TYPE, false, _bav._bodyData);
      vdecl.visit(_bav);
      assertEquals("There should not be any errors.", 0, errors.size());
      LinkedList<VariableData> vds = _md1.getVars();
//      for (int i = 0; i<vds.size(); i++) {
//        System.out.println(vds.get(i).getName() + " " + vds.get(i).getMav() + " " + vds.get(i).getType().getName() + " " +
//                           vds.get(i).hasValue() + " " + vds.get(i).getEnclosingData().getName());
//      }
      assertTrue("field1 was added.", _md1.getVars().contains(vd1));
      assertTrue("field2 was added.", _md1.getVars().contains(vd2));
      
      // Check one that doesn't work
      VariableDeclaration vdecl2 = new VariableDeclaration(JExprParser.NO_SOURCE_INFO,
                                                        _packageMav,
                                                        new VariableDeclarator[] {
        new UninitializedVariableDeclarator(JExprParser.NO_SOURCE_INFO, 
                                            new PrimitiveType(JExprParser.NO_SOURCE_INFO, "double"), 
                                            new Word (JExprParser.NO_SOURCE_INFO, "field3")),
        new UninitializedVariableDeclarator(JExprParser.NO_SOURCE_INFO, 
                                            new PrimitiveType(JExprParser.NO_SOURCE_INFO, "int"), 
                                            new Word (JExprParser.NO_SOURCE_INFO, "field3"))});
      VariableData vd3 = new VariableData("field3", _packageMav, SymbolData.DOUBLE_TYPE, false, _bav._bodyData);
      vdecl2.visit(_bav);
      assertEquals("There should be one error.", 1, errors.size());
      assertEquals("The error message should be correct", "You cannot have two variables with the same name.", errors.get(0).getFirst());
      assertTrue("field3 was added.", _md1.getVars().contains(vd3));
    }
    
    public void testForTryCatchStatement() {
      //Make sure that no error is thrown
      BracedBody emptyBody = new BracedBody(JExprParser.NO_SOURCE_INFO, new BodyItemI[0]);
      Block b = new Block(JExprParser.NO_SOURCE_INFO, emptyBody);

      NormalTryCatchStatement ntcs = new NormalTryCatchStatement(JExprParser.NO_SOURCE_INFO, b, new CatchBlock[0]);
      TryCatchFinallyStatement tcfs = new TryCatchFinallyStatement(JExprParser.NO_SOURCE_INFO, b, new CatchBlock[0], b);
      ntcs.visit(_bav);
      tcfs.visit(_bav);
      assertEquals("After visiting both NormalTryCatchStatement and TryCatchFinallyStatement, there should be no errors", 0, errors.size());
      
      //make sure that if there is an error in one of the bodies, it is caught:   (this is an arbitrary error).
      BracedBody errorBody = new BracedBody(JExprParser.NO_SOURCE_INFO, new BodyItemI[] {
        new ExpressionStatement(JExprParser.NO_SOURCE_INFO, 
                                new BitwiseOrExpression(JExprParser.NO_SOURCE_INFO, new IntegerLiteral(JExprParser.NO_SOURCE_INFO, 1), new IntegerLiteral(JExprParser.NO_SOURCE_INFO, 2)))});
      Block errorBlock = new Block(JExprParser.NO_SOURCE_INFO, errorBody);
      
      ntcs = new NormalTryCatchStatement(JExprParser.NO_SOURCE_INFO, errorBlock, new CatchBlock[0]);
      ntcs.visit(_bav);
      assertEquals("Should be one error", 1, errors.size());
      assertEquals("Error message should be correct", "Bitwise or expressions cannot be used at any language level.  Perhaps you meant to compare two values using regular or (||)", errors.get(0).getFirst());
      
      //make sure that if there is an error in one of the catch statements, it is caught: (this is an arbitrary error).
      UninitializedVariableDeclarator uvd = new UninitializedVariableDeclarator(JExprParser.NO_SOURCE_INFO, new PrimitiveType(JExprParser.NO_SOURCE_INFO, "int"), new Word(JExprParser.NO_SOURCE_INFO, "i"));
      FormalParameter fp = new FormalParameter(JExprParser.NO_SOURCE_INFO, uvd, false);

      tcfs = new TryCatchFinallyStatement(JExprParser.NO_SOURCE_INFO, b, new CatchBlock[] {
        new CatchBlock(JExprParser.NO_SOURCE_INFO, fp, errorBlock)}, b);
        
     tcfs.visit(_bav);
     assertEquals("Should be two errors", 2, errors.size());
     assertEquals("Error message should be correct", "Bitwise or expressions cannot be used at any language level.  Perhaps you meant to compare two values using regular or (||)", errors.get(1).getFirst());
    }
    
    public void testForInnerClassDef() {
     
      //test one that works
      SymbolData obj = new SymbolData("java.lang.Object");
      symbolTable.put("java.lang.Object", obj);
      InnerClassDef cd0 = new InnerClassDef(JExprParser.NO_SOURCE_INFO, _packageMav, new Word(JExprParser.NO_SOURCE_INFO, "Rod"),
                                       new TypeParameter[0], new ClassOrInterfaceType(JExprParser.NO_SOURCE_INFO, "java.lang.Object", new Type[0]), new ReferenceType[0], 
                                       new BracedBody(JExprParser.NO_SOURCE_INFO, new BodyItemI[0]));

      cd0.visit(_bav);
      assertEquals("There should be no errors", 0, errors.size());
      SymbolData innerClass = _bav._bodyData.getInnerClassOrInterface("Rod");
      assertNotNull("Should have a inner class named Rod", innerClass);
      
      //test one with explicit modifiers
      InnerClassDef cd1 = new InnerClassDef(JExprParser.NO_SOURCE_INFO, _publicMav, new Word(JExprParser.NO_SOURCE_INFO, "Todd"),
                                       new TypeParameter[0], new ClassOrInterfaceType(JExprParser.NO_SOURCE_INFO, "java.lang.Object", new Type[0]), new ReferenceType[0], 
                                            new BracedBody(JExprParser.NO_SOURCE_INFO, new BodyItemI[0]));
      cd1.visit(_bav);
      assertEquals("There should be 1 error", 1, errors.size());
      assertEquals("The error message should be correct", "No modifiers may appear before a class declaration here", errors.getLast().getFirst());

      

    }
    
    public void testForInnerInterfaceDef() {
      //There should always be an error
      InnerInterfaceDef iid = new InnerInterfaceDef(JExprParser.NO_SOURCE_INFO, _packageMav, new Word(JExprParser.NO_SOURCE_INFO, "Broken"),
                                                    new TypeParameter[0], new ReferenceType[0], 
                                                    new BracedBody(JExprParser.NO_SOURCE_INFO, new BodyItemI[0]));
      
      iid.visit(_bav);
      assertEquals("There should be 1 error", 1, errors.size());
      assertEquals("The error message should be correct", "Inner interface declarations cannot appear here", errors.getLast().getFirst());
      
    }
    
  }
}



See more files for this project here

DrJava

DrJava is a lightweight programming environment for Java designed to foster test-driven software development. It includes an intelligent program editor, an interactions pane for evaluating program text, a source level debugger, and a unit testing tool.

Project homepage: http://sourceforge.net/projects/drjava
Programming language(s): Java
License: other

  AdvancedLevelTest.java
  AdvancedVisitor.java
  ArrayData.java
  Augmentor.java
  BlockData.java
  Bob.java
  BodyBodyAdvancedVisitor.java
  BodyBodyElementaryVisitor.java
  BodyBodyIntermediateVisitor.java
  BodyData.java
  BodyTypeChecker.java
  CharConverter.java
  ClassBodyAdvancedVisitor.java
  ClassBodyElementaryVisitor.java
  ClassBodyIntermediateVisitor.java
  ClassBodyTypeChecker.java
  ConstructorBodyTypeChecker.java
  Data.java
  ElementaryLevelTest.java
  ElementaryVisitor.java
  ExpressionTypeChecker.java
  InstanceData.java
  InterfaceBodyAdvancedVisitor.java
  InterfaceBodyIntermediateVisitor.java
  InterfaceBodyTypeChecker.java
  IntermediateLevelTest.java
  IntermediateVisitor.java
  JExprParseException.java
  JExprParserTest.java
  JExpressionIFPrunableDepthFirstVisitor_void.java
  LValueTypeChecker.java
  LValueWithValueTypeChecker.java
  LanguageLevelConverter.java
  LanguageLevelVisitor.java
  MethodData.java
  PackageData.java
  Pair.java
  PrimitiveData.java
  SourceInfo.java
  SymbolData.java
  Symboltable.java
  TryCatchBodyTypeChecker.java
  TypeChecker.java
  TypeData.java
  VariableData.java
  VoidMethodsNotAllowedClassBodyTypeChecker.java
  jexpr.ast
  jexpr.jj