📄 resolvevisitor.java
字号:
/* * $Id: ResolveVisitor.java,v 1.22 2006/06/25 19:58:43 blackdrag Exp $ * * Copyright 2003 (C) James Strachan and Bob Mcwhirter. All Rights Reserved. * * Redistribution and use of this software and associated documentation * ("Software"), with or without modification, are permitted provided that the * following conditions are met: 1. Redistributions of source code must retain * copyright statements and notices. Redistributions must also contain a copy * of this document. 2. 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. 3. * The name "groovy" must not be used to endorse or promote products derived * from this Software without prior written permission of The Codehaus. For * written permission, please contact info@codehaus.org. 4. Products derived * from this Software may not be called "groovy" nor may "groovy" appear in * their names without prior written permission of The Codehaus. "groovy" is a * registered trademark of The Codehaus. 5. Due credit should be given to The * Codehaus - http://groovy.codehaus.org/ * * THIS SOFTWARE IS PROVIDED BY THE CODEHAUS AND CONTRIBUTORS ``AS IS'' AND ANY * EXPRESSED 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 CODEHAUS OR ITS 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 org.codehaus.groovy.control;import groovy.lang.GroovyClassLoader;import java.io.IOException;import java.io.File;import java.lang.reflect.Field;import java.util.HashMap;import java.util.Iterator;import java.util.LinkedList;import java.util.List;import java.util.Map;import java.net.URL;import java.net.MalformedURLException;import org.codehaus.groovy.ast.ASTNode;import org.codehaus.groovy.ast.AnnotatedNode;import org.codehaus.groovy.ast.AnnotationNode;import org.codehaus.groovy.ast.ClassCodeVisitorSupport;import org.codehaus.groovy.ast.ClassHelper;import org.codehaus.groovy.ast.ClassNode;import org.codehaus.groovy.ast.CodeVisitorSupport;import org.codehaus.groovy.ast.CompileUnit;import org.codehaus.groovy.ast.ConstructorNode;import org.codehaus.groovy.ast.DynamicVariable;import org.codehaus.groovy.ast.FieldNode;import org.codehaus.groovy.ast.ImportNode;import org.codehaus.groovy.ast.MethodNode;import org.codehaus.groovy.ast.ModuleNode;import org.codehaus.groovy.ast.Parameter;import org.codehaus.groovy.ast.PropertyNode;import org.codehaus.groovy.ast.Variable;import org.codehaus.groovy.ast.VariableScope;import org.codehaus.groovy.ast.expr.BinaryExpression;import org.codehaus.groovy.ast.expr.BooleanExpression;import org.codehaus.groovy.ast.expr.ClassExpression;import org.codehaus.groovy.ast.expr.ClosureExpression;import org.codehaus.groovy.ast.expr.ConstructorCallExpression;import org.codehaus.groovy.ast.expr.DeclarationExpression;import org.codehaus.groovy.ast.expr.Expression;import org.codehaus.groovy.ast.expr.ExpressionTransformer;import org.codehaus.groovy.ast.expr.MethodCallExpression;import org.codehaus.groovy.ast.expr.PropertyExpression;import org.codehaus.groovy.ast.expr.VariableExpression;import org.codehaus.groovy.ast.stmt.AssertStatement;import org.codehaus.groovy.ast.stmt.BlockStatement;import org.codehaus.groovy.ast.stmt.CaseStatement;import org.codehaus.groovy.ast.stmt.CatchStatement;import org.codehaus.groovy.ast.stmt.DoWhileStatement;import org.codehaus.groovy.ast.stmt.ExpressionStatement;import org.codehaus.groovy.ast.stmt.ForStatement;import org.codehaus.groovy.ast.stmt.IfStatement;import org.codehaus.groovy.ast.stmt.ReturnStatement;import org.codehaus.groovy.ast.stmt.Statement;import org.codehaus.groovy.ast.stmt.SwitchStatement;import org.codehaus.groovy.ast.stmt.SynchronizedStatement;import org.codehaus.groovy.ast.stmt.ThrowStatement;import org.codehaus.groovy.ast.stmt.WhileStatement;import org.codehaus.groovy.ast.GroovyClassVisitor;import org.codehaus.groovy.classgen.Verifier;import org.codehaus.groovy.control.messages.ExceptionMessage;import org.codehaus.groovy.control.messages.SyntaxErrorMessage;import org.codehaus.groovy.syntax.SyntaxException;import org.codehaus.groovy.syntax.Types;/** * Visitor to resolve Types and convert VariableExpression to * ClassExpressions if needed. * * Note: the method to start the resolving is startResolving(ClassNode, SourceUnit). * * * @author Jochen Theodorou */public class ResolveVisitor extends ClassCodeVisitorSupport implements ExpressionTransformer { private ClassNode currentClass; // note: BigInteger and BigDecimal are also imported by default private static final String[] DEFAULT_IMPORTS = {"java.lang.", "java.io.", "java.net.", "java.util.", "groovy.lang.", "groovy.util."}; private CompilationUnit compilationUnit; private Map cachedClasses = new HashMap(); private static final Object NO_CLASS = new Object(); private static final Object SCRIPT = new Object(); private SourceUnit source; private VariableScope currentScope; private boolean isTopLevelProperty = true; public ResolveVisitor(CompilationUnit cu) { compilationUnit = cu; } public void startResolving(ClassNode node,SourceUnit source) { this.source = source; visitClass(node); } public void visitConstructor(ConstructorNode node) { VariableScope oldScope = currentScope; currentScope = node.getVariableScope(); Parameter[] paras = node.getParameters(); for (int i=0; i<paras.length; i++) { ClassNode t = paras[i].getType(); resolveOrFail(t,node); } ClassNode[] exceptions = node.getExceptions(); for (int i=0; i<exceptions.length; i++) { ClassNode t = exceptions[i]; resolveOrFail(t,node); } Statement code = node.getCode(); if (code!=null) code.visit(this); currentScope = oldScope; } public void visitSwitch(SwitchStatement statement) { Expression exp = statement.getExpression(); statement.setExpression(transform(exp)); List list = statement.getCaseStatements(); for (Iterator iter = list.iterator(); iter.hasNext(); ) { CaseStatement caseStatement = (CaseStatement) iter.next(); caseStatement.visit(this); } statement.getDefaultStatement().visit(this); } public void visitMethod(MethodNode node) { VariableScope oldScope = currentScope; currentScope = node.getVariableScope(); Parameter[] paras = node.getParameters(); for (int i=0; i<paras.length; i++) { ClassNode t = paras[i].getType(); resolveOrFail(t,node); if (paras[i].hasInitialExpression()) { Expression init = paras[i].getInitialExpression(); paras[i].setInitialExpression(transform(init)); } } ClassNode[] exceptions = node.getExceptions(); for (int i=0; i<exceptions.length; i++) { ClassNode t = exceptions[i]; resolveOrFail(t,node); } resolveOrFail(node.getReturnType(),node); Statement code = node.getCode(); if (code!=null) code.visit(this); currentScope = oldScope; } public void visitField(FieldNode node) { ClassNode t = node.getType(); resolveOrFail(t,node); Expression init = node.getInitialExpression(); node.setInitialValueExpression(transform(init)); } public void visitProperty(PropertyNode node) { ClassNode t = node.getType(); resolveOrFail(t,node); Statement code = node.getGetterBlock(); if (code!=null) code.visit(this); code = node.getSetterBlock(); if (code!=null) code.visit(this); } public void visitIfElse(IfStatement ifElse) { ifElse.setBooleanExpression((BooleanExpression) (transform(ifElse.getBooleanExpression()))); super.visitIfElse(ifElse); } private void resolveOrFail(ClassNode type, String msg, ASTNode node) { if (resolve(type)) return; addError("unable to resolve class "+type.getName()+" "+msg,node); } private void resolveOrFail(ClassNode type, ASTNode node, boolean prefereImports) { if (prefereImports && resolveAliasFromModule(type)) return; resolveOrFail(type,node); } private void resolveOrFail(ClassNode type, ASTNode node) { resolveOrFail(type,"",node); } private boolean resolve(ClassNode type) { String name = type.getName(); return resolve(type,true,true,true); } private boolean resolve(ClassNode type, boolean testModuleImports, boolean testDefaultImports, boolean testStaticInnerClasses) { if (type.isResolved()) return true; if (type.isArray()) { ClassNode element = type.getComponentType(); boolean resolved = resolve(element,testModuleImports,testDefaultImports,testStaticInnerClasses); if (resolved) { ClassNode cn = element.makeArray(); type.setRedirect(cn); } return resolved; } // test if vanilla name is current class name if (currentClass==type) return true; if (currentClass.getNameWithoutPackage().equals(type.getName())) { type.setRedirect(currentClass); return true; } return resolveFromModule(type,testModuleImports) || resolveFromCompileUnit(type) || resovleFromDefaultImports(type,testDefaultImports) || resolveFromStaticInnerClasses(type,testStaticInnerClasses) || resolveFromClassCache(type) || resolveToClass(type) || resolveToScript(type); } private boolean resolveFromClassCache(ClassNode type) { String name = type.getName(); Object val = cachedClasses.get(name); if (val==null || val==NO_CLASS){ return false; } else { setClass(type,(Class) val); return true; } } // NOTE: copied from GroovyClassLoader private long getTimeStamp(Class cls) { Field field; Long o; try { field = cls.getField(Verifier.__TIMESTAMP); o = (Long) field.get(null); } catch (Exception e) { return Long.MAX_VALUE; } return o.longValue(); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -