preselect available type, leave inacessible in combo

This commit is contained in:
anna
2010-08-09 18:54:31 +04:00
parent a97f796ed0
commit d8b0141c02
6 changed files with 111 additions and 48 deletions
@@ -71,7 +71,7 @@ public class IntroduceConstantHandler extends BaseExpressionToFieldHandler {
PsiLocalVariable local,
PsiExpression[] occurences,
boolean isStatic) {
return IntroduceConstantHandler.this.showRefactoringDialog(project, editor, aClass, local.getInitializer(), local.getType(), occurences, null, null);
return IntroduceConstantHandler.this.showRefactoringDialog(project, editor, aClass, local.getInitializer(), local.getType(), occurences, local, null);
}
};
return localToFieldHandler.convertLocalToField(localVariable, editor);
@@ -86,6 +86,7 @@ public class IntroduceConstantHandler extends BaseExpressionToFieldHandler {
PsiExpression[] occurences,
PsiElement anchorElement,
PsiElement anchorElementIfAll) {
final PsiMethod containingMethod = PsiTreeUtil.getParentOfType(expr != null ? expr : anchorElement, PsiMethod.class);
for (PsiExpression occurrence : occurences) {
if (RefactoringUtil.isAssignmentLHS(occurrence)) {
String message =
@@ -133,7 +134,7 @@ public class IntroduceConstantHandler extends BaseExpressionToFieldHandler {
final IntroduceConstantDialog dialog =
new IntroduceConstantDialog(project, parentClass, expr, localVariable, false, occurences, getParentClass(),
new TypeSelectorManagerImpl(project, type, expr, occurences));
new TypeSelectorManagerImpl(project, type, containingMethod, expr, occurences));
dialog.show();
if (!dialog.isOK()) {
if (occurences.length > 1) {
@@ -20,7 +20,6 @@ import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.wm.WindowManager;
import com.intellij.psi.*;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtil;
import com.intellij.refactoring.HelpID;
@@ -28,7 +27,6 @@ import com.intellij.refactoring.RefactoringBundle;
import com.intellij.refactoring.ui.TypeSelectorManagerImpl;
import com.intellij.refactoring.util.CommonRefactoringUtil;
import com.intellij.refactoring.util.occurences.*;
import com.intellij.util.ArrayUtil;
import org.jetbrains.annotations.NotNull;
public class IntroduceFieldHandler extends BaseExpressionToFieldHandler {
@@ -96,13 +94,12 @@ public class IntroduceFieldHandler extends BaseExpressionToFieldHandler {
final boolean currentMethodConstructor = containingMethod != null && containingMethod.isConstructor();
final boolean allowInitInMethod = (!currentMethodConstructor || !isInSuperOrThis) && anchorElement instanceof PsiStatement;
final boolean allowInitInMethodIfAll = (!currentMethodConstructor || !isInSuperOrThis) && anchorElementIfAll instanceof PsiStatement;
type = checkIfTypeAccessible(type, project, parentClass, containingMethod);
IntroduceFieldDialog dialog = new IntroduceFieldDialog(
project, parentClass, expr, localVariable,
currentMethodConstructor,
false, declareStatic, occurencesNumber,
allowInitInMethod, allowInitInMethodIfAll,
new TypeSelectorManagerImpl(project, type, expr, occurences)
new TypeSelectorManagerImpl(project, type, containingMethod, expr, occurences)
);
dialog.show();
@@ -125,23 +122,6 @@ public class IntroduceFieldHandler extends BaseExpressionToFieldHandler {
dialog.getFieldType(), localVariable != null, (TargetDestination)null, false, false);
}
private static PsiType checkIfTypeAccessible(PsiType type, Project project, PsiClass parentClass, PsiMethod containingMethod) {
final PsiClass typeClass = PsiUtil.resolveClassInType(type);
if (typeClass != null) {
if (typeClass instanceof PsiTypeParameter) {
if (ArrayUtil.find(parentClass.getTypeParameters(), typeClass) == -1) { //unknown type parameter
type = PsiType.getJavaLangObject(PsiManager.getInstance(project), GlobalSearchScope.allScope(project));
}
} else if (PsiTreeUtil.isAncestor(containingMethod, typeClass, true)) { //local class type
final PsiClassType[] superTypes = typeClass.getSuperTypes();
if (superTypes.length > 0) {
return checkIfTypeAccessible(superTypes[0], project, parentClass, containingMethod);
}
}
}
return type;
}
private static boolean isInSuperOrThis(PsiExpression occurence) {
return !NotInSuperCallOccurenceFilter.INSTANCE.isOK(occurence) || !NotInThisCallFilter.INSTANCE.isOK(occurence);
}
@@ -21,11 +21,14 @@ import com.intellij.codeInsight.ExpectedTypesProvider;
import com.intellij.codeInsight.TailType;
import com.intellij.openapi.project.Project;
import com.intellij.psi.*;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.statistics.StatisticsInfo;
import com.intellij.psi.statistics.StatisticsManager;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtil;
import com.intellij.psi.util.TypeConversionUtil;
import com.intellij.refactoring.util.RefactoringHierarchyUtil;
import com.intellij.util.ArrayUtil;
import gnu.trove.THashMap;
import org.jetbrains.annotations.NotNull;
@@ -35,7 +38,7 @@ import java.util.*;
* @author dsl
*/
public class TypeSelectorManagerImpl implements TypeSelectorManager {
private final PsiType myDefaultType;
private PsiType myDefaultType;
private final PsiExpression myMainOccurence;
private final PsiExpression[] myOccurrences;
private final PsiType[] myTypesForMain;
@@ -47,27 +50,7 @@ public class TypeSelectorManagerImpl implements TypeSelectorManager {
private ExpectedTypesProvider myExpectedTypesProvider;
public TypeSelectorManagerImpl(Project project, PsiType type, PsiExpression mainOccurence, PsiExpression[] occurrences) {
myFactory = JavaPsiFacade.getInstance(project).getElementFactory();
myDefaultType = type;
myMainOccurence = mainOccurence;
myOccurrences = occurrences;
myExpectedTypesProvider = ExpectedTypesProvider.getInstance(project);
myOccurrenceClassProvider = createOccurrenceClassProvider();
myTypesForMain = getTypesForMain();
myTypesForAll = getTypesForAll(true);
myIsOneSuggestion =
myTypesForMain.length == 1 && myTypesForAll.length == 1 &&
myTypesForAll[0].equals(myTypesForMain[0]);
if (myIsOneSuggestion) {
myTypeSelector = new TypeSelector(myTypesForAll[0]);
}
else {
myTypeSelector = new TypeSelector();
}
this(project, type, null, mainOccurence, occurrences);
}
public TypeSelectorManagerImpl(Project project, PsiType type, PsiExpression[] occurrences) {
@@ -94,10 +77,64 @@ public class TypeSelectorManagerImpl implements TypeSelectorManager {
}
}
public TypeSelectorManagerImpl(Project project,
PsiType type,
PsiMethod containingMethod,
PsiExpression mainOccurence,
PsiExpression[] occurrences) {
myFactory = JavaPsiFacade.getInstance(project).getElementFactory();
myDefaultType = type;
myMainOccurence = mainOccurence;
myOccurrences = occurrences;
myExpectedTypesProvider = ExpectedTypesProvider.getInstance(project);
myOccurrenceClassProvider = createOccurrenceClassProvider();
myTypesForMain = getTypesForMain();
myTypesForAll = getTypesForAll(true);
if (containingMethod != null) {
if (PsiUtil.resolveClassInType(type) != null) {
myDefaultType = checkIfTypeAccessible(type, project, containingMethod);
}
}
myIsOneSuggestion =
myTypesForMain.length == 1 && myTypesForAll.length == 1 &&
myTypesForAll[0].equals(myTypesForMain[0]);
if (myIsOneSuggestion) {
myTypeSelector = new TypeSelector(myTypesForAll[0]);
}
else {
myTypeSelector = new TypeSelector();
}
}
private PsiType checkIfTypeAccessible(PsiType type, Project project, PsiMethod containingMethod) {
PsiClass parentClass = containingMethod.getContainingClass();
final PsiClass typeClass = PsiUtil.resolveClassInType(type);
if (typeClass != null) {
if (typeClass instanceof PsiTypeParameter) {
if (ArrayUtil.find(parentClass.getTypeParameters(), typeClass) == -1) { //unknown type parameter
return PsiType.getJavaLangObject(PsiManager.getInstance(project), GlobalSearchScope.allScope(project));
}
} else if (PsiTreeUtil.isAncestor(containingMethod, typeClass, true)) { //local class type
final int nextTypeIdx = ArrayUtil.find(myTypesForAll, type) + 1;
if (nextTypeIdx < myTypesForAll.length) {
return checkIfTypeAccessible(myTypesForAll[nextTypeIdx], project, containingMethod);
}
}
}
return type;
}
public PsiType[] getTypesForAll() {
return myTypesForAll;
}
public PsiType getDefaultType() {
return myDefaultType;
}
private ExpectedTypesProvider.ExpectedClassProvider createOccurrenceClassProvider() {
final Set<PsiClass> occurrenceClasses = new HashSet<PsiClass>();
for (final PsiExpression occurence : myOccurrences) {
@@ -0,0 +1,6 @@
class Test {
void foo() {
class C {}
C c<caret>c;
}
}
@@ -0,0 +1,7 @@
class Test {
class C {}
void foo() {
C c<caret>c;
}
}
@@ -1,12 +1,13 @@
package com.intellij.refactoring;
import com.intellij.JavaTestUtil;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.openapi.projectRoots.impl.JavaSdkImpl;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiJavaFile;
import com.intellij.psi.PsiLocalVariable;
import com.intellij.psi.*;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.refactoring.ui.TypeSelectorManagerImpl;
import com.intellij.testFramework.LightCodeInsightTestCase;
import com.intellij.testFramework.TestDataPath;
import com.intellij.util.VisibilityUtil;
@@ -87,6 +88,37 @@ public class IntroduceConstantTest extends LightCodeInsightTestCase {
checkResultByFile(BASE_PATH + getTestName(false) + "_after.java");
}
public void testResultedType() throws Exception {
checkDefaultType("java.lang.Object");
}
public void testResultedTypeWhenNonLocal() throws Exception {
checkDefaultType("Test.C");
}
private void checkDefaultType(final String expectedType) throws Exception {
configureByFile(BASE_PATH + getTestName(false) + ".java");
new MockIntroduceConstantHandler(null){
@Override
protected Settings showRefactoringDialog(Project project,
Editor editor,
PsiClass parentClass,
PsiExpression expr,
PsiType type,
PsiExpression[] occurences,
PsiElement anchorElement,
PsiElement anchorElementIfAll) {
final TypeSelectorManagerImpl selectorManager =
new TypeSelectorManagerImpl(project, type, PsiTreeUtil.getParentOfType(anchorElement, PsiMethod.class), expr, occurences);
final PsiType psiType = selectorManager.getDefaultType();
Assert.assertEquals(psiType.getCanonicalText(), expectedType);
return new Settings("xxx", true, true, true,
InitializationPlace.IN_FIELD_DECLARATION, getVisibility(), null, psiType, false,
parentClass, false, false);
}
}.invoke(getProject(), getEditor(), getFile(), null);
}
protected Sdk getProjectJDK() {
return JavaSdkImpl.getMockJdk17("java 1.5");
}