mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-04-30 02:09:59 +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:
@@ -39,13 +39,13 @@ import com.intellij.psi.impl.search.ThrowSearchUtil;
|
||||
import com.intellij.psi.meta.PsiMetaData;
|
||||
import com.intellij.psi.meta.PsiMetaOwner;
|
||||
import com.intellij.psi.search.*;
|
||||
import com.intellij.psi.search.searches.ClassInheritorsSearch;
|
||||
import com.intellij.psi.search.searches.MethodReferencesSearch;
|
||||
import com.intellij.psi.search.searches.OverridingMethodsSearch;
|
||||
import com.intellij.psi.search.searches.ReferencesSearch;
|
||||
import com.intellij.psi.search.searches.*;
|
||||
import com.intellij.psi.targets.AliasingPsiTarget;
|
||||
import com.intellij.psi.targets.AliasingPsiTargetMapper;
|
||||
import com.intellij.psi.util.*;
|
||||
import com.intellij.psi.util.MethodSignature;
|
||||
import com.intellij.psi.util.PropertyUtil;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import com.intellij.psi.util.PsiUtilCore;
|
||||
import com.intellij.psi.xml.XmlAttributeValue;
|
||||
import com.intellij.refactoring.util.JavaNonCodeSearchElementDescriptionProvider;
|
||||
import com.intellij.refactoring.util.NonCodeSearchDescriptionLocation;
|
||||
@@ -347,6 +347,14 @@ public class JavaFindUsagesHandler extends FindUsagesHandler{
|
||||
else if (classOptions.isImplementingClasses){
|
||||
if (!addImplementingClasses(psiClass, processor, classOptions)) return false;
|
||||
}
|
||||
|
||||
FunctionalExpressionSearch.search(psiClass, classOptions.searchScope).forEach(new PsiElementProcessorAdapter<PsiFunctionalExpression>(
|
||||
new PsiElementProcessor<PsiFunctionalExpression>() {
|
||||
@Override
|
||||
public boolean execute(@NotNull PsiFunctionalExpression expression) {
|
||||
return addResult(processor, expression, options);
|
||||
}
|
||||
}));
|
||||
}
|
||||
else if (classOptions.isDerivedClasses) {
|
||||
if (!addInheritors(psiClass, processor, classOptions)) return false;
|
||||
|
||||
@@ -21,6 +21,7 @@ import com.intellij.openapi.util.Comparing;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.javadoc.PsiDocTagValue;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.psi.search.searches.FunctionalExpressionSearch;
|
||||
import com.intellij.psi.search.searches.MethodReferencesSearch;
|
||||
import com.intellij.psi.search.searches.OverridingMethodsSearch;
|
||||
import com.intellij.psi.search.searches.ReferencesSearch;
|
||||
@@ -39,6 +40,7 @@ import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.containers.HashSet;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
@@ -71,6 +73,15 @@ class JavaChangeSignatureUsageSearcher {
|
||||
PsiMethod[] overridingMethods = findSimpleUsagesWithoutParameters(method, result, true, true, true);
|
||||
findUsagesInCallers(result);
|
||||
|
||||
final ArrayList<PsiMethod> methods = new ArrayList<>(Arrays.asList(overridingMethods));
|
||||
methods.add(method);
|
||||
|
||||
for (PsiMethod psiMethod : methods) {
|
||||
for (PsiFunctionalExpression functionalExpression : FunctionalExpressionSearch.search(psiMethod.getContainingClass())) {
|
||||
result.add(new FunctionalInterfaceChangedUsageInfo(functionalExpression, psiMethod));
|
||||
}
|
||||
}
|
||||
|
||||
//Parameter name changes are not propagated
|
||||
findParametersUsage(method, result, overridingMethods);
|
||||
}
|
||||
@@ -318,4 +329,16 @@ class JavaChangeSignatureUsageSearcher {
|
||||
RefactoringUIUtil.getDescription(myMethod, true));
|
||||
}
|
||||
}
|
||||
|
||||
private static class FunctionalInterfaceChangedUsageInfo extends UnresolvableCollisionUsageInfo {
|
||||
|
||||
public FunctionalInterfaceChangedUsageInfo(PsiElement element, PsiElement referencedElement) {
|
||||
super(element, referencedElement);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return "Functional expression will be corrupted";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -232,7 +232,7 @@ public class InlineMethodProcessor extends BaseRefactoringProcessor {
|
||||
GenericInlineHandler.collectConflicts(ref, myMethod, myInliners, conflicts);
|
||||
}
|
||||
|
||||
final PsiReturnStatement[] returnStatements = RefactoringUtil.findReturnStatements(myMethod);
|
||||
final PsiReturnStatement[] returnStatements = PsiUtil.findReturnStatements(myMethod);
|
||||
for (PsiReturnStatement statement : returnStatements) {
|
||||
PsiExpression value = statement.getReturnValue();
|
||||
if (value != null && !(value instanceof PsiCallExpression)) {
|
||||
@@ -819,7 +819,7 @@ public class InlineMethodProcessor extends BaseRefactoringProcessor {
|
||||
}
|
||||
|
||||
if (resultName != null || tailCallType == InlineUtil.TailCallType.Simple) {
|
||||
PsiReturnStatement[] returnStatements = RefactoringUtil.findReturnStatements(myMethodCopy);
|
||||
PsiReturnStatement[] returnStatements = PsiUtil.findReturnStatements(myMethodCopy);
|
||||
for (PsiReturnStatement returnStatement : returnStatements) {
|
||||
final PsiExpression returnValue = returnStatement.getReturnValue();
|
||||
if (returnValue == null) continue;
|
||||
@@ -1464,7 +1464,7 @@ public class InlineMethodProcessor extends BaseRefactoringProcessor {
|
||||
}
|
||||
|
||||
public static boolean checkBadReturns(PsiMethod method) {
|
||||
PsiReturnStatement[] returns = RefactoringUtil.findReturnStatements(method);
|
||||
PsiReturnStatement[] returns = PsiUtil.findReturnStatements(method);
|
||||
if (returns.length == 0) return false;
|
||||
PsiCodeBlock body = method.getBody();
|
||||
ControlFlow controlFlow;
|
||||
|
||||
@@ -557,7 +557,7 @@ public abstract class TurnRefsToSuperProcessorBase extends BaseRefactoringProces
|
||||
addLink(parent, returnType);
|
||||
}
|
||||
|
||||
final PsiReturnStatement[] returnStatements = RefactoringUtil.findReturnStatements(method);
|
||||
final PsiReturnStatement[] returnStatements = PsiUtil.findReturnStatements(method);
|
||||
for (final PsiReturnStatement returnStatement : returnStatements) {
|
||||
final PsiExpression returnValue = returnStatement.getReturnValue();
|
||||
if (returnValue != null) {
|
||||
|
||||
@@ -252,27 +252,6 @@ public class RefactoringUtil {
|
||||
}
|
||||
}
|
||||
|
||||
public static PsiReturnStatement[] findReturnStatements(PsiMethod method) {
|
||||
ArrayList<PsiReturnStatement> vector = new ArrayList<PsiReturnStatement>();
|
||||
PsiCodeBlock body = method.getBody();
|
||||
if (body != null) {
|
||||
addReturnStatements(vector, body);
|
||||
}
|
||||
return vector.toArray(new PsiReturnStatement[vector.size()]);
|
||||
}
|
||||
|
||||
private static void addReturnStatements(ArrayList<PsiReturnStatement> vector, PsiElement element) {
|
||||
if (element instanceof PsiReturnStatement) {
|
||||
vector.add((PsiReturnStatement)element);
|
||||
}
|
||||
else if (!(element instanceof PsiClass)) {
|
||||
PsiElement[] children = element.getChildren();
|
||||
for (PsiElement child : children) {
|
||||
addReturnStatements(vector, child);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static PsiElement getParentStatement(PsiElement place, boolean skipScopingStatements) {
|
||||
PsiElement parent = place;
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* 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.search.searches;
|
||||
|
||||
import com.intellij.openapi.extensions.ExtensionPointName;
|
||||
import com.intellij.psi.PsiClass;
|
||||
import com.intellij.psi.PsiFunctionalExpression;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.psi.search.PsiSearchHelper;
|
||||
import com.intellij.psi.search.SearchScope;
|
||||
import com.intellij.util.Query;
|
||||
import com.intellij.util.QueryExecutor;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class FunctionalExpressionSearch extends ExtensibleQueryFactory<PsiFunctionalExpression, FunctionalExpressionSearch.SearchParameters> {
|
||||
public static ExtensionPointName<QueryExecutor> EP_NAME = ExtensionPointName.create("com.intellij.functionalInterfaceSearch");
|
||||
public static final FunctionalExpressionSearch INSTANCE = new FunctionalExpressionSearch();
|
||||
|
||||
public static class SearchParameters {
|
||||
private final PsiClass myElementToSearch;
|
||||
private final SearchScope myScope;
|
||||
|
||||
public SearchParameters(PsiClass aClass, SearchScope scope) {
|
||||
myElementToSearch = aClass;
|
||||
myScope = scope;
|
||||
}
|
||||
|
||||
public PsiClass getElementToSearch() {
|
||||
return myElementToSearch;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public SearchScope getEffectiveSearchScope () {
|
||||
SearchScope accessScope = PsiSearchHelper.SERVICE.getInstance(myElementToSearch.getProject()).getUseScope(myElementToSearch);
|
||||
return myScope.intersectWith(accessScope);
|
||||
}
|
||||
}
|
||||
|
||||
public static Query<PsiFunctionalExpression> search(final PsiClass aClass, SearchScope scope) {
|
||||
return INSTANCE.createUniqueResultsQuery(new SearchParameters(aClass, scope));
|
||||
}
|
||||
|
||||
public static Query<PsiFunctionalExpression> search(final PsiClass aClass) {
|
||||
return search(aClass, GlobalSearchScope.allScope(aClass.getProject()));
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -21,6 +21,7 @@ import com.intellij.openapi.util.Computable;
|
||||
import com.intellij.pom.java.LanguageLevel;
|
||||
import com.intellij.psi.infos.MethodCandidateInfo;
|
||||
import com.intellij.psi.util.*;
|
||||
import org.jetbrains.annotations.Contract;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -72,12 +73,14 @@ public class LambdaUtil {
|
||||
|
||||
@Nullable
|
||||
public static PsiMethod getFunctionalInterfaceMethod(PsiClassType.ClassResolveResult result) {
|
||||
final PsiClass psiClass = result.getElement();
|
||||
if (psiClass != null) {
|
||||
final MethodSignature methodSignature = getFunction(psiClass);
|
||||
if (methodSignature != null) {
|
||||
return getMethod(psiClass, methodSignature);
|
||||
}
|
||||
return getFunctionalInterfaceMethod(result.getElement());
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static PsiMethod getFunctionalInterfaceMethod(PsiClass aClass) {
|
||||
final MethodSignature methodSignature = getFunction(aClass);
|
||||
if (methodSignature != null) {
|
||||
return getMethod(aClass, methodSignature);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@@ -108,6 +111,11 @@ public class LambdaUtil {
|
||||
}
|
||||
final PsiClassType.ClassResolveResult resolveResult = PsiUtil.resolveGenericsClassInType(GenericsUtil.eliminateWildcards(type));
|
||||
final PsiClass aClass = resolveResult.getElement();
|
||||
return isFunctionalClass(aClass);
|
||||
}
|
||||
|
||||
@Contract("null -> false")
|
||||
public static boolean isFunctionalClass(PsiClass aClass) {
|
||||
if (aClass != null) {
|
||||
if (aClass instanceof PsiTypeParameter) return false;
|
||||
final List<MethodSignature> signatures = findFunctionCandidates(aClass);
|
||||
@@ -115,7 +123,7 @@ public class LambdaUtil {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
public static boolean isValidLambdaContext(@Nullable PsiElement context) {
|
||||
return context instanceof PsiTypeCastExpression ||
|
||||
context instanceof PsiAssignmentExpression ||
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public interface PsiFunctionalExpression extends PsiExpression {
|
||||
/**
|
||||
* @return SAM type the lambda expression corresponds to
|
||||
* null when no SAM type could be found
|
||||
*/
|
||||
@Nullable
|
||||
PsiType getFunctionalInterfaceType();
|
||||
}
|
||||
@@ -21,7 +21,7 @@ import org.jetbrains.annotations.Nullable;
|
||||
/**
|
||||
* Represents a Java lambda expression.
|
||||
*/
|
||||
public interface PsiLambdaExpression extends PsiExpression {
|
||||
public interface PsiLambdaExpression extends PsiFunctionalExpression {
|
||||
/**
|
||||
* Returns this lambda expression's parameter list.
|
||||
*
|
||||
@@ -39,13 +39,6 @@ public interface PsiLambdaExpression extends PsiExpression {
|
||||
@Nullable
|
||||
PsiElement getBody();
|
||||
|
||||
/**
|
||||
* @return SAM type the lambda expression corresponds to
|
||||
* null when no SAM type could be found
|
||||
*/
|
||||
@Nullable
|
||||
PsiType getFunctionalInterfaceType();
|
||||
|
||||
boolean isVoidCompatible();
|
||||
boolean isValueCompatible();
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ import org.jetbrains.annotations.Nullable;
|
||||
/**
|
||||
* Represents a method or constructor reference.
|
||||
*/
|
||||
public interface PsiMethodReferenceExpression extends PsiReferenceExpression {
|
||||
public interface PsiMethodReferenceExpression extends PsiReferenceExpression, PsiFunctionalExpression {
|
||||
/**
|
||||
* Returns the type element used as the qualifier of the reference.
|
||||
*
|
||||
@@ -28,13 +28,6 @@ public interface PsiMethodReferenceExpression extends PsiReferenceExpression {
|
||||
*/
|
||||
@Nullable
|
||||
PsiTypeElement getQualifierType();
|
||||
|
||||
/**
|
||||
* @return SAM type the method reference expression corresponds to
|
||||
* null when no SAM type could be found
|
||||
*/
|
||||
@Nullable
|
||||
PsiType getFunctionalInterfaceType();
|
||||
|
||||
/**
|
||||
* @return if there is only one possible compile-time declaration with only one possible invocation type,
|
||||
|
||||
@@ -1092,4 +1092,25 @@ public final class PsiUtil extends PsiUtilCore {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static PsiReturnStatement[] findReturnStatements(PsiMethod method) {
|
||||
ArrayList<PsiReturnStatement> vector = new ArrayList<PsiReturnStatement>();
|
||||
PsiCodeBlock body = method.getBody();
|
||||
if (body != null) {
|
||||
addReturnStatements(vector, body);
|
||||
}
|
||||
return vector.toArray(new PsiReturnStatement[vector.size()]);
|
||||
}
|
||||
|
||||
private static void addReturnStatements(ArrayList<PsiReturnStatement> vector, PsiElement element) {
|
||||
if (element instanceof PsiReturnStatement) {
|
||||
vector.add((PsiReturnStatement)element);
|
||||
}
|
||||
else if (!(element instanceof PsiClass)) {
|
||||
PsiElement[] children = element.getChildren();
|
||||
for (PsiElement child : children) {
|
||||
addReturnStatements(vector, child);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -146,5 +146,16 @@ public abstract class JavaMethodElementType extends JavaStubElementType<PsiMetho
|
||||
sink.occurrence(JavaStubIndexKeys.JVM_STATIC_MEMBERS_TYPES, stub.getReturnTypeText(false).getShortTypeText());
|
||||
}
|
||||
}
|
||||
|
||||
for (StubElement stubElement : stub.getChildrenStubs()) {
|
||||
if (stubElement instanceof PsiParameterListStub) {
|
||||
for (StubElement paramStub : ((PsiParameterListStub)stubElement).getChildrenStubs()) {
|
||||
if (paramStub instanceof PsiParameterStub) {
|
||||
sink.occurrence(JavaStubIndexKeys.METHOD_TYPES, ((PsiParameterStub)paramStub).getType(false).getShortTypeText());
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,8 +28,9 @@ public class JavaStubIndexKeys {
|
||||
public static final StubIndexKey<String, PsiMethod> METHODS = StubIndexKey.createIndexKey("java.method.name");
|
||||
public static final StubIndexKey<String, PsiMember> JVM_STATIC_MEMBERS_NAMES = StubIndexKey.createIndexKey("jvm.static.member.name");
|
||||
public static final StubIndexKey<String, PsiMember> JVM_STATIC_MEMBERS_TYPES = StubIndexKey.createIndexKey("jvm.static.member.type");
|
||||
public static final StubIndexKey<String,PsiAnonymousClass> ANONYMOUS_BASEREF = StubIndexKey.createIndexKey("java.anonymous.baseref");
|
||||
public static final StubIndexKey<String,PsiClass> CLASS_SHORT_NAMES = StubIndexKey.createIndexKey("java.class.shortname");
|
||||
public static final StubIndexKey<String, PsiAnonymousClass> ANONYMOUS_BASEREF = StubIndexKey.createIndexKey("java.anonymous.baseref");
|
||||
public static final StubIndexKey<String, PsiMethod> METHOD_TYPES = StubIndexKey.createIndexKey("java.method.parameter.types");
|
||||
public static final StubIndexKey<String, PsiClass> CLASS_SHORT_NAMES = StubIndexKey.createIndexKey("java.class.shortname");
|
||||
public static final StubIndexKey<Integer,PsiClass> CLASS_FQN = StubIndexKey.createIndexKey("java.class.fqn");
|
||||
|
||||
private JavaStubIndexKeys() {
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
interface SAM {
|
||||
void <caret>foo();
|
||||
}
|
||||
|
||||
class Test {
|
||||
{
|
||||
bar(() -> {});
|
||||
}
|
||||
|
||||
void bar(SAM sam){}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
interface SAM {
|
||||
void <caret>foo();
|
||||
}
|
||||
|
||||
class Test {
|
||||
{
|
||||
SAM sam = () -> {};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
interface SA<caret>M {
|
||||
void foo();
|
||||
}
|
||||
|
||||
class Test {
|
||||
{
|
||||
bar(() -> {});
|
||||
}
|
||||
|
||||
void bar(SAM sam){}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* 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.codeInsight.daemon.lambda;
|
||||
|
||||
import com.intellij.psi.PsiType;
|
||||
import com.intellij.refactoring.BaseRefactoringProcessor;
|
||||
import com.intellij.refactoring.ChangeSignatureBaseTest;
|
||||
import com.intellij.refactoring.changeSignature.ParameterInfoImpl;
|
||||
import com.intellij.refactoring.changeSignature.ThrownExceptionInfo;
|
||||
|
||||
public class ChangeSignatureTouchLambdaTest extends ChangeSignatureBaseTest {
|
||||
|
||||
public void testVariableDeclaration() {
|
||||
doTestConflict();
|
||||
}
|
||||
|
||||
public void testMethodArgument() throws Exception {
|
||||
doTestConflict();
|
||||
}
|
||||
|
||||
private void doTestConflict() {
|
||||
try {
|
||||
doTest(null, null, null, new ParameterInfoImpl[] {new ParameterInfoImpl(-1, "b", PsiType.BOOLEAN)}, new ThrownExceptionInfo[0], false);
|
||||
fail("Conflict expected");
|
||||
}
|
||||
catch (BaseRefactoringProcessor.ConflictsInTestsException ignored) { }
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getRelativePath() {
|
||||
return "/codeInsight/daemonCodeAnalyzer/lambda/changeSignature/";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* 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.codeInsight.daemon.lambda;
|
||||
|
||||
import com.intellij.JavaTestUtil;
|
||||
import com.intellij.psi.PsiClass;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFunctionalExpression;
|
||||
import com.intellij.psi.search.searches.FunctionalExpressionSearch;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
public class FindFunctionalInterfaceTest extends LightCodeInsightFixtureTestCase {
|
||||
public void testMethodArgument() throws Exception {
|
||||
myFixture.configureByFile(getTestName(false) + ".java");
|
||||
final PsiElement elementAtCaret = myFixture.getElementAtCaret();
|
||||
assertNotNull(elementAtCaret);
|
||||
final PsiClass psiClass = PsiTreeUtil.getParentOfType(elementAtCaret, PsiClass.class, false);
|
||||
assertTrue(psiClass != null && psiClass.isInterface());
|
||||
final Collection<PsiFunctionalExpression> expressions = FunctionalExpressionSearch.search(psiClass).findAll();
|
||||
assertTrue(expressions.size() == 1);
|
||||
final PsiFunctionalExpression next = expressions.iterator().next();
|
||||
assertNotNull(next);
|
||||
assertEquals("() -> {}", next.getText());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getBasePath() {
|
||||
return JavaTestUtil.getRelativeJavaTestDataPath() + "/codeInsight/daemonCodeAnalyzer/lambda/findUsages/";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,172 @@
|
||||
/*
|
||||
* 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.refactoring;
|
||||
|
||||
import com.intellij.JavaTestUtil;
|
||||
import com.intellij.codeInsight.TargetElementUtilBase;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.refactoring.changeSignature.ChangeSignatureProcessor;
|
||||
import com.intellij.refactoring.changeSignature.JavaThrownExceptionInfo;
|
||||
import com.intellij.refactoring.changeSignature.ParameterInfoImpl;
|
||||
import com.intellij.refactoring.changeSignature.ThrownExceptionInfo;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public abstract class ChangeSignatureBaseTest extends LightRefactoringTestCase {
|
||||
protected PsiElementFactory myFactory;
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
protected String getTestDataPath() {
|
||||
return JavaTestUtil.getJavaTestDataPath();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setUp() throws Exception {
|
||||
super.setUp();
|
||||
myFactory = JavaPsiFacade.getInstance(getProject()).getElementFactory();
|
||||
}
|
||||
|
||||
protected void doTest(@Nullable String returnType,
|
||||
@Nullable final String[] parameters,
|
||||
@Nullable final String[] exceptions,
|
||||
boolean delegate) {
|
||||
GenParams genParams = parameters == null ? new SimpleParameterGen() : new GenParams() {
|
||||
@Override
|
||||
public ParameterInfoImpl[] genParams(PsiMethod method) throws IncorrectOperationException {
|
||||
ParameterInfoImpl[] parameterInfos = new ParameterInfoImpl[parameters.length];
|
||||
for (int i = 0; i < parameters.length; i++) {
|
||||
PsiType type = myFactory.createTypeFromText(parameters[i], method);
|
||||
parameterInfos[i] = new ParameterInfoImpl(-1, "p" + (i + 1), type);
|
||||
}
|
||||
return parameterInfos;
|
||||
}
|
||||
};
|
||||
|
||||
GenExceptions genExceptions = exceptions == null ? new SimpleExceptionsGen() : new GenExceptions() {
|
||||
@Override
|
||||
public ThrownExceptionInfo[] genExceptions(PsiMethod method) throws IncorrectOperationException {
|
||||
ThrownExceptionInfo[] exceptionInfos = new ThrownExceptionInfo[exceptions.length];
|
||||
for (int i = 0; i < exceptions.length; i++) {
|
||||
PsiType type = myFactory.createTypeFromText(exceptions[i], method);
|
||||
exceptionInfos[i] = new JavaThrownExceptionInfo(-1, (PsiClassType)type);
|
||||
}
|
||||
return exceptionInfos;
|
||||
}
|
||||
};
|
||||
|
||||
doTest(null, null, returnType, genParams, genExceptions, delegate);
|
||||
}
|
||||
|
||||
protected void doTest(@Nullable String newReturnType, ParameterInfoImpl[] parameterInfos, boolean generateDelegate) {
|
||||
doTest(null, null, newReturnType, parameterInfos, new ThrownExceptionInfo[0], generateDelegate);
|
||||
}
|
||||
|
||||
protected void doTest(@PsiModifier.ModifierConstant @Nullable String newVisibility,
|
||||
@Nullable String newName,
|
||||
@Nullable String newReturnType,
|
||||
ParameterInfoImpl[] parameterInfo,
|
||||
ThrownExceptionInfo[] exceptionInfo,
|
||||
boolean generateDelegate) {
|
||||
SimpleParameterGen params = new SimpleParameterGen(parameterInfo);
|
||||
SimpleExceptionsGen exceptions = new SimpleExceptionsGen(exceptionInfo);
|
||||
doTest(newVisibility, newName, newReturnType, params, exceptions, generateDelegate);
|
||||
}
|
||||
|
||||
protected void doTest(@PsiModifier.ModifierConstant @Nullable String newVisibility,
|
||||
@Nullable String newName,
|
||||
@Nullable @NonNls String newReturnType,
|
||||
GenParams genParams,
|
||||
boolean generateDelegate) {
|
||||
doTest(newVisibility, newName, newReturnType, genParams, new SimpleExceptionsGen(), generateDelegate);
|
||||
}
|
||||
|
||||
protected void doTest(@PsiModifier.ModifierConstant @Nullable String newVisibility,
|
||||
@Nullable String newName,
|
||||
@Nullable String newReturnType,
|
||||
GenParams genParams,
|
||||
GenExceptions genExceptions,
|
||||
boolean generateDelegate) {
|
||||
String basePath = getRelativePath() + getTestName(false);
|
||||
configureByFile(basePath + ".java");
|
||||
PsiElement targetElement = TargetElementUtilBase.findTargetElement(getEditor(), TargetElementUtilBase.ELEMENT_NAME_ACCEPTED);
|
||||
assertTrue("<caret> is not on method name", targetElement instanceof PsiMethod);
|
||||
PsiMethod method = (PsiMethod)targetElement;
|
||||
PsiType newType = newReturnType != null ? myFactory.createTypeFromText(newReturnType, method) : method.getReturnType();
|
||||
new ChangeSignatureProcessor(getProject(), method, generateDelegate, newVisibility,
|
||||
newName != null ? newName : method.getName(),
|
||||
newType, genParams.genParams(method), genExceptions.genExceptions(method)).run();
|
||||
checkResultByFile(basePath + "_after.java");
|
||||
}
|
||||
|
||||
protected String getRelativePath() {
|
||||
return "/refactoring/changeSignature/";
|
||||
}
|
||||
|
||||
protected interface GenParams {
|
||||
ParameterInfoImpl[] genParams(PsiMethod method) throws IncorrectOperationException;
|
||||
}
|
||||
|
||||
protected interface GenExceptions {
|
||||
ThrownExceptionInfo[] genExceptions(PsiMethod method) throws IncorrectOperationException;
|
||||
}
|
||||
|
||||
protected static class SimpleParameterGen implements GenParams {
|
||||
private ParameterInfoImpl[] myInfos;
|
||||
|
||||
public SimpleParameterGen() { }
|
||||
|
||||
public SimpleParameterGen(ParameterInfoImpl[] infos) {
|
||||
myInfos = infos;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ParameterInfoImpl[] genParams(PsiMethod method) {
|
||||
if (myInfos == null) {
|
||||
myInfos = new ParameterInfoImpl[method.getParameterList().getParametersCount()];
|
||||
for (int i = 0; i < myInfos.length; i++) {
|
||||
myInfos[i] = new ParameterInfoImpl(i);
|
||||
}
|
||||
}
|
||||
for (ParameterInfoImpl info : myInfos) {
|
||||
info.updateFromMethod(method);
|
||||
}
|
||||
return myInfos;
|
||||
}
|
||||
}
|
||||
|
||||
protected static class SimpleExceptionsGen implements GenExceptions {
|
||||
private final ThrownExceptionInfo[] myInfos;
|
||||
|
||||
public SimpleExceptionsGen() {
|
||||
myInfos = new ThrownExceptionInfo[0];
|
||||
}
|
||||
|
||||
public SimpleExceptionsGen(ThrownExceptionInfo[] infos) {
|
||||
myInfos = infos;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ThrownExceptionInfo[] genExceptions(PsiMethod method) {
|
||||
for (ThrownExceptionInfo info : myInfos) {
|
||||
info.updateFromMethod(method);
|
||||
}
|
||||
return myInfos;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -15,7 +15,6 @@
|
||||
*/
|
||||
package com.intellij.refactoring;
|
||||
|
||||
import com.intellij.JavaTestUtil;
|
||||
import com.intellij.codeInsight.TargetElementUtilBase;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.refactoring.changeSignature.ChangeSignatureProcessor;
|
||||
@@ -24,29 +23,13 @@ import com.intellij.refactoring.changeSignature.ParameterInfoImpl;
|
||||
import com.intellij.refactoring.changeSignature.ThrownExceptionInfo;
|
||||
import com.intellij.refactoring.util.CanonicalTypes;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.HashSet;
|
||||
|
||||
/**
|
||||
* @author dsl
|
||||
*/
|
||||
public class ChangeSignatureTest extends LightRefactoringTestCase {
|
||||
private PsiElementFactory myFactory;
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
protected String getTestDataPath() {
|
||||
return JavaTestUtil.getJavaTestDataPath();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setUp() throws Exception {
|
||||
super.setUp();
|
||||
myFactory = JavaPsiFacade.getInstance(getProject()).getElementFactory();
|
||||
}
|
||||
public class ChangeSignatureTest extends ChangeSignatureBaseTest {
|
||||
|
||||
public void testSimple() {
|
||||
doTest(null, null, null, new ParameterInfoImpl[0], new ThrownExceptionInfo[0], false);
|
||||
@@ -399,7 +382,7 @@ public class ChangeSignatureTest extends LightRefactoringTestCase {
|
||||
}
|
||||
|
||||
public void testPropagateParameter() {
|
||||
String basePath = "/refactoring/changeSignature/" + getTestName(false);
|
||||
String basePath = getRelativePath() + getTestName(false);
|
||||
configureByFile(basePath + ".java");
|
||||
final PsiElement targetElement = TargetElementUtilBase.findTargetElement(getEditor(), TargetElementUtilBase.ELEMENT_NAME_ACCEPTED);
|
||||
assertTrue("<caret> is not on method name", targetElement instanceof PsiMethod);
|
||||
@@ -430,125 +413,4 @@ public class ChangeSignatureTest extends LightRefactoringTestCase {
|
||||
}
|
||||
|
||||
/* workers */
|
||||
|
||||
private void doTest(@Nullable String returnType, @Nullable final String[] parameters, @Nullable final String[] exceptions, boolean delegate) {
|
||||
GenParams genParams = parameters == null ? new SimpleParameterGen() : new GenParams() {
|
||||
@Override
|
||||
public ParameterInfoImpl[] genParams(PsiMethod method) throws IncorrectOperationException {
|
||||
ParameterInfoImpl[] parameterInfos = new ParameterInfoImpl[parameters.length];
|
||||
for (int i = 0; i < parameters.length; i++) {
|
||||
PsiType type = myFactory.createTypeFromText(parameters[i], method);
|
||||
parameterInfos[i] = new ParameterInfoImpl(-1, "p" + (i + 1), type);
|
||||
}
|
||||
return parameterInfos;
|
||||
}
|
||||
};
|
||||
|
||||
GenExceptions genExceptions = exceptions == null ? new SimpleExceptionsGen() : new GenExceptions() {
|
||||
@Override
|
||||
public ThrownExceptionInfo[] genExceptions(PsiMethod method) throws IncorrectOperationException {
|
||||
ThrownExceptionInfo[] exceptionInfos = new ThrownExceptionInfo[exceptions.length];
|
||||
for (int i = 0; i < exceptions.length; i++) {
|
||||
PsiType type = myFactory.createTypeFromText(exceptions[i], method);
|
||||
exceptionInfos[i] = new JavaThrownExceptionInfo(-1, (PsiClassType)type);
|
||||
}
|
||||
return exceptionInfos;
|
||||
}
|
||||
};
|
||||
|
||||
doTest(null, null, returnType, genParams, genExceptions, delegate);
|
||||
}
|
||||
|
||||
private void doTest(@Nullable String newReturnType, ParameterInfoImpl[] parameterInfos, boolean generateDelegate) {
|
||||
doTest(null, null, newReturnType, parameterInfos, new ThrownExceptionInfo[0], generateDelegate);
|
||||
}
|
||||
|
||||
private void doTest(@PsiModifier.ModifierConstant @Nullable String newVisibility,
|
||||
@Nullable String newName,
|
||||
@Nullable String newReturnType,
|
||||
ParameterInfoImpl[] parameterInfo,
|
||||
ThrownExceptionInfo[] exceptionInfo,
|
||||
boolean generateDelegate) {
|
||||
SimpleParameterGen params = new SimpleParameterGen(parameterInfo);
|
||||
SimpleExceptionsGen exceptions = new SimpleExceptionsGen(exceptionInfo);
|
||||
doTest(newVisibility, newName, newReturnType, params, exceptions, generateDelegate);
|
||||
}
|
||||
|
||||
private void doTest(@PsiModifier.ModifierConstant @Nullable String newVisibility,
|
||||
@Nullable String newName,
|
||||
@Nullable @NonNls String newReturnType,
|
||||
GenParams genParams,
|
||||
boolean generateDelegate) {
|
||||
doTest(newVisibility, newName, newReturnType, genParams, new SimpleExceptionsGen(), generateDelegate);
|
||||
}
|
||||
|
||||
private void doTest(@PsiModifier.ModifierConstant @Nullable String newVisibility,
|
||||
@Nullable String newName,
|
||||
@Nullable String newReturnType,
|
||||
GenParams genParams,
|
||||
GenExceptions genExceptions,
|
||||
boolean generateDelegate) {
|
||||
String basePath = "/refactoring/changeSignature/" + getTestName(false);
|
||||
configureByFile(basePath + ".java");
|
||||
PsiElement targetElement = TargetElementUtilBase.findTargetElement(getEditor(), TargetElementUtilBase.ELEMENT_NAME_ACCEPTED);
|
||||
assertTrue("<caret> is not on method name", targetElement instanceof PsiMethod);
|
||||
PsiMethod method = (PsiMethod)targetElement;
|
||||
PsiType newType = newReturnType != null ? myFactory.createTypeFromText(newReturnType, method) : method.getReturnType();
|
||||
new ChangeSignatureProcessor(getProject(), method, generateDelegate, newVisibility,
|
||||
newName != null ? newName : method.getName(),
|
||||
newType, genParams.genParams(method), genExceptions.genExceptions(method)).run();
|
||||
checkResultByFile(basePath + "_after.java");
|
||||
}
|
||||
|
||||
private interface GenParams {
|
||||
ParameterInfoImpl[] genParams(PsiMethod method) throws IncorrectOperationException;
|
||||
}
|
||||
|
||||
private static class SimpleParameterGen implements GenParams {
|
||||
private ParameterInfoImpl[] myInfos;
|
||||
|
||||
public SimpleParameterGen() { }
|
||||
|
||||
public SimpleParameterGen(ParameterInfoImpl[] infos) {
|
||||
myInfos = infos;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ParameterInfoImpl[] genParams(PsiMethod method) {
|
||||
if (myInfos == null) {
|
||||
myInfos = new ParameterInfoImpl[method.getParameterList().getParametersCount()];
|
||||
for (int i = 0; i < myInfos.length; i++) {
|
||||
myInfos[i] = new ParameterInfoImpl(i);
|
||||
}
|
||||
}
|
||||
for (ParameterInfoImpl info : myInfos) {
|
||||
info.updateFromMethod(method);
|
||||
}
|
||||
return myInfos;
|
||||
}
|
||||
}
|
||||
|
||||
private interface GenExceptions {
|
||||
ThrownExceptionInfo[] genExceptions(PsiMethod method) throws IncorrectOperationException;
|
||||
}
|
||||
|
||||
private static class SimpleExceptionsGen implements GenExceptions {
|
||||
private final ThrownExceptionInfo[] myInfos;
|
||||
|
||||
public SimpleExceptionsGen() {
|
||||
myInfos = new ThrownExceptionInfo[0];
|
||||
}
|
||||
|
||||
public SimpleExceptionsGen(ThrownExceptionInfo[] infos) {
|
||||
myInfos = infos;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ThrownExceptionInfo[] genExceptions(PsiMethod method) {
|
||||
for (ThrownExceptionInfo info : myInfos) {
|
||||
info.updateFromMethod(method);
|
||||
}
|
||||
return myInfos;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -107,6 +107,7 @@
|
||||
<extensionPoint name="overridingMethodsSearch" interface="com.intellij.util.QueryExecutor"/>
|
||||
<extensionPoint name="superMethodsSearch" interface="com.intellij.util.QueryExecutor"/>
|
||||
<extensionPoint name="allClassesSearch" interface="com.intellij.util.QueryExecutor"/>
|
||||
<extensionPoint name="functionalExpressionSearch" interface="com.intellij.util.QueryExecutor"/>
|
||||
|
||||
<extensionPoint name="compiler.inspectionValidator"
|
||||
interface="com.intellij.openapi.compiler.util.InspectionValidator"
|
||||
@@ -277,6 +278,8 @@
|
||||
|
||||
<definitionsScopedSearch implementation="com.intellij.codeInsight.navigation.MethodImplementationsSearch"/>
|
||||
<definitionsScopedSearch implementation="com.intellij.codeInsight.navigation.ClassImplementationsSearch"/>
|
||||
|
||||
<functionalExpressionSearch implementation="com.intellij.psi.impl.search.JavaFunctionalExpressionSearcher"/>
|
||||
|
||||
<fileTypeFactory implementation="com.intellij.openapi.fileTypes.impl.JavaFileTypeFactory"/>
|
||||
|
||||
@@ -1318,6 +1321,7 @@
|
||||
<stubIndex implementation="com.intellij.psi.impl.java.stubs.index.JavaStaticMemberTypeIndex"/>
|
||||
<stubIndex implementation="com.intellij.psi.impl.java.stubs.index.JavaShortClassNameIndex"/>
|
||||
<stubIndex implementation="com.intellij.psi.impl.java.stubs.index.JavaSuperClassNameOccurenceIndex"/>
|
||||
<stubIndex implementation="com.intellij.psi.impl.java.stubs.index.JavaMethodParameterTypesIndex"/>
|
||||
|
||||
<stubElementTypeHolder class="com.intellij.psi.impl.java.stubs.JavaStubElementTypes"/>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user