import com.intellij.psi.util.PsiUtil;
import com.intellij.refactoring.RefactorJBundle;
import com.intellij.refactoring.extractclass.usageInfo.*;
+import com.intellij.refactoring.move.MoveInstanceMembersUtil;
import com.intellij.refactoring.psi.MethodInheritanceUtils;
import com.intellij.refactoring.psi.TypeParametersVisitor;
import com.intellij.refactoring.util.FixableUsageInfo;
final PsiField member = psiClass.findFieldByName(field.getName(), false);
if (member != null) {
members.add(member);
+ final PsiExpression initializer = member.getInitializer();
+ if (initializer != null) {
+ final boolean[] moveInitializerToConstructor = new boolean[1];
+ initializer.accept(new JavaRecursiveElementWalkingVisitor(){
+ @Override
+ public void visitReferenceExpression(PsiReferenceExpression expression) {
+ super.visitReferenceExpression(expression);
+ final PsiElement resolved = expression.resolve();
+ if (resolved instanceof PsiField && !members.contains(resolved)) {
+ moveInitializerToConstructor[0] = true;
+ }
+ }
+ });
+
+ if (moveInitializerToConstructor[0]) {
+ final PsiElementFactory elementFactory = JavaPsiFacade.getElementFactory(myProject);
+ PsiMethod constructor;
+ final PsiMethod[] constructors = psiClass.getConstructors();
+ if (constructors.length == 0) {
+ constructor = elementFactory.createConstructor();
+ constructor.setName(psiClass.getName());
+ constructor = (PsiMethod)psiClass.add(constructor);
+ } else {
+ constructor = constructors[0];
+ }
+ MoveInstanceMembersUtil.moveInitializerToConstructor(elementFactory, constructor, member);
+ }
+ }
+ }
+ }
+
+ if (myGenerateAccessors) {
+ final NecessaryAccessorsVisitor visitor = new NecessaryAccessorsVisitor();
+ for (PsiField field : fields) {
+ field.accept(visitor);
+ }
+ for (PsiMethod method : methods) {
+ method.accept(visitor);
+ }
+ for (PsiClass innerClass : innerClasses) {
+ innerClass.accept(visitor);
+ }
+ for (PsiField field : visitor.getFieldsNeedingGetter()) {
+ sourceClass.add(PropertyUtil.generateGetterPrototype(field));
+ }
+
+ for (PsiField field : visitor.getFieldsNeedingSetter()) {
+ sourceClass.add(PropertyUtil.generateSetterPrototype(field));
}
}
super.performRefactoring(usageInfos);
super.visitReferenceExpression(expression);
if (isProhibitedReference(expression)) {
final PsiField field = getReferencedField(expression);
- if (!hasGetter(field)) {
+ if (!hasGetter(field) && !isStaticFinal(field)) {
fieldsNeedingGetter.add(field);
}
}
}
+ private boolean isStaticFinal(PsiField field) {
+ final PsiModifierList modifierList = field.getModifierList();
+ logger.assertTrue(modifierList != null);
+ return modifierList.hasModifierProperty(PsiModifier.STATIC) && modifierList.hasModifierProperty(PsiModifier.FINAL);
+ }
+
public void visitAssignmentExpression(PsiAssignmentExpression expression) {
super.visitAssignmentExpression(expression);
final PsiExpression lhs = expression.getLExpression();
if (isProhibitedReference(lhs)) {
final PsiField field = getReferencedField(lhs);
- if (!hasGetter(field)) {
+ if (!hasGetter(field) && !isStaticFinal(field)) {
fieldsNeedingSetter.add(field);
}
}
}
if (isProhibitedReference(operand)) {
final PsiField field = getReferencedField(operand);
- if (!hasSetter(field)) {
+ if (!hasSetter(field) && !isStaticFinal(field)) {
fieldsNeedingSetter.add(field);
}
}
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
import com.intellij.psi.codeStyle.VariableKind;
-import com.intellij.psi.javadoc.PsiDocComment;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.util.PropertyUtil;
import com.intellij.psi.util.PsiUtil;
out.append(' ' + backPointerName + ";");
}
outputFieldsAndInitializers(out);
- if (hasNonStatic() || requiresBackPointer) {
+ if (needConstructor() || requiresBackPointer) {
outputConstructor(out);
}
outputMethods(out);
return false;
}
- private boolean hasNonStatic() {
+ private boolean needConstructor() {
for ( PsiField field : fields) {
if (!field.hasModifierProperty(PsiModifier.STATIC)) {
return true;
private void outputConstructor(@NonNls StringBuffer out) {
out.append("\tpublic " + className + '(');
- boolean isFirst = true;
if (requiresBackPointer) {
final String parameterName = myJavaCodeStyleManager.propertyNameToVariableName(backPointerName, VariableKind.PARAMETER);
out.append(originalClassName);
out.append('>');
}
out.append(' ' + parameterName);
- isFirst = false;
- }
- for (final PsiField field : fields) {
- if (field.hasModifierProperty(PsiModifier.STATIC)) {
- continue;
- }
- if (!field.hasInitializer()) {
- continue;
- }
- final PsiExpression initializer = field.getInitializer();
- if (PsiUtil.isConstantExpression(initializer)) {
- continue;
- }
- if (!isFirst) {
- out.append(", ");
- }
- isFirst = false;
- final PsiType type = field.getType();
- final String typeText = type.getCanonicalText();
- final String name = calculateStrippedName(field);
- final String parameterName = myJavaCodeStyleManager.propertyNameToVariableName(name, VariableKind.PARAMETER);
- out.append(typeText + ' ' + parameterName);
}
out.append(")");
}
}
- for (final PsiField field : fields) {
- if (field.hasModifierProperty(PsiModifier.STATIC)) {
- continue;
- }
- if (!field.hasInitializer()) {
- continue;
- }
- final PsiExpression initializer = field.getInitializer();
- if (PsiUtil.isConstantExpression(initializer)) {
- continue;
- }
- final String name = calculateStrippedName(field);
- final String parameterName = myJavaCodeStyleManager.propertyNameToVariableName(name, VariableKind.PARAMETER);
- final String fieldName = field.getName();
- if (fieldName.equals(parameterName)) {
- out.append("\t\tthis." + fieldName + " = " + parameterName + ";");
- }
- else {
- out.append("\t\t" + fieldName + " = " + parameterName + ";");
- }
- }
out.append("\t}");
}
private void outputField(PsiField field, @NonNls StringBuffer out) {
- final PsiDocComment docComment = getJavadocForVariable(field);
- if (docComment != null) {
- out.append(docComment.getText());
- }
- final PsiType type = field.getType();
- final String typeText = type.getCanonicalText();
- final String name = field.getName();
-
- @NonNls String modifierString;
- if (field.hasModifierProperty(PsiModifier.PUBLIC) && field.hasModifierProperty(PsiModifier.STATIC)) {
- modifierString = "public ";
- }
- else {
- modifierString = "private ";
- }
- if (field.hasModifierProperty(PsiModifier.STATIC)) {
- modifierString += "static ";
- }
- if (field.hasModifierProperty(PsiModifier.FINAL) && (myFieldsNeedingSetters == null || !myFieldsNeedingSetters.contains(field))) {
- modifierString += "final ";
- }
- if (field.hasModifierProperty(PsiModifier.TRANSIENT)) {
- modifierString += "transient ";
- }
- final PsiModifierList modifierList = field.getModifierList();
- final PsiAnnotation[] annotations = modifierList.getAnnotations();
- for (PsiAnnotation annotation : annotations) {
- final String annotationText = annotation.getText();
- out.append(annotationText);
- }
- out.append('\t');
- out.append(modifierString);
- out.append(typeText);
- out.append(' ');
- out.append(name);
- if (field.hasInitializer()) {
- final PsiExpression initializer = field.getInitializer();
- if (PsiUtil.isConstantExpression(initializer)) {
- out.append('=');
- out.append(initializer.getText());
- }
- }
- out.append(";");
- }
-
- private static PsiDocComment getJavadocForVariable(PsiVariable variable) {
- final PsiElement[] children = variable.getChildren();
- for (PsiElement child : children) {
- if (child instanceof PsiDocComment) {
- return (PsiDocComment)child;
- }
- }
- return null;
+ field.accept(new Mutator(out));
}
public void setRequiresBackPointer(boolean requiresBackPointer) {
myFieldsNeedingSetters = fieldsNeedingSetters;
}
+ private boolean fieldIsExtracted(PsiField field) {
+ for (PsiField psiField : fields) {
+ if (psiField.equals(field)) {
+ return true;
+ }
+ }
+ final PsiClass containingClass = field.getContainingClass();
+ return innerClasses.contains(containingClass);
+ }
+
private class Mutator extends JavaElementVisitor {
@NonNls
private final StringBuffer out;
out.append(backPointerName);
}
- private boolean fieldIsExtracted(PsiField field) {
- for (PsiField psiField : fields) {
- if (psiField.equals(field)) {
- return true;
- }
- }
- final PsiClass containingClass = field.getContainingClass();
- return innerClasses.contains(containingClass);
- }
+
public void visitMethodCallExpression(PsiMethodCallExpression call) {
final PsiReferenceExpression expression = call.getMethodExpression();
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtil;
import com.intellij.refactoring.RefactoringBundle;
+import com.intellij.refactoring.move.MoveInstanceMembersUtil;
import com.intellij.refactoring.util.RefactoringUIUtil;
import com.intellij.refactoring.util.RefactoringUtil;
import com.intellij.refactoring.util.javadoc.MethodJavaDocHelper;
if (referencedElement instanceof PsiField && mySettings.getNameForField((PsiField)referencedElement) != null) {
final PsiField field = PsiTreeUtil.getParentOfType(element, PsiField.class);
if (field != null) {
- moveInitializerToConstructor(factory, constructor, field);
+ MoveInstanceMembersUtil.moveInitializerToConstructor(factory, constructor, field);
}
}
}
modifierList.setModifierProperty(PsiModifier.FINAL, false);
}
- private static void moveInitializerToConstructor(PsiElementFactory factory, PsiMethod constructor, PsiField field) {
- final PsiExpression initializer = field.getInitializer();
- PsiExpression initializerCopy = (PsiExpression)initializer.copy();
- final PsiCodeBlock body = constructor.getBody();
- if (body != null) {
- try {
- String fieldName = field.getName();
- final PsiReferenceExpression refExpr = (PsiReferenceExpression)factory.createExpressionFromText(fieldName, body);
- if (refExpr.resolve() != null) fieldName = "this." + fieldName;
- PsiExpressionStatement statement = (PsiExpressionStatement)factory.createStatementFromText(fieldName + "= y;", null);
- if (initializerCopy instanceof PsiArrayInitializerExpression) {
- PsiType type = initializer.getType();
- PsiNewExpression newExpression =
- (PsiNewExpression)factory.createExpressionFromText("new " + type.getCanonicalText() + "{}", body);
- newExpression.getArrayInitializer().replace(initializerCopy);
- initializerCopy = newExpression;
- }
- ((PsiAssignmentExpression)statement.getExpression()).getRExpression().replace(initializerCopy);
- statement = (PsiExpressionStatement)field.getManager().getCodeStyleManager().reformat(statement);
- body.add(statement);
- initializer.delete();
- }
- catch (IncorrectOperationException e) {
- LOG.error(e);
- }
- }
- }
-
private void addAssignmentToField(final String parameterName, final PsiMethod constructor) {
@NonNls String fieldName = convertToFieldName(parameterName);
final PsiManager manager = PsiManager.getInstance(myProject);
*/
package com.intellij.refactoring.move;
+import com.intellij.openapi.diagnostic.Logger;
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.IncorrectOperationException;
import com.intellij.util.containers.HashSet;
import org.jetbrains.annotations.Nullable;
* @author ven
*/
public class MoveInstanceMembersUtil {
+ private static final Logger LOG = Logger.getInstance("#" + MoveInstanceMembersUtil.class.getName());
+
/**
* @param member nonstatic class member to search for class references in
* @return Set<PsiMember> in result map may be null in case no member is needed, but class itself is.
}
return null;
}
+
+ public static void moveInitializerToConstructor(PsiElementFactory factory, PsiMethod constructor, PsiField field) {
+ final PsiExpression initializer = field.getInitializer();
+ PsiExpression initializerCopy = (PsiExpression)initializer.copy();
+ final PsiCodeBlock body = constructor.getBody();
+ if (body != null) {
+ try {
+ String fieldName = field.getName();
+ final PsiReferenceExpression refExpr = (PsiReferenceExpression)factory.createExpressionFromText(fieldName, body);
+ if (refExpr.resolve() != null) fieldName = "this." + fieldName;
+ PsiExpressionStatement statement = (PsiExpressionStatement)factory.createStatementFromText(fieldName + "= y;", null);
+ if (initializerCopy instanceof PsiArrayInitializerExpression) {
+ PsiType type = initializer.getType();
+ PsiNewExpression newExpression =
+ (PsiNewExpression)factory.createExpressionFromText("new " + type.getCanonicalText() + "{}", body);
+ newExpression.getArrayInitializer().replace(initializerCopy);
+ initializerCopy = newExpression;
+ }
+ ((PsiAssignmentExpression)statement.getExpression()).getRExpression().replace(initializerCopy);
+ statement = (PsiExpressionStatement)field.getManager().getCodeStyleManager().reformat(statement);
+ body.add(statement);
+ initializer.delete();
+ }
+ catch (IncorrectOperationException e) {
+ LOG.error(e);
+ }
+ }
+ }
}
--- /dev/null
+public class Extracted {
+ static final int[] myT;
+
+ public Extracted() {
+ this.myT = new int[]{Test.ii};
+ }
+}
\ No newline at end of file
--- /dev/null
+class Test {
+ static final int ii = 1;
+}
\ No newline at end of file
--- /dev/null
+class Test {
+ static final int ii = 1;
+ static final int[] myT = {ii};
+}
\ No newline at end of file
--- /dev/null
+public class Extracted {
+ private final Test test;
+ int[] myT;
+
+ public Extracted(Test test) {
+ this.test = test;
+ this.myT = new int[]{test.getIi()};
+ }
+}
\ No newline at end of file
--- /dev/null
+class Test {
+ int ii = 1;
+
+ public int getIi() {
+ return ii;
+ }
+}
\ No newline at end of file
--- /dev/null
+class Test {
+ int ii = 1;
+ int[] myT = {ii};
+}
\ No newline at end of file
--- /dev/null
+public class Extracted {
+ static final int[] myT = {1, 2};
+}
\ No newline at end of file
--- /dev/null
+class Test {
+}
\ No newline at end of file
--- /dev/null
+class Test {
+ static final int[] myT = {1,2};
+}
\ No newline at end of file
public class Extracted {
- private int myT;
+ int myT;
public int getMyT() {
return myT;
public class Extracted {
- private int myT;
+ int myT;
public Extracted() {
}
public class Extracted<R> {
private final Test<R> test;
- private R myT;
+ public R myT;
public Extracted(Test<R> test) {
this.test = test;
public class Extracted {
- private int myT;
+ int myT;
public int getMyT() {
return myT;
public class Extracted {
- private int myT;
+ int myT;
public Extracted() {
}
public class Extracted<T> {
private final Test<T> test;
- private T myT;
+ T myT;
public Extracted(Test<T> test) {
this.test = test;
public class Extracted<T> {
- private T myT;
+ public T myT;
public Extracted() {
}
public class Extracted<T> {
- private T myT;
+ T myT;
public Extracted() {
}
doTestFieldAndMethod();
}
+ public void testFieldInitializers() throws Exception {
+ doTestField(null);
+ }
+
+ public void testDependantFieldInitializers() throws Exception {
+ doTestField(null);
+ }
+
+ public void testDependantNonStaticFieldInitializers() throws Exception {
+ doTestField(null, true);
+ }
+
public void testInheritanceDelegation() throws Exception {
doTestMethod();
}