diff --git a/refactoring.java/src/org/netbeans/modules/refactoring/java/plugins/Bundle.properties b/refactoring.java/src/org/netbeans/modules/refactoring/java/plugins/Bundle.properties
--- a/refactoring.java/src/org/netbeans/modules/refactoring/java/plugins/Bundle.properties
+++ b/refactoring.java/src/org/netbeans/modules/refactoring/java/plugins/Bundle.properties
@@ -137,6 +137,8 @@
ERR_EmptyReferenceName=Name of the reference to the outer class can not be empty.
ERR_OuterNameAlreadyUsed=Name "{0}" is already used as a name of field from {1}.
WRN_OuterNameAlreadyUsed=Name "{0}" is already used as a name of field from {1}.
+ERR_InnerToOuter_OuterNameClash=Name "{0}" is already used as a parameter of constructor from {1}.
+ERR_InnerToOuter_OuterNameClashSubtype=Name {0} is already used in subtype of {1} ({2}) as a parameter of constructor.
# --- USE SUPERTYPE REFACTORING ------------------------------------------------------
TXT_UseSuperType=Use Supertype of {0} where possible
diff --git a/refactoring.java/src/org/netbeans/modules/refactoring/java/plugins/InnerToOuterRefactoringPlugin.java b/refactoring.java/src/org/netbeans/modules/refactoring/java/plugins/InnerToOuterRefactoringPlugin.java
--- a/refactoring.java/src/org/netbeans/modules/refactoring/java/plugins/InnerToOuterRefactoringPlugin.java
+++ b/refactoring.java/src/org/netbeans/modules/refactoring/java/plugins/InnerToOuterRefactoringPlugin.java
@@ -54,6 +54,7 @@
import java.util.List;
import java.util.Set;
import javax.lang.model.element.Element;
+import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.NestingKind;
import javax.lang.model.element.TypeElement;
import javax.lang.model.element.VariableElement;
@@ -179,6 +180,17 @@
break;
}
}
+
+ List constructors = ElementFilter.constructorsIn(((TypeElement)resolved).getEnclosedElements());
+ for( ExecutableElement execElement: constructors ) {
+ List extends VariableElement> parameters = execElement.getParameters();
+
+ for( VariableElement variableElement: parameters ) {
+ if(variableElement.getSimpleName().toString().equals(name)) {
+ return new Problem(true, NbBundle.getMessage(InnerToOuterRefactoringPlugin.class, "ERR_InnerToOuter_OuterNameClash", name, resolved.getSimpleName())); // NOI18N
+ }
+ }
+ }
}
}
return problem;
diff --git a/refactoring.java/src/org/netbeans/modules/refactoring/java/plugins/InnerToOuterTransformer.java b/refactoring.java/src/org/netbeans/modules/refactoring/java/plugins/InnerToOuterTransformer.java
--- a/refactoring.java/src/org/netbeans/modules/refactoring/java/plugins/InnerToOuterTransformer.java
+++ b/refactoring.java/src/org/netbeans/modules/refactoring/java/plugins/InnerToOuterTransformer.java
@@ -252,8 +252,8 @@
@Override
public Tree visitClass(ClassTree classTree, Element element) {
Element currentElement = workingCopy.getTrees().getElement(getCurrentPath());
- GeneratorUtilities genUtils = GeneratorUtilities.get(workingCopy); // helper
- if (currentElement!=null && currentElement == outer) {
+ GeneratorUtilities genUtils = GeneratorUtilities.get(workingCopy); // helper
+ if (isOuterClass(currentElement)) {
Element outerouter = outer.getEnclosingElement();
Tree superVisit = super.visitClass(classTree, element);
TreePath tp = workingCopy.getTrees().getPath(inner);
@@ -279,24 +279,6 @@
CompilationUnitTree compilationUnit = tp.getCompilationUnit();
String relativePath = RefactoringUtils.getPackageName(compilationUnit).replace('.', '/') + '/' + refactoring.getClassName() + ".java"; // NOI18N
CompilationUnitTree newCompilation = JavaPluginUtils.createCompilationUnit(sourceRoot, relativePath, newInnerClass, workingCopy, make);
-// try {
-// newCompilation = genUtils.createFromTemplate(sourceRoot, relativePath, ElementKind.CLASS);
-// List extends Tree> typeDecls = newCompilation.getTypeDecls();
-// if(workingCopy.getTreeUtilities().getComments(newInnerClass, true).isEmpty()) {
-// if (!typeDecls.isEmpty()) {
-// ClassTree templateClazz = (ClassTree) typeDecls.get(0);
-// genUtils.copyComments(templateClazz, newInnerClass, true);
-// }
-// }
-// if(typeDecls.isEmpty()) {
-// newCompilation = make.addCompUnitTypeDecl(newCompilation, newInnerClass);
-// } else {
-// rewrite(typeDecls.get(0), newInnerClass);
-// }
-// } catch (IOException ex) {
-// Exceptions.printStackTrace(ex);
-// newCompilation = make.CompilationUnit(sourceRoot, relativePath, null, Collections.singletonList(newInnerClass));
-// }
rewrite(null, newCompilation);
return newOuter;
} else {
@@ -313,46 +295,49 @@
return newOuterOuter;
}
- } else if (refactoring.getReferenceName() != null && currentElement!=null && workingCopy.getTypes().isSubtype(currentElement.asType(), inner.asType()) && currentElement!=inner) {
- VariableTree variable = make.Variable(make.Modifiers(Collections.emptySet()), refactoring.getReferenceName(), make.Type(outer.asType()), null);
- for (Tree member:classTree.getMembers()) {
- if (member.getKind() == Tree.Kind.METHOD) {
- MethodTree m = (MethodTree) member;
- if (m.getReturnType()==null) {
- MethodInvocationTree superCall = (MethodInvocationTree) ((ExpressionStatementTree) m.getBody().getStatements().get(0)).getExpression();
- List newArgs = new ArrayList(superCall.getArguments());
-
- MethodTree newConstructor = null;
- ExpressionTree exprTree = (ExpressionTree)make.Identifier(variable.getName().toString());
- if (hasVarArgs(m)) {
- int index = m.getParameters().size() - 1;
- newArgs.add(index, exprTree);
- newConstructor = make.insertMethodParameter(m, index, variable);
- } else {
- newArgs.add(exprTree);
- newConstructor = make.addMethodParameter(m, variable);
- }
- MethodInvocationTree method = make.MethodInvocation(
- Collections.emptyList(),
- make.Identifier("super"), // NOI18N
- newArgs);
-
- BlockTree block = make.insertBlockStatement(m.getBody(), 0, make.ExpressionStatement(method));
- block = make.removeBlockStatement(block, 1);
-
- newConstructor = make.Constructor(
- make.Modifiers(newConstructor.getModifiers().getFlags(), newConstructor.getModifiers().getAnnotations()),
- newConstructor.getTypeParameters(),
- newConstructor.getParameters(),
- newConstructor.getThrows(),
- block);
-
- rewrite(m, newConstructor);
+ } else if (refactoring.getReferenceName() != null && isInnerSubclass(currentElement)) {
+ VariableTree outerVar = make.Variable(make.Modifiers(Collections.emptySet()), refactoring.getReferenceName(), make.Type(outer.asType()), null);
+
+ for (MethodTree constructor: getConstructors(classTree)) {
+
+ for( VariableTree var: constructor.getParameters() ) {
+ if( var.getName().contentEquals(refactoring.getReferenceName()) ) {
+ problem = MoveTransformer.createProblem(problem, true, NbBundle.getMessage(InnerToOuterTransformer.class, "ERR_InnerToOuter_OuterNameClashSubtype", refactoring.getReferenceName(), refactoring.getClassName(), currentElement.getSimpleName()));
}
}
- }
- }
-
+
+ MethodInvocationTree superCall = (MethodInvocationTree) ((ExpressionStatementTree) constructor.getBody().getStatements().get(0)).getExpression();
+ List superCallArgs = new ArrayList(superCall.getArguments());
+
+ MethodTree newConstructor = null;
+ ExpressionTree outerIdent = (ExpressionTree)make.Identifier(outerVar.getName().toString());
+ if (hasVarArgs(constructor)) {
+ int index = constructor.getParameters().size() - 1;
+ superCallArgs.add(index, outerIdent);
+ newConstructor = make.insertMethodParameter(constructor, index, outerVar);
+ } else {
+ superCallArgs.add(outerIdent);
+ newConstructor = make.addMethodParameter(constructor, outerVar);
+ }
+ MethodInvocationTree method = make.MethodInvocation(
+ Collections.emptyList(),
+ make.Identifier("super"), // NOI18N
+ superCallArgs);
+
+ BlockTree block = make.insertBlockStatement(constructor.getBody(), 0, make.ExpressionStatement(method));
+ block = make.removeBlockStatement(block, 1);
+
+ newConstructor = make.Constructor(
+ make.Modifiers(newConstructor.getModifiers().getFlags(), newConstructor.getModifiers().getAnnotations()),
+ newConstructor.getTypeParameters(),
+ newConstructor.getParameters(),
+ newConstructor.getThrows(),
+ block);
+
+ rewrite(constructor, newConstructor);
+ }
+ }
+
if (currentElement == inner) {
try {
isInInnerClass = true;
@@ -529,6 +514,12 @@
return false;
}
+ /**
+ * Determines whether the given method has variable arguments list (has ... in its declaration).
+ *
+ * @param mt method to test
+ * @return
+ */
private boolean hasVarArgs(MethodTree mt) {
List list = mt.getParameters();
if (list.isEmpty()) {
@@ -616,4 +607,39 @@
}
return false;
}
+
+ /**
+ * Determines whether the given element and the outer class are the same.
+ *
+ * @param el element to test
+ * @return
+ */
+ private boolean isOuterClass(Element el) {
+ return el!=null && el == outer;
+ }
+
+ /**
+ * Determines whether the given element is a subclass of the inner class.
+ *
+ * @param el element to test
+ * @return {@code true} if the given element is the subclass of the inner class and {@code false} otherwise
+ */
+ private boolean isInnerSubclass(Element el) {
+ return el!=null && workingCopy.getTypes().isSubtype(el.asType(), inner.asType()) && el!=inner;
+ }
+
+ private List getConstructors(ClassTree classTree) {
+ List constructors = new LinkedList();
+
+ for (Tree member: classTree.getMembers()) {
+ if (member.getKind() == Tree.Kind.METHOD) {
+ MethodTree m = (MethodTree) member;
+ if (m.getReturnType()==null) {
+ constructors.add(m);
+ }
+ }
+ }
+
+ return constructors;
+ }
}