diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/extensions/GroovyMethodDescriptor.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/extensions/GroovyMethodDescriptor.java index 3b61d06b9452..2f0312e0f538 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/extensions/GroovyMethodDescriptor.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/extensions/GroovyMethodDescriptor.java @@ -1,11 +1,14 @@ package org.jetbrains.plugins.groovy.extensions; import com.intellij.openapi.util.text.StringUtil; +import com.intellij.psi.PsiMethod; import com.intellij.util.xmlb.annotations.AbstractCollection; import com.intellij.util.xmlb.annotations.Attribute; import com.intellij.util.xmlb.annotations.Property; import com.intellij.util.xmlb.annotations.Tag; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrCall; import java.util.*; @@ -41,6 +44,9 @@ public class GroovyMethodDescriptor { @Attribute("namedArgs") public String namedArgs; + @Attribute("namedArgsProvider") + public String namedArgsProvider; + @Attribute("namedArgsShowFirst") public Boolean isNamedArgsShowFirst; @@ -91,6 +97,8 @@ public class GroovyMethodDescriptor { return null; } + assert namedArgsProvider == null; + Map res = new HashMap(); @@ -148,4 +156,7 @@ public class GroovyMethodDescriptor { return descriptor; } + public interface NamedArgumentProvider { + void collectNamedArguments(Map res, @NotNull GrCall callExpression, @NotNull PsiMethod method); + } } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/extensions/GroovyMethodInfo.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/extensions/GroovyMethodInfo.java index 18f34b456fee..8804dbad26e6 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/extensions/GroovyMethodInfo.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/extensions/GroovyMethodInfo.java @@ -6,6 +6,7 @@ import com.intellij.psi.PsiParameter; import com.intellij.psi.PsiParameterList; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrCall; import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil; import java.util.*; @@ -23,6 +24,9 @@ public class GroovyMethodInfo { private Map myNamedArguments; + private GroovyMethodDescriptor.NamedArgumentProvider myNamedArgProviderInstance; + private String myNamedArgProviderClassName; + public static Map>> getMethodMap() { Map>> res = MAP; @@ -97,9 +101,14 @@ public class GroovyMethodInfo { Map namedArgumentsMap = method.getArgumentsMap(); if (namedArgumentsMap != null) { - assert info.myNamedArguments == null; + assert !info.isProvideNamedArguments(); info.myNamedArguments = namedArgumentsMap; } + + if (method.namedArgsProvider != null) { + assert !info.isProvideNamedArguments(); + info.myNamedArgProviderClassName = method.namedArgsProvider; + } } @Nullable @@ -107,9 +116,26 @@ public class GroovyMethodInfo { return myReturnType; } - @Nullable - public Map getNamedArguments() { - return myNamedArguments; + public void addNamedArguments(Map res, @NotNull GrCall call, @NotNull PsiMethod method) { + if (myNamedArguments != null) { + res.putAll(myNamedArguments); + } + else if (myNamedArgProviderClassName != null) { + if (myNamedArgProviderInstance == null) { + try { + myNamedArgProviderInstance = (GroovyMethodDescriptor.NamedArgumentProvider)Class.forName(myNamedArgProviderClassName).newInstance(); + } + catch (Exception e) { + throw new RuntimeException(e); + } + } + + myNamedArgProviderInstance.collectNamedArguments(res, call, method); + } + } + + public boolean isProvideNamedArguments() { + return myNamedArguments != null || myNamedArgProviderClassName != null; } public boolean isApplicable(@NotNull PsiMethod method) { diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/extensions/GroovyNamedArgumentProvider.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/extensions/GroovyNamedArgumentProvider.java index ba233474f142..bdff4fc26dee 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/extensions/GroovyNamedArgumentProvider.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/extensions/GroovyNamedArgumentProvider.java @@ -90,7 +90,7 @@ public abstract class GroovyNamedArgumentProvider { if (!method.isConstructor() && !canBeMap(parameters[0])) continue; - collectVariantsFromSimpleDescriptors(namedArguments, method); + collectVariantsFromSimpleDescriptors(namedArguments, call, method); } for (GroovyNamedArgumentProvider namedArgumentProvider : EP_NAME.getExtensions()) { @@ -102,11 +102,10 @@ public abstract class GroovyNamedArgumentProvider { return namedArguments; } - private static void collectVariantsFromSimpleDescriptors(Map res, PsiMethod method) { + private static void collectVariantsFromSimpleDescriptors(Map res, @NotNull GrCall call, @NotNull PsiMethod method) { for (GroovyMethodInfo methodInfo : GroovyMethodInfo.getInfos(method)) { - Map namedArguments = methodInfo.getNamedArguments(); - if (namedArguments != null && methodInfo.isApplicable(method)) { - res.putAll(namedArguments); + if (methodInfo.isProvideNamedArguments() && methodInfo.isApplicable(method)) { + methodInfo.addNamedArguments(res, call, method); break; } } @@ -253,7 +252,7 @@ public abstract class GroovyNamedArgumentProvider { } } - protected static class TypeCondition extends ArgumentDescriptor { + public static class TypeCondition extends ArgumentDescriptor { private final PsiType myType; public TypeCondition(PsiType type, PsiElement navigationElement) {