mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 06:05:01 +07:00
search for functional interface implementations by lambdas and method references: change signature/find usages; to be continued (IDEA-104286; IDEA-90824)
This commit is contained in:
+50
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @author max
|
||||
*/
|
||||
package com.intellij.psi.impl.java.stubs.index;
|
||||
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.PsiMethod;
|
||||
import com.intellij.psi.impl.search.JavaSourceFilterScope;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.psi.stubs.StringStubIndexExtension;
|
||||
import com.intellij.psi.stubs.StubIndex;
|
||||
import com.intellij.psi.stubs.StubIndexKey;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
public class JavaMethodParameterTypesIndex extends StringStubIndexExtension<PsiMethod> {
|
||||
|
||||
private static final JavaMethodParameterTypesIndex ourInstance = new JavaMethodParameterTypesIndex();
|
||||
public static JavaMethodParameterTypesIndex getInstance() {
|
||||
return ourInstance;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public StubIndexKey<String, PsiMethod> getKey() {
|
||||
return JavaStubIndexKeys.METHOD_TYPES;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<PsiMethod> get(final String s, final Project project, @NotNull final GlobalSearchScope scope) {
|
||||
return StubIndex.getElements(getKey(), s, project, new JavaSourceFilterScope(scope), PsiMethod.class);
|
||||
}
|
||||
}
|
||||
+148
@@ -0,0 +1,148 @@
|
||||
/*
|
||||
* 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 com.intellij.psi.impl.search;
|
||||
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Computable;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.impl.java.stubs.index.JavaMethodParameterTypesIndex;
|
||||
import com.intellij.psi.search.EverythingGlobalScope;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.psi.search.SearchScope;
|
||||
import com.intellij.psi.search.searches.FunctionalExpressionSearch;
|
||||
import com.intellij.psi.search.searches.MethodReferencesSearch;
|
||||
import com.intellij.psi.search.searches.ReferencesSearch;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import com.intellij.util.Processor;
|
||||
import com.intellij.util.QueryExecutor;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
|
||||
public class JavaFunctionalExpressionSearcher implements QueryExecutor<PsiFunctionalExpression, FunctionalExpressionSearch.SearchParameters> {
|
||||
|
||||
@Override
|
||||
public boolean execute(@NotNull FunctionalExpressionSearch.SearchParameters queryParameters,
|
||||
@NotNull Processor<PsiFunctionalExpression> consumer) {
|
||||
final PsiClass aClass = queryParameters.getElementToSearch();
|
||||
if (!ApplicationManager.getApplication().runReadAction(new Computable<Boolean>() {
|
||||
@Override
|
||||
public Boolean compute() {
|
||||
return LambdaUtil.isFunctionalClass(aClass);
|
||||
}
|
||||
}) || !PsiUtil.isLanguageLevel8OrHigher(aClass)) {
|
||||
return true;
|
||||
}
|
||||
final ArrayList<PsiFunctionalExpression> functionalExpressions = new ArrayList<>();
|
||||
collectFunctionalExpressions(aClass, functionalExpressions, queryParameters.getEffectiveSearchScope());
|
||||
for (PsiFunctionalExpression functionalExpression : functionalExpressions) {
|
||||
if (!consumer.process(functionalExpression)) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static void collectFunctionalExpressions(final PsiClass aClass, final Collection<PsiFunctionalExpression> result, final SearchScope searchScope) {
|
||||
final SearchScope classScope = ApplicationManager.getApplication().runReadAction(new Computable<SearchScope>() {
|
||||
@Override
|
||||
public SearchScope compute() {
|
||||
return aClass.getUseScope();
|
||||
}
|
||||
});
|
||||
final SearchScope useScope = searchScope.intersectWith(classScope);
|
||||
final Project project = aClass.getProject();
|
||||
final GlobalSearchScope scope = useScope instanceof GlobalSearchScope ? (GlobalSearchScope)useScope : new EverythingGlobalScope(project);
|
||||
final Collection<PsiMethod> lambdaCandidates = ApplicationManager.getApplication().runReadAction(new Computable<Collection<PsiMethod>>() {
|
||||
@Override
|
||||
public Collection<PsiMethod> compute() {
|
||||
final String functionalInterfaceName = aClass.getName();
|
||||
final GlobalSearchScope useClassScope = classScope instanceof GlobalSearchScope ? (GlobalSearchScope)classScope : scope;
|
||||
return JavaMethodParameterTypesIndex.getInstance().get(functionalInterfaceName, project, useClassScope);
|
||||
}
|
||||
});
|
||||
for (PsiMethod psiMethod : lambdaCandidates) {
|
||||
for (PsiReference ref : MethodReferencesSearch.search(psiMethod, scope, false)) {
|
||||
final PsiElement refElement = ref.getElement();
|
||||
if (refElement != null) {
|
||||
final PsiElement candidateElement = refElement.getParent();
|
||||
if (candidateElement instanceof PsiCallExpression) {
|
||||
final PsiExpressionList argumentList = ((PsiCallExpression)candidateElement).getArgumentList();
|
||||
if (argumentList != null) {
|
||||
ApplicationManager.getApplication().runReadAction(new Runnable() {
|
||||
public void run() {
|
||||
final PsiExpression[] args = argumentList.getExpressions();
|
||||
for (PsiExpression arg : args) {
|
||||
if (arg instanceof PsiFunctionalExpression) {
|
||||
final PsiFunctionalExpression functionalExpression = (PsiFunctionalExpression)arg;
|
||||
final PsiType functionalType = functionalExpression.getFunctionalInterfaceType();
|
||||
if (PsiUtil.resolveClassInType(functionalType) == aClass) {
|
||||
result.add(functionalExpression);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (PsiReference reference : ReferencesSearch.search(aClass, scope)) {
|
||||
final PsiElement element = reference.getElement();
|
||||
if (element != null) {
|
||||
final PsiElement parent = element.getParent();
|
||||
if (parent instanceof PsiTypeElement) {
|
||||
final PsiElement gParent = parent.getParent();
|
||||
if (gParent instanceof PsiVariable) {
|
||||
final PsiExpression initializer = PsiUtil.skipParenthesizedExprDown(((PsiVariable)gParent).getInitializer());
|
||||
if (initializer instanceof PsiFunctionalExpression) {
|
||||
result.add((PsiFunctionalExpression)initializer);
|
||||
}
|
||||
for (PsiReference varRef : ReferencesSearch.search(parent, scope)) {
|
||||
final PsiElement varElement = varRef.getElement();
|
||||
if (varElement != null) {
|
||||
final PsiElement varElementParent = varElement.getParent();
|
||||
if (varElementParent instanceof PsiAssignmentExpression &&
|
||||
((PsiAssignmentExpression)varElementParent).getLExpression() == varElement) {
|
||||
final PsiExpression rExpression = PsiUtil.skipParenthesizedExprDown(((PsiAssignmentExpression)varElementParent).getRExpression());
|
||||
if (rExpression instanceof PsiFunctionalExpression) {
|
||||
result.add((PsiFunctionalExpression)rExpression);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (gParent instanceof PsiMethod) {
|
||||
final PsiReturnStatement[] returnStatements = ApplicationManager.getApplication().runReadAction(
|
||||
new Computable<PsiReturnStatement[]>() {
|
||||
@Override
|
||||
public PsiReturnStatement[] compute() {
|
||||
return PsiUtil.findReturnStatements((PsiMethod)gParent);
|
||||
}
|
||||
});
|
||||
for (PsiReturnStatement returnStatement : returnStatements) {
|
||||
final PsiExpression returnValue = returnStatement.getReturnValue();
|
||||
if (returnValue instanceof PsiFunctionalExpression) {
|
||||
result.add((PsiFunctionalExpression)returnValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user