⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tablemaker.java

📁 Checkstyle 可寻找:·不能使用的或者多余的输入 ·空格更好的地方不使用跳格符
💻 JAVA
📖 第 1 页 / 共 3 页
字号:

// Transmogrify License
// 
// Copyright (c) 2001, ThoughtWorks, Inc.
// 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 name of the ThoughtWorks, Inc. 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.

package com.puppycrawl.tools.checkstyle.checks.usage.transmogrify;

import java.io.File;
import java.util.Enumeration;
import java.util.Vector;

import com.puppycrawl.tools.checkstyle.api.TokenTypes;




/**
 * this is the class that does the work of the "walking" step --
 * going through the SymTabAST and constructing the definitions and
 * references.  The SymTabAST is constructed in a DOMish fashion, i.e.
 * each node knows about its first child and its next sibling.  The
 * DFS search is carried out by two functions -- walkTree, which
 * deals with a single SymTabAST node, and walkSibilngs, which deals with
 * all the siblings of an SymTabAST node.
 */

public class TableMaker {
  private SymbolTable symbolTable;
  private SymTabAST _tree;
  private File currentFile;
  private Vector imports = new Vector();

  /**
   * Constructor for the TableMaker class
   *
   * @param tree is the<code>SymTabAST</code> from which to
   * build the <code>TableMaker</code>. It is the tree which wil be walked
   * in order to build definitions and references.
   */
  public TableMaker(SymTabAST tree)
  {
    _tree = tree;
  }

  /**
   * returns the <code> SymTabAST </code> which is the
   * SymTabAST generated from the parsed Java Source files.
   *
   * @return <code>SymTabAST</code>
   */
  public SymTabAST getTree() {
    return _tree;
  }

  /**
   * returns the <code>SymbolTable</code> that has been constructed by
   * this <code>TableMaker</code>
   *
   * @return <code>SymbolTable</code>
   * @throws <code>SymbolTableException</code>
   */
  public SymbolTable getTable() throws SymbolTableException {
    if (symbolTable == null) {
      symbolTable = new SymbolTable( _tree );

      createDefinitions();

      resolveReferences();
    }

    return symbolTable;
  }

  /**
   * walks the tree and finishes creating definitions.
   *
   * @return <code>void</code>
   * @throws <code>SymbolTableException</code>
   * @see #walkTree()
   * @see #finishCreatingDefinitions()
   */
  private void createDefinitions() throws SymbolTableException {
    walkTree();
    finishCreatingDefinitions();
  }

  /**
   * finishes up creating definitions process
   * starts at the base of the Table
   *
   * @return <code>void</code>
   * @throws <code>SymbolTableException</code>
   * @see net.sourceforge.transmogrify.symtab.SymbolTable
   * @see #finishCreatingDefinition(Definition)
   */
  private void finishCreatingDefinitions() throws SymbolTableException {
    finishCreatingDefinition(symbolTable.getBaseScope());
  }

  /**
   * begins at the base of the Table and starts finishing definition creation.
   *
   * @param def <code>Definition</code> needs to be completed
   * @return <code>void</code>
   * @throws <code>SymbolTableException</code>
   * @see ClassFinisher
   * @see VariableFinisher
   * @see MethodFinisher
   * @see CatchFinisher
   */
  private void finishCreatingDefinition(Definition def) throws SymbolTableException {

    if (def instanceof AnonymousInnerClass) {
      AnonymousInnerClass innerClass = (AnonymousInnerClass)def;
      innerClass.finishMakingDefinition();
    }
    else if (def instanceof ClassDef) {
      new ClassFinisher(def).finish();
    }
    else if ( def instanceof VariableDef ) {
      new VariableFinisher( def ).finish();
    }
    else if (def instanceof DefaultConstructor) {}
    else if ( def instanceof MethodDef ) {
      new MethodFinisher( def ).finish();
    }
    else if (def instanceof BlockDef) {
      SymTabAST firstChild = (SymTabAST)def.getTreeNode().getFirstChild();
      //handle Checkstyle grammar
      if (firstChild.getType() == TokenTypes.LPAREN) {
          firstChild = (SymTabAST) firstChild.getNextSibling();
      }
      if (firstChild.getType() == TokenTypes.PARAMETER_DEF) {
        // this is a catch block
        new CatchFinisher((BlockDef)def).finish();
      }
    }

    if ( def instanceof Scope ) {
      finishCreatingChildren((Scope)def);
    }
  }


  /**
   * iterates through all the definitions in the <code> Scope </code>
   * finishes creating each <code>Scope</code>.
   *
   * @param scope <code> Scope </code> where defininitions will be finished.
   * @return <code>void</code>
   * @throws <code>SymbolTableException</code>
   * @see net.sourceforge.transmogrify.symtab.Scope
   * @see #finishCreatingDefinition(Definition)
   */
  private void finishCreatingChildren( Scope scope ) throws SymbolTableException {
    Enumeration definitions = scope.getDefinitions();
    while ( definitions.hasMoreElements() ) {
      Definition child = (Definition)(definitions.nextElement());
      finishCreatingDefinition(child);
    }
  }

  /**
   * resolves <code>SymbolTable</code> using <code>Resolver</code>
   *
   * @return <code>void</code>
   * @see net.sourceforge.transmogrify.symtab.Resolver
   * @see net.sourceforge.transmogrify.symtab.SymbolTable
   */
  private void resolveReferences() {
    new Resolver( symbolTable ).resolve();
  }

  /**
   * starts walking the <code> SymTabAST </code>
   *
   * @return <code>void</code>
   * @see #walkSiblings(SymTabAST,boolean)
   * @see net.sourceforge.transmogrify.symtab.antlr.SymTabAST
   */
  public void walkTree() {
    walkSiblings((SymTabAST)_tree.getFirstChild(), false);
  }

  /**
   * processes a single SymTabAST node based on its type and passes of its
   * children for further processing where appropriate.
   *
   * @param tree the <code>SymTabAST</code> node to process
   * @param makeAnonymousScopes sets to <code>false</code> after walking Class,
   *                            Methods and Try otherwise sets to <code>true</code>
   * @return <code>void</code>
   * @see #walkSiblings(SymTabAST, boolean)
   * @see #processAnonymousInnerClass(SymTabAST, SymTabAST)
   * @see #processBlock(SymTabAST, boolean)
   * @see #processClass(SymTabAST)
   * @see #processConstructorDef(SymTabAST)
   * @see #processElse(SymTabAST)
   * @see #processFile(SymTabAST)
   * @see #processFinally(SymTabAST)
   * @see #processFor(SymTabAST)
   * @see #processImplicitPackage(SymTabAST)
   * @see #processImport(SymTabAST)
   * @see #processLabel(SymTabAST)
   * @see #processMethodDef(SymTabAST)
   * @see #processPackage(SymTabAST)
   * @see #processTry(SymTabAST)
   * @see net.sourceforge.transmogrify.symtab.antlr.SymTabAST
   * @see net.sourceforge.transmogrify.symtab.antlr.JavaTokenTypes
   */
  public void walkTree(SymTabAST tree, boolean makeAnonymousScopes) {

    if (tree != null) {

      tree.setScope( symbolTable.getCurrentScope() );

      switch(tree.getType()) {
      case 0:
        processFile(tree);
        if ( tree.getFirstChild().getType() != TokenTypes.PACKAGE_DEF ) {
          processImplicitPackage( tree.getFile() );
        }

        walkSiblings((SymTabAST)tree.getFirstChild(), false);

        // pop package scope
        symbolTable.popScope();
        clearImports();
        break;

      case TokenTypes.LITERAL_NEW:
        SymTabAST symtabTree = tree;
        //walk parameters, in case of anonymous inner class
        walkTree(symtabTree.findFirstToken(TokenTypes.ELIST),
          makeAnonymousScopes);
        SymTabAST objblock
          = symtabTree.findFirstToken(TokenTypes.OBJBLOCK);
        if (objblock != null) {
          SymTabAST classExtended
            = symtabTree.findFirstToken(TokenTypes.IDENT);

          processAnonymousInnerClass(objblock, classExtended);
        }
        break;

      case TokenTypes.SLIST:
        if (makeAnonymousScopes) {
          processBlock(tree, true);
        }
        else {
          walkSiblings((SymTabAST)tree.getFirstChild(), true);
        }
        break;

      case TokenTypes.CTOR_DEF:
        processConstructorDef(tree);
        break;

      case TokenTypes.METHOD_DEF:
        processMethodDef(tree);
        break;

      case TokenTypes.LITERAL_FINALLY:
        processFinally(tree);
        break;

      case TokenTypes.LITERAL_TRY:
        processTry(tree);
        break;

      case TokenTypes.VARIABLE_DEF:
        processVariableDef(tree);
        break;

      case TokenTypes.PACKAGE_DEF:
        processPackage(tree);
        break;

      case TokenTypes.LABELED_STAT:
        processLabel(tree);
        break;

      case TokenTypes.IMPORT:
        processImport(tree);
        break;

      case TokenTypes.CLASS_DEF:
      case TokenTypes.INTERFACE_DEF:
        processClass(tree);
        break;

      case TokenTypes.LITERAL_FOR:
        processFor(tree);
        break;

      case TokenTypes.LITERAL_IF:
        processIf(tree);
        break;
      
      case TokenTypes.LITERAL_ASSERT:
        processAssert(tree);
        break;

      case TokenTypes.LITERAL_CATCH:
      case TokenTypes.LITERAL_WHILE:
      case TokenTypes.LITERAL_SWITCH:
      case TokenTypes.LITERAL_DO:
      case TokenTypes.LITERAL_SYNCHRONIZED:
      case TokenTypes.STATIC_INIT:
      case TokenTypes.INSTANCE_INIT:
        processBlock(tree, false);
        break;

      default:
        walkSiblings((SymTabAST)tree.getFirstChild(), false);
      }
    }
  }

  /**
 * @param tree
 */
public void processAssert(SymTabAST tree) {
    BlockDef block = makeBlock(tree);

    SymTabAST expr = tree.findFirstToken(TokenTypes.EXPR);
    SymTabAST message = (SymTabAST)expr.getNextSibling();
    while ((message != null) && (message.getType() != TokenTypes.EXPR)) {
        message = (SymTabAST) message.getNextSibling();
    }


    symbolTable.pushScope( block );
    walkTree(expr, false);
    if (message != null) {  
        walkTree(message, false);
    }
    symbolTable.popScope();   
}

/**
   * processes the given <code>SymTabAST</code> and each of its siblings
   *
   * @param tree <code>SymTabAST</code> node to process
   * @param makeAnonymousScopes
   *
   * @return <code>void</code>
   * @see #walkTree(SymTabAST, boolean)
   * @see net.sourceforge.transmogrify.symtab.antlr.SymTabAST
   */
  public void walkSiblings(SymTabAST tree, boolean makeAnonymousScopes) {
    while(tree != null) {
      walkTree(tree, makeAnonymousScopes);
      tree = (SymTabAST)tree.getNextSibling();
    }
  }

  /**
   * processes the given <code>SymTabAST</code> as a package defintion
   *
   * @param tree the <code>SymTabAST</code> to process
   * @return <code>void</code>
   * @see net.sourceforge.transmogrify.symtab.antlr.SymTabAST
   * @see net.sourceforge.transmogrify.symtab.PackageDef
   * @see net.sourceforge.transmogrify.symtab.SymbolTable
   */
  public void processPackage(SymTabAST tree) {
    SymTabAST firstChild = (SymTabAST)tree.getFirstChild();

    String name = ASTUtil.constructDottedName(firstChild);
    firstChild.ignoreChildren();

    PackageDef pkg = symbolTable.getPackage(name);

    if (pkg == null) {
      pkg = createPackage( (SymTabAST)(tree.getFirstChild()) );
    }

    symbolTable.pushScope(pkg);
  }

  /**
   * processes a java class that use default no package
   *
   * @param file <code>File</code> object of the java class
   * @return <code>void</code>
   * @see net.sourceforge.transmogrify.symtab.PackageDef
   * @see net.sourceforge.transmogrify.symtab.SymbolTable
   */
  public void processImplicitPackage( File file ) {
    String name = file.getParent();
    if (name == null) {
        name = "";
    }
    PackageDef pkg = symbolTable.getPackage( name );

    if ( pkg == null ) {
      pkg = new PackageDef( name, symbolTable.getBaseScope(), null );
      symbolTable.definePackage( pkg, symbolTable.getBaseScope() );
    }

    symbolTable.pushScope( pkg );
  }

  /**
   * gets the package represented by the tree.  The method
   * analyzes the tree, constructs an appropriate package name
   * and fetches it from the internal package list. If the package does not
   * exist it is created.
   *
   * @param tree <code>SymTabAST</code> to consider
   *
   * @return <code>PackageDef</code> the resulting package definition
   * @see #getPackage(Scope, SymTabAST)
   */
  private PackageDef createPackage( SymTabAST tree ) {
    PackageDef result = null;

    if (tree.getType() == TokenTypes.DOT) {
      // find the package result of left child
      SymTabAST leftChild = (SymTabAST)tree.getFirstChild();
      SymTabAST rightChild = (SymTabAST)leftChild.getNextSibling();

      PackageDef context = createPackage(leftChild);
      result = getPackage( context, rightChild );
    }
    else {
      result = getPackage(symbolTable.getBaseScope(), tree);
    }

    return result;
  }

  /**
   * gets the package determined by the tree and parent package def.
   * The method analyzes the tree and parent scope and retrieves the
   * appropriate package definition from the internal package list.
   * If the package does not exist it is created.
   *
   * @param tree <code>SymTabAST</code> to consider
   * @param parent the parent package definition
   *
   * @return PackageDef the resulting package definition
   * @see net.sourceforge.transmogrify.symtab.PackageDef
   * @see net.sourceforge.transmogrify.symtab.SymbolTable
   * @see net.sourceforge.transmogrify.symtab.antlr.SymTabAST
   */
  private PackageDef getPackage(Scope parent, SymTabAST tree ) {
    String name = tree.getText();
    PackageDef result = null;
    if (!(parent instanceof BaseScope)) {
      result = symbolTable.getPackage(parent.getQualifiedName() + "." + name);
    }
    else {
      result = symbolTable.getPackage(name);
    }

    if (result == null) {
      result = new PackageDef(tree.getText(), parent, tree);
      symbolTable.definePackage(result, parent);
    }

    return result;
  }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -