use of org.codehaus.groovy.ast.DynamicVariable in project groovy-core by groovy.
the class TraitReceiverTransformer method transform.
@Override
public Expression transform(final Expression exp) {
ClassNode weavedType = weaved.getOriginType();
if (exp instanceof BinaryExpression) {
return transformBinaryExpression((BinaryExpression) exp, weavedType);
} else if (exp instanceof StaticMethodCallExpression) {
StaticMethodCallExpression call = (StaticMethodCallExpression) exp;
ClassNode ownerType = call.getOwnerType();
if (traitClass.equals(ownerType)) {
MethodCallExpression result = new MethodCallExpression(new VariableExpression(weaved), call.getMethod(), transform(call.getArguments()));
result.setSafe(false);
result.setImplicitThis(false);
result.setSpreadSafe(false);
result.setSourcePosition(call);
return result;
}
} else if (exp instanceof MethodCallExpression) {
MethodCallExpression call = (MethodCallExpression) exp;
Expression obj = call.getObjectExpression();
if (call.isImplicitThis() || "this".equals(obj.getText())) {
return transformMethodCallOnThis(call);
} else if ("super".equals(obj.getText())) {
return transformSuperMethodCall(call);
}
} else if (exp instanceof FieldExpression) {
return transformFieldExpression((FieldExpression) exp);
} else if (exp instanceof VariableExpression) {
VariableExpression vexp = (VariableExpression) exp;
Variable accessedVariable = vexp.getAccessedVariable();
if (accessedVariable instanceof FieldNode) {
FieldNode fn = (FieldNode) accessedVariable;
Expression receiver = createFieldHelperReceiver();
MethodCallExpression mce;
boolean isStatic = fn.isStatic();
if (isStatic) {
receiver = createStaticReceiver(receiver);
}
mce = new MethodCallExpression(receiver, Traits.helperGetterName(fn), ArgumentListExpression.EMPTY_ARGUMENTS);
mce.setSourcePosition(exp);
mce.setImplicitThis(false);
markDynamicCall(mce, fn, isStatic);
return mce;
} else if (accessedVariable instanceof PropertyNode) {
String propName = accessedVariable.getName();
if (knownFields.contains(propName)) {
String method = Traits.helperGetterName(new FieldNode(propName, 0, ClassHelper.OBJECT_TYPE, weavedType, null));
MethodCallExpression mce = new MethodCallExpression(createFieldHelperReceiver(), method, ArgumentListExpression.EMPTY_ARGUMENTS);
mce.setSourcePosition(exp);
mce.setImplicitThis(false);
return mce;
} else {
return new PropertyExpression(new VariableExpression(weaved), accessedVariable.getName());
}
} else if (accessedVariable instanceof DynamicVariable) {
return new PropertyExpression(new VariableExpression(weaved), accessedVariable.getName());
}
if (vexp.isThisExpression()) {
VariableExpression res = new VariableExpression(weaved);
res.setSourcePosition(exp);
return res;
}
if (vexp.isSuperExpression()) {
throwSuperError(vexp);
}
} else if (exp instanceof PropertyExpression) {
PropertyExpression pexp = (PropertyExpression) exp;
Expression object = pexp.getObjectExpression();
if (pexp.isImplicitThis() || "this".equals(object.getText())) {
String propName = pexp.getPropertyAsString();
if (knownFields.contains(propName)) {
String method = Traits.helperGetterName(new FieldNode(propName, 0, ClassHelper.OBJECT_TYPE, weavedType, null));
MethodCallExpression mce = new MethodCallExpression(createFieldHelperReceiver(), method, ArgumentListExpression.EMPTY_ARGUMENTS);
mce.setSourcePosition(exp);
mce.setImplicitThis(false);
return mce;
}
}
} else if (exp instanceof ClosureExpression) {
MethodCallExpression mce = new MethodCallExpression(exp, "rehydrate", new ArgumentListExpression(new VariableExpression(weaved), new VariableExpression(weaved), new VariableExpression(weaved)));
mce.setImplicitThis(false);
mce.setSourcePosition(exp);
((ClosureExpression) exp).getCode().visit(this);
// The rewrite we do is causing some troubles with type checking, which will
// not be able to perform closure parameter type inference
// so we store the replacement, which will be done *after* type checking.
exp.putNodeMetaData(TraitASTTransformation.POST_TYPECHECKING_REPLACEMENT, mce);
return exp;
}
// todo: unary expressions (field++, field+=, ...)
return super.transform(exp);
}
use of org.codehaus.groovy.ast.DynamicVariable in project groovy-core by groovy.
the class MarkupBuilderCodeTransformer method transform.
@Override
public Expression transform(final Expression exp) {
if (exp instanceof BinaryExpression) {
return transformBinaryExpression((BinaryExpression) exp);
}
if (exp instanceof MethodCallExpression) {
return transformMethodCall((MethodCallExpression) exp);
}
if (exp instanceof ClosureExpression) {
ClosureExpression cl = (ClosureExpression) exp;
cl.getCode().visit(this);
return cl;
}
if (exp instanceof VariableExpression) {
VariableExpression var = (VariableExpression) exp;
if (var.getAccessedVariable() instanceof DynamicVariable) {
MethodCallExpression callGetModel = new MethodCallExpression(new VariableExpression("this"), "getModel", ArgumentListExpression.EMPTY_ARGUMENTS);
callGetModel.setImplicitThis(true);
callGetModel.setSourcePosition(exp);
String varName = var.getName();
if ("model".equals(varName) || "unescaped".equals(varName)) {
return callGetModel;
}
MethodCallExpression mce = new MethodCallExpression(callGetModel, "get", new ArgumentListExpression(new ConstantExpression(varName)));
mce.setSourcePosition(exp);
mce.setImplicitThis(false);
MethodCallExpression yield = new MethodCallExpression(new VariableExpression("this"), "tryEscape", new ArgumentListExpression(mce));
yield.setImplicitThis(true);
yield.setSourcePosition(exp);
yield.putNodeMetaData(TARGET_VARIABLE, varName);
return autoEscape ? yield : mce;
}
}
return super.transform(exp);
}
use of org.codehaus.groovy.ast.DynamicVariable in project groovy by apache.
the class ResolveVisitor method transformVariableExpression.
protected Expression transformVariableExpression(final VariableExpression ve) {
visitAnnotations(ve);
Variable v = ve.getAccessedVariable();
if (!(v instanceof DynamicVariable) && !checkingVariableTypeInDeclaration) {
/*
* GROOVY-4009: when a normal variable is simply being used, there is no need to try to
* resolve its type. Variable type resolve should proceed only if the variable is being declared.
*/
return ve;
}
if (v instanceof DynamicVariable) {
String name = ve.getName();
ClassNode t = ClassHelper.make(name);
// asking isResolved here allows to check if a primitive
// type name like "int" was used to make t. In such a case
// we have nothing left to do.
boolean isClass = t.isResolved();
if (!isClass) {
// compiler skip the resolving at several places in this class.
if (Character.isLowerCase(name.charAt(0))) {
t = new LowerCaseClass(name);
}
isClass = resolve(t);
}
if (isClass) {
// for each parentscope too
for (VariableScope scope = currentScope; scope != null && !scope.isRoot(); scope = scope.getParent()) {
if (scope.removeReferencedClassVariable(ve.getName()) == null)
break;
}
return new ClassExpression(t);
}
}
resolveOrFail(ve.getType(), ve);
ClassNode origin = ve.getOriginType();
if (origin != ve.getType())
resolveOrFail(origin, ve);
return ve;
}
use of org.codehaus.groovy.ast.DynamicVariable in project groovy by apache.
the class VariableScopeVisitor method findVariableDeclaration.
private Variable findVariableDeclaration(final String name) {
if ("super".equals(name) || "this".equals(name))
return null;
Variable variable = null;
VariableScope scope = currentScope;
boolean crossingStaticContext = false;
// try to find a declaration of a variable
while (true) {
crossingStaticContext = (crossingStaticContext || scope.isInStaticContext());
Variable var = scope.getDeclaredVariable(name);
if (var != null) {
variable = var;
break;
}
var = scope.getReferencedLocalVariable(name);
if (var != null) {
variable = var;
break;
}
var = scope.getReferencedClassVariable(name);
if (var != null) {
variable = var;
break;
}
ClassNode node = scope.getClassScope();
if (node != null) {
Variable member = findClassMember(node, name);
boolean requireStatic = (crossingStaticContext || inSpecialConstructorCall);
while (member == null && node.getOuterClass() != null && !isAnonymous(node)) {
requireStatic = requireStatic || isStatic(node.getModifiers());
member = findClassMember((node = node.getOuterClass()), name);
}
if (member != null) {
// prevent a static context (e.g. a static method) from accessing a non-static member (e.g. a non-static field)
if (requireStatic ? member.isInStaticContext() : !node.isScript()) {
variable = member;
}
}
// GROOVY-5961
if (!isAnonymous(scope.getClassScope()))
break;
}
scope = scope.getParent();
}
if (variable == null) {
variable = new DynamicVariable(name, crossingStaticContext);
}
boolean isClassVariable = (scope.isClassScope() && !scope.isReferencedLocalVariable(name)) || (scope.isReferencedClassVariable(name) && scope.getDeclaredVariable(name) == null);
VariableScope end = scope;
scope = currentScope;
while (scope != end) {
if (isClassVariable) {
scope.putReferencedClassVariable(variable);
} else {
scope.putReferencedLocalVariable(variable);
}
scope = scope.getParent();
}
return variable;
}
use of org.codehaus.groovy.ast.DynamicVariable in project groovy by apache.
the class LogASTTransformation method visit.
@Override
public void visit(final ASTNode[] nodes, final SourceUnit sourceUnit) {
init(nodes, sourceUnit);
AnnotatedNode targetClass = (AnnotatedNode) nodes[1];
AnnotationNode logAnnotation = (AnnotationNode) nodes[0];
final LoggingStrategy loggingStrategy = createLoggingStrategy(logAnnotation, sourceUnit.getClassLoader(), compilationUnit.getTransformLoader());
if (loggingStrategy == null)
return;
final String logFieldName = lookupLogFieldName(logAnnotation);
final String categoryName = lookupCategoryName(logAnnotation);
final int logFieldModifiers = lookupLogFieldModifiers(targetClass, logAnnotation);
if (!(targetClass instanceof ClassNode))
throw new GroovyBugError("Class annotation " + logAnnotation.getClassNode().getName() + " annotated no Class, this must not happen.");
final ClassNode classNode = (ClassNode) targetClass;
ClassCodeExpressionTransformer transformer = new ClassCodeExpressionTransformer() {
private FieldNode logNode;
@Override
protected SourceUnit getSourceUnit() {
return sourceUnit;
}
@Override
public Expression transform(final Expression exp) {
if (exp == null)
return null;
if (exp instanceof MethodCallExpression) {
return transformMethodCallExpression(exp);
}
if (exp instanceof ClosureExpression) {
return transformClosureExpression((ClosureExpression) exp);
}
return super.transform(exp);
}
@Override
public void visitClass(final ClassNode node) {
FieldNode logField = node.getField(logFieldName);
if (logField != null && logField.getOwner().equals(node)) {
addError("Class annotated with Log annotation cannot have log field declared", logField);
} else if (logField != null && !Modifier.isPrivate(logField.getModifiers())) {
addError("Class annotated with Log annotation cannot have log field declared because the field exists in the parent class: " + logField.getOwner().getName(), logField);
} else {
if (loggingStrategy instanceof LoggingStrategyV2) {
LoggingStrategyV2 loggingStrategyV2 = (LoggingStrategyV2) loggingStrategy;
logNode = loggingStrategyV2.addLoggerFieldToClass(node, logFieldName, categoryName, logFieldModifiers);
} else {
// support the old style but they won't be as configurable
logNode = loggingStrategy.addLoggerFieldToClass(node, logFieldName, categoryName);
}
}
super.visitClass(node);
}
private Expression transformClosureExpression(final ClosureExpression exp) {
if (exp.getCode() instanceof BlockStatement) {
BlockStatement code = (BlockStatement) exp.getCode();
super.visitBlockStatement(code);
}
return exp;
}
private Expression transformMethodCallExpression(final Expression exp) {
Expression modifiedCall = addGuard((MethodCallExpression) exp);
return modifiedCall == null ? super.transform(exp) : modifiedCall;
}
private Expression addGuard(final MethodCallExpression mce) {
// only add guard to methods of the form: logVar.logMethod(params)
if (!(mce.getObjectExpression() instanceof VariableExpression)) {
return null;
}
VariableExpression variableExpression = (VariableExpression) mce.getObjectExpression();
if (!variableExpression.getName().equals(logFieldName) || !(variableExpression.getAccessedVariable() instanceof DynamicVariable)) {
return null;
}
String methodName = mce.getMethodAsString();
if (methodName == null)
return null;
if (!loggingStrategy.isLoggingMethod(methodName))
return null;
// since there is no saving
if (usesSimpleMethodArgumentsOnly(mce))
return null;
variableExpression.setAccessedVariable(logNode);
return loggingStrategy.wrapLoggingMethodCall(variableExpression, methodName, mce);
}
private boolean usesSimpleMethodArgumentsOnly(final MethodCallExpression mce) {
Expression arguments = mce.getArguments();
if (arguments instanceof TupleExpression) {
TupleExpression tuple = (TupleExpression) arguments;
for (Expression exp : tuple.getExpressions()) {
if (!isSimpleExpression(exp))
return false;
}
return true;
}
return !isSimpleExpression(arguments);
}
private boolean isSimpleExpression(final Expression exp) {
if (exp instanceof ConstantExpression)
return true;
if (exp instanceof VariableExpression)
return true;
return false;
}
};
transformer.visitClass(classNode);
// GROOVY-6373: references to 'log' field are normally already FieldNodes by now, so revisit scoping
new VariableScopeVisitor(sourceUnit, true).visitClass(classNode);
}
Aggregations