use of org.codehaus.groovy.ast.Parameter in project groovy-core by groovy.
the class TupleConstructorASTTransformation method createConstructor.
public static void createConstructor(ClassNode cNode, boolean includeFields, boolean includeProperties, boolean includeSuperFields, boolean includeSuperProperties, boolean callSuper, boolean force, List<String> excludes, List<String> includes, boolean useSetters) {
// no processing if existing constructors found
List<ConstructorNode> constructors = cNode.getDeclaredConstructors();
if (constructors.size() > 1 && !force)
return;
boolean foundEmpty = constructors.size() == 1 && constructors.get(0).getFirstStatement() == null;
if (constructors.size() == 1 && !foundEmpty && !force)
return;
// HACK: JavaStubGenerator could have snuck in a constructor we don't want
if (foundEmpty)
constructors.remove(0);
List<FieldNode> superList = new ArrayList<FieldNode>();
if (includeSuperProperties) {
superList.addAll(getSuperPropertyFields(cNode.getSuperClass()));
}
if (includeSuperFields) {
superList.addAll(getSuperNonPropertyFields(cNode.getSuperClass()));
}
List<FieldNode> list = new ArrayList<FieldNode>();
if (includeProperties) {
list.addAll(getInstancePropertyFields(cNode));
}
if (includeFields) {
list.addAll(getInstanceNonPropertyFields(cNode));
}
final List<Parameter> params = new ArrayList<Parameter>();
final List<Expression> superParams = new ArrayList<Expression>();
final BlockStatement body = new BlockStatement();
for (FieldNode fNode : superList) {
String name = fNode.getName();
if (shouldSkip(name, excludes, includes))
continue;
params.add(createParam(fNode, name));
boolean hasSetter = cNode.getProperty(name) != null && !fNode.isFinal();
if (callSuper) {
superParams.add(varX(name));
} else {
if (useSetters && hasSetter) {
body.addStatement(stmt(callThisX(getSetterName(name), varX(name))));
} else {
body.addStatement(assignS(propX(varX("this"), name), varX(name)));
}
}
}
if (callSuper) {
body.addStatement(stmt(ctorX(ClassNode.SUPER, args(superParams))));
}
for (FieldNode fNode : list) {
String name = fNode.getName();
if (shouldSkip(name, excludes, includes))
continue;
Parameter nextParam = createParam(fNode, name);
params.add(nextParam);
boolean hasSetter = cNode.getProperty(name) != null && !fNode.isFinal();
if (useSetters && hasSetter) {
body.addStatement(stmt(callThisX(getSetterName(name), varX(nextParam))));
} else {
body.addStatement(assignS(propX(varX("this"), name), varX(nextParam)));
}
}
cNode.addConstructor(new ConstructorNode(ACC_PUBLIC, params.toArray(new Parameter[params.size()]), ClassNode.EMPTY_ARRAY, body));
// or if there is only one Map property (for backwards compatibility)
if (params.size() > 0) {
ClassNode firstParam = params.get(0).getType();
if (params.size() > 1 || firstParam.equals(ClassHelper.OBJECT_TYPE)) {
if (firstParam.equals(ClassHelper.MAP_TYPE)) {
addMapConstructors(cNode, true, "The class " + cNode.getName() + " was incorrectly initialized via the map constructor with null.");
} else {
ClassNode candidate = HMAP_TYPE;
while (candidate != null) {
if (candidate.equals(firstParam)) {
addMapConstructors(cNode, true, "The class " + cNode.getName() + " was incorrectly initialized via the map constructor with null.");
break;
}
candidate = candidate.getSuperClass();
}
}
}
}
}
use of org.codehaus.groovy.ast.Parameter in project groovy-core by groovy.
the class StaticTypeCheckingVisitor method visitMethodCallArguments.
protected void visitMethodCallArguments(final ClassNode receiver, ArgumentListExpression arguments, boolean visitClosures, final MethodNode selectedMethod) {
Parameter[] params = selectedMethod != null ? selectedMethod.getParameters() : Parameter.EMPTY_ARRAY;
List<Expression> expressions = new LinkedList<Expression>(arguments.getExpressions());
if (selectedMethod instanceof ExtensionMethodNode) {
params = ((ExtensionMethodNode) selectedMethod).getExtensionMethodNode().getParameters();
expressions.add(0, new VariableExpression("$self", receiver));
}
ArgumentListExpression newArgs = new ArgumentListExpression(expressions);
for (int i = 0, expressionsSize = expressions.size(); i < expressionsSize; i++) {
final Expression expression = expressions.get(i);
if (visitClosures && expression instanceof ClosureExpression || !visitClosures && !(expression instanceof ClosureExpression)) {
if (i < params.length && visitClosures) {
Parameter param = params[i];
checkClosureWithDelegatesTo(receiver, selectedMethod, newArgs, params, expression, param);
if (selectedMethod instanceof ExtensionMethodNode) {
if (i > 0) {
inferClosureParameterTypes(receiver, arguments, (ClosureExpression) expression, param, selectedMethod);
}
} else {
inferClosureParameterTypes(receiver, newArgs, (ClosureExpression) expression, param, selectedMethod);
}
}
expression.visit(this);
if (expression.getNodeMetaData(StaticTypesMarker.DELEGATION_METADATA) != null) {
expression.removeNodeMetaData(StaticTypesMarker.DELEGATION_METADATA);
}
}
}
}
use of org.codehaus.groovy.ast.Parameter in project groovy-core by groovy.
the class StaticTypeCheckingVisitor method inferReturnTypeGenerics.
/**
* If a method call returns a parameterized type, then we can perform additional inference on the
* return type, so that the type gets actual type parameters. For example, the method
* Arrays.asList(T...) is generified with type T which can be deduced from actual type
* arguments.
*
* @param method the method node
* @param arguments the method call arguments
* @param explicitTypeHints explicit type hints as found for example in Collections.<String>emptyList()
* @return parameterized, infered, class node
*/
protected ClassNode inferReturnTypeGenerics(ClassNode receiver, MethodNode method, Expression arguments, GenericsType[] explicitTypeHints) {
ClassNode returnType = method.getReturnType();
if (method instanceof ExtensionMethodNode && (isUsingGenericsOrIsArrayUsingGenerics(returnType))) {
// check if the placeholder corresponds to the placeholder of the first parameter
ExtensionMethodNode emn = (ExtensionMethodNode) method;
MethodNode dgmMethod = emn.getExtensionMethodNode();
ClassNode dc = emn.getDeclaringClass();
ArgumentListExpression argList = new ArgumentListExpression();
VariableExpression vexp = new VariableExpression("$foo", receiver);
vexp.setNodeMetaData(ExtensionMethodDeclaringClass.class, dc);
argList.addExpression(vexp);
if (arguments instanceof ArgumentListExpression) {
List<Expression> expressions = ((ArgumentListExpression) arguments).getExpressions();
for (Expression arg : expressions) {
argList.addExpression(arg);
}
} else {
argList.addExpression(arguments);
}
return inferReturnTypeGenerics(receiver, dgmMethod, argList);
}
if (!isUsingGenericsOrIsArrayUsingGenerics(returnType))
return returnType;
if (getGenericsWithoutArray(returnType) == null)
return returnType;
Map<String, GenericsType> resolvedPlaceholders = resolvePlaceHoldersFromDeclaration(receiver, getDeclaringClass(method, arguments), method, method.isStatic());
if (!receiver.isGenericsPlaceHolder()) {
GenericsUtils.extractPlaceholders(receiver, resolvedPlaceholders);
}
resolvePlaceholdersFromExplicitTypeHints(method, explicitTypeHints, resolvedPlaceholders);
if (resolvedPlaceholders.isEmpty())
return returnType;
Map<String, GenericsType> placeholdersFromContext = extractGenericsParameterMapOfThis(typeCheckingContext.getEnclosingMethod());
applyGenericsConnections(placeholdersFromContext, resolvedPlaceholders);
// then resolve receivers from method arguments
Parameter[] parameters = method.getParameters();
boolean isVargs = isVargs(parameters);
ArgumentListExpression argList = InvocationWriter.makeArgumentList(arguments);
List<Expression> expressions = argList.getExpressions();
int paramLength = parameters.length;
if (expressions.size() >= paramLength) {
for (int i = 0; i < paramLength; i++) {
boolean lastArg = i == paramLength - 1;
ClassNode type = parameters[i].getType();
ClassNode actualType = getType(expressions.get(i));
while (!type.isUsingGenerics() && type.isArray() && actualType.isArray()) {
type = type.getComponentType();
actualType = actualType.getComponentType();
}
if (isUsingGenericsOrIsArrayUsingGenerics(type)) {
if (implementsInterfaceOrIsSubclassOf(actualType, CLOSURE_TYPE) && isSAMType(type)) {
// implicit closure coercion in action!
Map<String, GenericsType> pholders = applyGenericsContextToParameterClass(resolvedPlaceholders, type);
actualType = convertClosureTypeToSAMType(expressions.get(i), actualType, type, pholders);
}
if (isVargs && lastArg && actualType.isArray()) {
actualType = actualType.getComponentType();
}
if (isVargs && lastArg && type.isArray()) {
type = type.getComponentType();
}
actualType = wrapTypeIfNecessary(actualType);
Map<String, GenericsType> connections = new HashMap<String, GenericsType>();
extractGenericsConnections(connections, actualType, type);
extractGenericsConnectionsForSuperClassAndInterfaces(resolvedPlaceholders, connections);
applyGenericsConnections(connections, resolvedPlaceholders);
}
}
}
return applyGenericsContext(resolvedPlaceholders, returnType);
}
use of org.codehaus.groovy.ast.Parameter in project groovy-core by groovy.
the class StaticTypeCheckingVisitor method checkGroovyStyleConstructor.
/**
* Checks that a constructor style expression is valid regarding the number of arguments and the argument types.
*
* @param node the class node for which we will try to find a matching constructor
* @param arguments the constructor arguments
*/
protected MethodNode checkGroovyStyleConstructor(final ClassNode node, final ClassNode[] arguments, final ASTNode source) {
if (node.equals(ClassHelper.OBJECT_TYPE) || node.equals(ClassHelper.DYNAMIC_TYPE)) {
// in that case, we are facing a list constructor assigned to a def or object
return null;
}
List<ConstructorNode> constructors = node.getDeclaredConstructors();
if (constructors.isEmpty() && arguments.length == 0) {
return null;
}
List<MethodNode> constructorList = findMethod(node, "<init>", arguments);
if (constructorList.isEmpty()) {
if (isBeingCompiled(node) && arguments.length == 1 && LINKEDHASHMAP_CLASSNODE.equals(arguments[0])) {
// there will be a default hash map constructor added later
ConstructorNode cn = new ConstructorNode(Opcodes.ACC_PUBLIC, new Parameter[] { new Parameter(LINKEDHASHMAP_CLASSNODE, "args") }, ClassNode.EMPTY_ARRAY, EmptyStatement.INSTANCE);
return cn;
} else {
addStaticTypeError("No matching constructor found: " + node + toMethodParametersString("<init>", arguments), source);
return null;
}
} else if (constructorList.size() > 1) {
addStaticTypeError("Ambiguous constructor call " + node + toMethodParametersString("<init>", arguments), source);
return null;
}
return constructorList.get(0);
}
use of org.codehaus.groovy.ast.Parameter in project groovy-core by groovy.
the class StaticTypeCheckingVisitor method typeCheckMethodsWithGenericsOrFail.
protected boolean typeCheckMethodsWithGenericsOrFail(ClassNode receiver, ClassNode[] arguments, MethodNode candidateMethod, Expression location) {
if (!typeCheckMethodsWithGenerics(receiver, arguments, candidateMethod)) {
Map<String, GenericsType> classGTs = GenericsUtils.extractPlaceholders(receiver);
ClassNode[] ptypes = new ClassNode[candidateMethod.getParameters().length];
final Parameter[] parameters = candidateMethod.getParameters();
for (int i = 0; i < parameters.length; i++) {
final Parameter parameter = parameters[i];
ClassNode type = parameter.getType();
ptypes[i] = fullyResolveType(type, classGTs);
}
addStaticTypeError("Cannot call " + toMethodGenericTypesString(candidateMethod) + receiver.toString(false) + "#" + toMethodParametersString(candidateMethod.getName(), ptypes) + " with arguments " + formatArgumentList(arguments), location);
return false;
}
return true;
}
Aggregations