diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GrAnnotationUtil.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GrAnnotationUtil.java index 61a82e9d6f43..eb1f818ff0fd 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GrAnnotationUtil.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GrAnnotationUtil.java @@ -34,4 +34,14 @@ public class GrAnnotationUtil { } return null; } + + @Nullable + public static Integer inferIntegerAttribute(@NotNull PsiAnnotation annotation, @NotNull String attributeName) { + final PsiAnnotationMemberValue targetValue = annotation.findAttributeValue(attributeName); + if (targetValue instanceof PsiLiteral) { + final Object value = ((PsiLiteral)targetValue).getValue(); + if (value instanceof Integer) return (Integer)value; + } + return null; + } } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/blocks/GrDelegatesToUtil.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/blocks/GrDelegatesToUtil.java index 1268813ca790..89597e1d2f04 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/blocks/GrDelegatesToUtil.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/blocks/GrDelegatesToUtil.java @@ -56,7 +56,7 @@ public class GrDelegatesToUtil { if (signature == null) return null; final GrClosureSignatureUtil.ArgInfo[] map = GrClosureSignatureUtil.mapParametersToArguments( - signature, call.getNamedArguments(), call.getExpressionArguments(), call.getClosureArguments(), place, false, true + signature, call.getNamedArguments(), call.getExpressionArguments(), call.getClosureArguments(), place, false, false ); if (map == null) { @@ -112,7 +112,18 @@ public class GrDelegatesToUtil { final int parameter = findTargetParameter(delegatesTo, target); if (parameter >= 0) { - return map[parameter].type; + final PsiType type = map[parameter].type; + final Integer index = GrAnnotationUtil.inferIntegerAttribute(delegatesTo, "genericTypeIndex"); + if (index == null) { + return type; + } + if (type instanceof PsiClassType) { + final PsiType[] parameters = ((PsiClassType)type).getParameters(); + if (parameters.length > index) { + return parameters[index]; + } + } + return null; } } else if (value instanceof PsiExpression) { diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/ResolveWithDelegatesToTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/ResolveWithDelegatesToTest.groovy index e30592ea8dd0..37b73b4c7bf0 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/ResolveWithDelegatesToTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/ResolveWithDelegatesToTest.groovy @@ -631,6 +631,15 @@ foo(4) { ''', 'Integer') } + void testGenericTypeIndex() { + assertScript('''\ +def foo(@DelegatesTo.Target def map, @DelegatesTo(genericTypeIndex = 1) Closure c) {} + +foo([1:'ab', 2:'cde']) { + substring(1) +} +''', 'String') + } void assertScript(String text, String resolvedClass) { myFixture.configureByText('_a.groovy', text)