use of org.codehaus.groovy.ast.GenericsType in project groovy-core by groovy.
the class StaticTypeCheckingVisitor method makeThis.
private ClassNode makeThis() {
ClassNode ret = typeCheckingContext.getEnclosingClassNode();
if (typeCheckingContext.isInStaticContext) {
ClassNode staticRet = CLASS_Type.getPlainNodeReference();
GenericsType gt = new GenericsType(ret);
staticRet.setGenericsTypes(new GenericsType[] { gt });
ret = staticRet;
}
return ret;
}
use of org.codehaus.groovy.ast.GenericsType in project groovy-core by groovy.
the class StaticTypeCheckingVisitor method resolvePlaceholdersFromExplicitTypeHints.
private void resolvePlaceholdersFromExplicitTypeHints(final MethodNode method, final GenericsType[] explicitTypeHints, final Map<String, GenericsType> resolvedPlaceholders) {
if (explicitTypeHints != null) {
GenericsType[] methodGenericTypes = method.getGenericsTypes();
if (methodGenericTypes != null && methodGenericTypes.length == explicitTypeHints.length) {
for (int i = 0; i < explicitTypeHints.length; i++) {
GenericsType methodGenericType = methodGenericTypes[i];
GenericsType explicitTypeHint = explicitTypeHints[i];
resolvedPlaceholders.put(methodGenericType.getName(), explicitTypeHint);
}
for (GenericsType typeHint : explicitTypeHints) {
System.err.println("Type hint = " + typeHint);
}
}
}
}
use of org.codehaus.groovy.ast.GenericsType in project groovy-core by groovy.
the class StaticTypeCheckingVisitor method extractPlaceHolders.
private static Map<String, GenericsType> extractPlaceHolders(MethodNode method, ClassNode receiver, ClassNode declaringClass) {
if (declaringClass.equals(OBJECT_TYPE)) {
Map<String, GenericsType> resolvedPlaceholders = new HashMap<String, GenericsType>();
if (method != null)
addMethodLevelDeclaredGenerics(method, resolvedPlaceholders);
return resolvedPlaceholders;
}
Map<String, GenericsType> resolvedPlaceholders = null;
if (isPrimitiveType(receiver) && !isPrimitiveType(declaringClass)) {
receiver = getWrapper(receiver);
}
final List<ClassNode> queue;
if (receiver instanceof UnionTypeClassNode) {
queue = Arrays.asList(((UnionTypeClassNode) receiver).getDelegates());
} else {
queue = Collections.singletonList(receiver);
}
for (ClassNode item : queue) {
ClassNode current = item;
while (current != null) {
boolean continueLoop = true;
//extract the place holders
Map<String, GenericsType> currentPlaceHolders = new HashMap<String, GenericsType>();
if (isGenericsPlaceHolderOrArrayOf(declaringClass) || declaringClass.equals(current)) {
extractGenericsConnections(currentPlaceHolders, current, declaringClass);
if (method != null)
addMethodLevelDeclaredGenerics(method, currentPlaceHolders);
continueLoop = false;
} else {
GenericsUtils.extractPlaceholders(current, currentPlaceHolders);
}
if (resolvedPlaceholders != null) {
// merge maps
Set<Map.Entry<String, GenericsType>> entries = currentPlaceHolders.entrySet();
for (Map.Entry<String, GenericsType> entry : entries) {
GenericsType gt = entry.getValue();
if (!gt.isPlaceholder())
continue;
GenericsType referenced = resolvedPlaceholders.get(gt.getName());
if (referenced == null)
continue;
entry.setValue(referenced);
}
}
resolvedPlaceholders = currentPlaceHolders;
// we are done if we are now in the declaring class
if (!continueLoop)
break;
current = getNextSuperClass(current, declaringClass);
if (current == null && CLASS_Type.equals(declaringClass)) {
// this can happen if the receiver is Class<Foo>, then
// the actual receiver is Foo and declaringClass is Class
current = declaringClass;
}
}
}
if (resolvedPlaceholders == null) {
String descriptor = "<>";
if (method != null)
descriptor = method.getTypeDescriptor();
throw new GroovyBugError("Declaring class for method call to '" + descriptor + "' declared in " + declaringClass.getName() + " was not matched with found receiver " + receiver.getName() + "." + " This should not have happened!");
}
return resolvedPlaceholders;
}
use of org.codehaus.groovy.ast.GenericsType in project groovy-core by groovy.
the class StaticTypeCheckingVisitor method checkClosureWithDelegatesTo.
private void checkClosureWithDelegatesTo(final ClassNode receiver, final MethodNode mn, final ArgumentListExpression arguments, final Parameter[] params, final Expression expression, final Parameter param) {
List<AnnotationNode> annotations = param.getAnnotations(DELEGATES_TO);
if (annotations != null && !annotations.isEmpty()) {
for (AnnotationNode annotation : annotations) {
// in theory, there can only be one annotation of that type
Expression value = annotation.getMember("value");
Expression strategy = annotation.getMember("strategy");
Expression genericTypeIndex = annotation.getMember("genericTypeIndex");
Expression type = annotation.getMember("type");
Integer stInt = Closure.OWNER_FIRST;
if (strategy != null) {
stInt = (Integer) evaluateExpression(new CastExpression(ClassHelper.Integer_TYPE, strategy), typeCheckingContext.source.getConfiguration());
}
if (value instanceof ClassExpression && !value.getType().equals(DELEGATES_TO_TARGET)) {
if (genericTypeIndex != null) {
addStaticTypeError("Cannot use @DelegatesTo(genericTypeIndex=" + genericTypeIndex.getText() + ") without @DelegatesTo.Target because generic argument types are not available at runtime", value);
}
// temporarily store the delegation strategy and the delegate type
expression.putNodeMetaData(StaticTypesMarker.DELEGATION_METADATA, new DelegationMetadata(value.getType(), stInt, typeCheckingContext.delegationMetadata));
} else if (type != null && !"".equals(type.getText()) && type instanceof ConstantExpression) {
String typeString = type.getText();
ClassNode[] resolved = GenericsUtils.parseClassNodesFromString(typeString, getSourceUnit(), typeCheckingContext.compilationUnit, mn, type);
if (resolved != null) {
if (resolved.length == 1) {
resolved = resolveGenericsFromTypeHint(receiver, arguments, mn, resolved);
expression.putNodeMetaData(StaticTypesMarker.DELEGATION_METADATA, new DelegationMetadata(resolved[0], stInt, typeCheckingContext.delegationMetadata));
} else {
addStaticTypeError("Incorrect type hint found in method " + (mn), type);
}
}
} else {
final List<Expression> expressions = arguments.getExpressions();
final int expressionsSize = expressions.size();
Expression parameter = annotation.getMember("target");
String parameterName = parameter != null && parameter instanceof ConstantExpression ? parameter.getText() : "";
// todo: handle vargs!
for (int j = 0, paramsLength = params.length; j < paramsLength; j++) {
final Parameter methodParam = params[j];
List<AnnotationNode> targets = methodParam.getAnnotations(DELEGATES_TO_TARGET);
if (targets != null && targets.size() == 1) {
// @DelegatesTo.Target Obj foo
AnnotationNode targetAnnotation = targets.get(0);
Expression idMember = targetAnnotation.getMember("value");
String id = idMember != null && idMember instanceof ConstantExpression ? idMember.getText() : "";
if (id.equals(parameterName)) {
if (j < expressionsSize) {
Expression actualArgument = expressions.get(j);
ClassNode actualType = getType(actualArgument);
if (genericTypeIndex != null && genericTypeIndex instanceof ConstantExpression) {
int gti = Integer.parseInt(genericTypeIndex.getText());
// type annotated with @DelegatesTo.Target
ClassNode paramType = methodParam.getType();
GenericsType[] genericsTypes = paramType.getGenericsTypes();
if (genericsTypes == null) {
addStaticTypeError("Cannot use @DelegatesTo(genericTypeIndex=" + genericTypeIndex.getText() + ") with a type that doesn't use generics", methodParam);
} else if (gti < 0 || gti >= genericsTypes.length) {
addStaticTypeError("Index of generic type @DelegatesTo(genericTypeIndex=" + genericTypeIndex.getText() + ") " + (gti < 0 ? "lower" : "greater") + " than those of the selected type", methodParam);
} else {
ClassNode pType = GenericsUtils.parameterizeType(actualType, paramType);
GenericsType[] pTypeGenerics = pType.getGenericsTypes();
if (pTypeGenerics != null && pTypeGenerics.length > gti) {
actualType = pTypeGenerics[gti].getType();
} else {
addStaticTypeError("Unable to map actual type [" + actualType.toString(false) + "] onto " + paramType.toString(false), methodParam);
}
}
}
expression.putNodeMetaData(StaticTypesMarker.DELEGATION_METADATA, new DelegationMetadata(actualType, stInt, typeCheckingContext.delegationMetadata));
break;
}
}
}
}
if (expression.getNodeMetaData(StaticTypesMarker.DELEGATION_METADATA) == null) {
addError("Not enough arguments found for a @DelegatesTo method call. Please check that you either use an explicit class or @DelegatesTo.Target with a correct id", arguments);
}
}
}
}
}
use of org.codehaus.groovy.ast.GenericsType in project groovy-core by groovy.
the class StaticTypeCheckingVisitor method toMethodGenericTypesString.
private String toMethodGenericTypesString(MethodNode node) {
GenericsType[] genericsTypes = node.getGenericsTypes();
if (genericsTypes == null)
return "";
StringBuilder sb = new StringBuilder("<");
for (int i = 0; i < genericsTypes.length; i++) {
final GenericsType genericsType = genericsTypes[i];
sb.append(genericsType.toString());
if (i < genericsTypes.length - 1) {
sb.append(",");
}
}
sb.append("> ");
return sb.toString();
}
Aggregations