mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
deep make static
This commit is contained in:
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Created by IntelliJ IDEA.
|
||||
* User: dsl
|
||||
* Date: 16.04.2002
|
||||
* Time: 17:09:40
|
||||
* To change template for new class use
|
||||
* Code Style | Class Templates options (Tools | IDE Options).
|
||||
*/
|
||||
package com.intellij.refactoring.makeStatic;
|
||||
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.usageView.UsageInfo;
|
||||
|
||||
class ChainedCallUsageInfo extends UsageInfo {
|
||||
ChainedCallUsageInfo(PsiElement element) {
|
||||
super(element);
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -131,7 +131,7 @@ public class MakeClassStaticProcessor extends MakeMethodOrClassStaticProcessor<P
|
||||
}
|
||||
|
||||
|
||||
setupTypeParameterList();
|
||||
setupTypeParameterList(myMember);
|
||||
|
||||
// Add static modifier
|
||||
final PsiModifierList modifierList = myMember.getModifierList();
|
||||
|
||||
+16
-7
@@ -111,16 +111,21 @@ public abstract class MakeMethodOrClassStaticProcessor<T extends PsiTypeParamete
|
||||
refUsages.set(filterInternalUsages(usagesIn));
|
||||
}
|
||||
}
|
||||
refUsages.set(filterOverriding(usagesIn));
|
||||
|
||||
final ArrayList<UsageInfo> toMakeStatic = new ArrayList<>();
|
||||
refUsages.set(filterOverriding(usagesIn, toMakeStatic));
|
||||
if (!findAdditionalMembers(toMakeStatic)) return false;
|
||||
prepareSuccessful();
|
||||
return true;
|
||||
}
|
||||
|
||||
private static UsageInfo[] filterOverriding(UsageInfo[] usages) {
|
||||
protected boolean findAdditionalMembers(ArrayList<UsageInfo> toMakeStatic) {return true;}
|
||||
|
||||
private static UsageInfo[] filterOverriding(UsageInfo[] usages, List<UsageInfo> suggestToMakeStatic) {
|
||||
ArrayList<UsageInfo> result = new ArrayList<UsageInfo>();
|
||||
for (UsageInfo usage : usages) {
|
||||
if (!(usage instanceof OverridingMethodUsageInfo)) {
|
||||
if (usage instanceof ChainedCallUsageInfo) {
|
||||
suggestToMakeStatic.add(usage);
|
||||
} else if (!(usage instanceof OverridingMethodUsageInfo)) {
|
||||
result.add(usage);
|
||||
}
|
||||
}
|
||||
@@ -253,14 +258,18 @@ public abstract class MakeMethodOrClassStaticProcessor<T extends PsiTypeParamete
|
||||
if (!PsiTreeUtil.isAncestor(myMember, element, true) || qualifier != null) {
|
||||
result.add(new UsageInfo(element));
|
||||
}
|
||||
|
||||
processExternalReference(element, method, result);
|
||||
}
|
||||
}
|
||||
|
||||
protected void processExternalReference(PsiElement element, PsiMethod method, ArrayList<UsageInfo> result) {}
|
||||
|
||||
//should be called before setting static modifier
|
||||
protected void setupTypeParameterList() throws IncorrectOperationException {
|
||||
final PsiTypeParameterList list = myMember.getTypeParameterList();
|
||||
protected void setupTypeParameterList(T member) throws IncorrectOperationException {
|
||||
final PsiTypeParameterList list = member.getTypeParameterList();
|
||||
assert list != null;
|
||||
final PsiTypeParameterList newList = RefactoringUtil.createTypeParameterListWithUsedTypeParameters(myMember);
|
||||
final PsiTypeParameterList newList = RefactoringUtil.createTypeParameterListWithUsedTypeParameters(member);
|
||||
if (newList != null) {
|
||||
list.replace(newList);
|
||||
}
|
||||
|
||||
+51
-2
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
package com.intellij.refactoring.makeStatic;
|
||||
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.*;
|
||||
@@ -23,25 +24,53 @@ import com.intellij.psi.javadoc.PsiDocTag;
|
||||
import com.intellij.psi.util.InheritanceUtil;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import com.intellij.refactoring.changeSignature.inCallers.JavaCallerChooser;
|
||||
import com.intellij.refactoring.util.RefactoringUtil;
|
||||
import com.intellij.refactoring.util.javadoc.MethodJavaDocHelper;
|
||||
import com.intellij.usageView.UsageInfo;
|
||||
import com.intellij.util.Consumer;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import com.intellij.util.containers.MultiMap;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author dsl
|
||||
*/
|
||||
public class MakeMethodStaticProcessor extends MakeMethodOrClassStaticProcessor<PsiMethod> {
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.refactoring.makeMethodStatic.MakeMethodStaticProcessor");
|
||||
private List<PsiMethod> myAdditionalMethods;
|
||||
|
||||
public MakeMethodStaticProcessor(final Project project, final PsiMethod method, final Settings settings) {
|
||||
super(project, method, settings);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean findAdditionalMembers(ArrayList<UsageInfo> toMakeStatic) {
|
||||
if (!toMakeStatic.isEmpty()) {
|
||||
myAdditionalMethods = new ArrayList<PsiMethod>();
|
||||
if (ApplicationManager.getApplication().isUnitTestMode()) {
|
||||
for (UsageInfo usageInfo : toMakeStatic) {
|
||||
myAdditionalMethods.add((PsiMethod)usageInfo.getElement());
|
||||
}
|
||||
}
|
||||
else {
|
||||
final JavaCallerChooser chooser = new MakeStaticJavaCallerChooser(myMember, myProject, new Consumer<Set<PsiMethod>>() {
|
||||
@Override
|
||||
public void consume(Set<PsiMethod> methods) {
|
||||
myAdditionalMethods.addAll(methods);
|
||||
}
|
||||
});
|
||||
if (!chooser.showAndGet()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected MultiMap<PsiElement, String> getConflictDescriptions(UsageInfo[] usages) {
|
||||
MultiMap<PsiElement, String> descriptions = super.getConflictDescriptions(usages);
|
||||
@@ -122,9 +151,19 @@ public class MakeMethodStaticProcessor extends MakeMethodOrClassStaticProcessor<
|
||||
anchor = javaDocHelper.addParameterAfter(fieldParameter.name, anchor);
|
||||
}
|
||||
}
|
||||
setupTypeParameterList();
|
||||
makeStatic(myMember);
|
||||
|
||||
if (myAdditionalMethods != null) {
|
||||
for (PsiMethod method : myAdditionalMethods) {
|
||||
makeStatic(method);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void makeStatic(PsiMethod member) {
|
||||
setupTypeParameterList(member);
|
||||
// Add static modifier
|
||||
final PsiModifierList modifierList = myMember.getModifierList();
|
||||
final PsiModifierList modifierList = member.getModifierList();
|
||||
modifierList.setModifierProperty(PsiModifier.STATIC, true);
|
||||
modifierList.setModifierProperty(PsiModifier.FINAL, false);
|
||||
modifierList.setModifierProperty(PsiModifier.DEFAULT, false);
|
||||
@@ -265,4 +304,14 @@ public class MakeMethodStaticProcessor extends MakeMethodOrClassStaticProcessor<
|
||||
protected void findExternalUsages(final ArrayList<UsageInfo> result) {
|
||||
findExternalReferences(myMember, result);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void processExternalReference(PsiElement element, PsiMethod method, ArrayList<UsageInfo> result) {
|
||||
if (!mySettings.isChangeSignature()) {
|
||||
final PsiMethod containingMethod = MakeStaticJavaCallerChooser.isTheLastClassRef(element, method);
|
||||
if (containingMethod != null) {
|
||||
result.add(new ChainedCallUsageInfo(containingMethod));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+99
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
* 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.makeStatic;
|
||||
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Condition;
|
||||
import com.intellij.psi.PsiClass;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiMethod;
|
||||
import com.intellij.psi.PsiModifier;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.refactoring.changeSignature.MethodNodeBase;
|
||||
import com.intellij.refactoring.changeSignature.inCallers.JavaCallerChooser;
|
||||
import com.intellij.refactoring.changeSignature.inCallers.JavaMethodNode;
|
||||
import com.intellij.util.Consumer;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
class MakeStaticJavaCallerChooser extends JavaCallerChooser {
|
||||
private final Project myProject;
|
||||
|
||||
public MakeStaticJavaCallerChooser(PsiMethod method, Project project, Consumer<Set<PsiMethod>> consumer) {
|
||||
super(method, project, "Select Methods To Propagate Static", null, consumer);
|
||||
myProject = project;
|
||||
}
|
||||
|
||||
static PsiMethod isTheLastClassRef(PsiElement element, PsiMethod member) {
|
||||
final PsiMethod containingMethod = PsiTreeUtil.getParentOfType(element, PsiMethod.class, false);
|
||||
if ( containingMethod != null &&
|
||||
!containingMethod.isConstructor() &&
|
||||
containingMethod.findDeepestSuperMethods().length == 0 &&
|
||||
!containingMethod.equals(member)) {
|
||||
final PsiClass containingClass = containingMethod.getContainingClass();
|
||||
if (containingClass != null) {
|
||||
final PsiClass gContainingClass = containingClass.getContainingClass();
|
||||
if (gContainingClass == null || gContainingClass.hasModifierProperty(PsiModifier.STATIC)) {
|
||||
final InternalUsageInfo[] refsInMember = MakeStaticUtil.findClassRefsInMember(containingMethod, true);
|
||||
for (InternalUsageInfo info : refsInMember) {
|
||||
final PsiElement referencedElement = info.getReferencedElement();
|
||||
if (!member.equals(referencedElement) && !containingMethod.equals(referencedElement)) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return containingMethod;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected JavaMethodNode createTreeNode(PsiMethod nodeMethod,
|
||||
com.intellij.util.containers.HashSet<PsiMethod> called,
|
||||
Runnable cancelCallback) {
|
||||
return new MakeStaticJavaMethodNode(nodeMethod, called, cancelCallback, nodeMethod != null ? nodeMethod.getProject() : myProject);
|
||||
}
|
||||
|
||||
private static class MakeStaticJavaMethodNode extends JavaMethodNode {
|
||||
|
||||
private final PsiMethod myCurrentMethod;
|
||||
|
||||
public MakeStaticJavaMethodNode(PsiMethod currentMethod,
|
||||
HashSet<PsiMethod> called,
|
||||
Runnable cancelCallback,
|
||||
Project project) {
|
||||
super(currentMethod, called, project, cancelCallback);
|
||||
myCurrentMethod = currentMethod;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected MethodNodeBase<PsiMethod> createNode(PsiMethod caller, HashSet<PsiMethod> called) {
|
||||
return new MakeStaticJavaMethodNode(caller, called, myCancelCallback, myProject);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Condition<PsiMethod> getFilter() {
|
||||
return new Condition<PsiMethod>() {
|
||||
@Override
|
||||
public boolean value(PsiMethod method) {
|
||||
return !myCurrentMethod.equals(method) && isTheLastClassRef(method, myCurrentMethod) != null;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
class P {
|
||||
static void foo() {
|
||||
foo();
|
||||
bazz(0);
|
||||
}
|
||||
|
||||
private static void bazz(int k) {
|
||||
bazz(k);
|
||||
bazz(k);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
class PP {
|
||||
void foo(){}
|
||||
}
|
||||
|
||||
class PPImpl extends PP {
|
||||
void foo() {
|
||||
foo();
|
||||
bazz(0);
|
||||
}
|
||||
|
||||
private static void bazz(int k) {
|
||||
bazz(k);
|
||||
bazz(k);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
class P {
|
||||
void foo() {
|
||||
foo();
|
||||
bazz(0);
|
||||
}
|
||||
|
||||
private void <caret>bazz(int k) {
|
||||
bazz(k);
|
||||
bazz(k);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
class PP {
|
||||
void foo(){}
|
||||
}
|
||||
|
||||
class PPImpl extends PP {
|
||||
void foo() {
|
||||
foo();
|
||||
bazz(0);
|
||||
}
|
||||
|
||||
private void <caret>bazz(int k) {
|
||||
bazz(k);
|
||||
bazz(k);
|
||||
}
|
||||
}
|
||||
@@ -172,6 +172,18 @@ public class MakeMethodStaticTest extends LightRefactoringTestCase {
|
||||
checkResultByFile("/refactoring/makeMethodStatic/after22.java");
|
||||
}
|
||||
|
||||
public void testDeepStaticOverrides() throws Exception {
|
||||
configureByFile("/refactoring/makeMethodStatic/beforeOverrides.java");
|
||||
perform(false);
|
||||
checkResultByFile("/refactoring/makeMethodStatic/afterOverrides.java");
|
||||
}
|
||||
|
||||
public void testDeepStatic() throws Exception {
|
||||
configureByFile("/refactoring/makeMethodStatic/beforeDeep.java");
|
||||
perform(false);
|
||||
checkResultByFile("/refactoring/makeMethodStatic/afterDeep.java");
|
||||
}
|
||||
|
||||
public void testPreserveTypeParams() throws Exception {
|
||||
configureByFile("/refactoring/makeMethodStatic/beforePreserveTypeParams.java");
|
||||
performWithFields();
|
||||
|
||||
Reference in New Issue
Block a user