use of org.codehaus.groovy.ast.expr.TupleExpression in project groovy by apache.
the class RecursivenessTester method methodParamsMatchCallArgs.
private boolean methodParamsMatchCallArgs(MethodNode method, Expression call) {
TupleExpression arguments;
if (call instanceof MethodCallExpression) {
arguments = ((TupleExpression) ((MethodCallExpression) call).getArguments());
} else {
arguments = ((TupleExpression) ((StaticMethodCallExpression) call).getArguments());
}
if (method.getParameters().length != arguments.getExpressions().size())
return false;
List<List<ClassNode>> classNodePairs = transpose(Arrays.asList(Arrays.stream(method.getParameters()).map(Parameter::getType).collect(Collectors.toList()), arguments.getExpressions().stream().map(Expression::getType).collect(Collectors.toList())));
return classNodePairs.stream().allMatch(t -> areTypesCallCompatible(t.get(0), t.get(1)));
}
use of org.codehaus.groovy.ast.expr.TupleExpression in project groovy by apache.
the class StaticInvocationWriter method writeDirectMethodCall.
@Override
protected boolean writeDirectMethodCall(final MethodNode target, final boolean implicitThis, final Expression receiver, final TupleExpression args) {
if (target == null)
return false;
ClassNode classNode = controller.getClassNode();
if (target instanceof ExtensionMethodNode) {
ExtensionMethodNode emn = (ExtensionMethodNode) target;
MethodVisitor mv = controller.getMethodVisitor();
MethodNode node = emn.getExtensionMethodNode();
Parameter[] parameters = node.getParameters();
ClassNode returnType = node.getReturnType();
List<Expression> argumentList = new ArrayList<>();
if (emn.isStaticExtension()) {
argumentList.add(nullX());
} else {
Expression fixedReceiver = null;
if (isThisOrSuper(receiver) && classNode.getOuterClass() != null && controller.isInGeneratedFunction()) {
ClassNode current = classNode.getOuterClass();
fixedReceiver = varX("thisObject", current);
// adjust for multiple levels of nesting if needed
while (current.getOuterClass() != null && !classNode.equals(current)) {
FieldNode thisField = current.getField("this$0");
current = current.getOuterClass();
if (thisField != null) {
fixedReceiver = propX(fixedReceiver, "this$0");
fixedReceiver.setType(current);
}
}
}
argumentList.add(fixedReceiver != null ? fixedReceiver : receiver);
}
argumentList.addAll(args.getExpressions());
loadArguments(argumentList, parameters);
String owner = BytecodeHelper.getClassInternalName(node.getDeclaringClass());
String desc = BytecodeHelper.getMethodDescriptor(returnType, parameters);
mv.visitMethodInsn(INVOKESTATIC, owner, target.getName(), desc, false);
controller.getOperandStack().remove(argumentList.size());
if (isPrimitiveVoid(returnType)) {
returnType = ClassHelper.OBJECT_TYPE;
mv.visitInsn(ACONST_NULL);
}
controller.getOperandStack().push(returnType);
return true;
}
if (target == StaticTypeCheckingVisitor.CLOSURE_CALL_VARGS) {
// wrap arguments into an array
Expression arr = new ArrayExpression(ClassHelper.OBJECT_TYPE, args.getExpressions());
return super.writeDirectMethodCall(target, implicitThis, receiver, args(arr));
}
if (!target.isPublic() && controller.isInGeneratedFunction() && target.getDeclaringClass() != classNode) {
if (!tryBridgeMethod(target, receiver, implicitThis, args, classNode)) {
// replace call with an invoker helper call
MethodNode methodNode = target.isStatic() ? INVOKERHELPER_INVOKESTATICMETHOD : INVOKERHELPER_INVOKEMETHOD;
MethodCallExpression mce = callX(classX(INVOKERHELPER_CLASSNODE), methodNode.getName(), args(target.isStatic() ? classX(target.getDeclaringClass()) : receiver, constX(target.getName()), new ArrayExpression(ClassHelper.OBJECT_TYPE, args.getExpressions())));
mce.setMethodTarget(methodNode);
mce.visit(controller.getAcg());
}
return true;
}
if (target.isPrivate() && tryPrivateMethod(target, implicitThis, receiver, args, classNode)) {
return true;
}
Expression fixedReceiver = null;
boolean fixedImplicitThis = implicitThis;
if (target.isProtected()) {
ClassNode node = receiver == null ? ClassHelper.OBJECT_TYPE : controller.getTypeChooser().resolveType(receiver, controller.getClassNode());
if (!implicitThis && !isThisOrSuper(receiver) && !samePackageName(node, classNode) && StaticTypeCheckingSupport.implementsInterfaceOrIsSubclassOf(node, target.getDeclaringClass())) {
controller.getSourceUnit().addError(new SyntaxException("Method " + target.getName() + " is protected in " + target.getDeclaringClass().toString(false), receiver != null ? receiver : args));
} else if (!node.isDerivedFrom(target.getDeclaringClass()) && tryBridgeMethod(target, receiver, implicitThis, args, classNode)) {
return true;
}
} else if (target.isPublic() && receiver != null) {
if (implicitThis && controller.isInGeneratedFunction() && !classNode.isDerivedFrom(target.getDeclaringClass()) && !classNode.implementsInterface(target.getDeclaringClass())) {
ClassNode thisType = controller.getThisType();
// GROOVY-7242
if (isTrait(thisType.getOuterClass()))
thisType = ClassHelper.dynamicType();
fixedReceiver = varX("thisObject", thisType);
// account for multiple levels of inner types
while (thisType.getOuterClass() != null && !target.getDeclaringClass().equals(thisType)) {
FieldNode thisField = thisType.getField("this$0");
thisType = thisType.getOuterClass();
if (thisField != null) {
fixedReceiver = propX(fixedReceiver, "this$0");
fixedReceiver.setType(thisType);
fixedImplicitThis = false;
}
}
}
}
if (receiver != null && !isSuperExpression(receiver)) {
// in order to avoid calls to castToType, which is the dynamic behaviour, we make sure that we call CHECKCAST instead then replace the top operand type
return super.writeDirectMethodCall(target, fixedImplicitThis, new CheckcastReceiverExpression(fixedReceiver != null ? fixedReceiver : receiver, target), args);
}
return super.writeDirectMethodCall(target, implicitThis, receiver, args);
}
use of org.codehaus.groovy.ast.expr.TupleExpression in project groovy by apache.
the class StaticInvocationWriter method writeSpecialConstructorCall.
@Override
public void writeSpecialConstructorCall(final ConstructorCallExpression call) {
MethodNode mn = call.getNodeMetaData(StaticTypesMarker.DIRECT_METHOD_CALL_TARGET);
if (mn == null) {
super.writeSpecialConstructorCall(call);
return;
}
controller.getCompileStack().pushInSpecialConstructorCall();
ConstructorNode cn;
if (mn instanceof ConstructorNode) {
cn = (ConstructorNode) mn;
} else {
cn = new ConstructorNode(mn.getModifiers(), mn.getParameters(), mn.getExceptions(), mn.getCode());
cn.setDeclaringClass(mn.getDeclaringClass());
}
// load "this"
controller.getMethodVisitor().visitVarInsn(ALOAD, 0);
String ownerDescriptor = BytecodeHelper.getClassInternalName(cn.getDeclaringClass());
TupleExpression args = makeArgumentList(call.getArguments());
int before = controller.getOperandStack().getStackLength();
loadArguments(args.getExpressions(), cn.getParameters());
finnishConstructorCall(cn, ownerDescriptor, controller.getOperandStack().getStackLength() - before);
// on a special call, there's no object on stack
controller.getOperandStack().remove(1);
controller.getCompileStack().pop();
}
use of org.codehaus.groovy.ast.expr.TupleExpression in project groovy by apache.
the class StaticImportVisitor method transformConstructorCallExpression.
protected Expression transformConstructorCallExpression(ConstructorCallExpression cce) {
inSpecialConstructorCall = cce.isSpecialCall();
Expression expression = cce.getArguments();
if (expression instanceof TupleExpression) {
TupleExpression tuple = (TupleExpression) expression;
if (tuple.getExpressions().size() == 1) {
expression = tuple.getExpression(0);
if (expression instanceof NamedArgumentListExpression) {
NamedArgumentListExpression namedArgs = (NamedArgumentListExpression) expression;
List<MapEntryExpression> entryExpressions = namedArgs.getMapEntryExpressions();
for (int i = 0; i < entryExpressions.size(); i++) {
entryExpressions.set(i, (MapEntryExpression) transformMapEntryExpression(entryExpressions.get(i), cce.getType()));
}
}
}
}
Expression ret = cce.transformExpression(this);
inSpecialConstructorCall = false;
return ret;
}
use of org.codehaus.groovy.ast.expr.TupleExpression in project groovy by apache.
the class StaticInvocationWriter method tryBridgeMethod.
/**
* Attempts to make a direct method call on a bridge method, if it exists.
*/
protected boolean tryBridgeMethod(final MethodNode target, final Expression receiver, final boolean implicitThis, final TupleExpression args, final ClassNode thisClass) {
ClassNode lookupClassNode;
if (target.isProtected()) {
lookupClassNode = controller.getClassNode();
while (lookupClassNode != null && !lookupClassNode.isDerivedFrom(target.getDeclaringClass())) {
lookupClassNode = lookupClassNode.getOuterClass();
}
if (lookupClassNode == null) {
return false;
}
} else {
lookupClassNode = target.getDeclaringClass().redirect();
}
Map<MethodNode, MethodNode> bridges = lookupClassNode.getNodeMetaData(StaticCompilationMetadataKeys.PRIVATE_BRIDGE_METHODS);
MethodNode bridge = bridges == null ? null : bridges.get(target);
if (bridge != null) {
Expression fixedReceiver = receiver;
if (implicitThis) {
if (!controller.isInGeneratedFunction()) {
if (!thisClass.isDerivedFrom(lookupClassNode))
fixedReceiver = propX(classX(lookupClassNode), "this");
} else if (thisClass != null) {
ClassNode current = thisClass.getOuterClass();
fixedReceiver = varX("thisObject", current);
// adjust for multiple levels of nesting if needed
while (current.getOuterClass() != null && !lookupClassNode.equals(current)) {
FieldNode thisField = current.getField("this$0");
current = current.getOuterClass();
if (thisField != null) {
fixedReceiver = propX(fixedReceiver, "this$0");
fixedReceiver.setType(current);
}
}
}
}
ArgumentListExpression newArgs = args(target.isStatic() ? nullX() : fixedReceiver);
for (Expression expression : args.getExpressions()) {
newArgs.addExpression(expression);
}
return writeDirectMethodCall(bridge, implicitThis, fixedReceiver, newArgs);
}
return false;
}
Aggregations