mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-01-09 08:09:39 +07:00
Merge branch 'master' of git@git.labs.intellij.net:idea/community
This commit is contained in:
@@ -284,7 +284,8 @@ public class InlineToAnonymousClassHandler extends JavaInlineActionHandler {
|
||||
}
|
||||
final PsiElement parentElement = element.getParent();
|
||||
if (parentElement != null) {
|
||||
if (parentElement.getParent() instanceof PsiClassObjectAccessExpression) {
|
||||
final PsiElement grandPa = parentElement.getParent();
|
||||
if (grandPa instanceof PsiClassObjectAccessExpression) {
|
||||
return "Class cannot be inlined because it has usages of its class literal";
|
||||
}
|
||||
if (ourCatchClausePattern.accepts(parentElement)) {
|
||||
|
||||
@@ -134,7 +134,7 @@ public class InlineToAnonymousClassProcessor extends BaseRefactoringProcessor {
|
||||
}
|
||||
|
||||
public MultiMap<PsiElement, String> getConflicts(final UsageInfo[] usages) {
|
||||
MultiMap<PsiElement, String> result = new MultiMap<PsiElement, String>();
|
||||
final MultiMap<PsiElement, String> result = new MultiMap<PsiElement, String>();
|
||||
ReferencedElementsCollector collector = new ReferencedElementsCollector() {
|
||||
protected void checkAddMember(@NotNull final PsiMember member) {
|
||||
if (PsiTreeUtil.isAncestor(myClass, member, false)) {
|
||||
@@ -150,6 +150,53 @@ public class InlineToAnonymousClassProcessor extends BaseRefactoringProcessor {
|
||||
}
|
||||
};
|
||||
InlineMethodProcessor.addInaccessibleMemberConflicts(myClass, usages, collector, result);
|
||||
myClass.accept(new JavaRecursiveElementVisitor(){
|
||||
@Override
|
||||
public void visitParameter(PsiParameter parameter) {
|
||||
super.visitParameter(parameter);
|
||||
if (PsiUtil.resolveClassInType(parameter.getType()) != myClass) return;
|
||||
|
||||
for (PsiReference psiReference : ReferencesSearch.search(parameter)) {
|
||||
final PsiElement refElement = psiReference.getElement();
|
||||
if (refElement instanceof PsiExpression) {
|
||||
final PsiReferenceExpression referenceExpression = PsiTreeUtil.getParentOfType(refElement, PsiReferenceExpression.class);
|
||||
if (referenceExpression != null && referenceExpression.getQualifierExpression() == refElement) {
|
||||
final PsiElement resolvedMember = referenceExpression.resolve();
|
||||
if (resolvedMember != null && PsiTreeUtil.isAncestor(myClass, resolvedMember, false)) {
|
||||
if (resolvedMember instanceof PsiMethod) {
|
||||
if (myClass.findMethodsBySignature((PsiMethod)resolvedMember, true).length > 1) { //skip inherited methods
|
||||
continue;
|
||||
}
|
||||
}
|
||||
result.putValue(refElement, "Class cannot be inlined because a call to its member inside body");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitNewExpression(PsiNewExpression expression) {
|
||||
super.visitNewExpression(expression);
|
||||
if (PsiUtil.resolveClassInType(expression.getType()) != myClass) return;
|
||||
result.putValue(expression, "Class cannot be inlined because a call to its constructor inside body");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitMethodCallExpression(PsiMethodCallExpression expression) {
|
||||
super.visitMethodCallExpression(expression);
|
||||
final PsiReferenceExpression methodExpression = expression.getMethodExpression();
|
||||
final PsiExpression qualifierExpression = methodExpression.getQualifierExpression();
|
||||
if (qualifierExpression != null && PsiUtil.resolveClassInType(qualifierExpression.getType()) != myClass) return;
|
||||
final PsiElement resolved = methodExpression.resolve();
|
||||
if (resolved instanceof PsiMethod) {
|
||||
final PsiMethod method = (PsiMethod)resolved;
|
||||
if ("getClass".equals(method.getName()) && method.getParameterList().getParametersCount() == 0) {
|
||||
result.putValue(methodExpression, "Result of getClass() invocation would be changed");
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@@ -183,7 +183,7 @@ class InlineToAnonymousConstructorProcessor {
|
||||
ProcessingContext context = new ProcessingContext();
|
||||
if (ourAssignmentPattern.accepts(stmt, context)) {
|
||||
PsiAssignmentExpression expression = context.get(ourAssignmentKey);
|
||||
if (!processAssignmentInConstructor(expression)) {
|
||||
if (processAssignmentInConstructor(expression)) {
|
||||
initializerBlock.addBefore(replaceParameterReferences(stmt, null, false), initializerBlock.getRBrace());
|
||||
}
|
||||
}
|
||||
@@ -205,7 +205,7 @@ class InlineToAnonymousConstructorProcessor {
|
||||
if (expression.getLExpression() instanceof PsiReferenceExpression) {
|
||||
PsiReferenceExpression lExpr = (PsiReferenceExpression) expression.getLExpression();
|
||||
final PsiExpression rExpr = expression.getRExpression();
|
||||
if (rExpr == null) return true;
|
||||
if (rExpr == null) return false;
|
||||
final PsiElement psiElement = lExpr.resolve();
|
||||
if (psiElement instanceof PsiField) {
|
||||
PsiField field = (PsiField) psiElement;
|
||||
@@ -217,25 +217,20 @@ class InlineToAnonymousConstructorProcessor {
|
||||
}
|
||||
catch (IncorrectOperationException e) {
|
||||
LOG.error(e);
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
if (!localVarRefs.isEmpty()) {
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
myFieldInitializers.put(field.getName(), initializer);
|
||||
}
|
||||
}
|
||||
else if (psiElement instanceof PsiVariable) {
|
||||
try {
|
||||
replaceParameterReferences(rExpr.copy(), new ArrayList<PsiReferenceExpression>(), false);
|
||||
}
|
||||
catch (IncorrectOperationException e) {
|
||||
LOG.error(e);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean isConstant(final PsiExpression expr) {
|
||||
|
||||
@@ -15,17 +15,17 @@
|
||||
*/
|
||||
package com.intellij.refactoring.move;
|
||||
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.util.InheritanceUtil;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.util.containers.HashSet;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.Map;
|
||||
import java.util.LinkedHashMap;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author ven
|
||||
*/
|
||||
@@ -120,7 +120,7 @@ public class MoveInstanceMembersUtil {
|
||||
if (referencedClass == null) return null;
|
||||
final PsiClass parentClass = PsiTreeUtil.getParentOfType(expression, PsiClass.class);
|
||||
assert parentClass != null;
|
||||
if (!PsiTreeUtil.isAncestor(referencedClass, parentClass, false)) {
|
||||
if (InheritanceUtil.isInheritorOrSelf(parentClass, referencedClass, false)) {
|
||||
referencedClass = parentClass;
|
||||
}
|
||||
return referencedClass;
|
||||
|
||||
@@ -128,6 +128,13 @@ public class MoveClassToInnerProcessor extends BaseRefactoringProcessor {
|
||||
final List<PsiElement> importStatements = new ArrayList<PsiElement>();
|
||||
if (!CodeStyleSettingsManager.getSettings(myProject).INSERT_INNER_CLASS_IMPORTS) {
|
||||
usages = filterUsagesInImportStatements(usages, importStatements);
|
||||
} else {
|
||||
//rebind imports first
|
||||
Arrays.sort(usages, new Comparator<UsageInfo>() {
|
||||
public int compare(UsageInfo o1, UsageInfo o2) {
|
||||
return PsiUtil.BY_POSITION.compare(o1.getElement(), o2.getElement());
|
||||
}
|
||||
});
|
||||
}
|
||||
saveNonCodeUsages(usages);
|
||||
final Map<PsiElement, PsiElement> oldToNewElementsMapping = new HashMap<PsiElement, PsiElement>();
|
||||
@@ -346,7 +353,7 @@ public class MoveClassToInnerProcessor extends BaseRefactoringProcessor {
|
||||
private boolean isInaccessibleFromTarget(final PsiElement element, final String visibility) {
|
||||
final PsiPackage elementPackage = JavaDirectoryService.getInstance().getPackage(element.getContainingFile().getContainingDirectory());
|
||||
return !PsiUtil.isAccessible(myTargetClass, element, null) ||
|
||||
(visibility.equals(PsiModifier.PACKAGE_LOCAL) && !Comparing.equal(elementPackage, myTargetPackage));
|
||||
(!myTargetClass.isInterface() && visibility.equals(PsiModifier.PACKAGE_LOCAL) && !Comparing.equal(elementPackage, myTargetPackage));
|
||||
}
|
||||
|
||||
private void detectInaccessibleMemberUsages(final ConflictsCollector collector) {
|
||||
|
||||
@@ -31,6 +31,7 @@ import com.intellij.psi.*;
|
||||
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
|
||||
import com.intellij.psi.codeStyle.SuggestedNameInfo;
|
||||
import com.intellij.psi.codeStyle.VariableKind;
|
||||
import com.intellij.psi.util.InheritanceUtil;
|
||||
import com.intellij.refactoring.HelpID;
|
||||
import com.intellij.refactoring.JavaRefactoringSettings;
|
||||
import com.intellij.refactoring.PackageWrapper;
|
||||
@@ -52,6 +53,8 @@ import org.jetbrains.annotations.Nullable;
|
||||
import javax.swing.*;
|
||||
import java.awt.event.ItemEvent;
|
||||
import java.awt.event.ItemListener;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
public class MoveInnerDialog extends RefactoringDialog {
|
||||
private final Project myProject;
|
||||
@@ -133,7 +136,7 @@ public class MoveInnerDialog extends RefactoringDialog {
|
||||
}
|
||||
|
||||
if (myCbPassOuterClass.isEnabled()) {
|
||||
final boolean thisNeeded = MoveInstanceMembersUtil.getThisClassesToMembers(myInnerClass).containsKey(myOuterClass);
|
||||
boolean thisNeeded = isThisNeeded(myInnerClass, myOuterClass);
|
||||
myCbPassOuterClass.setSelected(thisNeeded);
|
||||
myParameterField.setEnabled(thisNeeded);
|
||||
}
|
||||
@@ -153,6 +156,16 @@ public class MoveInnerDialog extends RefactoringDialog {
|
||||
super.init();
|
||||
}
|
||||
|
||||
public static boolean isThisNeeded(final PsiClass innerClass, final PsiClass outerClass) {
|
||||
final Map<PsiClass, Set<PsiMember>> classesToMembers = MoveInstanceMembersUtil.getThisClassesToMembers(innerClass);
|
||||
for (PsiClass psiClass : classesToMembers.keySet()) {
|
||||
if (InheritanceUtil.isInheritorOrSelf(outerClass, psiClass, true)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public JComponent getPreferredFocusedComponent() {
|
||||
return myClassNameField;
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@ import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiMethod;
|
||||
import com.intellij.psi.PsiParameter;
|
||||
import com.intellij.refactoring.JavaRefactoringSettings;
|
||||
import com.intellij.refactoring.RefactoringBundle;
|
||||
import com.intellij.usageView.UsageInfo;
|
||||
|
||||
import java.util.Collection;
|
||||
@@ -34,7 +35,7 @@ public class AutomaticParametersRenamerFactory implements AutomaticRenamerFactor
|
||||
}
|
||||
|
||||
public String getOptionName() {
|
||||
return "Rename parameters in hierarchy";
|
||||
return RefactoringBundle.message("rename.parameters.hierarchy");
|
||||
}
|
||||
|
||||
public boolean isEnabled() {
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
class Simple {
|
||||
void foo(Simple s) {
|
||||
final Class<? extends Simple> aClass = getClass();
|
||||
final Class<? extends Simple> aClass1 = s.getClass();
|
||||
final Class<? extends String> nonConflictStrClass = "".getClass();
|
||||
}
|
||||
}
|
||||
|
||||
class Usage {
|
||||
Simple s = new Sim<caret>ple();
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
public class WithCtor {
|
||||
private int myInt = 8;
|
||||
private String myString = "Sashya";
|
||||
|
||||
public WithCtor() {
|
||||
}
|
||||
|
||||
public WithCtor(int anInt, String string) {
|
||||
int i = 2;
|
||||
i = 3;
|
||||
myInt = i + anInt;
|
||||
int j = 4;
|
||||
j = 5;
|
||||
myString = string.substring(j);
|
||||
}
|
||||
}
|
||||
|
||||
class Usage {
|
||||
private WithCtor wc1 = new With<caret>Ctor(17, "Sa");
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
class Usage {
|
||||
private Object wc1 = new Object() {
|
||||
private int myInt = 8;
|
||||
private String myString = "Sashya";
|
||||
|
||||
{
|
||||
int i = 2;
|
||||
i = 3;
|
||||
myInt = i + 17;
|
||||
int j = 4;
|
||||
j = 5;
|
||||
myString = "Sa".substring(j);
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
public class SelfParams {
|
||||
private int myVar = 0;
|
||||
|
||||
private int myProp = 0;
|
||||
public int getProp() {
|
||||
return myProp;
|
||||
}
|
||||
public void setProp(int prop) {
|
||||
myProp = prop;
|
||||
}
|
||||
|
||||
public void copy(SelfParams sp) {
|
||||
this.myVar = sp.myVar;
|
||||
this.myProp = sp.getProp();
|
||||
}
|
||||
}
|
||||
|
||||
class Usage {
|
||||
SelfParams s = new Self<caret>Params();
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
public class Simple implements Runnable{
|
||||
void foo(Simple s) {
|
||||
System.out.println(s.toString());
|
||||
s.run();
|
||||
}
|
||||
|
||||
public void run(){
|
||||
}
|
||||
}
|
||||
|
||||
class Usage {
|
||||
Simple s = new Sim<caret>ple();
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
class Usage {
|
||||
Runnable s = new Runnable() {
|
||||
void foo(Runnable s) {
|
||||
System.out.println(s.toString());
|
||||
s.run();
|
||||
}
|
||||
|
||||
public void run(){
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
package pack2;
|
||||
|
||||
public class A {
|
||||
public static class Class1 {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package packUser;
|
||||
|
||||
import pack2.A.Class1;
|
||||
|
||||
public class Class2 {
|
||||
Class1 myClass1;
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
package pack1;
|
||||
|
||||
public class Class1 {
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
package pack2;
|
||||
|
||||
public class A {
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package packUser;
|
||||
|
||||
import pack1.Class1;
|
||||
|
||||
public class Class2 {
|
||||
Class1 myClass1;
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package pack1;
|
||||
|
||||
import pack2.A;
|
||||
|
||||
class Usage {
|
||||
A.Class1 cl1;
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
package pack2;
|
||||
|
||||
public interface A {
|
||||
static class Class1 {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
package pack1;
|
||||
|
||||
class Class1 {
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
package pack1;
|
||||
class Usage {
|
||||
Class1 cl1;
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
package pack2;
|
||||
|
||||
public interface A {
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package pack1;
|
||||
class D {
|
||||
protected void iAmProtected() {
|
||||
}
|
||||
}
|
||||
|
||||
public class DImpl extends D {
|
||||
}
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
package pack1;
|
||||
|
||||
public class MyRunnable {
|
||||
private DImpl d;
|
||||
|
||||
public MyRunnable(DImpl d) {
|
||||
this.d = d;
|
||||
}
|
||||
|
||||
public void run() {
|
||||
d.iAmProtected();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package pack1;
|
||||
class D {
|
||||
protected void iAmProtected() {
|
||||
}
|
||||
}
|
||||
|
||||
public class DImpl extends D {
|
||||
public class MyRunnable {
|
||||
public void run() {
|
||||
iAmProtected();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
public class D {
|
||||
protected void iAmProtected() {
|
||||
}
|
||||
}
|
||||
|
||||
class DImpl extends D {
|
||||
void f<caret>oo(F f) {
|
||||
class MyRunnable {
|
||||
public void run() {
|
||||
iAmProtected();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class F {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
public class D {
|
||||
protected void iAmProtected() {
|
||||
}
|
||||
}
|
||||
|
||||
class DImpl extends D {
|
||||
}
|
||||
|
||||
class F {
|
||||
|
||||
void foo(D d) {
|
||||
class MyRunnable {
|
||||
public void run() {
|
||||
d.iAmProtected();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
public interface Bar extends IFoo, IBar {
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
public class BarImpl implements Bar {
|
||||
public String getText() {
|
||||
return "hello";
|
||||
}
|
||||
|
||||
public IBar getIBar() {
|
||||
return this;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
public interface IBar {
|
||||
String getText();
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
public interface IFoo {
|
||||
IBar getIBar();
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
public interface Bar extends IFoo, IBar {
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
public class BarImpl implements Bar {
|
||||
public String getText() {
|
||||
return "hello";
|
||||
}
|
||||
|
||||
public IBar getIBar() {
|
||||
return this;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
public interface IBar {
|
||||
String getText();
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
public interface IFoo {
|
||||
String <caret>getText();
|
||||
IBar getIBar();
|
||||
}
|
||||
@@ -9,6 +9,7 @@ import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.PsiClass;
|
||||
import com.intellij.psi.PsiDocumentManager;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.codeStyle.CodeStyleSettingsManager;
|
||||
import com.intellij.psi.impl.source.PostprocessReformattingAspect;
|
||||
import com.intellij.psi.search.ProjectScope;
|
||||
import com.intellij.refactoring.move.moveClassesOrPackages.MoveClassToInnerProcessor;
|
||||
@@ -35,6 +36,17 @@ public class MoveClassToInnerTest extends CodeInsightTestCase {
|
||||
doTest(new String[] { "pack1.Class1" }, "pack2.A");
|
||||
}
|
||||
|
||||
public void testInsertInnerClassImport() throws Exception {
|
||||
final boolean imports = CodeStyleSettingsManager.getSettings(myProject).INSERT_INNER_CLASS_IMPORTS;
|
||||
try {
|
||||
CodeStyleSettingsManager.getSettings(myProject).INSERT_INNER_CLASS_IMPORTS = true;
|
||||
doTest(new String[] { "pack1.Class1" }, "pack2.A");
|
||||
}
|
||||
finally {
|
||||
CodeStyleSettingsManager.getSettings(myProject).INSERT_INNER_CLASS_IMPORTS = imports;
|
||||
}
|
||||
}
|
||||
|
||||
public void testSimultaneousMove() throws Exception {
|
||||
doTest(new String[] { "pack1.Class1", "pack0.Class0" }, "pack2.A");
|
||||
}
|
||||
@@ -67,6 +79,10 @@ public class MoveClassToInnerTest extends CodeInsightTestCase {
|
||||
doTest(new String[] { "pack1.Class1" }, "pack1.A");
|
||||
}
|
||||
|
||||
public void testLocallyUsedPackageLocalToPublicInterface() throws Exception {
|
||||
doTest(new String[]{"pack1.Class1"}, "pack2.A");
|
||||
}
|
||||
|
||||
public void testPackageLocalClass() throws Exception {
|
||||
doTestConflicts("pack1.Class1", "pack2.A", "Field <b><code>Class1.c2</code></b> uses a package-local class <b><code>pack1.Class2</code></b>.");
|
||||
}
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
package com.intellij.refactoring;
|
||||
|
||||
import com.intellij.JavaTestUtil;
|
||||
import com.intellij.openapi.fileEditor.FileDocumentManager;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.impl.source.PostprocessReformattingAspect;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.refactoring.move.moveInner.MoveInnerDialog;
|
||||
import com.intellij.refactoring.move.moveInner.MoveInnerImpl;
|
||||
import com.intellij.refactoring.move.moveInner.MoveInnerProcessor;
|
||||
import com.intellij.JavaTestUtil;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -64,6 +65,21 @@ public class MoveInnerTest extends MultiFileTestCase {
|
||||
doTest(createAction("p.A.E", "E", false, null, false, false, null));
|
||||
}
|
||||
|
||||
public void testQualifyThisHierarchy() throws Exception {
|
||||
final String innerClassName = "pack1.DImpl.MyRunnable";
|
||||
doTest(new MyPerformAction(innerClassName, "MyRunnable", false, "d",
|
||||
false, false, null) {
|
||||
@Override
|
||||
protected boolean isPassOuterClass() {
|
||||
final PsiClass outerClass = getJavaFacade().findClass("pack1.DImpl", GlobalSearchScope.moduleScope(myModule));
|
||||
assertNotNull(outerClass);
|
||||
final PsiClass innerClass = getJavaFacade().findClass(innerClassName, GlobalSearchScope.moduleScope(myModule));
|
||||
assertNotNull(innerClass);
|
||||
return MoveInnerDialog.isThisNeeded(innerClass, outerClass);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private PerformAction createAction(@NonNls final String innerClassName,
|
||||
@NonNls final String newClassName,
|
||||
final boolean passOuterClass,
|
||||
@@ -71,28 +87,52 @@ public class MoveInnerTest extends MultiFileTestCase {
|
||||
final boolean searchInComments,
|
||||
final boolean searchInNonJava,
|
||||
@NonNls @Nullable final String packageName) {
|
||||
return new PerformAction() {
|
||||
public void performAction(VirtualFile rootDir, VirtualFile rootAfter) throws Exception {
|
||||
final JavaPsiFacade manager = getJavaFacade();
|
||||
final PsiClass aClass = manager.findClass(innerClassName, GlobalSearchScope.moduleScope(myModule));
|
||||
final MoveInnerProcessor moveInnerProcessor = new MoveInnerProcessor(myProject, null);
|
||||
final PsiElement targetContainer = packageName != null ? findDirectory(packageName) : MoveInnerImpl.getTargetContainer(aClass, false);
|
||||
assertNotNull(targetContainer);
|
||||
moveInnerProcessor.setup(aClass, newClassName, passOuterClass, parameterName,
|
||||
searchInComments, searchInNonJava, targetContainer);
|
||||
moveInnerProcessor.run();
|
||||
PostprocessReformattingAspect.getInstance(getProject()).doPostponedFormatting();
|
||||
PsiDocumentManager.getInstance(myProject).commitAllDocuments();
|
||||
FileDocumentManager.getInstance().saveAllDocuments();
|
||||
}
|
||||
|
||||
private PsiElement findDirectory(final String packageName) {
|
||||
final PsiPackage aPackage = JavaPsiFacade.getInstance(myPsiManager.getProject()).findPackage(packageName);
|
||||
assert aPackage != null;
|
||||
final PsiDirectory[] directories = aPackage.getDirectories();
|
||||
return directories [0];
|
||||
}
|
||||
};
|
||||
return new MyPerformAction(innerClassName, newClassName, passOuterClass, parameterName, searchInComments, searchInNonJava, packageName);
|
||||
}
|
||||
|
||||
private class MyPerformAction implements PerformAction {
|
||||
private final String myInnerClassName;
|
||||
private final String myPackageName;
|
||||
private final String myNewClassName;
|
||||
private final boolean myPassOuterClass;
|
||||
private final String myParameterName;
|
||||
private final boolean mySearchInComments;
|
||||
private final boolean mySearchInNonJava;
|
||||
|
||||
public MyPerformAction(String innerClassName, String newClassName, boolean passOuterClass, String parameterName, boolean searchInComments,
|
||||
boolean searchInNonJava,
|
||||
String packageName) {
|
||||
myInnerClassName = innerClassName;
|
||||
myPackageName = packageName;
|
||||
myNewClassName = newClassName;
|
||||
myPassOuterClass = passOuterClass;
|
||||
myParameterName = parameterName;
|
||||
mySearchInComments = searchInComments;
|
||||
mySearchInNonJava = searchInNonJava;
|
||||
}
|
||||
|
||||
public void performAction(VirtualFile rootDir, VirtualFile rootAfter) throws Exception {
|
||||
final JavaPsiFacade manager = getJavaFacade();
|
||||
final PsiClass aClass = manager.findClass(myInnerClassName, GlobalSearchScope.moduleScope(myModule));
|
||||
final MoveInnerProcessor moveInnerProcessor = new MoveInnerProcessor(myProject, null);
|
||||
final PsiElement targetContainer = myPackageName != null ? findDirectory(myPackageName) : MoveInnerImpl.getTargetContainer(aClass, false);
|
||||
assertNotNull(targetContainer);
|
||||
moveInnerProcessor.setup(aClass, myNewClassName, isPassOuterClass(), myParameterName, mySearchInComments, mySearchInNonJava, targetContainer);
|
||||
moveInnerProcessor.run();
|
||||
PostprocessReformattingAspect.getInstance(getProject()).doPostponedFormatting();
|
||||
PsiDocumentManager.getInstance(myProject).commitAllDocuments();
|
||||
FileDocumentManager.getInstance().saveAllDocuments();
|
||||
}
|
||||
|
||||
protected boolean isPassOuterClass() {
|
||||
return myPassOuterClass;
|
||||
}
|
||||
|
||||
private PsiElement findDirectory(final String packageName) {
|
||||
final PsiPackage aPackage = JavaPsiFacade.getInstance(myPsiManager.getProject()).findPackage(packageName);
|
||||
assert aPackage != null;
|
||||
final PsiDirectory[] directories = aPackage.getDirectories();
|
||||
return directories [0];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package com.intellij.refactoring;
|
||||
|
||||
import com.intellij.JavaTestUtil;
|
||||
import com.intellij.codeInsight.TargetElementUtilBase;
|
||||
import com.intellij.idea.Bombed;
|
||||
import com.intellij.openapi.roots.ProjectRootManager;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.PsiClass;
|
||||
@@ -12,6 +13,7 @@ import com.intellij.testFramework.IdeaTestUtil;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Calendar;
|
||||
|
||||
public class SafeDeleteTest extends MultiFileTestCase {
|
||||
private VirtualFile myRootBefore;
|
||||
@@ -51,6 +53,12 @@ public class SafeDeleteTest extends MultiFileTestCase {
|
||||
doTest("IFoo");
|
||||
}
|
||||
|
||||
@Bombed(day = 3, month = Calendar.FEBRUARY, description = "should not delete method implementing IBar interface")
|
||||
public void testMultipleInterfacesImplementationThroughCommonInterface() throws Exception {
|
||||
myDoCompare = false;
|
||||
doTest("IFoo");
|
||||
}
|
||||
|
||||
public void testExtendsList() throws Exception {
|
||||
myDoCompare = false;
|
||||
doTest("B");
|
||||
|
||||
@@ -13,6 +13,8 @@ import com.intellij.usageView.UsageInfo;
|
||||
import com.intellij.util.containers.MultiMap;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
/**
|
||||
* @author yole
|
||||
*/
|
||||
@@ -218,6 +220,14 @@ public class InlineToAnonymousClassTest extends LightCodeInsightTestCase {
|
||||
doTest(false, true);
|
||||
}
|
||||
|
||||
public void testMultipleAssignments() throws Exception {
|
||||
doTest(false, true);
|
||||
}
|
||||
|
||||
public void testParamTypeReplacement() throws Exception {
|
||||
doTest(false, true);
|
||||
}
|
||||
|
||||
public void testNoInlineAbstract() throws Exception {
|
||||
doTestNoInline("Abstract classes cannot be inlined");
|
||||
}
|
||||
@@ -318,13 +328,29 @@ public class InlineToAnonymousClassTest extends LightCodeInsightTestCase {
|
||||
doTestPreprocessUsages("Class is never used");
|
||||
}
|
||||
|
||||
public void testNoInlineRecursiveAccess() throws Exception {
|
||||
doTestConflict("Class cannot be inlined because a call to its member inside body", "Class cannot be inlined because a call to its member inside body");
|
||||
}
|
||||
|
||||
public void testConflictInaccessibleOuterField() throws Exception {
|
||||
doTestConflict(
|
||||
"Field <b><code>C2.a</code></b> that is used in inlined method is not accessible from call site(s) in method <b><code>C2User.test()</code></b>");
|
||||
}
|
||||
|
||||
public void testGetClassConflict() throws Exception {
|
||||
doTestConflict("Result of getClass() invocation would be changed", "Result of getClass() invocation would be changed");
|
||||
}
|
||||
|
||||
public void doTestConflict(final String... expected) throws Exception {
|
||||
InlineToAnonymousClassProcessor processor = prepareProcessor();
|
||||
UsageInfo[] usages = processor.findUsages();
|
||||
MultiMap<PsiElement,String> conflicts = processor.getConflicts(usages);
|
||||
assertEquals(1, conflicts.size());
|
||||
assertEquals("Field <b><code>C2.a</code></b> that is used in inlined method is not accessible from call site(s) in method <b><code>C2User.test()</code></b>",
|
||||
conflicts.values().iterator().next());
|
||||
assertEquals(expected.length, conflicts.size());
|
||||
final Iterator<? extends String> iterator = conflicts.values().iterator();
|
||||
for (String s : expected) {
|
||||
assertTrue(iterator.hasNext());
|
||||
assertEquals(s, iterator.next());
|
||||
}
|
||||
}
|
||||
|
||||
private void doTestNoInline(final String expectedMessage) throws Exception {
|
||||
|
||||
@@ -31,6 +31,8 @@ public class MoveInstanceMethodTest extends LightCodeInsightTestCase {
|
||||
|
||||
public void testQualifiedThis() throws Exception { doTest(true, 0); }
|
||||
|
||||
public void testQualifyThisHierarchy() throws Exception {doTest(true, 0);}
|
||||
|
||||
public void testTwoParams() throws Exception { doTest(true, 0); }
|
||||
|
||||
public void testNoThisParam() throws Exception { doTest(false, 0); }
|
||||
|
||||
@@ -35,6 +35,7 @@ public class ToggleBookmarkAction extends BookmarksAction implements DumbAware {
|
||||
Project project = PlatformDataKeys.PROJECT.getData(dataContext);
|
||||
if (project == null) return;
|
||||
BookmarkInContextInfo info = new BookmarkInContextInfo(dataContext, project).invoke();
|
||||
if (info.getFile() == null) return;
|
||||
|
||||
if (info.getBookmarkAtPlace() != null) {
|
||||
BookmarkManager.getInstance(project).removeBookmark(info.getBookmarkAtPlace());
|
||||
|
||||
@@ -47,12 +47,13 @@ public abstract class ToggleNumberedBookmarkActionBase extends AnAction implemen
|
||||
DataContext dataContext = e.getDataContext();
|
||||
final Project project = PlatformDataKeys.PROJECT.getData(dataContext);
|
||||
|
||||
final BookmarkManager manager = BookmarkManager.getInstance(project);
|
||||
BookmarksAction.BookmarkInContextInfo info = new BookmarksAction.BookmarkInContextInfo(dataContext, project).invoke();
|
||||
if (info.getFile() == null) return;
|
||||
|
||||
final Bookmark oldBookmark = info.getBookmarkAtPlace();
|
||||
|
||||
if (oldBookmark != null) {
|
||||
manager.removeBookmark(oldBookmark);
|
||||
BookmarkManager.getInstance(project).removeBookmark(oldBookmark);
|
||||
}
|
||||
|
||||
if (oldBookmark == null || oldBookmark.getMnemonic() != '0' + myNumber) {
|
||||
|
||||
@@ -560,6 +560,7 @@ automatic.renamer.rename.to.column=Rename To
|
||||
rename.0.and.its.usages.to=Rename {0} and its usages to:
|
||||
rename.variables=Rename &variables
|
||||
rename.inheritors=Rename &inheritors
|
||||
rename.parameters.hierarchy=Rename parameters in hier&archy
|
||||
rename.bound.forms=Rename bound &forms
|
||||
inner.class.0.is.already.defined.in.class.1=Inner class {0} is already defined in class {1}.\nContinue anyway?
|
||||
class.0.already.exists=Class {0} already exists
|
||||
|
||||
Reference in New Issue
Block a user