mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-01-06 11:50:54 +07:00
change signature: propagate params/exceptions to implicit constructors
This commit is contained in:
@@ -26,6 +26,7 @@ import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.DialogWrapper;
|
||||
import com.intellij.openapi.ui.Messages;
|
||||
import com.intellij.openapi.util.Comparing;
|
||||
import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.codeStyle.CodeStyleManager;
|
||||
@@ -182,11 +183,16 @@ public class ChangeSignatureProcessor extends BaseRefactoringProcessor {
|
||||
result.add(new UsageInfo(ref.getElement()));
|
||||
}
|
||||
else if (element instanceof PsiMethod && ((PsiMethod)element).isConstructor()) {
|
||||
DefaultConstructorImplicitUsageInfo implicitUsageInfo = new DefaultConstructorImplicitUsageInfo((PsiMethod)element, method);
|
||||
DefaultConstructorImplicitUsageInfo implicitUsageInfo = new DefaultConstructorImplicitUsageInfo((PsiMethod)element,
|
||||
((PsiMethod)element).getContainingClass(), method);
|
||||
result.add(implicitUsageInfo);
|
||||
}
|
||||
else if(element instanceof PsiClass) {
|
||||
result.add(new NoConstructorClassUsageInfo((PsiClass)element));
|
||||
LOG.assertTrue(method.isConstructor());
|
||||
final PsiClass psiClass = (PsiClass)element;
|
||||
if (shouldPropagateToNonPhysicalMethod(method, result, psiClass, myPropagateParametersMethods)) continue;
|
||||
if (shouldPropagateToNonPhysicalMethod(method, result, psiClass, myPropagateExceptionsMethods)) continue;
|
||||
result.add(new NoConstructorClassUsageInfo(psiClass));
|
||||
}
|
||||
else if (ref instanceof PsiCallReference) {
|
||||
result.add(new CallReferenceUsageInfo((PsiCallReference) ref));
|
||||
@@ -223,6 +229,16 @@ public class ChangeSignatureProcessor extends BaseRefactoringProcessor {
|
||||
return overridingMethods;
|
||||
}
|
||||
|
||||
private static boolean shouldPropagateToNonPhysicalMethod(PsiMethod method, ArrayList<UsageInfo> result, PsiClass containingClass, final Set<PsiMethod> propagateMethods) {
|
||||
for (PsiMethod psiMethod : propagateMethods) {
|
||||
if (!psiMethod.isPhysical() && Comparing.strEqual(psiMethod.getName(), containingClass.getName())) {
|
||||
result.add(new DefaultConstructorImplicitUsageInfo(psiMethod, containingClass, method));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void findUsagesInCallers(final ArrayList<UsageInfo> usages) {
|
||||
for (PsiMethod caller : myPropagateParametersMethods) {
|
||||
usages.add(new CallerUsageInfo(caller, true, myPropagateExceptionsMethods.contains(caller)));
|
||||
@@ -512,7 +528,17 @@ public class ChangeSignatureProcessor extends BaseRefactoringProcessor {
|
||||
|
||||
if (usage instanceof DefaultConstructorImplicitUsageInfo) {
|
||||
final DefaultConstructorImplicitUsageInfo defConstructorUsage = (DefaultConstructorImplicitUsageInfo)usage;
|
||||
addSuperCall(defConstructorUsage.getConstructor(), defConstructorUsage.getBaseConstructor(),usages);
|
||||
PsiMethod constructor = defConstructorUsage.getConstructor();
|
||||
if (!constructor.isPhysical()) {
|
||||
final boolean toPropagate = myPropagateParametersMethods.remove(constructor);
|
||||
final PsiClass containingClass = defConstructorUsage.getContainingClass();
|
||||
constructor = (PsiMethod)containingClass.add(constructor);
|
||||
PsiUtil.setModifierProperty(constructor, VisibilityUtil.getVisibilityModifier(containingClass.getModifierList()), true);
|
||||
if (toPropagate) {
|
||||
myPropagateParametersMethods.add(constructor);
|
||||
}
|
||||
}
|
||||
addSuperCall(constructor, defConstructorUsage.getBaseConstructor(),usages);
|
||||
}
|
||||
else if (usage instanceof NoConstructorClassUsageInfo) {
|
||||
addDefaultConstructor(((NoConstructorClassUsageInfo)usage).getPsiClass(),usages);
|
||||
|
||||
@@ -136,7 +136,7 @@ public abstract class CallerChooser extends DialogWrapper {
|
||||
|
||||
final PsiMethod caller = node.getMethod();
|
||||
final PsiMethod callee = parentNode != null ? parentNode.getMethod() : null;
|
||||
if (caller != null && callee != null) {
|
||||
if (caller != null && caller.isPhysical() && callee != null) {
|
||||
HighlightManager highlighter = HighlightManager.getInstance(myProject);
|
||||
EditorColorsManager colorManager = EditorColorsManager.getInstance();
|
||||
TextAttributes attributes = colorManager.getGlobalScheme().getAttributes(EditorColors.TEXT_SEARCH_RESULT_ATTRIBUTES);
|
||||
@@ -162,9 +162,12 @@ public abstract class CallerChooser extends DialogWrapper {
|
||||
if (method == null) return "";
|
||||
final PsiFile file = method.getContainingFile();
|
||||
Document document = PsiDocumentManager.getInstance(myProject).getDocument(file);
|
||||
final int start = document.getLineStartOffset(document.getLineNumber(method.getTextRange().getStartOffset()));
|
||||
final int end = document.getLineEndOffset(document.getLineNumber(method.getTextRange().getEndOffset()));
|
||||
return document.getText().substring(start, end);
|
||||
if (document != null) {
|
||||
final int start = document.getLineStartOffset(document.getLineNumber(method.getTextRange().getStartOffset()));
|
||||
final int end = document.getLineEndOffset(document.getLineNumber(method.getTextRange().getEndOffset()));
|
||||
return document.getText().substring(start, end);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
private int getStartOffset (@NotNull final PsiMethod method) {
|
||||
|
||||
@@ -103,6 +103,9 @@ public class MethodNode extends CheckedTreeNode {
|
||||
if (enclosingContext instanceof PsiMethod &&
|
||||
!myMethod.equals(enclosingContext) && !myCalled.contains(myMethod)) { //do not add recursive methods
|
||||
callers.add((PsiMethod) enclosingContext);
|
||||
} else if (element instanceof PsiClass) {
|
||||
final PsiClass aClass = (PsiClass)element;
|
||||
callers.add(JavaPsiFacade.getElementFactory(project).createMethodFromText(aClass.getName() + "(){}", aClass));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -137,8 +140,10 @@ public class MethodNode extends CheckedTreeNode {
|
||||
SimpleTextAttributes.EXCLUDED_ATTRIBUTES;
|
||||
renderer.append(buffer.toString(), attributes);
|
||||
|
||||
final String packageName = getPackageName(myMethod.getContainingClass());
|
||||
renderer.append(" (" + packageName + ")", new SimpleTextAttributes(SimpleTextAttributes.STYLE_ITALIC, Color.GRAY));
|
||||
if (containingClass != null) {
|
||||
final String packageName = getPackageName(containingClass);
|
||||
renderer.append(" (" + packageName + ")", new SimpleTextAttributes(SimpleTextAttributes.STYLE_ITALIC, Color.GRAY));
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
|
||||
@@ -152,7 +152,7 @@ public class IntroduceParameterProcessor extends BaseRefactoringProcessor implem
|
||||
PsiElement ref = ref1.getElement();
|
||||
if (ref instanceof PsiMethod && ((PsiMethod)ref).isConstructor()) {
|
||||
DefaultConstructorImplicitUsageInfo implicitUsageInfo =
|
||||
new DefaultConstructorImplicitUsageInfo((PsiMethod)ref, myMethodToSearchFor);
|
||||
new DefaultConstructorImplicitUsageInfo((PsiMethod)ref, ((PsiMethod)ref).getContainingClass(), myMethodToSearchFor);
|
||||
result.add(implicitUsageInfo);
|
||||
}
|
||||
else if (ref instanceof PsiClass) {
|
||||
|
||||
@@ -23,11 +23,13 @@ import com.intellij.usageView.UsageInfo;
|
||||
*/
|
||||
public class DefaultConstructorImplicitUsageInfo extends UsageInfo {
|
||||
private final PsiMethod myOverridingConstructor;
|
||||
private final PsiClass myContainingClass;
|
||||
private final PsiMethod myBaseConstructor;
|
||||
|
||||
public DefaultConstructorImplicitUsageInfo(PsiMethod overridingConstructor, PsiMethod baseConstructor) {
|
||||
public DefaultConstructorImplicitUsageInfo(PsiMethod overridingConstructor, PsiClass containingClass, PsiMethod baseConstructor) {
|
||||
super(overridingConstructor);
|
||||
myOverridingConstructor = overridingConstructor;
|
||||
myContainingClass = containingClass;
|
||||
myBaseConstructor = baseConstructor;
|
||||
}
|
||||
|
||||
@@ -38,4 +40,8 @@ public class DefaultConstructorImplicitUsageInfo extends UsageInfo {
|
||||
public PsiMethod getBaseConstructor() {
|
||||
return myBaseConstructor;
|
||||
}
|
||||
|
||||
public PsiClass getContainingClass() {
|
||||
return myContainingClass;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,38 +0,0 @@
|
||||
/*
|
||||
* Copyright 2000-2009 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.util.usageInfo;
|
||||
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.refactoring.util.RefactoringUtil;
|
||||
import com.intellij.usageView.UsageInfo;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class DefaultConstructorUsageCollector implements RefactoringUtil.ImplicitConstructorUsageVisitor {
|
||||
private final ArrayList<UsageInfo> myUsages;
|
||||
|
||||
public void visitConstructor(PsiMethod constructor, PsiMethod baseConstructor) {
|
||||
myUsages.add(new DefaultConstructorImplicitUsageInfo(constructor, baseConstructor));
|
||||
}
|
||||
|
||||
public void visitClassWithoutConstructors(PsiClass aClass) {
|
||||
myUsages.add(new NoConstructorClassUsageInfo(aClass));
|
||||
}
|
||||
|
||||
public DefaultConstructorUsageCollector(ArrayList<UsageInfo> result) {
|
||||
myUsages = result;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
public class P {
|
||||
public P<caret>() {
|
||||
}
|
||||
}
|
||||
|
||||
class PP extends P {
|
||||
public PP(){
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
public class P {
|
||||
public P() throws Exception {
|
||||
}
|
||||
}
|
||||
|
||||
class PP extends P {
|
||||
public PP() throws Exception {
|
||||
super();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
public class P {
|
||||
public P<caret>() {
|
||||
}
|
||||
}
|
||||
|
||||
class PP extends P {
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
public class P {
|
||||
public P() throws Exception {
|
||||
}
|
||||
}
|
||||
|
||||
class PP extends P {
|
||||
PP() throws Exception {
|
||||
super();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
public class P {
|
||||
public P<caret>() {
|
||||
}
|
||||
}
|
||||
|
||||
class PP extends P {
|
||||
public PP(){
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
public class P {
|
||||
public P(Class clazz) {
|
||||
}
|
||||
}
|
||||
|
||||
class PP extends P {
|
||||
public PP(Class clazz){
|
||||
super(clazz);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
public class P {
|
||||
public P<caret>() {
|
||||
}
|
||||
}
|
||||
|
||||
class PP extends P {
|
||||
public PP(){
|
||||
}
|
||||
}
|
||||
|
||||
class PPP extends P {
|
||||
public PPP(){
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
public class P {
|
||||
public P(Class clazz) {
|
||||
}
|
||||
}
|
||||
|
||||
class PP extends P {
|
||||
public PP(Class clazz){
|
||||
super(clazz);
|
||||
}
|
||||
}
|
||||
|
||||
class PPP extends P {
|
||||
public PPP(Class clazz){
|
||||
super(clazz);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
public class P {
|
||||
public P<caret>() {
|
||||
}
|
||||
}
|
||||
|
||||
class PP extends P {
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
public class P {
|
||||
public P(Class clazz) {
|
||||
}
|
||||
}
|
||||
|
||||
class PP extends P {
|
||||
PP(Class clazz) {
|
||||
super(clazz);
|
||||
}
|
||||
}
|
||||
@@ -4,12 +4,15 @@ import com.intellij.JavaTestUtil;
|
||||
import com.intellij.codeInsight.TargetElementUtilBase;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.psi.search.searches.ClassInheritorsSearch;
|
||||
import com.intellij.psi.search.searches.MethodReferencesSearch;
|
||||
import com.intellij.refactoring.changeSignature.ChangeSignatureProcessor;
|
||||
import com.intellij.refactoring.changeSignature.ParameterInfoImpl;
|
||||
import com.intellij.refactoring.changeSignature.ThrownExceptionInfo;
|
||||
import com.intellij.refactoring.util.CanonicalTypes;
|
||||
import com.intellij.testFramework.LightCodeInsightTestCase;
|
||||
import com.intellij.util.containers.HashSet;
|
||||
import junit.framework.Assert;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Set;
|
||||
@@ -34,21 +37,71 @@ public class ChangeSignaturePropagationTest extends LightCodeInsightTestCase {
|
||||
exceptionPropagationTest();
|
||||
}
|
||||
|
||||
public void testParamWithNoConstructor() throws Exception {
|
||||
final PsiMethod method = getPrimaryMethod();
|
||||
parameterPropagationTest(method, collectNonPhysicalMethodsToPropagate(method));
|
||||
}
|
||||
|
||||
public void testExceptionWithNoConstructor() throws Exception {
|
||||
final PsiMethod method = getPrimaryMethod();
|
||||
exceptionPropagationTest(method, collectNonPhysicalMethodsToPropagate(method));
|
||||
}
|
||||
|
||||
private static HashSet<PsiMethod> collectNonPhysicalMethodsToPropagate(PsiMethod method) {
|
||||
final HashSet<PsiMethod> methodsToPropagate = new HashSet<PsiMethod>();
|
||||
final PsiReference[] references =
|
||||
MethodReferencesSearch.search(method, GlobalSearchScope.allScope(getProject()), true).toArray(PsiReference.EMPTY_ARRAY);
|
||||
for (PsiReference reference : references) {
|
||||
final PsiElement element = reference.getElement();
|
||||
Assert.assertTrue(element instanceof PsiClass);
|
||||
PsiClass containingClass = (PsiClass)element;
|
||||
methodsToPropagate.add(JavaPsiFacade.getElementFactory(getProject()).createMethodFromText(containingClass.getName() + "(){}", containingClass));
|
||||
}
|
||||
return methodsToPropagate;
|
||||
}
|
||||
|
||||
public void testParamWithImplicitConstructor() throws Exception {
|
||||
final PsiMethod method = getPrimaryMethod();
|
||||
parameterPropagationTest(method, collectDefaultConstructorsToPropagate(method));
|
||||
}
|
||||
|
||||
public void testParamWithImplicitConstructors() throws Exception {
|
||||
final PsiMethod method = getPrimaryMethod();
|
||||
parameterPropagationTest(method, collectDefaultConstructorsToPropagate(method));
|
||||
}
|
||||
|
||||
public void testExceptionWithImplicitConstructor() throws Exception {
|
||||
final PsiMethod method = getPrimaryMethod();
|
||||
exceptionPropagationTest(method, collectDefaultConstructorsToPropagate(method));
|
||||
}
|
||||
|
||||
private static HashSet<PsiMethod> collectDefaultConstructorsToPropagate(PsiMethod method) {
|
||||
final HashSet<PsiMethod> methodsToPropagate = new HashSet<PsiMethod>();
|
||||
for (PsiClass inheritor : ClassInheritorsSearch.search(method.getContainingClass())) {
|
||||
methodsToPropagate.add(inheritor.getConstructors()[0]);
|
||||
}
|
||||
return methodsToPropagate;
|
||||
}
|
||||
|
||||
private void parameterPropagationTest() throws Exception {
|
||||
PsiMethod method = getPrimaryMethod();
|
||||
PsiClass aClass = method.getContainingClass();
|
||||
final PsiMethod method = getPrimaryMethod();
|
||||
parameterPropagationTest(method, new HashSet<PsiMethod>(Arrays.asList(method.getContainingClass().getMethods())));
|
||||
}
|
||||
|
||||
private void parameterPropagationTest(final PsiMethod method, final HashSet<PsiMethod> psiMethods) throws Exception {
|
||||
PsiType newParamType = JavaPsiFacade.getElementFactory(getProject()).createTypeByFQClassName("java.lang.Class", GlobalSearchScope.allScope(getProject()));
|
||||
final ParameterInfoImpl[] newParameters = new ParameterInfoImpl[]{new ParameterInfoImpl(-1, "clazz", newParamType, "null")};
|
||||
final Set<PsiMethod> methodsToPropagateParameters = new HashSet<PsiMethod>(Arrays.asList(aClass.getMethods()));
|
||||
doTest(newParameters, new ThrownExceptionInfo[0], methodsToPropagateParameters, null, method);
|
||||
doTest(newParameters, new ThrownExceptionInfo[0], psiMethods, null, method);
|
||||
}
|
||||
|
||||
private void exceptionPropagationTest() throws Exception {
|
||||
PsiMethod method = getPrimaryMethod();
|
||||
PsiClass aClass = method.getContainingClass();
|
||||
final PsiMethod method = getPrimaryMethod();
|
||||
exceptionPropagationTest(method, new HashSet<PsiMethod>(Arrays.asList(method.getContainingClass().getMethods())));
|
||||
}
|
||||
|
||||
private void exceptionPropagationTest(final PsiMethod method, final Set<PsiMethod> methodsToPropagateExceptions) throws Exception {
|
||||
PsiClassType newExceptionType = JavaPsiFacade.getElementFactory(getProject()).createTypeByFQClassName("java.lang.Exception", GlobalSearchScope.allScope(getProject()));
|
||||
final ThrownExceptionInfo[] newExceptions = new ThrownExceptionInfo[]{new ThrownExceptionInfo(-1, newExceptionType)};
|
||||
final Set<PsiMethod> methodsToPropagateExceptions = new HashSet<PsiMethod>(Arrays.asList(aClass.getMethods()));
|
||||
doTest(new ParameterInfoImpl[0], newExceptions, null, methodsToPropagateExceptions, method);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user