IDEA-87401 For intention "Assign Parameter to Field", provide a "Assign All Unassigned Parameters to Fields" implemented

This commit is contained in:
Danila Ponomarenko
2012-06-18 20:25:08 +04:00
parent 4849752e85
commit c0f55c7ea5
47 changed files with 172 additions and 129 deletions
@@ -43,19 +43,10 @@ public class AssignFieldFromParameterAction extends BaseIntentionAction {
final PsiParameter myParameter = FieldFromParameterUtils.findParameterAtCursor(file, editor);
final PsiType type = FieldFromParameterUtils.getType(myParameter);
final PsiClass targetClass = PsiTreeUtil.getParentOfType(myParameter, PsiClass.class);
if (myParameter == null
|| !myParameter.isValid()
|| !myParameter.getManager().isInProject(myParameter)
|| !(myParameter.getDeclarationScope() instanceof PsiMethod)
|| ((PsiMethod)myParameter.getDeclarationScope()).getBody() == null
|| type == null
|| !type.isValid()
|| targetClass == null
|| targetClass.isInterface()
|| FieldFromParameterUtils.getParameterAssignedToField(myParameter) != null) {
if (!FieldFromParameterUtils.isAvailable(myParameter, type, targetClass)) {
return false;
}
final PsiField field = findFieldToAssign(myParameter);
final PsiField field = findFieldToAssign(project, myParameter);
if (field == null) return false;
if (!field.getLanguage().isKindOf(JavaLanguage.INSTANCE)) return false;
setText(CodeInsightBundle.message("intention.assign.field.from.parameter.text", field.getName()));
@@ -71,12 +62,12 @@ public class AssignFieldFromParameterAction extends BaseIntentionAction {
@Override
public void invoke(@NotNull Project project, Editor editor, PsiFile file) {
PsiParameter myParameter = FieldFromParameterUtils.findParameterAtCursor(file, editor);
final PsiParameter myParameter = FieldFromParameterUtils.findParameterAtCursor(file, editor);
if (!CodeInsightUtilBase.prepareFileForWrite(myParameter.getContainingFile())) return;
IdeDocumentHistory.getInstance(project).includeCurrentPlaceAsChangePlace();
try {
PsiField field = findFieldToAssign(myParameter);
PsiField field = findFieldToAssign(project, myParameter);
if (field != null) addFieldAssignmentStatement(project, field, myParameter, editor);
}
catch (IncorrectOperationException e) {
@@ -84,53 +75,18 @@ public class AssignFieldFromParameterAction extends BaseIntentionAction {
}
}
public static void addFieldAssignmentStatement(@NotNull Project project,
@NotNull PsiField field,
@NotNull PsiParameter parameter,
@NotNull Editor editor) throws IncorrectOperationException {
final PsiMethod method = (PsiMethod)parameter.getDeclarationScope();
PsiCodeBlock methodBody = method.getBody();
if (methodBody == null) return;
PsiManager psiManager = PsiManager.getInstance(project);
PsiElementFactory factory = JavaPsiFacade.getInstance(psiManager.getProject()).getElementFactory();
String fieldName = field.getName();
String parameterName = parameter.getName();
final boolean isMethodStatic = method.hasModifierProperty(PsiModifier.STATIC);
PsiClass targetClass = method.getContainingClass();
String stmtText = fieldName + " = " + parameterName + ";";
if (Comparing.strEqual(fieldName, parameterName) || JavaPsiFacade.getInstance(project).getResolveHelper().resolveReferencedVariable(fieldName, methodBody) != field) {
@NonNls String prefix = isMethodStatic ? targetClass.getName() == null ? "" : targetClass.getName() + "." : "this.";
stmtText = prefix + stmtText;
}
PsiStatement assignmentStmt = factory.createStatementFromText(stmtText, methodBody);
assignmentStmt = (PsiStatement)CodeStyleManager.getInstance(project).reformat(assignmentStmt);
PsiStatement[] statements = methodBody.getStatements();
int i = FieldFromParameterUtils.findFieldAssignmentAnchor(statements, null, targetClass, parameter);
PsiElement inserted;
if (i == statements.length) {
inserted = methodBody.add(assignmentStmt);
}
else {
inserted = methodBody.addAfter(assignmentStmt, i > 0 ? statements[i - 1] : null);
}
editor.getCaretModel().moveToOffset(inserted.getTextRange().getEndOffset());
editor.getScrollingModel().scrollToCaret(ScrollType.RELATIVE);
}
@Nullable
private static PsiField findFieldToAssign(final PsiParameter myParameter) {
final JavaCodeStyleManager styleManager = JavaCodeStyleManager.getInstance(myParameter.getProject());
private static PsiField findFieldToAssign(@NotNull Project project,
@NotNull PsiParameter myParameter) {
final JavaCodeStyleManager styleManager = JavaCodeStyleManager.getInstance(project);
final String parameterName = myParameter.getName();
String propertyName = styleManager.variableNameToPropertyName(parameterName, VariableKind.PARAMETER);
final String propertyName = styleManager.variableNameToPropertyName(parameterName, VariableKind.PARAMETER);
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, FieldFromParameterUtils.getSubstitutedType(myParameter));
final VariableKind kind = isMethodStatic ? VariableKind.STATIC_FIELD : VariableKind.FIELD;
final SuggestedNameInfo suggestedNameInfo = styleManager.suggestVariableName(kind, propertyName, null, FieldFromParameterUtils.getSubstitutedType(myParameter));
final String fieldName = suggestedNameInfo.names[0];
@@ -143,5 +99,37 @@ public class AssignFieldFromParameterAction extends BaseIntentionAction {
return field;
}
public static void addFieldAssignmentStatement(@NotNull Project project,
@NotNull PsiField field,
@NotNull PsiParameter parameter,
@NotNull Editor editor) throws IncorrectOperationException {
final PsiMethod method = (PsiMethod)parameter.getDeclarationScope();
final PsiCodeBlock methodBody = method.getBody();
if (methodBody == null) return;
final PsiElementFactory factory = JavaPsiFacade.getInstance(project).getElementFactory();
final String fieldName = field.getName();
final String parameterName = parameter.getName();
final boolean isMethodStatic = method.hasModifierProperty(PsiModifier.STATIC);
final PsiClass targetClass = method.getContainingClass();
if (targetClass == null) return;
String stmtText = fieldName + " = " + parameterName + ";";
if (Comparing.strEqual(fieldName, parameterName) || JavaPsiFacade.getInstance(project).getResolveHelper().resolveReferencedVariable(fieldName, methodBody) != field) {
@NonNls String prefix = isMethodStatic ? targetClass.getName() == null ? "" : targetClass.getName() + "." : "this.";
stmtText = prefix + stmtText;
}
final PsiStatement assignmentStmt = (PsiStatement)CodeStyleManager.getInstance(project).reformat(factory.createStatementFromText(stmtText, methodBody));
final PsiStatement[] statements = methodBody.getStatements();
final int i = FieldFromParameterUtils.findFieldAssignmentAnchor(statements, null, targetClass, parameter);
final PsiElement inserted;
if (i == statements.length) {
inserted = methodBody.add(assignmentStmt);
}
else {
inserted = methodBody.addAfter(assignmentStmt, i > 0 ? statements[i - 1] : null);
}
editor.getCaretModel().moveToOffset(inserted.getTextRange().getEndOffset());
editor.getScrollingModel().scrollToCaret(ScrollType.RELATIVE);
}
}
@@ -33,8 +33,6 @@ 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.search.LocalSearchScope;
import com.intellij.psi.search.searches.ReferencesSearch;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.ui.SimpleColoredComponent;
import com.intellij.ui.SimpleTextAttributes;
@@ -70,7 +68,8 @@ public class CreateAssignFieldsFromParametersAction extends BaseIntentionAction
for (PsiParameter parameter : parameters) {
params.add(SmartPointerManager.getInstance(project).createSmartPsiElementPointer(parameter));
}
if (params.size() <= 1) return false;
if (params.isEmpty()) return false;
if (params.size() == 1 && psiParameter != null) return false;
if (psiParameter == null) {
psiParameter = params.iterator().next().getElement();
LOG.assertTrue(psiParameter != null);
@@ -115,18 +114,9 @@ public class CreateAssignFieldsFromParametersAction extends BaseIntentionAction
private static boolean isAvailable(PsiParameter psiParameter) {
final PsiType type = FieldFromParameterUtils.getSubstitutedType(psiParameter);
PsiClass targetClass = PsiTreeUtil.getParentOfType(psiParameter, PsiClass.class);
return psiParameter.isValid()
&& psiParameter.getLanguage().isKindOf(JavaLanguage.INSTANCE)
&& psiParameter.getDeclarationScope() instanceof PsiMethod
&& ((PsiMethod)psiParameter.getDeclarationScope()).getBody() != null
&& psiParameter.getManager().isInProject(psiParameter)
&& type != null
&& type.isValid()
&& FieldFromParameterUtils.getParameterAssignedToField(psiParameter) == null
&& targetClass != null
&& !targetClass.isInterface()
;
final PsiClass targetClass = PsiTreeUtil.getParentOfType(psiParameter, PsiClass.class);
return FieldFromParameterUtils.isAvailable(psiParameter, type, targetClass) &&
psiParameter.getLanguage().isKindOf(JavaLanguage.INSTANCE);
}
@NotNull
@@ -54,16 +54,8 @@ public class CreateFieldFromParameterAction extends BaseIntentionAction {
private static boolean isAvailable(PsiParameter psiParameter) {
final PsiType type = FieldFromParameterUtils.getSubstitutedType(psiParameter);
final PsiClass targetClass = PsiTreeUtil.getParentOfType(psiParameter, PsiClass.class);
return psiParameter.isValid()
&& psiParameter.getLanguage().isKindOf(JavaLanguage.INSTANCE)
&& psiParameter.getDeclarationScope() instanceof PsiMethod
&& ((PsiMethod)psiParameter.getDeclarationScope()).getBody() != null
&& psiParameter.getManager().isInProject(psiParameter)
&& type != null
&& type.isValid()
&& FieldFromParameterUtils.getParameterAssignedToField(psiParameter) == null
&& targetClass != null
&& !targetClass.isInterface();
return FieldFromParameterUtils.isAvailable(psiParameter, type, targetClass) &&
psiParameter.getLanguage().isKindOf(JavaLanguage.INSTANCE);
}
@Override
@@ -50,7 +50,8 @@ class CreateFieldFromParameterDialog extends DialogWrapper {
public CreateFieldFromParameterDialog(Project project,
String[] names,
PsiClass targetClass,
final boolean fieldMayBeFinal, PsiType... types) {
boolean fieldMayBeFinal,
PsiType... types) {
super(project, true);
myProject = project;
myNames = names;
@@ -16,7 +16,6 @@
package com.intellij.codeInsight.intention.impl;
import com.intellij.codeInsight.NullableNotNullManager;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Pair;
@@ -254,6 +253,20 @@ public final class FieldFromParameterUtils {
}
}
public static boolean isAvailable(@Nullable PsiParameter myParameter,
@Nullable PsiType type,
@Nullable PsiClass targetClass){
return myParameter != null
&& myParameter.isValid()
&& myParameter.getManager().isInProject(myParameter)
&& myParameter.getDeclarationScope() instanceof PsiMethod
&& ((PsiMethod)myParameter.getDeclarationScope()).getBody() != null
&& type != null
&& type.isValid()
&& targetClass != null
&& !targetClass.isInterface()
&& getParameterAssignedToField(myParameter) == null;
}
private FieldFromParameterUtils() {
}
}
@@ -1,4 +1,4 @@
// "Create Field For Parameter 'id'" "true"
// "Create Field for Parameter 'id'" "true"
class Person {
private String __fname;
@@ -1,4 +1,4 @@
// "Create Field For Parameter 'test'" "true"
// "Create Field for Parameter 'test'" "true"
package codeInsight.createFieldFromParameterAction.test1;
@@ -1,4 +1,4 @@
// "Create Field For Parameter 'length'" "true"
// "Create Field for Parameter 'length'" "true"
package codeInsight.createFieldFromParameterAction.test1;
@@ -1,4 +1,4 @@
// "Create Field For Parameter 'p1'" "true"
// "Create Field for Parameter 'p1'" "true"
class Test{
private final int myP1;
@@ -1,4 +1,4 @@
// "Create Field For Parameter 'p1'" "true"
// "Create Field for Parameter 'p1'" "true"
class Test{
int myP1;
@@ -1,4 +1,4 @@
// "Create Field For Parameter 'p1'" "true"
// "Create Field for Parameter 'p1'" "true"
class Test{
int myP1;
@@ -1,4 +1,4 @@
// "Create Field For Parameter 'p1'" "true"
// "Create Field for Parameter 'p1'" "true"
class Test{
private static int p1;
@@ -1,4 +1,4 @@
// "Create Field For Parameter 'p1'" "true"
// "Create Field for Parameter 'p1'" "true"
class Test{
private String[] myP1;
@@ -1,4 +1,4 @@
// "Create Field For Parameter 'p1'" "true"
// "Create Field for Parameter 'p1'" "true"
import java.util.*;
class Test{
@@ -1,10 +0,0 @@
// "Create Field For Parameter 'p1'" "true"
class Test{
private String myP1;
<T extends String> void f(T p1){
myP1 = p1;
}
}
@@ -1,4 +1,4 @@
// "Create Field For Parameter 'p1'" "true"
// "Create Field for Parameter 'p1'" "true"
class Test<T>{
private T myP1;
@@ -1,4 +1,4 @@
// "Create Field For Parameter 'p1'" "true"
// "Create Field for Parameter 'p1'" "true"
import java.util.*;
class Test<T>{
@@ -1,4 +1,4 @@
// "Create Field For Parameter 'p1'" "true"
// "Create Field for Parameter 'p1'" "true"
import java.util.*;
class Test{
@@ -1,4 +1,4 @@
// "Create Field For Parameter 'name'" "true"
// "Create Field for Parameter 'name'" "true"
import org.jetbrains.annotations.NotNull;
@@ -1,4 +1,4 @@
// "Create Field For Parameter 'name'" "true"
// "Create Field for Parameter 'name'" "true"
package codeInsight.createFieldFromParameterAction.test1;
@@ -1,4 +1,4 @@
// "Create Field For Parameter 'p1'" "true"
// "Create Field for Parameter 'p1'" "true"
class Test{
private Object myP1;
@@ -1,4 +1,4 @@
// "Create Field For Parameter 'p1'" "true"
// "Create Field for Parameter 'p1'" "true"
class Test{
private String myP1;
@@ -1,4 +1,4 @@
// "Create Field For Parameter 'id'" "true"
// "Create Field for Parameter 'id'" "true"
class Person {
private String __fname, __lname, __street;
@@ -1,4 +1,4 @@
// "Create Field For Parameter 'test'" "true"
// "Create Field for Parameter 'test'" "true"
package codeInsight.createFieldFromParameterAction.test1;
@@ -1,4 +1,4 @@
// "Create Field For Parameter 'length'" "true"
// "Create Field for Parameter 'length'" "true"
package codeInsight.createFieldFromParameterAction.test1;
@@ -1,4 +1,4 @@
// "Create Field For Parameter 'p1'" "true"
// "Create Field for Parameter 'p1'" "true"
class Test{
int myP2;
@@ -1,4 +1,4 @@
// "Create Field For Parameter 'p1'" "true"
// "Create Field for Parameter 'p1'" "true"
class Test{
int myP1;
@@ -1,4 +1,4 @@
// "Create Field For Parameter 'p1'" "true"
// "Create Field for Parameter 'p1'" "true"
class Test{
int myP1;
@@ -1,4 +1,4 @@
// "Create Field For Parameter 'p1'" "false"
// "Create Field for Parameter 'p1'" "false"
class Test{
int myP1;
@@ -1,4 +1,4 @@
// "Create Field For Parameter 'p1'" "true"
// "Create Field for Parameter 'p1'" "true"
class Test{
static void f(int p<caret>1){
@@ -1,4 +1,4 @@
// "Create Field For Parameter 'p1'" "true"
// "Create Field for Parameter 'p1'" "true"
class Test{
void f(String[] p<caret>1){
@@ -1,4 +1,4 @@
// "Create Field For Parameter 'p1'" "true"
// "Create Field for Parameter 'p1'" "true"
import java.util.*;
class Test{
@@ -1,4 +1,4 @@
// "Create Field For Parameter 'p1'" "true"
// "Create Field for Parameter 'p1'" "false"
class Test{
<T extends String> void <caret>f(T p1){
@@ -1,4 +1,4 @@
// "Create Field For Parameter 'p1'" "false"
// "Create Field for Parameter 'p1'" "false"
class Test{
private final String myP1;
@@ -1,4 +1,4 @@
// "Create Field For Parameter 'p1'" "false"
// "Create Field for Parameter 'p1'" "false"
class Test{
<T extends String> void <caret>f(){
@@ -1,4 +1,4 @@
// "Create Field For Parameter 'p1'" "true"
// "Create Field for Parameter 'p1'" "true"
class Test<T>{
void f(T p<caret>1){
@@ -1,4 +1,4 @@
// "Create Field For Parameter 'p1'" "true"
// "Create Field for Parameter 'p1'" "true"
import java.util.*;
class Test<T>{
@@ -1,4 +1,4 @@
// "Create Field For Parameter 'p1'" "true"
// "Create Field for Parameter 'p1'" "true"
import java.util.*;
class Test{
@@ -1,4 +1,4 @@
// "Create Field For Parameter 'name'" "true"
// "Create Field for Parameter 'name'" "true"
import org.jetbrains.annotations.NotNull;
@@ -1,4 +1,4 @@
// "Create Field For Parameter 'name'" "true"
// "Create Field for Parameter 'name'" "true"
package codeInsight.createFieldFromParameterAction.test1;
@@ -1,4 +1,4 @@
// "Create Field For Parameter 'p1'" "true"
// "Create Field for Parameter 'p1'" "true"
class Test{
<T> void f(T p<caret>1){
@@ -1,4 +1,4 @@
// "Create Field For Parameter 'p1'" "true"
// "Create Field for Parameter 'p1'" "true"
class Test{
<T extends String> void f(T p<caret>1){
@@ -0,0 +1,46 @@
/*
* Copyright 2000-2012 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.codeInsight.daemon.quickFix;
import com.intellij.codeInsight.daemon.LightIntentionActionTestCase;
import com.intellij.psi.codeStyle.CodeStyleSettings;
import com.intellij.psi.codeStyle.CodeStyleSettingsManager;
/**
* @author Danila Ponomarenko
*/
public class CreateAssignFieldsFromParametersTest extends LightIntentionActionTestCase {
@Override
protected void setUp() throws Exception {
super.setUp();
CodeStyleSettings settings = CodeStyleSettingsManager.getSettings(getProject());
settings.FIELD_NAME_PREFIX = "my";
}
@Override
protected void tearDown() throws Exception {
CodeStyleSettings settings = CodeStyleSettingsManager.getSettings(getProject());
settings.FIELD_NAME_PREFIX = "";
super.tearDown();
}
public void test() throws Exception { doAllTests(); }
@Override
protected String getBasePath() {
return "/codeInsight/daemonCodeAnalyzer/quickFix/createAssignFieldsFromParameters";
}
}
@@ -192,8 +192,8 @@ intention.assign.field.from.parameter.text=Assign Parameter to Field ''{0}''
intention.assign.field.from.parameter.family=Assign Parameter to Field
intention.create.field.from.parameter.text=Create Field for Parameter ''{0}''
intention.create.field.from.parameter.family=Create Field for Parameter
intention.create.assign.fields.from.parameters.text=Create/Assign Fields for {0} Parameters
intention.create.assign.fields.from.parameters.family=Create/Assign Fields for Parameters
intention.create.assign.fields.from.parameters.text=Create/Assign Fields from {0} Parameters
intention.create.assign.fields.from.parameters.family=Create/Assign Fields from Parameters
intention.implement.abstract.method.searching.for.descendants.progress=Searching For Descendants...
intention.implement.abstract.method.error.no.classes.message=There are no classes found where this method can be implemented
intention.implement.abstract.method.error.no.classes.title=No Classes Found
@@ -0,0 +1,12 @@
public class X {
int p1;
int p2;
int p3;
void f(int p1, int p2, int p3) {
this.p1 = p1;
this.p2 = p2;
this.p3 = p3;
}
}
@@ -0,0 +1,6 @@
public class X {
int p1;
void f(<spot>int p1, int p2, int p3</spot>) {
}
}
@@ -0,0 +1,5 @@
<html>
<body>
This intention allows to create or assign multiple fields from method parameters.
</body>
</html>