@Attribute("referenceProvider")
public String referenceProvider;
+ @Attribute("values")
+ public String values;
+
protected Iterable<String> getNames() {
assert !StringUtil.isEmptyOrSpaces(name);
return StringUtil.tokenize(name, ATTR_NAMES_DELIMITER);
}
}
- public Map<String, String> getNamedArgumentsReferenceProviders() {
- if (myArguments == null) return Collections.emptyMap();
-
- Map<String, String> res = new HashMap<String, String>();
-
- for (NamedArgument argument : myArguments) {
- if (argument.referenceProvider != null) {
- for (String name : argument.getNames()) {
- Object oldValue = res.put(name, argument.referenceProvider);
- assert oldValue == null;
- }
- }
- }
-
- return res;
- }
-
@Nullable
public Map<String, NamedArgumentDescriptor> getArgumentsMap() {
if (myArguments == null && namedArgs == null) {
import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.GrLightMethodBuilder;
import org.jetbrains.plugins.groovy.refactoring.GroovyNamesUtil;
import org.jetbrains.plugins.groovy.util.ClassInstanceCache;
+import org.jetbrains.plugins.groovy.util.FixedValuesReferenceProvider;
import java.lang.reflect.Modifier;
import java.util.*;
private final String myNamedArgProviderClassName;
private GroovyNamedArgumentProvider myNamedArgProviderInstance;
- private Map<String, String> myNamedArgReferenceProviderClassNames;
+ private Map<String, NamedArgumentReference> myNamedArgReferenceProviders;
private static void ensureInit() {
if (METHOD_INFOS != null) return;
myNamedArguments = method.getArgumentsMap();
myNamedArgProviderClassName = method.namedArgsProvider;
- myNamedArgReferenceProviderClassNames = method.getNamedArgumentsReferenceProviders();
+ myNamedArgReferenceProviders = getNamedArgumentsReferenceProviders(method);
- myAllSupportedNamedArguments.addAll(myNamedArgReferenceProviderClassNames.keySet());
+ myAllSupportedNamedArguments.addAll(myNamedArgReferenceProviders.keySet());
if (ApplicationManager.getApplication().isInternal()) {
// Check classes to avoid typo.
assertClassExists(myReturnTypeCalculatorClassName, PairFunction.class);
- for (String className : myNamedArgReferenceProviderClassNames.values()) {
- assertClassExists(className, PsiReferenceProvider.class, GroovyNamedArgumentReferenceProvider.class);
+ for (NamedArgumentReference r : myNamedArgReferenceProviders.values()) {
+ assertClassExists(r.myProviderClassName, PsiReferenceProvider.class, GroovyNamedArgumentReferenceProvider.class);
}
}
}
}
}
+ private static Map<String, NamedArgumentReference> getNamedArgumentsReferenceProviders(GroovyMethodDescriptor methodDescriptor) {
+ if (methodDescriptor.myArguments == null) return Collections.emptyMap();
+
+ Map<String, NamedArgumentReference> res = new HashMap<String, NamedArgumentReference>();
+
+ for (GroovyMethodDescriptor.NamedArgument argument : methodDescriptor.myArguments) {
+ NamedArgumentReference r;
+
+ if (argument.referenceProvider != null) {
+ assert argument.values == null;
+ r = new NamedArgumentReference(argument.referenceProvider);
+ }
+ else if (argument.values != null) {
+ List<String> values = new ArrayList<String>();
+ for (StringTokenizer st = new StringTokenizer(argument.values, " ,;"); st.hasMoreTokens(); ) {
+ values.add(st.nextToken());
+ }
+
+ r = new NamedArgumentReference(values.toArray(new String[values.size()]));
+ }
+ else {
+ continue;
+ }
+
+ for (String name : argument.getNames()) {
+ Object oldValue = res.put(name, r);
+ assert oldValue == null;
+ }
+ }
+
+ return res;
+ }
+
private static void addMethodDescriptor(Map<String, Map<String, List<GroovyMethodInfo>>> res,
GroovyMethodDescriptor method,
@NotNull ClassLoader classLoader,
*/
@Nullable
public Object getNamedArgReferenceProvider(String namedArgumentName) {
- String className = myNamedArgReferenceProviderClassNames.get(namedArgumentName);
- if (className == null) return null;
+ NamedArgumentReference r = myNamedArgReferenceProviders.get(namedArgumentName);
+ if (r == null) return null;
- return ClassInstanceCache.getInstance(className, myClassLoader);
+ return r.getProvider(myClassLoader);
}
@Nullable
return true;
}
+
+ private static class NamedArgumentReference {
+ private final String myProviderClassName;
+ private final String[] myValues;
+
+ private volatile Object myProvider;
+
+ public NamedArgumentReference(String providerClassName) {
+ myProviderClassName = providerClassName;
+ myValues = null;
+ }
+
+ public NamedArgumentReference(String[] values) {
+ myValues = values;
+ myProviderClassName = null;
+ }
+
+ private Object doGetProvider(ClassLoader classLoader) {
+ if (myProviderClassName != null) {
+ return ClassInstanceCache.getInstance(myProviderClassName, classLoader);
+ }
+
+ return new FixedValuesReferenceProvider(myValues);
+ }
+
+ // @return instance of PsiReferenceProvider or GroovyNamedArgumentReferenceProvider or null.
+ public Object getProvider(ClassLoader classLoader) {
+ Object res = myProvider;
+ if (res == null) {
+ res = doGetProvider(classLoader);
+ myProvider = res;
+ }
+
+ return res;
+ }
+ }
}
--- /dev/null
+package org.jetbrains.plugins.groovy.util;
+
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiReference;
+import com.intellij.psi.PsiReferenceBase;
+import com.intellij.psi.PsiReferenceProvider;
+import com.intellij.util.ProcessingContext;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * @author Sergey Evdokimov
+ */
+public class FixedValuesReferenceProvider extends PsiReferenceProvider {
+
+ private final String[] myValues;
+
+ private boolean mySoft;
+
+ public FixedValuesReferenceProvider(@NotNull String[] values) {
+ this(values, false);
+ }
+
+ public FixedValuesReferenceProvider(@NotNull String[] values, boolean soft) {
+ myValues = values;
+ mySoft = soft;
+ }
+
+ @NotNull
+ @Override
+ public PsiReference[] getReferencesByElement(@NotNull PsiElement element, @NotNull ProcessingContext context) {
+ return new PsiReference[]{
+ new PsiReferenceBase<PsiElement>(element, mySoft) {
+ @Nullable
+ @Override
+ public PsiElement resolve() {
+ return null;
+ }
+
+ @NotNull
+ @Override
+ public Object[] getVariants() {
+ return myValues;
+ }
+ }
+ };
+ }
+}