use of org.codehaus.groovy.ast.expr.TupleExpression 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);
}
use of org.codehaus.groovy.ast.expr.TupleExpression in project groovy by apache.
the class ConstructorCallTransformer method transformConstructorCall.
Expression transformConstructorCall(final ConstructorCallExpression expr) {
ConstructorNode node = expr.getNodeMetaData(DIRECT_METHOD_CALL_TARGET);
if (node == null)
return expr;
Parameter[] params = node.getParameters();
if (// 2 is for inner class case
(params.length == 1 || params.length == 2) && StaticTypeCheckingSupport.implementsInterfaceOrIsSubclassOf(params[params.length - 1].getType(), ClassHelper.MAP_TYPE) && node.getCode() == StaticTypeCheckingVisitor.GENERATED_EMPTY_STATEMENT) {
Expression arguments = expr.getArguments();
if (arguments instanceof TupleExpression) {
TupleExpression tupleExpression = (TupleExpression) arguments;
List<Expression> expressions = tupleExpression.getExpressions();
if (expressions.size() == 1 || expressions.size() == 2) {
// 2 = inner class case
Expression expression = expressions.get(expressions.size() - 1);
if (expression instanceof MapExpression) {
MapExpression map = (MapExpression) expression;
// check that the node doesn't belong to the list of declared constructors
ClassNode declaringClass = node.getDeclaringClass();
for (ConstructorNode constructorNode : declaringClass.getDeclaredConstructors()) {
if (constructorNode == node) {
return staticCompilationTransformer.superTransform(expr);
}
}
// replace call to <init>(Map) or <init>(this, Map)
// with a call to <init>() or <init>(this) + appropriate setters
// for example, foo(x:1, y:2) is replaced with:
// { def tmp = new Foo(); tmp.x = 1; tmp.y = 2; return tmp }()
MapStyleConstructorCall result = new MapStyleConstructorCall(staticCompilationTransformer, declaringClass, map, expr);
return result;
}
}
}
}
return staticCompilationTransformer.superTransform(expr);
}
use of org.codehaus.groovy.ast.expr.TupleExpression in project groovy by apache.
the class MethodCallExpressionTransformer method transformMethodCallExpression.
Expression transformMethodCallExpression(final MethodCallExpression expr) {
Expression trn = tryTransformIsToCompareIdentity(expr);
if (trn != null) {
return trn;
}
ClassNode superCallReceiver = expr.getNodeMetaData(StaticTypesMarker.SUPER_MOP_METHOD_REQUIRED);
if (superCallReceiver != null) {
return transformMethodCallExpression(transformToMopSuperCall(superCallReceiver, expr));
}
Expression objectExpression = expr.getObjectExpression();
ClassNode type = staticCompilationTransformer.getTypeChooser().resolveType(objectExpression, staticCompilationTransformer.getClassNode());
if (isCallOnClosure(expr) && staticCompilationTransformer.getClassNode() != null) {
FieldNode field = staticCompilationTransformer.getClassNode().getField(expr.getMethodAsString());
if (field != null) {
VariableExpression vexp = new VariableExpression(field);
MethodCallExpression result = new MethodCallExpression(vexp, "call", staticCompilationTransformer.transform(expr.getArguments()));
result.setImplicitThis(false);
result.setSourcePosition(expr);
result.setSafe(expr.isSafe());
result.setSpreadSafe(expr.isSpreadSafe());
result.setMethodTarget(StaticTypeCheckingVisitor.CLOSURE_CALL_VARGS);
result.copyNodeMetaData(expr);
return result;
}
}
if (type != null && type.isArray()) {
String method = expr.getMethodAsString();
ClassNode componentType = type.getComponentType();
if ("getAt".equals(method)) {
Expression arguments = expr.getArguments();
if (arguments instanceof TupleExpression) {
List<Expression> argList = ((TupleExpression) arguments).getExpressions();
if (argList.size() == 1) {
Expression indexExpr = argList.get(0);
ClassNode argType = staticCompilationTransformer.getTypeChooser().resolveType(indexExpr, staticCompilationTransformer.getClassNode());
ClassNode indexType = ClassHelper.getWrapper(argType);
if (componentType.isEnum() && ClassHelper.Number_TYPE.equals(indexType)) {
// workaround for generated code in enums which use .next() returning a Number
indexType = ClassHelper.Integer_TYPE;
}
if (argType != null && ClassHelper.isWrapperInteger(indexType)) {
BinaryExpression binaryExpression = new BinaryExpression(objectExpression, Token.newSymbol("[", indexExpr.getLineNumber(), indexExpr.getColumnNumber()), indexExpr);
binaryExpression.putNodeMetaData(StaticTypesMarker.INFERRED_TYPE, componentType);
return staticCompilationTransformer.transform(binaryExpression);
}
}
}
} else if ("putAt".equals(method)) {
Expression arguments = expr.getArguments();
if (arguments instanceof TupleExpression) {
List<Expression> argList = ((TupleExpression) arguments).getExpressions();
if (argList.size() == 2) {
Expression indexExpr = argList.get(0);
Expression objExpr = argList.get(1);
ClassNode argType = staticCompilationTransformer.getTypeChooser().resolveType(indexExpr, staticCompilationTransformer.getClassNode());
if (argType != null && ClassHelper.isWrapperInteger(ClassHelper.getWrapper(argType))) {
BinaryExpression arrayGet = new BinaryExpression(objectExpression, Token.newSymbol("[", indexExpr.getLineNumber(), indexExpr.getColumnNumber()), indexExpr);
arrayGet.putNodeMetaData(StaticTypesMarker.INFERRED_TYPE, componentType);
BinaryExpression assignment = new BinaryExpression(arrayGet, Token.newSymbol("=", objExpr.getLineNumber(), objExpr.getColumnNumber()), objExpr);
return staticCompilationTransformer.transform(assignment);
}
}
}
}
}
return staticCompilationTransformer.superTransform(expr);
}
use of org.codehaus.groovy.ast.expr.TupleExpression in project groovy by apache.
the class BinaryExpressionTransformer method transformMultipleAssignment.
private Expression transformMultipleAssignment(final BinaryExpression bin) {
ListOfExpressionsExpression list = new ListOfExpressionsExpression();
List<Expression> leftExpressions = ((TupleExpression) bin.getLeftExpression()).getExpressions();
List<Expression> rightExpressions = ((ListExpression) bin.getRightExpression()).getExpressions();
Iterator<Expression> leftIt = leftExpressions.iterator();
Iterator<Expression> rightIt = rightExpressions.iterator();
if (bin instanceof DeclarationExpression) {
while (leftIt.hasNext()) {
Expression left = leftIt.next();
if (rightIt.hasNext()) {
Expression right = rightIt.next();
BinaryExpression bexp = new DeclarationExpression(left, bin.getOperation(), right);
bexp.setSourcePosition(right);
list.addExpression(bexp);
}
}
} else {
// (next, result) = [ result, next+result ]
// -->
// def tmp1 = result
// def tmp2 = next+result
// next = tmp1
// result = tmp2
int size = rightExpressions.size();
List<Expression> tmpAssignments = new ArrayList<>(size);
List<Expression> finalAssignments = new ArrayList<>(size);
for (int i = 0, n = Math.min(size, leftExpressions.size()); i < n; i += 1) {
Expression left = leftIt.next();
Expression right = rightIt.next();
VariableExpression tmpVar = varX("$tmpVar$" + tmpVarCounter++);
BinaryExpression bexp = new DeclarationExpression(tmpVar, bin.getOperation(), right);
bexp.setSourcePosition(right);
tmpAssignments.add(bexp);
bexp = binX(left, bin.getOperation(), varX(tmpVar));
bexp.setSourcePosition(left);
finalAssignments.add(bexp);
}
for (Expression tmpAssignment : tmpAssignments) {
list.addExpression(tmpAssignment);
}
for (Expression finalAssignment : finalAssignments) {
list.addExpression(finalAssignment);
}
}
return staticCompilationTransformer.transform(list);
}
use of org.codehaus.groovy.ast.expr.TupleExpression in project groovy by apache.
the class StaticTypeCheckingVisitor method getExtensionArguments.
private static ArgumentListExpression getExtensionArguments(final ClassNode receiver, final MethodNode method, final Expression arguments) {
// implicit first argument
VariableExpression self = varX("$self", receiver);
self.putNodeMetaData(ExtensionMethodDeclaringClass.class, method.getDeclaringClass());
ArgumentListExpression args = new ArgumentListExpression();
args.addExpression(self);
if (arguments instanceof TupleExpression) {
for (Expression argument : (TupleExpression) arguments) {
args.addExpression(argument);
}
} else {
args.addExpression(arguments);
}
return args;
}
Aggregations