org.codehaus.groovy.ast.tools.GenericsUtils Java Examples
The following examples show how to use
org.codehaus.groovy.ast.tools.GenericsUtils.
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: EqualsAndHashCodeASTTransformation.java From groovy with Apache License 2.0 | 6 votes |
private static void createCanEqual(ClassNode cNode) { boolean hasExistingCanEqual = hasDeclaredMethod(cNode, "canEqual", 1); if (hasExistingCanEqual && hasDeclaredMethod(cNode, "_canEqual", 1)) return; final BlockStatement body = new BlockStatement(); VariableExpression other = varX("other"); body.addStatement(returnS(isInstanceOfX(other, GenericsUtils.nonGeneric(cNode)))); MethodNode canEqual = addGeneratedMethod(cNode, hasExistingCanEqual ? "_canEqual" : "canEqual", hasExistingCanEqual ? ACC_PRIVATE : ACC_PUBLIC, ClassHelper.boolean_TYPE, params(param(OBJECT_TYPE, other.getName())), ClassNode.EMPTY_ARRAY, body); // don't null check this: prefer false to IllegalArgumentException NullCheckASTTransformation.markAsProcessed(canEqual); }
Example #2
Source File: AutoCloneASTTransformation.java From groovy with Apache License 2.0 | 5 votes |
private void createCloneSerialization(ClassNode cNode) { final BlockStatement body = new BlockStatement(); // def baos = new ByteArrayOutputStream() final Expression baos = localVarX("baos"); body.addStatement(declS(baos, ctorX(BAOS_TYPE))); // baos.withObjectOutputStream{ it.writeObject(this) } MethodCallExpression writeObject = callX(castX(OOS_TYPE, varX("it")), "writeObject", varX("this")); writeObject.setImplicitThis(false); ClosureExpression writeClos = closureX(block(stmt(writeObject))); writeClos.setVariableScope(new VariableScope()); body.addStatement(stmt(callX(baos, "withObjectOutputStream", args(writeClos)))); // def bais = new ByteArrayInputStream(baos.toByteArray()) final Expression bais = localVarX("bais"); body.addStatement(declS(bais, ctorX(BAIS_TYPE, args(callX(baos, "toByteArray"))))); // return bais.withObjectInputStream(getClass().classLoader){ (<type>) it.readObject() } MethodCallExpression readObject = callX(castX(OIS_TYPE, varX("it")), "readObject"); readObject.setImplicitThis(false); ClosureExpression readClos = closureX(block(stmt(castX(GenericsUtils.nonGeneric(cNode), readObject)))); readClos.setVariableScope(new VariableScope()); Expression classLoader = callX(callThisX("getClass"), "getClassLoader"); body.addStatement(returnS(callX(bais, "withObjectInputStream", args(classLoader, readClos)))); new VariableScopeVisitor(sourceUnit, true).visitClass(cNode); ClassNode[] exceptions = {make(CloneNotSupportedException.class)}; addGeneratedMethod(cNode, "clone", ACC_PUBLIC, GenericsUtils.nonGeneric(cNode), Parameter.EMPTY_ARRAY, exceptions, body); }
Example #3
Source File: BinaryExpressionHelper.java From groovy with Apache License 2.0 | 5 votes |
private VariableSlotLoader loadWithSubscript(final Expression expression) { AsmClassGenerator acg = controller.getAcg(); // if we have a BinaryExpression, check if it is with subscription if (expression instanceof BinaryExpression) { BinaryExpression bexp = (BinaryExpression) expression; if (bexp.getOperation().getType() == LEFT_SQUARE_BRACKET) { // right expression is the subscript expression // we store the result of the subscription on the stack Expression subscript = bexp.getRightExpression(); subscript.visit(acg); OperandStack operandStack = controller.getOperandStack(); ClassNode subscriptType = operandStack.getTopOperand(); if (subscriptType.isGenericsPlaceHolder() || GenericsUtils.hasPlaceHolders(subscriptType)) { subscriptType = controller.getTypeChooser().resolveType(bexp, controller.getClassNode()); } int id = controller.getCompileStack().defineTemporaryVariable("$subscript", subscriptType, true); VariableSlotLoader subscriptExpression = new VariableSlotLoader(subscriptType, id, operandStack); BinaryExpression rewrite = binX(bexp.getLeftExpression(), bexp.getOperation(), subscriptExpression); rewrite.copyNodeMetaData(bexp); rewrite.setSourcePosition(bexp); rewrite.visit(acg); return subscriptExpression; } } // normal loading of expression expression.visit(acg); return null; }
Example #4
Source File: ExternalizeMethodsASTTransformation.java From groovy with Apache License 2.0 | 5 votes |
private static void createReadExternal(ClassNode cNode, List<String> excludes, List<FieldNode> list) { final BlockStatement body = new BlockStatement(); Parameter oin = param(OBJECTINPUT_TYPE, "oin"); for (FieldNode fNode : list) { if (excludes != null && excludes.contains(fNode.getName())) continue; if ((fNode.getModifiers() & ACC_TRANSIENT) != 0) continue; String suffix = suffixForField(fNode); MethodCallExpression readObject = callX(varX(oin), "read" + suffix); readObject.setImplicitThis(false); body.addStatement(assignS(varX(fNode), suffix.equals("Object") ? castX(GenericsUtils.nonGeneric(fNode.getType()), readObject) : readObject)); } addGeneratedMethod(cNode, "readExternal", ACC_PUBLIC, ClassHelper.VOID_TYPE, params(oin), ClassNode.EMPTY_ARRAY, body); }
Example #5
Source File: Traits.java From groovy with Apache License 2.0 | 5 votes |
/** * Collects all interfaces of a class node, but reverses the order of the declaration of direct interfaces * of this class node. This is used to make sure a trait implementing A,B where both A and B have the same * method will take the method from B (latest), aligning the behavior with categories. * @param cNode a class node * @param interfaces ordered set of interfaces */ public static LinkedHashSet<ClassNode> collectAllInterfacesReverseOrder(ClassNode cNode, LinkedHashSet<ClassNode> interfaces) { if (cNode.isInterface()) interfaces.add(cNode); ClassNode[] directInterfaces = cNode.getInterfaces(); for (int i = directInterfaces.length-1; i >=0 ; i--) { final ClassNode anInterface = directInterfaces[i]; interfaces.add(GenericsUtils.parameterizeType(cNode,anInterface)); collectAllInterfacesReverseOrder(anInterface, interfaces); } return interfaces; }
Example #6
Source File: StaticTypeCheckingSupport.java From groovy with Apache License 2.0 | 5 votes |
static Map<GenericsTypeName, GenericsType> applyGenericsContextToParameterClass(final Map<GenericsTypeName, GenericsType> spec, final ClassNode parameterUsage) { GenericsType[] gts = parameterUsage.getGenericsTypes(); if (gts == null) return Collections.emptyMap(); GenericsType[] newGTs = applyGenericsContext(spec, gts); ClassNode newTarget = parameterUsage.redirect().getPlainNodeReference(); newTarget.setGenericsTypes(newGTs); return GenericsUtils.extractPlaceholders(newTarget); }
Example #7
Source File: StaticTypeCheckingSupport.java From groovy with Apache License 2.0 | 5 votes |
/** * Checks that the parameterized generics of an argument are compatible with the generics of the parameter. * * @param parameterType the parameter type of a method * @param argumentType the type of the argument passed to the method */ protected static boolean typeCheckMethodArgumentWithGenerics(final ClassNode parameterType, final ClassNode argumentType, final boolean lastArg) { if (UNKNOWN_PARAMETER_TYPE == argumentType) { // called with null return !isPrimitiveType(parameterType); } if (!isAssignableTo(argumentType, parameterType) && !lastArg) { // incompatible assignment return false; } if (!isAssignableTo(argumentType, parameterType) && lastArg) { if (parameterType.isArray()) { if (!isAssignableTo(argumentType, parameterType.getComponentType())) { return false; } } else { return false; } } if (parameterType.isUsingGenerics() && argumentType.isUsingGenerics()) { GenericsType gt = GenericsUtils.buildWildcardType(parameterType); if (!gt.isCompatibleWith(argumentType)) { boolean samCoercion = isSAMType(parameterType) && argumentType.equals(CLOSURE_TYPE); if (!samCoercion) return false; } } else if (parameterType.isArray() && argumentType.isArray()) { // verify component type return typeCheckMethodArgumentWithGenerics(parameterType.getComponentType(), argumentType.getComponentType(), lastArg); } else if (lastArg && parameterType.isArray()) { // verify component type, but if we reach that point, the only possibility is that the argument is // the last one of the call, so we're in the cast of a vargs call // (otherwise, we face a type checker bug) return typeCheckMethodArgumentWithGenerics(parameterType.getComponentType(), argumentType, lastArg); } return true; }
Example #8
Source File: StaticTypeCheckingSupport.java From groovy with Apache License 2.0 | 5 votes |
/** * Given a receiver and a method node, parameterize the method arguments using * available generic type information. * * @param receiver the class * @param m the method * @return the parameterized arguments */ public static Parameter[] parameterizeArguments(final ClassNode receiver, final MethodNode m) { Map<GenericsTypeName, GenericsType> genericFromReceiver = GenericsUtils.extractPlaceholders(receiver); Map<GenericsTypeName, GenericsType> contextPlaceholders = extractGenericsParameterMapOfThis(m); Parameter[] methodParameters = m.getParameters(); Parameter[] params = new Parameter[methodParameters.length]; for (int i = 0, n = methodParameters.length; i < n; i += 1) { Parameter methodParameter = methodParameters[i]; ClassNode paramType = methodParameter.getType(); params[i] = buildParameter(genericFromReceiver, contextPlaceholders, methodParameter, paramType); } return params; }
Example #9
Source File: StaticTypeCheckingSupport.java From groovy with Apache License 2.0 | 5 votes |
/** * Checks if a class node is assignable to another. This is used for example in * assignment checks where you want to verify that the assignment is valid. * * @return true if the class node is assignable to the other class node, false otherwise */ static boolean isAssignableTo(ClassNode type, ClassNode toBeAssignedTo) { if (type == toBeAssignedTo || type == UNKNOWN_PARAMETER_TYPE) return true; if (isPrimitiveType(type)) type = getWrapper(type); if (isPrimitiveType(toBeAssignedTo)) toBeAssignedTo = getWrapper(toBeAssignedTo); if (NUMBER_TYPES.containsKey(type.redirect()) && NUMBER_TYPES.containsKey(toBeAssignedTo.redirect())) { return NUMBER_TYPES.get(type.redirect()) <= NUMBER_TYPES.get(toBeAssignedTo.redirect()); } if (type.isArray() && toBeAssignedTo.isArray()) { return isAssignableTo(type.getComponentType(), toBeAssignedTo.getComponentType()); } if (type.isDerivedFrom(GSTRING_TYPE) && STRING_TYPE.equals(toBeAssignedTo)) { return true; } if (STRING_TYPE.equals(type) && toBeAssignedTo.isDerivedFrom(GSTRING_TYPE)) { return true; } if (implementsInterfaceOrIsSubclassOf(type, toBeAssignedTo)) { if (toBeAssignedTo.getGenericsTypes() != null) { // perform additional check on generics // ? extends toBeAssignedTo GenericsType gt = GenericsUtils.buildWildcardType(toBeAssignedTo); return gt.isCompatibleWith(type); } return true; } // SAM check if (type.isDerivedFrom(CLOSURE_TYPE) && isSAMType(toBeAssignedTo)) { return true; } return false; }
Example #10
Source File: DelegateASTTransformation.java From groovy with Apache License 2.0 | 5 votes |
private static void addGetterIfNeeded(DelegateDescription delegate, PropertyNode prop, String name, boolean allNames) { boolean isPrimBool = prop.getOriginType().equals(ClassHelper.boolean_TYPE); // do a little bit of pre-work since Groovy compiler hasn't added property accessors yet boolean willHaveGetAccessor = true; boolean willHaveIsAccessor = isPrimBool; String suffix = Verifier.capitalize(name); if (isPrimBool) { ClassNode cNode = prop.getDeclaringClass(); if (cNode.getGetterMethod("is" + suffix) != null && cNode.getGetterMethod("get" + suffix) == null) willHaveGetAccessor = false; if (cNode.getGetterMethod("get" + suffix) != null && cNode.getGetterMethod("is" + suffix) == null) willHaveIsAccessor = false; } Reference<Boolean> ownerWillHaveGetAccessor = new Reference<Boolean>(); Reference<Boolean> ownerWillHaveIsAccessor = new Reference<Boolean>(); extractAccessorInfo(delegate.owner, name, ownerWillHaveGetAccessor, ownerWillHaveIsAccessor); for (String prefix : new String[]{"get", "is"}) { String getterName = prefix + suffix; if ((prefix.equals("get") && willHaveGetAccessor && !ownerWillHaveGetAccessor.get() || prefix.equals("is") && willHaveIsAccessor && !ownerWillHaveIsAccessor.get()) && !shouldSkipPropertyMethod(name, getterName, delegate.excludes, delegate.includes, allNames)) { addGeneratedMethod(delegate.owner, getterName, ACC_PUBLIC, GenericsUtils.nonGeneric(prop.getType()), Parameter.EMPTY_ARRAY, null, returnS(propX(delegate.getOp, name))); } } }
Example #11
Source File: DelegateASTTransformation.java From groovy with Apache License 2.0 | 5 votes |
private static void addSetterIfNeeded(DelegateDescription delegate, PropertyNode prop, String name, boolean allNames) { String setterName = "set" + Verifier.capitalize(name); if ((prop.getModifiers() & ACC_FINAL) == 0 && delegate.owner.getSetterMethod(setterName) == null && delegate.owner.getProperty(name) == null && !shouldSkipPropertyMethod(name, setterName, delegate.excludes, delegate.includes, allNames)) { addGeneratedMethod(delegate.owner, setterName, ACC_PUBLIC, ClassHelper.VOID_TYPE, params(new Parameter(GenericsUtils.nonGeneric(prop.getType()), "value")), null, assignS(propX(delegate.getOp, name), varX("value")) ); } }
Example #12
Source File: AutoCloneASTTransformation.java From groovy with Apache License 2.0 | 5 votes |
private static void createClone(ClassNode cNode, List<FieldNode> fieldNodes, List<String> excludes) { final BlockStatement body = new BlockStatement(); // def _result = super.clone() as cNode final Expression result = localVarX("_result"); body.addStatement(declS(result, castX(cNode, callSuperX("clone")))); for (FieldNode fieldNode : fieldNodes) { if (excludes != null && excludes.contains(fieldNode.getName())) continue; ClassNode fieldType = fieldNode.getType(); Expression fieldExpr = varX(fieldNode); Expression to = propX(result, fieldNode.getName()); Statement doClone = assignS(to, castX(fieldType, callCloneDirectX(fieldExpr))); Statement doCloneDynamic = assignS(to, castX(fieldType, callCloneDynamicX(fieldExpr))); if (isCloneableType(fieldType)) { body.addStatement(doClone); } else if (possiblyCloneable(fieldType)) { body.addStatement(ifS(isInstanceOfX(fieldExpr, CLONEABLE_TYPE), doCloneDynamic)); } } // return _result body.addStatement(returnS(result)); ClassNode[] exceptions = {make(CloneNotSupportedException.class)}; addGeneratedMethod(cNode, "clone", ACC_PUBLIC, GenericsUtils.nonGeneric(cNode), Parameter.EMPTY_ARRAY, exceptions, body); }
Example #13
Source File: AutoCloneASTTransformation.java From groovy with Apache License 2.0 | 5 votes |
private static void addSimpleCloneHelperMethod(ClassNode cNode, List<FieldNode> fieldNodes, List<String> excludes) { Parameter methodParam = new Parameter(GenericsUtils.nonGeneric(cNode), "other"); final Expression other = varX(methodParam); boolean hasParent = cNode.getSuperClass() != ClassHelper.OBJECT_TYPE; BlockStatement methodBody = new BlockStatement(); if (hasParent) { methodBody.addStatement(stmt(callSuperX("cloneOrCopyMembers", args(other)))); } for (FieldNode fieldNode : fieldNodes) { String name = fieldNode.getName(); if (excludes != null && excludes.contains(name)) continue; ClassNode fieldType = fieldNode.getType(); Expression direct = propX(varX("this"), name); Expression to = propX(other, name); Statement assignDirect = assignS(to, direct); Statement assignCloned = assignS(to, castX(fieldType, callCloneDirectX(direct))); Statement assignClonedDynamic = assignS(to, castX(fieldType, callCloneDynamicX(direct))); if (isCloneableType(fieldType)) { methodBody.addStatement(assignCloned); } else if (!possiblyCloneable(fieldType)) { methodBody.addStatement(assignDirect); } else { methodBody.addStatement(ifElseS(isInstanceOfX(direct, CLONEABLE_TYPE), assignClonedDynamic, assignDirect)); } } ClassNode[] exceptions = {make(CloneNotSupportedException.class)}; addGeneratedMethod(cNode, "cloneOrCopyMembers", ACC_PROTECTED, ClassHelper.VOID_TYPE, params(methodParam), exceptions, methodBody); }
Example #14
Source File: AutoCloneASTTransformation.java From groovy with Apache License 2.0 | 5 votes |
private static void createSimpleClone(ClassNode cNode, List<FieldNode> fieldNodes, List<String> excludes) { if (cNode.getDeclaredConstructors().isEmpty()) { // add no-arg constructor addGeneratedConstructor(cNode, ACC_PUBLIC, Parameter.EMPTY_ARRAY, ClassNode.EMPTY_ARRAY, block(EmptyStatement.INSTANCE)); } addSimpleCloneHelperMethod(cNode, fieldNodes, excludes); final Expression result = localVarX("_result"); ClassNode[] exceptions = {make(CloneNotSupportedException.class)}; addGeneratedMethod(cNode, "clone", ACC_PUBLIC, GenericsUtils.nonGeneric(cNode), Parameter.EMPTY_ARRAY, exceptions, block( declS(result, ctorX(cNode)), stmt(callThisX("cloneOrCopyMembers", args(result))), returnS(result))); }
Example #15
Source File: StaticTypeCheckingSupport.java From groovy with Apache License 2.0 | 4 votes |
/** * Given a list of candidate methods, returns the one which best matches the argument types * * @param receiver * @param methods candidate methods * @param argumentTypes argument types * @return the list of methods which best matches the argument types. It is still possible that multiple * methods match the argument types. */ public static List<MethodNode> chooseBestMethod(final ClassNode receiver, final Collection<MethodNode> methods, final ClassNode... argumentTypes) { if (methods.isEmpty()) return Collections.emptyList(); if (isUsingUncheckedGenerics(receiver)) { ClassNode raw = makeRawType(receiver); return chooseBestMethod(raw, methods, argumentTypes); } List<MethodNode> bestChoices = new LinkedList<>(); int bestDist = Integer.MAX_VALUE; Collection<MethodNode> choicesLeft = removeCovariantsAndInterfaceEquivalents(methods); for (MethodNode candidateNode : choicesLeft) { ClassNode declaringClassForDistance = candidateNode.getDeclaringClass(); ClassNode actualReceiverForDistance = receiver != null ? receiver : candidateNode.getDeclaringClass(); MethodNode safeNode = candidateNode; ClassNode[] safeArgs = argumentTypes; boolean isExtensionMethodNode = candidateNode instanceof ExtensionMethodNode; if (isExtensionMethodNode) { safeArgs = new ClassNode[argumentTypes.length + 1]; System.arraycopy(argumentTypes, 0, safeArgs, 1, argumentTypes.length); safeArgs[0] = receiver; safeNode = ((ExtensionMethodNode) candidateNode).getExtensionMethodNode(); } // todo : corner case /* class B extends A {} Animal foo(A o) {...} Person foo(B i){...} B a = new B() Person p = foo(b) */ Map<GenericsType, GenericsType> declaringAndActualGenericsTypeMap = GenericsUtils.makeDeclaringAndActualGenericsTypeMap(declaringClassForDistance, actualReceiverForDistance); Parameter[] params = makeRawTypes(safeNode.getParameters(), declaringAndActualGenericsTypeMap); int dist = measureParametersAndArgumentsDistance(params, safeArgs); if (dist >= 0) { dist += getClassDistance(declaringClassForDistance, actualReceiverForDistance); dist += getExtensionDistance(isExtensionMethodNode); if (dist < bestDist) { bestChoices.clear(); bestChoices.add(candidateNode); bestDist = dist; } else if (dist == bestDist) { bestChoices.add(candidateNode); } } } if (bestChoices.size() > 1) { // GROOVY-6849: prefer extension methods in case of ambiguity List<MethodNode> onlyExtensionMethods = new LinkedList<>(); for (MethodNode choice : bestChoices) { if (choice instanceof ExtensionMethodNode) { onlyExtensionMethods.add(choice); } } if (onlyExtensionMethods.size() == 1) { return onlyExtensionMethods; } } return bestChoices; }
Example #16
Source File: StaticTypeCheckingSupport.java From groovy with Apache License 2.0 | 4 votes |
static void addMethodLevelDeclaredGenerics(final MethodNode method, final Map<GenericsTypeName, GenericsType> resolvedPlaceholders) { ClassNode dummy = OBJECT_TYPE.getPlainNodeReference(); dummy.setGenericsTypes(method.getGenericsTypes()); GenericsUtils.extractPlaceholders(dummy, resolvedPlaceholders); }
Example #17
Source File: StaticTypeCheckingSupport.java From groovy with Apache License 2.0 | 4 votes |
private static boolean typeCheckMethodsWithGenerics(final ClassNode receiver, final ClassNode[] argumentTypes, final MethodNode candidateMethod, final boolean isExtensionMethod) { boolean failure = false; // correct receiver for inner class // we assume the receiver is an instance of the declaring class of the // candidate method, but findMethod returns also outer class methods // for that receiver. For now we skip receiver based checks in that case // TODO: correct generics for when receiver is to be skipped boolean skipBecauseOfInnerClassNotReceiver = !implementsInterfaceOrIsSubclassOf(receiver, candidateMethod.getDeclaringClass()); Parameter[] parameters = candidateMethod.getParameters(); Map<GenericsTypeName, GenericsType> classGTs; if (skipBecauseOfInnerClassNotReceiver) { classGTs = Collections.emptyMap(); } else { classGTs = GenericsUtils.extractPlaceholders(receiver); } if (parameters.length > argumentTypes.length || parameters.length == 0) { // this is a limitation that must be removed in a future version // we cannot check generic type arguments if there are default parameters! return true; } // we have here different generics contexts we have to deal with. // There is firstly the context given through the class, and the method. // The method context may hide generics given through the class, but use // the non-hidden ones. Map<GenericsTypeName, GenericsType> resolvedMethodGenerics = new HashMap<>(); if (!skipBecauseOfInnerClassNotReceiver) { addMethodLevelDeclaredGenerics(candidateMethod, resolvedMethodGenerics); } // first remove hidden generics for (GenericsTypeName key : resolvedMethodGenerics.keySet()) { classGTs.remove(key); } // then use the remaining information to refine the given generics applyGenericsConnections(classGTs, resolvedMethodGenerics); // and then start our checks with the receiver if (!skipBecauseOfInnerClassNotReceiver) { failure = failure || inferenceCheck(Collections.emptySet(), resolvedMethodGenerics, candidateMethod.getDeclaringClass(), receiver, false); } // the outside context parts till now define placeholder we are not allowed to // generalize, thus we save that for later use... // extension methods are special, since they set the receiver as // first parameter. While we normally allow generalization for the first // parameter, in case of an extension method we must not. Set<GenericsTypeName> fixedGenericsPlaceHolders = extractResolvedPlaceHolders(resolvedMethodGenerics); for (int i = 0, n = argumentTypes.length; i < n; i += 1) { int pindex = min(i, parameters.length - 1); ClassNode wrappedArgument = argumentTypes[i]; ClassNode type = parameters[pindex].getOriginType(); failure = failure || inferenceCheck(fixedGenericsPlaceHolders, resolvedMethodGenerics, type, wrappedArgument, i >= parameters.length - 1); // set real fixed generics for extension methods if (isExtensionMethod && i == 0) fixedGenericsPlaceHolders = extractResolvedPlaceHolders(resolvedMethodGenerics); } return !failure; }
Example #18
Source File: StaticTypeCheckingSupport.java From groovy with Apache License 2.0 | 4 votes |
public static ClassNode getCorrectedClassNode(final ClassNode type, final ClassNode superClass, final boolean handlingGenerics) { if (handlingGenerics && missesGenericsTypes(type)) return superClass.getPlainNodeReference(); return GenericsUtils.correctToGenericsSpecRecurse(GenericsUtils.createGenericsSpec(type), superClass); }
Example #19
Source File: AutoCloneASTTransformation.java From groovy with Apache License 2.0 | 4 votes |
private static void createCloneCopyConstructor(ClassNode cNode, List<FieldNode> list, List<String> excludes) { if (cNode.getDeclaredConstructors().isEmpty()) { // add no-arg constructor BlockStatement noArgBody = new BlockStatement(); noArgBody.addStatement(EmptyStatement.INSTANCE); addGeneratedConstructor(cNode, ACC_PUBLIC, Parameter.EMPTY_ARRAY, ClassNode.EMPTY_ARRAY, noArgBody); } boolean hasThisCons = false; for (ConstructorNode consNode : cNode.getDeclaredConstructors()) { Parameter[] parameters = consNode.getParameters(); if (parameters.length == 1 && parameters[0].getType().equals(cNode)) { hasThisCons = true; } } if (!hasThisCons) { BlockStatement initBody = new BlockStatement(); Parameter initParam = param(GenericsUtils.nonGeneric(cNode), "other"); final Expression other = varX(initParam); boolean hasParent = cNode.getSuperClass() != ClassHelper.OBJECT_TYPE; if (hasParent) { initBody.addStatement(stmt(ctorX(ClassNode.SUPER, other))); } for (FieldNode fieldNode : list) { String name = fieldNode.getName(); if (excludes != null && excludes.contains(name)) continue; ClassNode fieldType = fieldNode.getType(); Expression direct = propX(other, name); Expression to = propX(varX("this"), name); Statement assignDirect = assignS(to, direct); Statement assignCloned = assignS(to, castX(fieldType, callCloneDirectX(direct))); Statement assignClonedDynamic = assignS(to, castX(fieldType, callCloneDynamicX(direct))); if (isCloneableType(fieldType)) { initBody.addStatement(assignCloned); } else if (!possiblyCloneable(fieldType)) { initBody.addStatement(assignDirect); } else { initBody.addStatement(ifElseS(isInstanceOfX(direct, CLONEABLE_TYPE), assignClonedDynamic, assignDirect)); } } addGeneratedConstructor(cNode, ACC_PROTECTED, params(initParam), ClassNode.EMPTY_ARRAY, initBody); } ClassNode[] exceptions = {make(CloneNotSupportedException.class)}; addGeneratedMethod(cNode, "clone", ACC_PUBLIC, GenericsUtils.nonGeneric(cNode), Parameter.EMPTY_ARRAY, exceptions, block(stmt(ctorX(cNode, args(varX("this")))))); }
Example #20
Source File: EqualsAndHashCodeASTTransformation.java From groovy with Apache License 2.0 | 4 votes |
public static void createEquals(ClassNode cNode, boolean includeFields, boolean callSuper, boolean useCanEqual, List<String> excludes, List<String> includes, boolean allNames, boolean allProperties) { if (useCanEqual) createCanEqual(cNode); // make a public method if none exists otherwise try a private method with leading underscore boolean hasExistingEquals = hasDeclaredMethod(cNode, "equals", 1); if (hasExistingEquals && hasDeclaredMethod(cNode, "_equals", 1)) return; final BlockStatement body = new BlockStatement(); VariableExpression other = varX("other"); // some short circuit cases for efficiency body.addStatement(ifS(equalsNullX(other), returnS(constX(Boolean.FALSE, true)))); body.addStatement(ifS(sameX(varX("this"), other), returnS(constX(Boolean.TRUE, true)))); if (useCanEqual) { body.addStatement(ifS(notX(isInstanceOfX(other, GenericsUtils.nonGeneric(cNode))), returnS(constX(Boolean.FALSE,true)))); } else { body.addStatement(ifS(notX(hasClassX(other, GenericsUtils.nonGeneric(cNode))), returnS(constX(Boolean.FALSE,true)))); } VariableExpression otherTyped = localVarX("otherTyped", GenericsUtils.nonGeneric(cNode)); CastExpression castExpression = new CastExpression(GenericsUtils.nonGeneric(cNode), other); castExpression.setStrict(true); body.addStatement(declS(otherTyped, castExpression)); if (useCanEqual) { body.addStatement(ifS(notX(callX(otherTyped, "canEqual", varX("this"))), returnS(constX(Boolean.FALSE,true)))); } final Set<String> names = new HashSet<String>(); final List<PropertyNode> pList = getAllProperties(names, cNode, true, includeFields, allProperties, false, false, false); for (PropertyNode pNode : pList) { if (shouldSkipUndefinedAware(pNode.getName(), excludes, includes, allNames)) continue; boolean canBeSelf = StaticTypeCheckingSupport.implementsInterfaceOrIsSubclassOf( pNode.getOriginType(), cNode ); if (!canBeSelf) { body.addStatement(ifS(notX(hasEqualPropertyX(otherTyped.getOriginType(), pNode, otherTyped)), returnS(constX(Boolean.FALSE, true)))); } else { body.addStatement( ifS(notX(hasSamePropertyX(pNode, otherTyped)), ifElseS(differentSelfRecursivePropertyX(pNode, otherTyped), returnS(constX(Boolean.FALSE, true)), ifS(notX(bothSelfRecursivePropertyX(pNode, otherTyped)), ifS(notX(hasEqualPropertyX(otherTyped.getOriginType(), pNode, otherTyped)), returnS(constX(Boolean.FALSE, true)))) ) ) ); } } List<FieldNode> fList = new ArrayList<FieldNode>(); if (includeFields) { fList.addAll(getInstanceNonPropertyFields(cNode)); } for (FieldNode fNode : fList) { if (shouldSkipUndefinedAware(fNode.getName(), excludes, includes, allNames)) continue; body.addStatement( ifS(notX(hasSameFieldX(fNode, otherTyped)), ifElseS(differentSelfRecursiveFieldX(fNode, otherTyped), returnS(constX(Boolean.FALSE,true)), ifS(notX(bothSelfRecursiveFieldX(fNode, otherTyped)), ifS(notX(hasEqualFieldX(fNode, otherTyped)), returnS(constX(Boolean.FALSE,true))))) )); } if (callSuper) { body.addStatement(ifS( notX(isTrueX(callSuperX("equals", other))), returnS(constX(Boolean.FALSE,true)) )); } // default body.addStatement(returnS(constX(Boolean.TRUE,true))); MethodNode equal = addGeneratedMethod(cNode, hasExistingEquals ? "_equals" : "equals", hasExistingEquals ? ACC_PRIVATE : ACC_PUBLIC, ClassHelper.boolean_TYPE, params(param(OBJECT_TYPE, other.getName())), ClassNode.EMPTY_ARRAY, body); // don't null check this: prefer false to IllegalArgumentException NullCheckASTTransformation.markAsProcessed(equal); }
Example #21
Source File: MethodInference.java From netbeans with Apache License 2.0 | 4 votes |
@CheckForNull private static ClassNode findReturnTypeFor( @NonNull ClassNode callerType, @NonNull String methodName, @NonNull Expression arguments, @NonNull AstPath path, @NonNull boolean isStatic, @NonNull BaseDocument baseDocument, @NonNull int offset ) { List<ClassNode> paramTypes = new ArrayList<>(); if (arguments instanceof ArgumentListExpression) { ArgumentListExpression argExpression = (ArgumentListExpression) arguments; for (Expression e : argExpression.getExpressions()) { if (e instanceof VariableExpression) { ModuleNode moduleNode = (ModuleNode) path.root(); int newOffset = ASTUtils.getOffset(baseDocument, e.getLineNumber(), e.getColumnNumber()); AstPath newPath = new AstPath(moduleNode, newOffset, baseDocument); TypeInferenceVisitor tiv = new TypeInferenceVisitor(moduleNode.getContext(), newPath, baseDocument, newOffset); tiv.collect(); ClassNode guessedType = tiv.getGuessedType(); if (null == guessedType) { System.out.println("Bad guessed type"); } else { paramTypes.add(tiv.getGuessedType()); } } else if(e instanceof ConstantExpression) { paramTypes.add(((ConstantExpression)e).getType()); } else if (e instanceof MethodCallExpression) { paramTypes.add(findCallerType(e, path, baseDocument, offset)); } else if (e instanceof BinaryExpression) { BinaryExpression binExpression = (BinaryExpression) e; paramTypes.add(binExpression.getType()); } else if (e instanceof ClassExpression) { ClassExpression classExpression = (ClassExpression) e; // This should be Class<classExpression.getType()> paramTypes.add(GenericsUtils.makeClassSafeWithGenerics(Class.class, classExpression.getType())); } else { System.out.println(e.getClass()); } } } MethodNode possibleMethod = tryFindPossibleMethod(callerType, methodName, paramTypes, isStatic); if (possibleMethod != null) { return possibleMethod.getReturnType(); } return null; }
Example #22
Source File: FromString.java From groovy with Apache License 2.0 | 2 votes |
/** * Parses a string representing a type, that must be aligned with the current context. * For example, <i>"List<T>"</i> must be converted into the appropriate ClassNode * for which <i>T</i> matches the appropriate placeholder. * * * @param option a string representing a type * @param sourceUnit the source unit (of the file being compiled) * @param compilationUnit the compilation unit (of the file being compiled) * @param mn the method node * @param usage * @return a class node if it could be parsed and resolved, null otherwise */ private static ClassNode[] parseOption(final String option, final SourceUnit sourceUnit, final CompilationUnit compilationUnit, final MethodNode mn, final ASTNode usage) { return GenericsUtils.parseClassNodesFromString(option, sourceUnit, compilationUnit, mn, usage); }