blob: 30bc357240b4b114dcd42837760a96f3cd40fd30 [file] [log] [blame]
/*
* Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
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.patterns.GroovyPatterns;
import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil;
/**
* @author Sergey Evdokimov
*/
public final class GroovyMethodArgumentReferenceContributor extends PsiReferenceContributor {
@Override
public void registerReferenceProviders(@NotNull PsiReferenceRegistrar registrar) {
registrar.registerReferenceProvider(GroovyPatterns.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;
//}
}
}