mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Merge remote-tracking branch 'origin/master'
This commit is contained in:
@@ -371,6 +371,8 @@
|
||||
|
||||
<psi.referenceContributor language="Properties" implementation="org.jetbrains.plugins.groovy.dgm.DGMReferenceContributor"/>
|
||||
|
||||
<psi.referenceContributor language="Groovy" implementation="org.jetbrains.plugins.groovy.lang.resolve.GroovyMethodArgumentReferenceContributor"/>
|
||||
|
||||
<weigher key="completion" implementationClass="org.jetbrains.plugins.groovy.lang.completion.weighers.GrWithWeigher"
|
||||
id="groovyWithWeigher" order="after prefix"/>
|
||||
<weigher key="completion" implementationClass="org.jetbrains.plugins.groovy.lang.completion.weighers.GrKindWeigher"
|
||||
|
||||
+26
-7
@@ -67,6 +67,14 @@ public class GroovyMethodDescriptor {
|
||||
|
||||
@Attribute("names")
|
||||
public String names;
|
||||
|
||||
@Attribute("referenceProvider")
|
||||
public String referenceProvider;
|
||||
|
||||
protected Iterable<String> getNames() {
|
||||
assert !StringUtil.isEmptyOrSpaces(names);
|
||||
return StringUtil.tokenize(names, ATTR_NAMES_DELIMITER);
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@@ -92,6 +100,23 @@ public class GroovyMethodDescriptor {
|
||||
}
|
||||
}
|
||||
|
||||
public Map<String, String> getNamedArgumentsReferenceProviders() {
|
||||
if (myArguments == null) return Collections.emptyMap();
|
||||
|
||||
Map<String, String> res = new HashMap<String, String>();
|
||||
|
||||
for (NamedArguments 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) {
|
||||
@@ -108,13 +133,7 @@ public class GroovyMethodDescriptor {
|
||||
for (NamedArguments arguments : myArguments) {
|
||||
NamedArgumentDescriptor descriptor = getDescriptor(isNamedArgsShowFirst, arguments.isFirst, arguments.type);
|
||||
|
||||
assert !StringUtil.isEmptyOrSpaces(arguments.names);
|
||||
|
||||
String names = arguments.names;
|
||||
|
||||
for (StringTokenizer st = new StringTokenizer(names, ATTR_NAMES_DELIMITER); st.hasMoreTokens(); ) {
|
||||
String name = st.nextToken();
|
||||
|
||||
for (String name : arguments.getNames()) {
|
||||
Object oldValue = res.put(name, descriptor);
|
||||
assert oldValue == null;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
package org.jetbrains.plugins.groovy.extensions;
|
||||
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.util.PairFunction;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrMethodCall;
|
||||
@@ -19,7 +21,9 @@ public class GroovyMethodInfo {
|
||||
|
||||
private static volatile Map<String, Map<String, List<GroovyMethodInfo>>> METHOD_INFOS;
|
||||
private static Map<String, Map<String, List<GroovyMethodInfo>>> LIGHT_METHOD_INFOS;
|
||||
|
||||
|
||||
private static final Set<String> myAllSupportedNamedArguments = new HashSet<String>();
|
||||
|
||||
private final List<String> myParams;
|
||||
private final ClassLoader myClassLoader;
|
||||
|
||||
@@ -28,9 +32,11 @@ public class GroovyMethodInfo {
|
||||
private PairFunction<GrMethodCall, PsiMethod, PsiType> myReturnTypeCalculatorInstance;
|
||||
|
||||
private final Map<String, NamedArgumentDescriptor> myNamedArguments;
|
||||
private final String myNamedArgProviderClassName;
|
||||
private final String myNamedArgProviderClassName;
|
||||
private GroovyNamedArgumentProvider myNamedArgProviderInstance;
|
||||
|
||||
private Map<String, String> myNamedArgReferenceProviderClassNames;
|
||||
|
||||
private static void ensureInit() {
|
||||
if (METHOD_INFOS != null) return;
|
||||
|
||||
@@ -92,15 +98,14 @@ public class GroovyMethodInfo {
|
||||
ensureInit();
|
||||
|
||||
List<GroovyMethodInfo> lightMethodInfos = null;
|
||||
if (method instanceof GrLightMethodBuilder) {
|
||||
Object methodKind = ((GrLightMethodBuilder)method).getMethodKind();
|
||||
if (methodKind instanceof String) {
|
||||
lightMethodInfos = getInfos(LIGHT_METHOD_INFOS, (String)methodKind, method);
|
||||
}
|
||||
|
||||
Object methodKind = GrLightMethodBuilder.getMethodKind(method);
|
||||
if (methodKind instanceof String) {
|
||||
lightMethodInfos = getInfos(LIGHT_METHOD_INFOS, (String)methodKind, method);
|
||||
}
|
||||
|
||||
List<GroovyMethodInfo> methodInfos = null;
|
||||
|
||||
|
||||
PsiClass containingClass = method.getContainingClass();
|
||||
if (containingClass != null) {
|
||||
methodInfos = getInfos(METHOD_INFOS, containingClass.getQualifiedName(), method);
|
||||
@@ -114,10 +119,7 @@ public class GroovyMethodInfo {
|
||||
return methodInfos;
|
||||
}
|
||||
else {
|
||||
List<GroovyMethodInfo> res = new ArrayList<GroovyMethodInfo>(lightMethodInfos.size() + methodInfos.size());
|
||||
res.addAll(lightMethodInfos);
|
||||
res.addAll(methodInfos);
|
||||
return res;
|
||||
return ContainerUtil.concat(lightMethodInfos, methodInfos);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -132,6 +134,31 @@ public class GroovyMethodInfo {
|
||||
myNamedArguments = method.getArgumentsMap();
|
||||
myNamedArgProviderClassName = method.namedArgsProvider;
|
||||
assert myNamedArguments == null || myNamedArgProviderClassName == null;
|
||||
|
||||
myNamedArgReferenceProviderClassNames = method.getNamedArgumentsReferenceProviders();
|
||||
|
||||
myAllSupportedNamedArguments.addAll(myNamedArgReferenceProviderClassNames.keySet());
|
||||
|
||||
if (ApplicationManager.getApplication().isInternal()) {
|
||||
// Check classes to avoid typo.
|
||||
|
||||
try {
|
||||
if (myReturnTypeCalculatorClassName != null) {
|
||||
classLoader.loadClass(myReturnTypeCalculatorClassName);
|
||||
}
|
||||
if (myNamedArgProviderClassName != null) {
|
||||
classLoader.loadClass(myNamedArgProviderClassName);
|
||||
}
|
||||
|
||||
for (String className : myNamedArgReferenceProviderClassNames.values()) {
|
||||
Class<?> aClass = classLoader.loadClass(className);
|
||||
assert PsiReferenceProvider.class.isAssignableFrom(aClass) || GroovyNamedArgumentReferenceProvider.class.isAssignableFrom(aClass);
|
||||
}
|
||||
}
|
||||
catch (ClassNotFoundException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void addMethodDescriptor(Map<String, Map<String, List<GroovyMethodInfo>>> res,
|
||||
@@ -187,6 +214,21 @@ public class GroovyMethodInfo {
|
||||
return myReturnTypeCalculatorInstance;
|
||||
}
|
||||
|
||||
public static Set<String> getAllSupportedNamedArguments() {
|
||||
return myAllSupportedNamedArguments;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return instance of PsiReferenceProvider or GroovyNamedArgumentReferenceProvider or null.
|
||||
*/
|
||||
@Nullable
|
||||
public Object getNamedArgReferenceProvider(String namedArgumentName) {
|
||||
String className = myNamedArgReferenceProviderClassNames.get(namedArgumentName);
|
||||
if (className == null) return null;
|
||||
|
||||
return ClassInstanceCache.getInstance(className, myClassLoader);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Map<String, NamedArgumentDescriptor> getNamedArguments() {
|
||||
return myNamedArguments;
|
||||
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
package org.jetbrains.plugins.groovy.extensions;
|
||||
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiReference;
|
||||
import com.intellij.util.ProcessingContext;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.GroovyResolveResult;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrNamedArgument;
|
||||
|
||||
/**
|
||||
* @author Sergey Evdokimov
|
||||
*/
|
||||
public interface GroovyNamedArgumentReferenceProvider {
|
||||
|
||||
PsiReference[] createRef(@NotNull PsiElement element,
|
||||
@NotNull GrNamedArgument namedArgument,
|
||||
@NotNull GroovyResolveResult resolveResult,
|
||||
@NotNull ProcessingContext context);
|
||||
}
|
||||
+17
-6
@@ -17,6 +17,7 @@ package org.jetbrains.plugins.groovy.lang.psi.impl.synthetic;
|
||||
|
||||
import com.intellij.codeInsight.completion.originInfo.OriginInfoAwareElement;
|
||||
import com.intellij.navigation.ItemPresentation;
|
||||
import com.intellij.openapi.util.Key;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.impl.ElementPresentationUtil;
|
||||
import com.intellij.psi.impl.PsiClassImplUtil;
|
||||
@@ -56,6 +57,9 @@ import java.util.Map;
|
||||
* @author Sergey Evdokimov
|
||||
*/
|
||||
public class GrLightMethodBuilder extends LightElement implements GrMethod, OriginInfoAwareElement {
|
||||
|
||||
public static final Key<String> KIND_KEY = Key.create("GrLightMethodBuilder.Key");
|
||||
|
||||
protected String myName;
|
||||
private PsiType myReturnType = PsiType.VOID;
|
||||
private final GrLightModifierList myModifierList;
|
||||
@@ -366,16 +370,23 @@ public class GrLightMethodBuilder extends LightElement implements GrMethod, Ori
|
||||
public void acceptChildren(GroovyElementVisitor visitor) {
|
||||
}
|
||||
|
||||
public static Object getMethodKind(@Nullable PsiElement method) {
|
||||
if (method == null) return null;
|
||||
|
||||
if (method instanceof GrLightMethodBuilder) {
|
||||
return ((GrLightMethodBuilder)method).getMethodKind();
|
||||
}
|
||||
|
||||
return method.getUserData(KIND_KEY);
|
||||
}
|
||||
|
||||
public static boolean checkKind(@Nullable PsiElement method, @NotNull Object kind) {
|
||||
return method instanceof GrLightMethodBuilder && kind.equals(((GrLightMethodBuilder)method).myMethodKind);
|
||||
return kind.equals(getMethodKind(method));
|
||||
}
|
||||
|
||||
public static boolean checkKind(@Nullable PsiElement method, @NotNull Object kind1, @NotNull Object kind2) {
|
||||
if (method instanceof GrLightMethodBuilder) {
|
||||
Object kind = ((GrLightMethodBuilder)method).getMethodKind();
|
||||
return kind1.equals(kind) || kind2.equals(kind);
|
||||
}
|
||||
return false;
|
||||
Object kind = getMethodKind(method);
|
||||
return kind1.equals(kind) || kind2.equals(kind);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+1
-1
@@ -67,7 +67,7 @@ public class GroovyPatterns extends PsiJavaPatterns {
|
||||
return PsiJavaPatterns.psiMethod().with(new PatternCondition<PsiMethod>("GrLightMethodBuilder") {
|
||||
@Override
|
||||
public boolean accepts(@NotNull PsiMethod method, ProcessingContext context) {
|
||||
return method instanceof GrLightMethodBuilder && key.equals(((GrLightMethodBuilder)method).getMethodKind());
|
||||
return GrLightMethodBuilder.checkKind(method, key);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
+159
@@ -0,0 +1,159 @@
|
||||
package org.jetbrains.plugins.groovy.lang.resolve;
|
||||
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.util.ProcessingContext;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.plugins.groovy.extensions.GroovyMethodInfo;
|
||||
import org.jetbrains.plugins.groovy.extensions.GroovyNamedArgumentReferenceProvider;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.GroovyResolveResult;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.GrListOrMap;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrArgumentList;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrNamedArgument;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrConditionalExpression;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrMethodCall;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil;
|
||||
|
||||
import static org.jetbrains.plugins.groovy.lang.psi.patterns.GroovyPatterns.stringLiteral;
|
||||
|
||||
/**
|
||||
* @author Sergey Evdokimov
|
||||
*/
|
||||
public final class GroovyMethodArgumentReferenceContributor extends PsiReferenceContributor {
|
||||
|
||||
@Override
|
||||
public void registerReferenceProviders(PsiReferenceRegistrar registrar) {
|
||||
registrar.registerReferenceProvider(stringLiteral(), new MyProvider());
|
||||
}
|
||||
|
||||
private static class MyProvider extends PsiReferenceProvider {
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiReference[] getReferencesByElement(@NotNull PsiElement element, @NotNull ProcessingContext context) {
|
||||
GrExpression argument = (GrExpression)element;
|
||||
PsiElement parent = element.getParent();
|
||||
|
||||
if (parent instanceof GrConditionalExpression) {
|
||||
// support case: foo(a > b ? "aaa" : "bbb")
|
||||
|
||||
if (((GrConditionalExpression)parent).getCondition() == parent) return PsiReference.EMPTY_ARRAY;
|
||||
argument = (GrConditionalExpression)parent;
|
||||
parent = parent.getParent();
|
||||
}
|
||||
|
||||
if (parent instanceof GrListOrMap) {
|
||||
// support case: foo(["aaa", "bbb"])
|
||||
if (!((GrListOrMap)parent).isMap()) {
|
||||
argument = (GrListOrMap)parent;
|
||||
parent = parent.getParent();
|
||||
}
|
||||
}
|
||||
|
||||
if (parent instanceof GrNamedArgument) {
|
||||
return createReferencesForNamedArgument(element, (GrNamedArgument)parent, context);
|
||||
}
|
||||
|
||||
if (parent instanceof GrArgumentList) {
|
||||
GrArgumentList argumentList = (GrArgumentList)parent;
|
||||
int index = argumentList.getExpressionArgumentIndex(argument);
|
||||
|
||||
PsiElement call = argumentList.getParent();
|
||||
if (!(call instanceof GrMethodCall)) return PsiReference.EMPTY_ARRAY;
|
||||
|
||||
return PsiReference.EMPTY_ARRAY;
|
||||
}
|
||||
|
||||
return PsiReference.EMPTY_ARRAY;
|
||||
}
|
||||
|
||||
private static PsiReference[] createReferencesForNamedArgument(@NotNull PsiElement element,
|
||||
GrNamedArgument namedArgument,
|
||||
@NotNull ProcessingContext context) {
|
||||
String labelName = namedArgument.getLabelName();
|
||||
if (labelName == null) return PsiReference.EMPTY_ARRAY;
|
||||
|
||||
if (!GroovyMethodInfo.getAllSupportedNamedArguments().contains(labelName)) {
|
||||
// Optimization: avoid unnecessary resolve.
|
||||
return PsiReference.EMPTY_ARRAY;
|
||||
}
|
||||
|
||||
PsiElement call = PsiUtil.getCallByNamedParameter(namedArgument);
|
||||
|
||||
if (!(call instanceof GrMethodCall)) return PsiReference.EMPTY_ARRAY;
|
||||
|
||||
GrExpression invokedExpression = ((GrMethodCall)call).getInvokedExpression();
|
||||
if (!(invokedExpression instanceof GrReferenceExpression)) return PsiReference.EMPTY_ARRAY;
|
||||
|
||||
for (GroovyResolveResult result : ((GrReferenceExpression)invokedExpression).multiResolve(false)) {
|
||||
PsiElement eMethod = result.getElement();
|
||||
if (!(eMethod instanceof PsiMethod)) continue;
|
||||
|
||||
PsiMethod method = (PsiMethod)eMethod;
|
||||
|
||||
for (GroovyMethodInfo info : GroovyMethodInfo.getInfos(method)) {
|
||||
Object referenceProvider = info.getNamedArgReferenceProvider(labelName);
|
||||
if (referenceProvider != null) {
|
||||
PsiReference[] refs;
|
||||
|
||||
if (referenceProvider instanceof GroovyNamedArgumentReferenceProvider) {
|
||||
refs = ((GroovyNamedArgumentReferenceProvider)referenceProvider).createRef(element, namedArgument, result, context);
|
||||
}
|
||||
else {
|
||||
refs = ((PsiReferenceProvider)referenceProvider).getReferencesByElement(element, context);
|
||||
}
|
||||
|
||||
if (refs.length > 0) {
|
||||
return refs;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return PsiReference.EMPTY_ARRAY;
|
||||
}
|
||||
|
||||
//@NotNull
|
||||
//private PsiReference[] createReferencesForArgument(@NotNull PsiElement element,
|
||||
// int index,
|
||||
// @NotNull GrMethodCall methodCall) {
|
||||
// GrExpression invokedExpression = methodCall.getInvokedExpression();
|
||||
// if (!(invokedExpression instanceof GrReferenceExpression)) return PsiReference.EMPTY_ARRAY;
|
||||
//
|
||||
// String methodName = ((GrReferenceExpression)invokedExpression).getReferenceName();
|
||||
// if (methodName == null) return PsiReference.EMPTY_ARRAY;
|
||||
//
|
||||
// for (String key : new String[] {methodName, null}) {
|
||||
// for (GroovyResolveResult result : ((GrReferenceExpression)invokedExpression).multiResolve(false)) {
|
||||
// PsiElement eMethod = result.getElement();
|
||||
// if (eMethod instanceof PsiMethod) {
|
||||
// PsiMethod method = (PsiMethod)eMethod;
|
||||
//
|
||||
// //noinspection ConstantConditions
|
||||
// if (key != null && !key.equals(method.getName())) continue;
|
||||
//
|
||||
// for (Pair<Contributor.Provider, Condition<PsiMethod>> pair : list) {
|
||||
// if (pair.second.value(method)) {
|
||||
// PsiReference[] res;
|
||||
// if (attrNameOrParameterIndex instanceof Integer) {
|
||||
// res = pair.first.createRef(element, methodCall, (Integer)attrNameOrParameterIndex, result);
|
||||
// }
|
||||
// else {
|
||||
// assert namedArgument != null;
|
||||
// res = pair.first.createRef(element, namedArgument, result);
|
||||
// }
|
||||
//
|
||||
// if (res.length > 0) {
|
||||
// return res;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// return PsiReference.EMPTY_ARRAY;
|
||||
//}
|
||||
}
|
||||
|
||||
}
|
||||
+9
@@ -35,6 +35,7 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefini
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrAccessorMethod;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrReflectedMethod;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.GrLightMethodBuilder;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.util.StaticChecker;
|
||||
import org.jetbrains.plugins.groovy.lang.resolve.ResolveUtil;
|
||||
import org.jetbrains.plugins.groovy.lang.resolve.processors.ClassHint;
|
||||
@@ -198,6 +199,14 @@ public class DynamicMemberUtils {
|
||||
}
|
||||
dynamicMethod.setOriginalInfo(originalInfo);
|
||||
|
||||
String kind = commentMap.get("kind");
|
||||
if (kind == null) {
|
||||
kind = classCommentMap.get("kind");
|
||||
}
|
||||
if (kind != null) {
|
||||
dynamicMethod.putUserData(GrLightMethodBuilder.KIND_KEY, kind);
|
||||
}
|
||||
|
||||
multiMap.putValue(null, dynamicMethod);
|
||||
multiMap.putValue(method.getName(), dynamicMethod);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user