/* * 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; //} } }