blob: eb4c0d04e6acfb7879ca78f17f81eab6e192c220 [file] [log] [blame]
/*
* Copyright 2003-2007 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.codehaus.groovy.control;
import java.util.Iterator;
import java.util.Map;
import org.codehaus.groovy.ast.ClassCodeExpressionTransformer;
import org.codehaus.groovy.ast.ClassNode;
import org.codehaus.groovy.ast.DynamicVariable;
import org.codehaus.groovy.ast.FieldNode;
import org.codehaus.groovy.ast.ModuleNode;
import org.codehaus.groovy.ast.Variable;
import org.codehaus.groovy.ast.expr.*;
/**
* Visitor to resolve constants and method calls from static Imports
*
* @author Jochen Theodorou
* @author Paul King
*/
public class StaticImportVisitor extends ClassCodeExpressionTransformer {
private ClassNode currentClass;
private CompilationUnit compilationUnit;
public StaticImportVisitor(CompilationUnit cu) {
compilationUnit = cu;
}
public void visitClass(ClassNode node) {
this.currentClass = node;
super.visitClass(node);
}
private Expression findStaticFieldImportFromModule(String name) {
ModuleNode module = currentClass.getModule();
if (module == null) return null;
Map aliases = module.getStaticImportAliases();
if (aliases.containsKey(name)) {
ClassNode node = (ClassNode) aliases.get(name);
Map fields = module.getStaticImportFields();
String fieldName = (String) fields.get(name);
Expression expression = findStaticField(node, fieldName);
if (expression != null) return expression;
}
Map importedClasses = module.getStaticImportClasses();
Iterator it = importedClasses.keySet().iterator();
while (it.hasNext()) {
String className = (String) it.next();
ClassNode node = (ClassNode) importedClasses.get(className);
Expression expression = findStaticField(node, name);
if (expression != null) return expression;
}
return null;
}
private Expression findStaticField(ClassNode staticImportType, String fieldName) {
if (staticImportType.isPrimaryClassNode() || staticImportType.isResolved()) {
staticImportType.getFields(); // force init
FieldNode field = staticImportType.getField(fieldName);
if (field != null && field.isStatic()) {
return new PropertyExpression(new ClassExpression(staticImportType), fieldName);
}
}
return null;
}
private Expression findStaticMethodImportFromModule(Expression method, Expression args) {
ModuleNode module = currentClass.getModule();
if (module == null || !(method instanceof ConstantExpression)) return null;
Map aliases = module.getStaticImportAliases();
ConstantExpression ce = (ConstantExpression) method;
final String name = (String) ce.getValue();
if (aliases.containsKey(name)) {
ClassNode node = (ClassNode) aliases.get(name);
Map fields = module.getStaticImportFields();
String fieldName = (String) fields.get(name);
Expression expression = findStaticMethod(node, fieldName, args);
if (expression != null) return expression;
}
Map importPackages = module.getStaticImportClasses();
Iterator it = importPackages.keySet().iterator();
while (it.hasNext()) {
String className = (String) it.next();
ClassNode starImportType = (ClassNode) importPackages.get(className);
Expression expression = findStaticMethod(starImportType, name, args);
if (expression != null) return expression;
}
return null;
}
private Expression findStaticMethod(ClassNode staticImportType, String methodName, Expression args) {
if (staticImportType.isPrimaryClassNode() || staticImportType.isResolved()) {
if (staticImportType.hasPossibleStaticMethod(methodName, args)) {
return new StaticMethodCallExpression(staticImportType, methodName, args);
}
}
return null;
}
public Expression transform(Expression exp) {
if (exp==null) return null;
if (exp instanceof VariableExpression) {
return transformVariableExpression((VariableExpression) exp);
}
if (exp instanceof MethodCallExpression) {
return transformMethodCallExpression((MethodCallExpression)exp);
}
return exp.transformExpression(this);
}
protected Expression transformVariableExpression(VariableExpression ve) {
Variable v = ve.getAccessedVariable();
if (v instanceof DynamicVariable) {
Expression result = findStaticFieldImportFromModule(ve.getName());
if (result != null) return result;
}
return ve;
}
protected Expression transformMethodCallExpression(MethodCallExpression mce) {
Expression args = transform(mce.getArguments());
Expression method = transform(mce.getMethod());
if (mce.isImplicitThis()) {
Expression ret = findStaticMethodImportFromModule(method, args);
if (ret != null) return ret;
return new MethodCallExpression(mce.getObjectExpression(), method, args);
}
return mce;
}
protected SourceUnit getSourceUnit() {
return null;
}
}