create field from parameter: respect method type parameters ( IDEA-54438)

This commit is contained in:
anna
2010-05-27 20:00:11 +04:00
parent 9e165bcd23
commit cbbee75ac1
3 changed files with 51 additions and 18 deletions
@@ -32,9 +32,11 @@ import com.intellij.psi.codeStyle.CodeStyleManager;
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
import com.intellij.psi.codeStyle.SuggestedNameInfo;
import com.intellij.psi.codeStyle.VariableKind;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.search.LocalSearchScope;
import com.intellij.psi.search.searches.ReferencesSearch;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtil;
import com.intellij.util.ArrayUtil;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NonNls;
@@ -51,11 +53,19 @@ public class CreateFieldFromParameterAction implements IntentionAction {
private String myName = "";
@Nullable
private static PsiType getType(final PsiParameter parameter) {
private static PsiType[] getTypes(final PsiParameter parameter) {
if (parameter == null) return null;
PsiType type = parameter.getType();
if (type instanceof PsiEllipsisType) type = ((PsiEllipsisType)type).toArrayType();
return type;
final PsiClass psiClass = PsiUtil.resolveClassInType(type);
if (psiClass instanceof PsiTypeParameter && parameter.getDeclarationScope() == ((PsiTypeParameter)psiClass).getOwner()) {
final PsiReferenceList extendsList = psiClass.getExtendsList();
LOG.assertTrue(extendsList != null);
final PsiClassType[] types = extendsList.getReferencedTypes();
if (types.length > 0) return types;
return new PsiType[]{PsiType.getJavaLangObject(parameter.getManager(), GlobalSearchScope.allScope(parameter.getProject()))};
}
return new PsiType[]{type};
}
@NotNull
@@ -67,15 +77,15 @@ public class CreateFieldFromParameterAction implements IntentionAction {
PsiParameter myParameter = findParameterAtCursor(file, editor);
if (myParameter == null) return false;
myName = myParameter.getName();
final PsiType type = getType(myParameter);
final PsiType[] types = getTypes(myParameter);
PsiClass targetClass = PsiTreeUtil.getParentOfType(myParameter, PsiClass.class);
return
myParameter.isValid()
&& myParameter.getDeclarationScope() instanceof PsiMethod
&& ((PsiMethod)myParameter.getDeclarationScope()).getBody() != null
&& myParameter.getManager().isInProject(myParameter)
&& type != null
&& type.isValid()
&& types != null
&& types[0].isValid()
&& !isParameterAssignedToField(myParameter)
&& targetClass != null
&& !targetClass.isInterface()
@@ -125,21 +135,21 @@ public class CreateFieldFromParameterAction implements IntentionAction {
if (!CodeInsightUtilBase.prepareFileForWrite(myParameter.getContainingFile())) return;
IdeDocumentHistory.getInstance(project).includeCurrentPlaceAsChangePlace();
final PsiType type = getType(myParameter);
final PsiType[] types = getTypes(myParameter);
final JavaCodeStyleManager styleManager = JavaCodeStyleManager.getInstance(project);
final String parameterName = myParameter.getName();
String propertyName = styleManager.variableNameToPropertyName(parameterName, VariableKind.PARAMETER);
String fieldNameToCalc;
boolean isFinalToCalc;
PsiType type;
final PsiClass targetClass = PsiTreeUtil.getParentOfType(myParameter, PsiClass.class);
final PsiMethod method = (PsiMethod)myParameter.getDeclarationScope();
final boolean isMethodStatic = method.hasModifierProperty(PsiModifier.STATIC);
VariableKind kind = isMethodStatic ? VariableKind.STATIC_FIELD : VariableKind.FIELD;
SuggestedNameInfo suggestedNameInfo = styleManager.suggestVariableName(kind, propertyName, null, type);
SuggestedNameInfo suggestedNameInfo = styleManager.suggestVariableName(kind, propertyName, null, types[0]);
String[] names = suggestedNameInfo.names;
if (isInteractive) {
@@ -158,11 +168,12 @@ public class CreateFieldFromParameterAction implements IntentionAction {
CreateFieldFromParameterDialog dialog = new CreateFieldFromParameterDialog(
project,
names,
type.getCanonicalText(), targetClass, myBeFinal);
targetClass, myBeFinal, types);
dialog.show();
if (!dialog.isOK()) return;
type = dialog.getType();
if (type == null) return;
fieldNameToCalc = dialog.getEnteredName();
isFinalToCalc = dialog.isDeclareFinal();
@@ -171,17 +182,19 @@ public class CreateFieldFromParameterAction implements IntentionAction {
else {
isFinalToCalc = !isMethodStatic;
fieldNameToCalc = names[0];
type= types[0];
}
final boolean isFinal = isFinalToCalc;
final String fieldName = fieldNameToCalc;
final PsiType fieldType = type;
ApplicationManager.getApplication().runWriteAction(new Runnable() {
public void run() {
try {
PsiManager psiManager = PsiManager.getInstance(project);
PsiElementFactory factory = JavaPsiFacade.getInstance(psiManager.getProject()).getElementFactory();
PsiField field = factory.createField(fieldName, type);
PsiField field = factory.createField(fieldName, fieldType);
PsiModifierList modifierList = field.getModifierList();
modifierList.setModifierProperty(PsiModifier.STATIC, isMethodStatic);
modifierList.setModifierProperty(PsiModifier.FINAL, isFinal);
@@ -24,8 +24,11 @@ import com.intellij.openapi.ui.Messages;
import com.intellij.psi.JavaPsiFacade;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiField;
import com.intellij.psi.PsiType;
import com.intellij.refactoring.ui.TypeSelector;
import com.intellij.ui.DocumentAdapter;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import javax.swing.event.DocumentEvent;
@@ -35,19 +38,23 @@ import java.awt.event.*;
class CreateFieldFromParameterDialog extends DialogWrapper {
private final Project myProject;
private final String[] myNames;
private final String myType;
private final PsiType[] myTypes;
private final PsiClass myTargetClass;
private final boolean myFieldMayBeFinal;
private JComponent myNameField;
private JCheckBox myCbFinal;
private static final @NonNls String PROPERTY_NAME = "CREATE_FIELD_FROM_PARAMETER_DECLARE_FINAL";
private TypeSelector myTypeSelector;
public CreateFieldFromParameterDialog(Project project, String[] names, String type, PsiClass targetClass, final boolean fieldMayBeFinal) {
public CreateFieldFromParameterDialog(Project project,
String[] names,
PsiClass targetClass,
final boolean fieldMayBeFinal, PsiType... types) {
super(project, true);
myProject = project;
myNames = names;
myType = type;
myTypes = types;
myTargetClass = targetClass;
myFieldMayBeFinal = fieldMayBeFinal;
@@ -175,13 +182,21 @@ class CreateFieldFromParameterDialog extends DialogWrapper {
gbConstraints.anchor = GridBagConstraints.EAST;
gbConstraints.fill = GridBagConstraints.BOTH;
gbConstraints.gridwidth = 2;
gbConstraints.gridwidth = 1;
gbConstraints.weightx = 1;
gbConstraints.weighty = 1;
gbConstraints.gridx = 0;
gbConstraints.gridy = 0;
JLabel type = new JLabel(CodeInsightBundle.message("dialog.create.field.from.parameter.field.type.label", myType));
panel.add(type, gbConstraints);
final JLabel typeLabel = new JLabel(CodeInsightBundle.message("dialog.create.field.from.parameter.field.type.label"));
panel.add(typeLabel, gbConstraints);
gbConstraints.gridx = 1;
if (myTypes.length > 1) {
myTypeSelector = new TypeSelector();
myTypeSelector.setTypes(myTypes);
} else {
myTypeSelector = new TypeSelector(myTypes[0]);
}
panel.add(myTypeSelector.getComponent(), gbConstraints);
gbConstraints.gridwidth = 1;
gbConstraints.weightx = 0;
@@ -249,4 +264,9 @@ class CreateFieldFromParameterDialog extends DialogWrapper {
public JComponent getPreferredFocusedComponent() {
return myNameField;
}
@Nullable
public PsiType getType() {
return myTypeSelector.getSelectedType();
}
}
@@ -161,7 +161,7 @@ intention.color.chooser.dialog=Choose Color
dialog.create.field.from.parameter.title=Create Field
dialog.create.field.from.parameter.already.exists.text=Use existing field {0}?
dialog.create.field.from.parameter.already.exists.title=Field Already Exists
dialog.create.field.from.parameter.field.type.label=Field of type {0}
dialog.create.field.from.parameter.field.type.label=Field of type:
dialog.create.field.from.parameter.field.name.label=Name:
dialog.create.field.from.parameter.declare.final.checkbox=Declare &final
dialog.create.class.destination.package.label=Destination package: