introduce field: selected type should be used instead of local variable type

This commit is contained in:
anna
2010-05-21 11:40:03 +04:00
parent 55590c7a3c
commit b594f2d5a7
7 changed files with 57 additions and 8 deletions

View File

@@ -20,6 +20,7 @@ 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;
@@ -27,6 +28,7 @@ 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 {
@@ -90,6 +92,7 @@ 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,
@@ -118,6 +121,23 @@ 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);
}
@@ -146,4 +166,4 @@ public class IntroduceFieldHandler extends BaseExpressionToFieldHandler {
return !isInSuperOrThis(occurence);
}
}
}
}

View File

@@ -111,7 +111,7 @@ public abstract class LocalToFieldHandler {
final PsiMethod enclosingConstructor = BaseExpressionToFieldHandler.getEnclosingConstructor(aaClass, local);
PsiField field = settings.isIntroduceEnumConstant() ? EnumConstantsUtil.createEnumConstant(aaClass, local, fieldName)
: createField(local, fieldName, initializerPlace == IN_FIELD_DECLARATION);
: createField(local, settings.getForcedType(), fieldName, initializerPlace == IN_FIELD_DECLARATION);
field = (PsiField)aaClass.add(field);
BaseExpressionToFieldHandler.setModifiers(field, settings, isStatic);
if (!settings.isIntroduceEnumConstant()) {
@@ -175,7 +175,7 @@ public abstract class LocalToFieldHandler {
return true;
}
private PsiField createField(PsiLocalVariable local, String fieldName, boolean includeInitializer) {
private PsiField createField(PsiLocalVariable local, PsiType forcedType, String fieldName, boolean includeInitializer) {
@NonNls StringBuilder pattern = new StringBuilder();
pattern.append("private int ");
pattern.append(fieldName);
@@ -191,10 +191,10 @@ public abstract class LocalToFieldHandler {
PsiField field = factory.createFieldFromText(pattern.toString(), null);
field = (PsiField)CodeStyleManager.getInstance(myProject).reformat(field);
field.getTypeElement().replace(factory.createTypeElement(local.getType()));
field.getTypeElement().replace(factory.createTypeElement(forcedType));
if (includeInitializer) {
PsiExpression initializer =
RefactoringUtil.convertInitializerToNormalExpression(local.getInitializer(), local.getType());
RefactoringUtil.convertInitializerToNormalExpression(local.getInitializer(), forcedType);
field.getInitializer().replace(initializer);
}
@@ -269,4 +269,4 @@ public abstract class LocalToFieldHandler {
if (enclosingConstructor == null) local.delete();
}
}
}

View File

@@ -0,0 +1,7 @@
public class FieldTest {
public final int integer;
void foo() {
integer = new Integer(0);
}
}

View File

@@ -0,0 +1,5 @@
public class FieldTest {
void foo() {
Integer <selection>ii</selection> = new Integer(0);
}
}

View File

@@ -1,5 +1,7 @@
package com.intellij.refactoring;
import com.intellij.psi.PsiPrimitiveType;
import com.intellij.psi.PsiType;
import com.intellij.refactoring.introduceField.BaseExpressionToFieldHandler;
import com.intellij.testFramework.LightCodeInsightTestCase;
import com.intellij.JavaTestUtil;
@@ -34,4 +36,15 @@ public class IntroduceFieldInSameClassTest extends LightCodeInsightTestCase {
private static void performRefactoring(final BaseExpressionToFieldHandler.InitializationPlace initializationPlace, final boolean declareStatic) {
new MockIntroduceFieldHandler(initializationPlace, declareStatic).invoke(getProject(), myEditor, myFile, null);
}
public void testForcedFieldType() throws Exception {
configureByFile("/refactoring/introduceField/beforeForcedFieldType.java");
new MockIntroduceFieldHandler(BaseExpressionToFieldHandler.InitializationPlace.IN_CURRENT_METHOD, false){
@Override
protected PsiType getFieldType(PsiType type) {
return PsiPrimitiveType.INT;
}
}.invoke(getProject(), myEditor, myFile, null);
checkResultByFile("/refactoring/introduceField/afterForcedFieldType.java");
}
}

View File

@@ -26,6 +26,10 @@ public class MockIntroduceFieldHandler extends IntroduceFieldHandler {
return new Settings(name.names[0], true, myDeclareStatic, true, myInitializationPlace,
PsiModifier.PUBLIC,
null,
type, true, (TargetDestination)null, false, false);
getFieldType(type), true, (TargetDestination)null, false, false);
}
protected PsiType getFieldType(PsiType type) {
return type;
}
}

View File

@@ -21,6 +21,6 @@ public class MockLocalToFieldHandler extends LocalToFieldHandler {
protected BaseExpressionToFieldHandler.Settings showRefactoringDialog(PsiClass aClass, PsiLocalVariable local, PsiExpression[] occurences,
boolean isStatic) {
return new BaseExpressionToFieldHandler.Settings("xxx", true, isStatic, true, BaseExpressionToFieldHandler.InitializationPlace.IN_FIELD_DECLARATION,
PsiModifier.PRIVATE, local, null, false, aClass, true, myMakeEnumConstant);
PsiModifier.PRIVATE, local, local.getType(), false, aClass, true, myMakeEnumConstant);
}
}