📄 resolver.java
字号:
// 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.util.Vector;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogConfigurationException;
import org.apache.commons.logging.LogFactory;
import com.puppycrawl.tools.checkstyle.api.TokenTypes;
/**
* The resolver is responsible for traversing all the various
* definitions in a symbol table and resolving references in them.
*
* @see SymbolTable
*/
public class Resolver extends DefinitionTraverser {
/** true if the log factory has been initialized */
private boolean mInitialized = false;
/** Factory for creating org.apache.commons.logging.Log instances */
private LogFactory mLogFactory;
/**
* constructor with <code>SymbolTable</code> to be resolved
*/
public Resolver(SymbolTable symbolTable) {
super(symbolTable);
try {
mLogFactory = LogFactory.getFactory();
}
catch (LogConfigurationException e) {
System.out.println("log configuration exception" + e);
}
mInitialized = true;
}
/**
* resolves the symbol table
* @return <code>void</code>
* @see #traverse()
*/
public void resolve() {
traverse();
}
protected void handleSList(SymTabAST node, Scope scope) {
SymTabASTIterator iterator = node.getChildren();
while (iterator.hasNext()) {
SymTabAST current = iterator.nextChild();
resolveExpression(current, scope, null, true);
}
}
protected void handleAnonymousInnerClass(AnonymousInnerClass innerClass) {
SymTabAST objblock = innerClass.getTreeNode();
SymTabAST expression = (SymTabAST) objblock.getFirstChild();
while (expression != null) {
resolveExpression(expression, innerClass, null, true);
expression = (SymTabAST) expression.getNextSibling();
}
}
/**
* processes a <code>ClassDef</code> and resolves references in it
*
* @param classDef the <code>ClassDef</code> to process
*/
protected void handleClass(ClassDef classDef) {
SymTabAST node = classDef.getTreeNode();
if (node != null) {
SymTabAST nameNode = node.findFirstToken(TokenTypes.IDENT);
nameNode.setDefinition(classDef, classDef, true);
SymTabAST extendsClause =
node.findFirstToken(TokenTypes.EXTENDS_CLAUSE);
SymTabAST extendedClassNode =
(SymTabAST) extendsClause.getFirstChild();
while (extendedClassNode != null) {
IClass superClass =
resolveClass(extendedClassNode, classDef, null, true);
extendedClassNode.setDefinition(superClass, classDef, true);
extendedClassNode =
(SymTabAST) extendedClassNode.getNextSibling();
}
SymTabAST implementsNode =
node.findFirstToken(TokenTypes.IMPLEMENTS_CLAUSE);
if (implementsNode != null) {
SymTabAST interfaceNode =
(SymTabAST) (implementsNode.getFirstChild());
while (interfaceNode != null) {
resolveClass(interfaceNode, classDef, null, true);
interfaceNode =
(SymTabAST) (interfaceNode.getNextSibling());
}
}
}
}
/**
* processes a <code>MethodDef</code> and resolves references in it
*
* @param method the <code>MethodDef</code> to process
*/
protected void handleMethod(MethodDef method) {
SymTabAST node = method.getTreeNode();
SymTabAST nameNode = node.findFirstToken(TokenTypes.IDENT);
nameNode.setDefinition(method, method, true);
// references to classes in return type
SymTabAST returnTypeNode = node.findFirstToken(TokenTypes.TYPE);
if (returnTypeNode != null) {
// this is not a constructor
resolveExpression(returnTypeNode, method, null, true);
}
SymTabAST throwsNode =
node.findFirstToken(TokenTypes.LITERAL_THROWS);
if (throwsNode != null) {
SymTabAST exception = (SymTabAST) throwsNode.getFirstChild();
while (exception != null) {
// handle Checkstyle grammar
if (exception.getType() != TokenTypes.COMMA) {
resolveClass(exception, method, null, true);
}
exception = (SymTabAST) exception.getNextSibling();
}
}
// references to classes in parameters
// the body -- this would be better its own function
SymTabAST slist = node.findFirstToken(TokenTypes.SLIST);
if (slist != null) {
handleSList(slist, method);
}
}
/**
* processes a <code>BlockDef</code> and resolves references in it
*
* @param block the <code>BlockDef</code> to process
*/
protected void handleBlock(BlockDef block) {
SymTabAST node = block.getTreeNode();
switch (node.getType()) {
case TokenTypes.LITERAL_FOR :
handleFor(block);
break;
case TokenTypes.LITERAL_IF :
handleIf(block);
break;
case TokenTypes.LITERAL_WHILE :
handleWhileAndSynchronized(block);
break;
case TokenTypes.LITERAL_DO :
handleDoWhile(block);
break;
case TokenTypes.LITERAL_TRY :
case TokenTypes.LITERAL_FINALLY :
SymTabAST slist = node.findFirstToken(TokenTypes.SLIST);
handleSList(slist, block);
break;
case TokenTypes.LITERAL_CATCH :
handleCatch(block);
break;
case TokenTypes.LITERAL_SWITCH :
handleSwitch(block);
break;
case TokenTypes.SLIST :
handleSList(node, block);
break;
case TokenTypes.EXPR :
resolveExpression(node, block, null, true);
break;
case TokenTypes.INSTANCE_INIT :
case TokenTypes.STATIC_INIT :
handleSList((SymTabAST) node.getFirstChild(), block);
break;
case TokenTypes.LITERAL_SYNCHRONIZED :
handleWhileAndSynchronized(block);
break;
case TokenTypes.LITERAL_ASSERT :
handleAssert(block);
break;
default :
if (mInitialized) {
final Log log = mLogFactory.getInstance(this.getClass());
log.error(
"Unhandled block "
+ block
+ " of type "
+ node.getType());
}
}
}
/**
* @param block
*/
private void handleAssert(BlockDef block) {
SymTabAST node = block.getTreeNode();
SymTabAST conditional =
(node.findFirstToken(TokenTypes.EXPR));
resolveExpression(conditional, block, null, true);
SymTabAST message = (SymTabAST) conditional.getNextSibling();
while ((message != null) && (message.getType() != TokenTypes.EXPR)) {
message = (SymTabAST) message.getNextSibling();
}
if (message != null) {
resolveExpression(message, block, null, true);
}
}
/**
* processes a switch statement and resolves references in it
*
* @param block the <code>BlockDef</code> to process
*/
private void handleSwitch(BlockDef block) {
SymTabAST node = block.getTreeNode();
SymTabAST expr = node.findFirstToken(TokenTypes.EXPR);
resolveExpression(expr, block, null, true);
SymTabAST caseGroup = (SymTabAST) (expr.getNextSibling());
while (caseGroup != null
&& (caseGroup.getType() != TokenTypes.CASE_GROUP)) {
caseGroup = (SymTabAST) caseGroup.getNextSibling();
}
if (caseGroup != null) {
while (caseGroup.getType() == TokenTypes.CASE_GROUP) {
SymTabAST caseNode =
caseGroup.findFirstToken(TokenTypes.LITERAL_CASE);
while (caseNode != null
&& caseNode.getType() == TokenTypes.LITERAL_CASE) {
resolveExpression(
(SymTabAST) caseNode.getFirstChild(),
block,
null,
true);
caseNode = (SymTabAST) caseNode.getNextSibling();
}
SymTabAST caseSlist =
caseGroup.findFirstToken(TokenTypes.SLIST);
handleSList(caseSlist, block);
caseGroup = (SymTabAST) (caseGroup.getNextSibling());
}
}
}
/**
* processes a catch block and resolves references in it
*
* @param block the <code>BlockDef</code> to process
*/
private void handleCatch(BlockDef block) {
SymTabAST node = block.getTreeNode();
SymTabAST slist = node.findFirstToken(TokenTypes.SLIST);
handleSList(slist, block);
}
/**
* processes a for loop and resolves references in it
*
* @param block the <code>BlockDef</code> to process
*/
private void handleFor(BlockDef block) {
SymTabAST node = block.getTreeNode();
SymTabAST body;
SymTabAST forEach = node.findFirstToken(TokenTypes.FOR_EACH_CLAUSE);
if (forEach == null) {
SymTabAST init = node.findFirstToken(TokenTypes.FOR_INIT);
// only need to handle the elist case. if the init node is a variable
// definition, the variable def will be handled later on in the resolution
if (init.getFirstChild() != null) {
if (init.getFirstChild().getType() == TokenTypes.ELIST) {
resolveExpression(
(SymTabAST) (init.getFirstChild()),
block,
null,
true);
}
}
SymTabAST cond = node.findFirstToken(TokenTypes.FOR_CONDITION);
if (cond.getFirstChild() != null) {
resolveExpression(
(SymTabAST) (cond.getFirstChild()),
block,
null,
true);
}
SymTabAST iterator = node.findFirstToken(TokenTypes.FOR_ITERATOR);
if (iterator.getFirstChild() != null) {
resolveExpression(
(SymTabAST) (iterator.getFirstChild()),
block,
null,
true);
}
body = (SymTabAST) (iterator.getNextSibling());
}
else {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -