resolvevisitor.java
来自「Groovy动态语言 运行在JVM中的动态语言 可以方便的处理业务逻辑变化大的业」· Java 代码 · 共 853 行 · 第 1/3 页
JAVA
853 行
// VariableExpressions will stop resolving
else if (!(it.getClass()==PropertyExpression.class)) {
return null;
} else {
PropertyExpression current = (PropertyExpression) it;
String propertyPart = current.getPropertyAsString();
// the class property stops resolving, dynamic property names too
if (propertyPart==null || propertyPart.equals("class")) {
return null;
}
name = propertyPart+"."+name;
}
}
if (name.length()>0) return name.substring(0,name.length()-1);
return null;
}
// iterate from the inner most to the outer and check for classes
// this check will ignore a .class property, for Exmaple Integer.class will be
// a PropertyExpression with the ClassExpression of Integer as objectExpression
// and class as property
private Expression correctClassClassChain(PropertyExpression pe){
LinkedList stack = new LinkedList();
ClassExpression found = null;
for (Expression it = pe; it!=null; it = ((PropertyExpression)it).getObjectExpression()) {
if (it instanceof ClassExpression) {
found = (ClassExpression) it;
break;
} else if (! (it.getClass()==PropertyExpression.class)) {
return pe;
}
stack.addFirst(it);
}
if (found==null) return pe;
if (stack.isEmpty()) return pe;
Object stackElement = stack.removeFirst();
if (!(stackElement.getClass()==PropertyExpression.class)) return pe;
PropertyExpression classPropertyExpression = (PropertyExpression) stackElement;
String propertyNamePart = classPropertyExpression.getPropertyAsString();
if (propertyNamePart==null || ! propertyNamePart.equals("class")) return pe;
if (stack.isEmpty()) return found;
stackElement = stack.removeFirst();
if (!(stackElement.getClass()==PropertyExpression.class)) return pe;
PropertyExpression classPropertyExpressionContainer = (PropertyExpression) stackElement;
classPropertyExpressionContainer.setObjectExpression(found);
return pe;
}
protected Expression transformPropertyExpression(PropertyExpression pe) {
boolean itlp = isTopLevelProperty;
Expression objectExpression = pe.getObjectExpression();
isTopLevelProperty = !(objectExpression.getClass()==PropertyExpression.class);
objectExpression = transform(objectExpression);
Expression property = transform(pe.getProperty());
isTopLevelProperty = itlp;
boolean spreadSafe = pe.isSpreadSafe();
pe = new PropertyExpression(objectExpression,property,pe.isSafe());
pe.setSpreadSafe(spreadSafe);
String className = lookupClassName(pe);
if (className!=null) {
ClassNode type = ClassHelper.make(className);
if (resolve(type)) return new ClassExpression(type);
}
if (objectExpression instanceof ClassExpression && pe.getPropertyAsString()!=null){
// possibly a inner class
ClassExpression ce = (ClassExpression) objectExpression;
ClassNode type = ClassHelper.make(ce.getType().getName()+"$"+pe.getPropertyAsString());
if (resolve(type,false,false,false)) return new ClassExpression(type);
}
if (isTopLevelProperty) return correctClassClassChain(pe);
return pe;
}
protected Expression transformVariableExpression(VariableExpression ve) {
if (ve.getName().equals("this")) return VariableExpression.THIS_EXPRESSION;
if (ve.getName().equals("super")) return VariableExpression.SUPER_EXPRESSION;
Variable v = ve.getAccessedVariable();
if (v instanceof DynamicVariable) {
ClassNode t = ClassHelper.make(ve.getName());
if (resolve(t)) {
// the name is a type so remove it from the scoping
// as it is only a classvariable, it is only in
// referencedClassVariables, but must be removed
// for each parentscope too
for (VariableScope scope = currentScope; scope!=null && !scope.isRoot(); scope = scope.getParent()) {
if (scope.isRoot()) break;
if (scope.getReferencedClassVariables().remove(ve.getName())==null) break;
}
ClassExpression ce = new ClassExpression(t);
ce.setSourcePosition(ve);
return ce;
} else if (!inClosure && ve.isInStaticContext()) {
addError("the name "+v.getName()+" doesn't refer to a declared variable or class. The static"+
" scope requires to declare variables before using them. If the variable should have"+
" been a class check the spelling.",ve);
}
}
resolveOrFail(ve.getType(),ve);
return ve;
}
protected Expression transformBinaryExpression(BinaryExpression be) {
Expression left = transform(be.getLeftExpression());
if (be.getOperation().getType()==Types.ASSIGNMENT_OPERATOR && left instanceof ClassExpression){
ClassExpression ce = (ClassExpression) left;
addError("you tried to assign a value to "+ce.getType().getName(),be.getLeftExpression());
return be;
}
if (left instanceof ClassExpression && be.getRightExpression() instanceof ListExpression) {
// we have C[] if the list is empty -> should be an array then!
ListExpression list = (ListExpression) be.getRightExpression();
ClassExpression ce = (ClassExpression) left;
if (list.getExpressions().isEmpty()) {
return new ClassExpression(left.getType().makeArray());
}
}
Expression right = transform(be.getRightExpression());
Expression ret = new BinaryExpression(left,be.getOperation(),right);
ret.setSourcePosition(be);
return ret;
}
protected Expression transformClosureExpression(ClosureExpression ce) {
boolean oldInClosure = inClosure;
inClosure = true;
Parameter[] paras = ce.getParameters();
if (paras!=null) {
for (int i=0; i<paras.length; i++) {
ClassNode t = paras[i].getType();
resolveOrFail(t,ce);
}
}
Statement code = ce.getCode();
if (code!=null) code.visit(this);
ClosureExpression newCe= new ClosureExpression(paras,code);
newCe.setVariableScope(ce.getVariableScope());
newCe.setSourcePosition(ce);
inClosure = oldInClosure;
return newCe;
}
protected Expression transformConstructorCallExpression(ConstructorCallExpression cce){
ClassNode type = cce.getType();
resolveOrFail(type,cce);
Expression expr = cce.transformExpression(this);
return expr;
}
protected Expression transformMethodCallExpression(MethodCallExpression mce) {
Expression obj = mce.getObjectExpression();
Expression newObject = transform(obj);
Expression args = transform(mce.getArguments());
Expression method = transform(mce.getMethod());
MethodCallExpression ret = new MethodCallExpression(newObject,method,args);
ret.setSafe(mce.isSafe());
ret.setImplicitThis(mce.isImplicitThis());
ret.setSpreadSafe(mce.isSpreadSafe());
ret.setSourcePosition(mce);
return ret;
}
protected Expression transformDeclarationExpression(DeclarationExpression de) {
Expression oldLeft = de.getLeftExpression();
Expression left = transform(oldLeft);
if (left!=oldLeft){
ClassExpression ce = (ClassExpression) left;
addError("you tried to assign a value to "+ce.getType().getName(),oldLeft);
return de;
}
Expression right = transform(de.getRightExpression());
if (right==de.getRightExpression()) return de;
return new DeclarationExpression((VariableExpression) left,de.getOperation(),right);
}
public void visitAnnotations(AnnotatedNode node) {
Map annotionMap = node.getAnnotations();
if (annotionMap.isEmpty()) return;
Iterator it = annotionMap.values().iterator();
while (it.hasNext()) {
AnnotationNode an = (AnnotationNode) it.next();
//skip builtin properties
if (an.isBuiltIn()) continue;
ClassNode type = an.getClassNode();
resolveOrFail(type,"unable to find class for annotation",an);
}
}
public void visitClass(ClassNode node) {
ClassNode oldNode = currentClass;
currentClass = node;
ModuleNode module = node.getModule();
if (!module.hasImportsResolved()) {
List l = module.getImports();
for (Iterator iter = l.iterator(); iter.hasNext();) {
ImportNode element = (ImportNode) iter.next();
ClassNode type = element.getType();
if (resolve(type,false,false,false)) continue;
addError("unable to resolve class "+type.getName(),type);
}
module.setImportsResolved(true);
}
ClassNode sn = node.getUnresolvedSuperClass();
if (sn!=null) resolveOrFail(sn,node,true);
ClassNode[] interfaces = node.getInterfaces();
for (int i=0; i<interfaces.length; i++) {
resolveOrFail(interfaces[i],node,true);
}
super.visitClass(node);
currentClass = oldNode;
}
public void visitReturnStatement(ReturnStatement statement) {
statement.setExpression(transform(statement.getExpression()));
}
public void visitAssertStatement(AssertStatement as) {
as.setBooleanExpression((BooleanExpression) (transform(as.getBooleanExpression())));
as.setMessageExpression(transform(as.getMessageExpression()));
}
public void visitCaseStatement(CaseStatement statement) {
statement.setExpression(transform(statement.getExpression()));
statement.getCode().visit(this);
}
public void visitCatchStatement(CatchStatement cs) {
resolveOrFail(cs.getExceptionType(),cs);
if (cs.getExceptionType()==ClassHelper.DYNAMIC_TYPE) {
cs.getVariable().setType(ClassHelper.make(Exception.class));
}
super.visitCatchStatement(cs);
}
public void visitDoWhileLoop(DoWhileStatement loop) {
loop.setBooleanExpression((BooleanExpression) (transform(loop.getBooleanExpression())));
super.visitDoWhileLoop(loop);
}
public void visitForLoop(ForStatement forLoop) {
forLoop.setCollectionExpression(transform(forLoop.getCollectionExpression()));
resolveOrFail(forLoop.getVariableType(),forLoop);
super.visitForLoop(forLoop);
}
public void visitSynchronizedStatement(SynchronizedStatement sync) {
sync.setExpression(transform(sync.getExpression()));
super.visitSynchronizedStatement(sync);
}
public void visitThrowStatement(ThrowStatement ts) {
ts.setExpression(transform(ts.getExpression()));
}
public void visitWhileLoop(WhileStatement loop) {
loop.setBooleanExpression((BooleanExpression) transform(loop.getBooleanExpression()));
super.visitWhileLoop(loop);
}
public void visitExpressionStatement(ExpressionStatement es) {
es.setExpression(transform(es.getExpression()));
}
public void visitBlockStatement(BlockStatement block) {
VariableScope oldScope = currentScope;
currentScope = block.getVariableScope();
super.visitBlockStatement(block);
currentScope = oldScope;
}
protected SourceUnit getSourceUnit() {
return source;
}
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?