use of org.codehaus.groovy.ast.expr.StaticMethodCallExpression in project groovy by apache.
the class TraitComposer method applyTrait.
private static void applyTrait(final ClassNode trait, final ClassNode cNode, final TraitHelpersTuple helpers, SourceUnit unit) {
ClassNode helperClassNode = helpers.getHelper();
ClassNode fieldHelperClassNode = helpers.getFieldHelper();
ClassNode staticFieldHelperClassNode = helpers.getStaticFieldHelper();
Map<String, ClassNode> genericsSpec = GenericsUtils.createGenericsSpec(trait, GenericsUtils.createGenericsSpec(cNode));
for (MethodNode methodNode : helperClassNode.getAllDeclaredMethods()) {
String name = methodNode.getName();
Parameter[] helperMethodParams = methodNode.getParameters();
int nParams = helperMethodParams.length;
if (nParams > 0 && !methodNode.isAbstract() && ((methodNode.getModifiers() & Opcodes.ACC_STATIC) != 0) && (!name.contains("$") || (methodNode.getModifiers() & Opcodes.ACC_SYNTHETIC) == 0)) {
ArgumentListExpression argList = new ArgumentListExpression();
argList.addExpression(new VariableExpression("this"));
Parameter[] origParams = new Parameter[nParams - 1];
Parameter[] params = new Parameter[nParams - 1];
System.arraycopy(methodNode.getParameters(), 1, params, 0, params.length);
MethodNode originalMethod = trait.getMethod(name, params);
Map<String, ClassNode> methodGenericsSpec = GenericsUtils.addMethodGenerics(Optional.ofNullable(originalMethod).orElse(methodNode), genericsSpec);
for (int i = 1; i < nParams; i += 1) {
Parameter parameter = helperMethodParams[i];
ClassNode originType = parameter.getOriginType();
ClassNode fixedType = correctToGenericsSpecRecurse(methodGenericsSpec, originType);
Parameter newParam = new Parameter(fixedType, parameter.getName());
List<AnnotationNode> copied = new LinkedList<>();
List<AnnotationNode> notCopied = new LinkedList<>();
GeneralUtils.copyAnnotatedNodeAnnotations(parameter, copied, notCopied);
newParam.addAnnotations(copied);
params[i - 1] = newParam;
origParams[i - 1] = parameter;
argList.addExpression(new VariableExpression(newParam));
}
createForwarderMethod(trait, cNode, methodNode, originalMethod, helperClassNode, methodGenericsSpec, helperMethodParams, origParams, params, argList, unit);
}
}
MethodCallExpression staticInitCall = new MethodCallExpression(new ClassExpression(helperClassNode), Traits.STATIC_INIT_METHOD, new ArgumentListExpression(new ClassExpression(cNode)));
MethodNode staticInitMethod = new MethodNode(Traits.STATIC_INIT_METHOD, Opcodes.ACC_STATIC | Opcodes.ACC_PUBLIC, ClassHelper.VOID_TYPE, new Parameter[] { new Parameter(ClassHelper.CLASS_Type, "clazz") }, ClassNode.EMPTY_ARRAY, EmptyStatement.INSTANCE);
staticInitMethod.setDeclaringClass(helperClassNode);
staticInitCall.setMethodTarget(staticInitMethod);
cNode.addStaticInitializerStatements(Collections.singletonList(new ExpressionStatement(staticInitCall)), false);
if (fieldHelperClassNode != null && !cNode.declaresInterface(fieldHelperClassNode)) {
// we should implement the field helper interface too
cNode.addInterface(fieldHelperClassNode);
// implementation of methods
List<MethodNode> declaredMethods = new LinkedList<>();
for (MethodNode declaredMethod : fieldHelperClassNode.getAllDeclaredMethods()) {
if (declaredMethod.getName().endsWith(Traits.DIRECT_GETTER_SUFFIX)) {
declaredMethods.add(0, declaredMethod);
} else {
declaredMethods.add(declaredMethod);
}
}
if (staticFieldHelperClassNode != null) {
for (MethodNode declaredMethod : staticFieldHelperClassNode.getAllDeclaredMethods()) {
if (declaredMethod.getName().endsWith(Traits.DIRECT_GETTER_SUFFIX)) {
declaredMethods.add(0, declaredMethod);
} else {
declaredMethods.add(declaredMethod);
}
}
}
for (MethodNode methodNode : declaredMethods) {
String fieldName = methodNode.getName();
if (fieldName.endsWith(Traits.DIRECT_GETTER_SUFFIX) || fieldName.endsWith(Traits.DIRECT_SETTER_SUFFIX)) {
int suffixIdx = fieldName.lastIndexOf('$');
fieldName = fieldName.substring(0, suffixIdx);
String operation = methodNode.getName().substring(suffixIdx + 1);
boolean getter = "get".equals(operation);
ClassNode returnType = correctToGenericsSpecRecurse(genericsSpec, methodNode.getReturnType());
int fieldMods = 0;
int isStatic = 0;
boolean publicField = true;
FieldNode helperField = null;
fieldMods = 0;
isStatic = 0;
// look first for field with encoded modifier information
for (Integer mod : Traits.FIELD_PREFIXES) {
helperField = fieldHelperClassNode.getField(String.format("$0x%04x", mod) + fieldName);
if (helperField != null) {
if ((mod & Opcodes.ACC_STATIC) != 0)
isStatic = Opcodes.ACC_STATIC;
fieldMods = fieldMods | mod;
break;
}
}
if (helperField == null) {
// look for possible legacy fields (trait compiled pre 2.4.8)
helperField = fieldHelperClassNode.getField(Traits.FIELD_PREFIX + Traits.PUBLIC_FIELD_PREFIX + fieldName);
if (helperField == null) {
publicField = false;
helperField = fieldHelperClassNode.getField(Traits.FIELD_PREFIX + Traits.PRIVATE_FIELD_PREFIX + fieldName);
}
if (helperField == null) {
publicField = true;
// try to find a static one
helperField = fieldHelperClassNode.getField(Traits.STATIC_FIELD_PREFIX + Traits.PUBLIC_FIELD_PREFIX + fieldName);
if (helperField == null) {
publicField = false;
helperField = fieldHelperClassNode.getField(Traits.STATIC_FIELD_PREFIX + Traits.PRIVATE_FIELD_PREFIX + fieldName);
}
fieldMods = fieldMods | Opcodes.ACC_STATIC;
isStatic = Opcodes.ACC_STATIC;
}
fieldMods = fieldMods | (publicField ? Opcodes.ACC_PUBLIC : Opcodes.ACC_PRIVATE);
}
if (getter) {
// add field
if (helperField != null) {
List<AnnotationNode> copied = new LinkedList<>();
List<AnnotationNode> notCopied = new LinkedList<>();
GeneralUtils.copyAnnotatedNodeAnnotations(helperField, copied, notCopied);
FieldNode fieldNode = cNode.addField(fieldName, fieldMods, returnType, null);
fieldNode.addAnnotations(copied);
// so instead set within (static) initializer
if (fieldNode.isFinal()) {
String baseName = fieldNode.isStatic() ? Traits.STATIC_INIT_METHOD : Traits.INIT_METHOD;
StaticMethodCallExpression mce = callX(helperClassNode, baseName + fieldNode.getName(), args(varX("this")));
if (helperClassNode.hasPossibleStaticMethod(mce.getMethod(), mce.getArguments())) {
Statement stmt = stmt(assignX(varX(fieldNode.getName(), fieldNode.getType()), mce));
if (isStatic == 0) {
cNode.addObjectInitializerStatements(stmt);
} else {
List<Statement> staticStatements = new ArrayList<Statement>();
staticStatements.add(stmt);
cNode.addStaticInitializerStatements(staticStatements, true);
}
}
}
}
}
Parameter[] newParams;
if (getter) {
newParams = Parameter.EMPTY_ARRAY;
} else {
ClassNode originType = methodNode.getParameters()[0].getOriginType();
ClassNode fixedType = originType.isGenericsPlaceHolder() ? ClassHelper.OBJECT_TYPE : correctToGenericsSpecRecurse(genericsSpec, originType);
newParams = new Parameter[] { new Parameter(fixedType, "val") };
}
Expression fieldExpr = varX(cNode.getField(fieldName));
boolean finalSetter = !getter && (fieldMods & Opcodes.ACC_FINAL) != 0;
Statement body = getter ? returnS(fieldExpr) : (finalSetter ? null : stmt(new BinaryExpression(fieldExpr, Token.newSymbol(Types.EQUAL, 0, 0), varX(newParams[0]))));
// add getter/setter even though setter not strictly needed for final fields
// but add empty body for setter for legacy compatibility
MethodNode impl = new MethodNode(methodNode.getName(), Opcodes.ACC_PUBLIC | isStatic, returnType, newParams, ClassNode.EMPTY_ARRAY, body);
AnnotationNode an = new AnnotationNode(COMPILESTATIC_CLASSNODE);
impl.addAnnotation(an);
cNode.addTransform(StaticCompileTransformation.class, an);
cNode.addMethod(impl);
}
}
}
cNode.addObjectInitializerStatements(new ExpressionStatement(new MethodCallExpression(new ClassExpression(helperClassNode), Traits.INIT_METHOD, new ArgumentListExpression(new VariableExpression("this")))));
}
use of org.codehaus.groovy.ast.expr.StaticMethodCallExpression in project groovy by apache.
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 mce = callX(varX(weaved), call.getMethod(), transform(call.getArguments()));
mce.setSafe(false);
mce.setSpreadSafe(false);
mce.setImplicitThis(false);
mce.setSourcePosition(exp);
return mce;
}
} else if (exp instanceof MethodCallExpression) {
MethodCallExpression mce = (MethodCallExpression) exp;
String obj = mce.getObjectExpression().getText();
if (mce.isImplicitThis() || "this".equals(obj)) {
return transformMethodCallOnThis(mce);
} else if ("super".equals(obj)) {
return transformSuperMethodCall(mce);
}
} else if (exp instanceof FieldExpression) {
FieldNode fn = ((FieldExpression) exp).getField();
return transformFieldReference(exp, fn, fn.isStatic());
} else if (exp instanceof VariableExpression) {
VariableExpression vexp = (VariableExpression) exp;
Variable accessedVariable = vexp.getAccessedVariable();
if (accessedVariable instanceof FieldNode || accessedVariable instanceof PropertyNode) {
if (knownFields.contains(vexp.getName())) {
boolean isStatic = Modifier.isStatic(accessedVariable.getModifiers());
return transformFieldReference(exp, accessedVariable instanceof FieldNode ? (FieldNode) accessedVariable : ((PropertyNode) accessedVariable).getField(), isStatic);
} else {
PropertyExpression propertyExpression = propX(varX(weaved), vexp.getName());
propertyExpression.getProperty().setSourcePosition(exp);
return propertyExpression;
}
} else if (accessedVariable instanceof DynamicVariable && !inClosure) {
// GROOVY-9386
PropertyExpression propertyExpression = propX(varX(weaved), vexp.getName());
propertyExpression.getProperty().setSourcePosition(exp);
return propertyExpression;
}
if (vexp.isThisExpression()) {
VariableExpression variableExpression = varX(weaved);
variableExpression.setSourcePosition(exp);
return variableExpression;
}
if (vexp.isSuperExpression()) {
throwSuperError(vexp);
}
} else if (exp instanceof PropertyExpression) {
PropertyExpression pexp = (PropertyExpression) exp;
String obj = pexp.getObjectExpression().getText();
if (pexp.isImplicitThis() || "this".equals(obj)) {
String propName = pexp.getPropertyAsString();
if (knownFields.contains(propName)) {
FieldNode fn = new FieldNode(propName, 0, ClassHelper.OBJECT_TYPE, weavedType, null);
return transformFieldReference(exp, fn, false);
}
}
} else if (exp instanceof ClosureExpression) {
MethodCallExpression mce = callX(exp, "rehydrate", args(varX(weaved), varX(weaved), varX(weaved)));
mce.setImplicitThis(false);
mce.setSourcePosition(exp);
boolean oldInClosure = inClosure;
inClosure = true;
((ClosureExpression) exp).getCode().visit(this);
inClosure = oldInClosure;
// 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.expr.StaticMethodCallExpression 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.StaticMethodCallExpression in project groovy by apache.
the class StaticMethodCallExpressionTransformer method transformStaticMethodCallExpression.
Expression transformStaticMethodCallExpression(final StaticMethodCallExpression orig) {
MethodNode target = (MethodNode) orig.getNodeMetaData(StaticTypesMarker.DIRECT_METHOD_CALL_TARGET);
if (target != null) {
MethodCallExpression call = new MethodCallExpression(new ClassExpression(orig.getOwnerType()), orig.getMethod(), orig.getArguments());
call.setMethodTarget(target);
call.setSourcePosition(orig);
call.copyNodeMetaData(orig);
return transformer.transform(call);
}
return transformer.superTransform(orig);
}
use of org.codehaus.groovy.ast.expr.StaticMethodCallExpression in project gradle by gradle.
the class ExpressionReplacingVisitorSupport method visitStaticMethodCallExpression.
@Override
public void visitStaticMethodCallExpression(StaticMethodCallExpression expr) {
StaticMethodCallExpression result = new StaticMethodCallExpression(expr.getOwnerType(), expr.getMethod(), replaceExpr(expr.getArguments()));
result.setType(expr.getType());
result.setSourcePosition(expr);
replaceVisitedExpressionWith(result);
}
Aggregations