blob: 33e993f1740b52c67394e6dc90b7616e9a18e13a [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 org.netbeans.modules.refactoring.java.plugins;
import com.sun.source.tree.*;
import com.sun.source.util.TreePath;
import com.sun.source.util.Trees;
import java.io.IOException;
import java.util.*;
import javax.lang.model.element.*;
import javax.lang.model.type.TypeMirror;
import javax.tools.JavaFileObject;
import org.netbeans.api.java.classpath.ClassPath;
import org.netbeans.api.java.source.GeneratorUtilities;
import org.netbeans.api.java.source.TreeUtilities;
import org.netbeans.api.java.source.WorkingCopy;
import org.netbeans.modules.refactoring.api.Problem;
import org.netbeans.modules.refactoring.java.RefactoringUtils;
import org.netbeans.modules.refactoring.java.api.InnerToOuterRefactoring;
import org.netbeans.modules.refactoring.java.api.JavaRefactoringUtils;
import org.netbeans.modules.refactoring.java.spi.RefactoringVisitor;
import org.netbeans.modules.refactoring.java.spi.ToPhaseException;
import org.openide.filesystems.FileObject;
import org.openide.util.Exceptions;
import org.openide.util.NbBundle;
/**
*
* @author Jan Becicka
*/
public class InnerToOuterTransformer extends RefactoringVisitor {
private Element inner;
private Element outer;
private InnerToOuterRefactoring refactoring;
private boolean isInInnerClass = false;
private Set<Element> referencedPrivateElement;
private Element getCurrentElement() {
return workingCopy.getTrees().getElement(getCurrentPath());
}
public InnerToOuterTransformer(InnerToOuterRefactoring re) {
this.refactoring = re;
}
@Override
public void setWorkingCopy(WorkingCopy wc) throws ToPhaseException {
super.setWorkingCopy(wc);
this.inner = refactoring.getSourceType().resolveElement(wc);
outer = wc.getElementUtilities().enclosingTypeElement(inner);
}
@Override
public Tree visitIdentifier(IdentifierTree node, Element p) {
if (JavaPluginUtils.isSyntheticPath(workingCopy, getCurrentPath())) {
return null;
}
Element current = getCurrentElement();
if (current == null) {
return null;
}
if (inner.equals(current)) {
Tree newTree = make.setLabel(node, refactoring.getClassName());
rewrite(node, newTree);
} else if (isThisReferenceToOuter() && isThisInInner()) {
if (current.getModifiers().contains(Modifier.PRIVATE)) {
referencedPrivateElement.add(current);
}
if (!workingCopy.getTypes().isSubtype(inner.asType(), workingCopy.getElementUtilities().enclosingTypeElement(current).asType())) {
IdentifierTree m;
if (refactoring.getReferenceName()==null || current.getModifiers().contains(Modifier.STATIC) || current.getKind().isClass() || current.getKind().isInterface() ) {
m = make.Identifier(outer.getSimpleName().toString() + "." + node.getName().toString()); // NOI18N
} else {
m = make.Identifier(refactoring.getReferenceName() + "." + node.getName().toString()); // NOI18N
}
rewrite(node, m);
}
} else if (isInInnerClass) {
GeneratorUtilities genUtils = GeneratorUtilities.get(workingCopy); // helper
// #it is impossible to call GeneratorUtilities.importFQNs
// for the whole nested class since the method creates new identity
// of the passed tree
if(current.getModifiers().contains(Modifier.STATIC) && current.getKind() == ElementKind.METHOD) {
TreePath path = getCurrentPath();
Tree parent = path.getParentPath() != null ? path.getParentPath().getLeaf() : null;
TreePath elementPath = workingCopy.getTrees().getPath(current);
JavaFileObject sourceFile = elementPath != null ? elementPath.getCompilationUnit().getSourceFile() : null;
if ( (parent != null && parent.getKind() == Tree.Kind.CASE && ((CaseTree) parent).getExpression() == node && current.getKind() == ElementKind.ENUM_CONSTANT)
|| path.getCompilationUnit().getSourceFile() == sourceFile) {
rewrite(node, make.Identifier(current.getSimpleName()));
} else {
rewrite(node, make.QualIdent(current));
}
} else {
Tree newTree = genUtils.importFQNs(node);
rewrite(node, newTree);
}
}
return super.visitIdentifier(node, p);
}
@Override
public Tree visitCase(CaseTree node, Element p) {
// Ignore case expression
return super.scan(node.getStatements(), p);
}
@Override
public Tree visitNewClass(NewClassTree arg0, Element arg1) {
Element currentElement = getCurrentElement();
if (refactoring.getReferenceName()!=null && currentElement!=null && workingCopy.getTypes().isSubtype(workingCopy.getElementUtilities().enclosingTypeElement(currentElement).asType(), inner.asType())) {
String thisString;
if (getCurrentClass()==inner) {
thisString = refactoring.getReferenceName();
} else if (workingCopy.getTypes().isSubtype(getCurrentClass().asType(),outer.asType())) {
thisString = "this"; // NOI18N
} else {
TypeElement thisOuter = getOuter(getCurrentClass());
if (thisOuter!=null) {
thisString = getOuter(getCurrentClass()).getQualifiedName().toString() + ".this"; // NOI18N
}
else {
thisString = "this"; // NOI18N
}
}
if (thisString != null && currentElement instanceof ExecutableElement) {
ExecutableElement constr = (ExecutableElement) currentElement;
ExpressionTree enclosingExpression = arg0.getEnclosingExpression();
boolean removeEnclosingExpression = false;
if(enclosingExpression != null) {
Element enclosingElement = workingCopy.getTrees().getElement(workingCopy.getTrees().getPath(workingCopy.getCompilationUnit(), enclosingExpression));
if(enclosingElement != null && workingCopy.getTypes().isSameType(enclosingElement.asType(), outer.asType())) {
thisString = enclosingExpression.toString();
removeEnclosingExpression = true;
}
}
int index = constr.getParameters().size();
if (constr.isVarArgs()) {
index--;
}
NewClassTree newClassTree = make.insertNewClassArgument(arg0, index, make.Identifier(thisString));
if(removeEnclosingExpression) {
newClassTree = make.NewClass(null, (List<? extends ExpressionTree>)newClassTree.getTypeArguments(), newClassTree.getIdentifier(), newClassTree.getArguments(), newClassTree.getClassBody());
}
rewrite(arg0, newClassTree);
}
} else if (refactoring.getReferenceName() != null && currentElement != null
// nested class will be moved to new file
&& outer != null && ((TypeElement) outer).getNestingKind() == NestingKind.TOP_LEVEL) {
// 163852: inner class has to be treated especially; inner == nested + not static
// translate all new NotMovingInner() -> referenceName.new NotMovingInner() in moved nested class
// 198186: but only if the inner class is not enclosed in the movingInner
Element enclElm = currentElement.getEnclosingElement();
ExpressionTree primary = arg0.getEnclosingExpression();
Element primaryElm = null;
if (primary != null) {
// be aware of Outer.this.new NotMovingInner() -> referenceName.new NotMovingInner()
// and also new NotMovingInner().new NotMovingInnerInner() >referenceName.new NotMovingInner().new NotMovingInnerInner()
primaryElm = workingCopy.getTrees().getElement(new TreePath(getCurrentPath(), primary));
primaryElm = primaryElm != null ? workingCopy.getTypes().asElement(primaryElm.asType()) : null;
}
Element enclosing = enclElm;
boolean enclosedByInner = false;
while(enclosing != null) {
if(enclosing == inner) {
enclosedByInner = true;
break;
} else if(enclosing == outer) {
break;
}
enclosing = enclosing.getEnclosingElement();
}
if (enclElm != null && enclElm.getKind() == ElementKind.CLASS
&& enclElm != inner && isInInnerClass && !enclosedByInner
&& !enclElm.getModifiers().contains(Modifier.STATIC)
&& ((TypeElement) enclElm).getNestingKind() == NestingKind.MEMBER
&& (primaryElm == null && primary == null || primaryElm == outer)) {
@SuppressWarnings("unchecked")
NewClassTree nju = make.NewClass(
make.Identifier(refactoring.getReferenceName()),
(List<? extends ExpressionTree>) arg0.getTypeArguments(),
// new Outer.Inner() -> referenceName.new Inner()
make.Identifier(enclElm.getSimpleName()),
arg0.getArguments(),
arg0.getClassBody());
rewrite(arg0, nju);
}
}
return super.visitNewClass(arg0, arg1);
}
private TypeElement getOuter(TypeElement element) {
while (element != null && !workingCopy.getTypes().isSubtype(element.asType(),outer.asType())) {
element = workingCopy.getElementUtilities().enclosingTypeElement(element);
}
return element;
}
@Override
public Tree visitMethod(MethodTree constructor, Element element) {
if (constructor.getReturnType()==null) {
//constructor
if (refactoring.getReferenceName() != null && !inner.equals(getCurrentClass())) {
Element current = getCurrentElement();
if (current != null && workingCopy.getTypes().isSubtype(current.getEnclosingElement().asType(), inner.asType())) {
MemberSelectTree arg = make.MemberSelect(make.Identifier(getCurrentClass().getEnclosingElement().getSimpleName()), "this"); // NOI18N
MethodInvocationTree superCall = (MethodInvocationTree) ((ExpressionStatementTree)constructor.getBody().getStatements().get(0)).getExpression();
int index = hasVarArgs(constructor) ? constructor.getParameters().size() - 1 : 0;
MethodInvocationTree newSuperCall = make.insertMethodInvocationArgument(superCall, index, arg);
rewrite(superCall, newSuperCall);
}
}
}
return super.visitMethod(constructor, element);
}
@Override
public Tree visitClass(ClassTree classTree, Element element) {
Element currentElement = workingCopy.getTrees().getElement(getCurrentPath());
if (currentElement == null) {
return super.visitClass(classTree, element);
}
GeneratorUtilities genUtils = GeneratorUtilities.get(workingCopy); // helper
if (currentElement!=null && currentElement == outer) {
Element outerouter = outer.getEnclosingElement();
Tree superVisit = super.visitClass(classTree, element);
TreePath tp = workingCopy.getTrees().getPath(inner);
if (tp==null) {
//#194346
return superVisit;
}
ClassTree innerClass = (ClassTree) tp.getLeaf();
ClassTree newInnerClass = innerClass;
newInnerClass = genUtils.importComments(newInnerClass, workingCopy.getCompilationUnit());
newInnerClass = make.setLabel(newInnerClass, refactoring.getClassName());
newInnerClass = refactorInnerClass(newInnerClass);
TreePath outerPath = workingCopy.getTrees().getPath(outer);
if (outerouter.getKind() == ElementKind.PACKAGE) {
FileObject sourceRoot=ClassPath.getClassPath(workingCopy.getFileObject(), ClassPath.SOURCE).findOwnerRoot(workingCopy.getFileObject());
ClassTree outerTree = (ClassTree) workingCopy.getTrees().getTree(outer);
ClassTree newOuter = make.removeClassMember(outerTree, innerClass);
rewrite(outerTree, newOuter);
if(outerPath != null) {
JavaRefactoringUtils.cacheTreePathInfo(outerPath, workingCopy);
}
CompilationUnitTree compilationUnit = tp.getCompilationUnit();
String relativePath = RefactoringUtils.getPackageName(compilationUnit).replace('.', '/') + '/' + refactoring.getClassName() + ".java"; // NOI18N
CompilationUnitTree newCompilation = JavaPluginUtils.createCompilationUnit(sourceRoot, relativePath, newInnerClass, workingCopy, make);
rewrite(null, newCompilation);
return newOuter;
} else {
ClassTree outerTree = (ClassTree) workingCopy.getTrees().getTree(outer);
if(!outerouter.getKind().isClass()) {
outerouter = workingCopy.getElementUtilities().enclosingTypeElement(outerouter);
}
ClassTree outerouterTree = (ClassTree) workingCopy.getTrees().getTree(outerouter);
ClassTree newOuter = make.removeClassMember(outerTree, innerClass);
ClassTree newOuterOuter = GeneratorUtilities.get(workingCopy).insertClassMember(outerouterTree, newInnerClass);
rewrite(outerTree, newOuter);
if(outerPath != null) {
JavaRefactoringUtils.cacheTreePathInfo(outerPath, workingCopy);
}
rewrite(outerouterTree, newOuterOuter);
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.<Modifier>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) {
for( VariableTree var: m.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) m.getBody().getStatements().get(0)).getExpression();
List<ExpressionTree> newArgs = new ArrayList<ExpressionTree>(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.<ExpressionTree>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);
}
}
}
}
if (currentElement == inner) {
try {
isInInnerClass = true;
return super.visitClass(classTree, element);
} finally {
isInInnerClass = false;
}
}
return super.visitClass(classTree, element);
}
@Override
public Tree visitCompilationUnit(CompilationUnitTree node, Element p) {
this.referencedPrivateElement = new HashSet<Element>();
Tree result = super.visitCompilationUnit(node, p);
for (Element privEl : this.referencedPrivateElement) {
problem = MoveTransformer.createProblem(problem, false, NbBundle.getMessage(InnerToOuterRefactoringPlugin.class, "WRN_InnerToOuterRefToPrivate", privEl));
}
Trees trees = workingCopy.getTrees();
CompilationUnitTree newNode = node;
for (ImportTree imp : node.getImports()) {
if(imp.isStatic()) {
Tree qualIdent = imp.getQualifiedIdentifier();
TypeElement el = workingCopy.getElements().getTypeElement(qualIdent.toString());
if(inner.equals(el)) {
newNode = make.removeCompUnitImport(newNode, imp);
}
}
}
if(newNode != node) {
rewrite(node, newNode);
}
return result;
}
private Problem problem;
public Problem getProblem() {
return problem;
}
private boolean containsImport(String imp) {
for (ImportTree et:workingCopy.getCompilationUnit().getImports()) {
if (et.getQualifiedIdentifier().toString().equals(imp)) {
return true;
}
}
return false;
}
@Override
public Tree visitMemberSelect(MemberSelectTree memberSelect, Element element) {
Element current = getCurrentElement();
if (current == null) {
return super.visitMemberSelect(memberSelect, inner);
}
if (inner.equals(current)) {
ExpressionTree ex = memberSelect.getExpression();
Tree newTree;
if (ex.getKind() == Tree.Kind.IDENTIFIER) {
newTree = make.Identifier(refactoring.getClassName());
rewrite(memberSelect, newTree);
TreePath tp = workingCopy.getTrees().getPath(inner);
if(tp != null) {
String innerPackageName = RefactoringUtils.getPackageName(tp.getCompilationUnit());
if (!innerPackageName.equals(RefactoringUtils.getPackageName(workingCopy.getCompilationUnit())) &&
!containsImport(innerPackageName + ".*")) { //NOI18N
String import1 = innerPackageName + "." + refactoring.getClassName(); //NOI18N
try {
CompilationUnitTree cut = RefactoringUtils.addImports(workingCopy.getCompilationUnit(), Collections.singletonList(import1), make);
rewrite(workingCopy.getCompilationUnit(), cut);
} catch (IOException ex1) {
Exceptions.printStackTrace(ex1);
}
}
}
} else if (ex.getKind() == Tree.Kind.MEMBER_SELECT) {
MemberSelectTree m = make.MemberSelect(((MemberSelectTree) ex).getExpression(),refactoring.getClassName());
rewrite(memberSelect,m);
}
} else if (isThisReferenceToOuter() && isThisInInner()) {
if (current.getModifiers().contains(Modifier.PRIVATE)) {
referencedPrivateElement.add(current);
}
if (!"class".equals(memberSelect.getIdentifier().toString()) && !current.getModifiers().contains(Modifier.STATIC)) { //NOI18N)
if (refactoring.getReferenceName()!=null) {
// Outer.this -> outer
// Outer.field -> outer.field
Tree m = "this".equals(memberSelect.getIdentifier().toString()) // NOI18N
? make.Identifier(refactoring.getReferenceName())
: make.MemberSelect(make.Identifier(refactoring.getReferenceName()), memberSelect.getIdentifier());
rewrite(memberSelect, m);
} else {
if (inner.getKind()!=ElementKind.INTERFACE && !inner.getModifiers().contains(Modifier.STATIC)) {
problem = MoveTransformer.createProblem(problem, true, NbBundle.getMessage(InnerToOuterTransformer.class, "ERR_InnerToOuter_UseDeclareField", memberSelect));
}
}
}
} else if (isThisReferenceToInner()) {
//outer reference to inner class
//member needn't to be private
Tree tree = workingCopy.getTrees().getTree(current);
if (tree != null && tree.getKind() == Tree.Kind.METHOD) {
MethodTree method = (MethodTree) tree;
if (method.getModifiers().getFlags().contains(Modifier.PRIVATE)) {
rewrite(method.getModifiers(), make.removeModifiersModifier(method.getModifiers(), Modifier.PRIVATE));
}
} else if (tree != null && tree.getKind() == Tree.Kind.VARIABLE) {
VariableTree variable = (VariableTree) tree;
if (variable.getModifiers().getFlags().contains(Modifier.PRIVATE)) {
rewrite(variable.getModifiers(), make.removeModifiersModifier(variable.getModifiers(), Modifier.PRIVATE));
}
}
}
return super.visitMemberSelect(memberSelect, element);
}
@Override
public Tree visitLambdaExpression(LambdaExpressionTree node, Element p) {
List<? extends VariableTree> params = node.getParameters();
boolean skipType = params.size() > 0 && (params.get(0).getType() == null
|| workingCopy.getTreeUtilities().isSynthetic(new TreePath(getCurrentPath(), params.get(0).getType())));
if(skipType) {
return scan(node.getBody(), p);
} else {
return super.visitLambdaExpression(node, p);
}
}
private boolean isThisReferenceToInner() {
Element cur = getCurrentElement();
if (cur==null || cur.getKind() == ElementKind.PACKAGE) {
return false;
}
Tree innerTree = workingCopy.getTrees().getTree(inner);
TreePath path = getCurrentPath();
while (path!=null) {
Tree t = path.getLeaf();
if (t == innerTree) {
return false;
}
path = path.getParentPath();
}
TypeElement encl = workingCopy.getElementUtilities().enclosingTypeElement(cur);
return encl!=null && workingCopy.getTypes().isSubtype(encl.asType(), inner.asType()) ;
}
private boolean isThisReferenceToOuter() {
Element cur = getCurrentElement();
if (cur==null || cur.getKind() == ElementKind.PACKAGE) {
return false;
}
TypeElement encl = workingCopy.getElementUtilities().enclosingTypeElement(cur);
if (outer.equals(encl)) {
TypeElement currentClass = getCurrentClass();
if (currentClass == null) {
return false;
}
if (workingCopy.getTypes().isSubtype(currentClass.asType(), inner.asType())) {
return true;
}
return outer.equals(cur.getEnclosingElement());
}
return false;
}
private TypeElement getCurrentClass() {
TreePath treePath = getCurrentPath();
while (treePath != null) {
if (TreeUtilities.CLASS_TREE_KINDS.contains(treePath.getLeaf().getKind())) {
return (TypeElement) workingCopy.getTrees().getElement(treePath);
} else if (treePath.getLeaf().getKind() == Tree.Kind.IMPORT) {
return (TypeElement) workingCopy.getTrees().getElement(getCurrentPath());
}
treePath = treePath.getParentPath();
}
return null;
}
private boolean isIn(Element el) {
if (el==null) {
return false;
}
Element current = el;
while (current.getKind() != ElementKind.PACKAGE) {
if (current.equals(inner)) {
return true;
}
current = current.getEnclosingElement();
}
return false;
}
private boolean hasVarArgs(MethodTree mt) {
List list = mt.getParameters();
if (list.isEmpty()) {
return false;
}
VariableTree vt = (VariableTree)list.get(list.size() - 1);
return vt.toString().indexOf("...") != -1; // [NOI18N] [TODO] temporal hack, will be rewritten
}
private ClassTree refactorInnerClass(ClassTree innerClass) {
ClassTree newInnerClass = innerClass;
String referenceName = refactoring.getReferenceName();
GeneratorUtilities genUtils = GeneratorUtilities.get(workingCopy);
final TypeMirror outerType;
if(workingCopy.getElementUtilities().isLocal(outer) && (outer.getKind().isClass() || outer.getKind().isInterface())) {
TypeElement outerTypeElement = (TypeElement) outer;
List<? extends TypeMirror> interfaces = outerTypeElement.getInterfaces();
if(interfaces.isEmpty()) {
outerType = outerTypeElement.getSuperclass();
} else {
outerType = interfaces.get(0);
}
} else {
outerType = outer.asType();
}
if (referenceName != null) {
VariableTree variable = make.Variable(make.Modifiers(EnumSet.of(Modifier.PRIVATE, Modifier.FINAL)), refactoring.getReferenceName(), make.Type(outerType), null);
newInnerClass = genUtils.insertClassMember(newInnerClass, variable);
}
ModifiersTree modifiersTree = newInnerClass.getModifiers();
ModifiersTree newModifiersTree = make.removeModifiersModifier(modifiersTree, Modifier.PRIVATE);
newModifiersTree = make.removeModifiersModifier(newModifiersTree, Modifier.STATIC);
newModifiersTree = make.removeModifiersModifier(newModifiersTree, Modifier.PROTECTED);
if (!outer.getModifiers().contains(Modifier.PUBLIC)) {
newModifiersTree = make.removeModifiersModifier(newModifiersTree, Modifier.PUBLIC);
}
rewrite(modifiersTree, newModifiersTree);
if (referenceName != null) {
for (Tree member:newInnerClass.getMembers()) {
if (member.getKind() == Tree.Kind.METHOD) {
MethodTree m = (MethodTree) member;
if (m.getName().contentEquals("<init>") || m.getReturnType() == null) {
VariableTree parameter = make.Variable(make.Modifiers(EnumSet.of(Modifier.FINAL)), refactoring.getReferenceName(), make.Type(outerType), null);
MethodTree newConstructor = hasVarArgs(m) ?
make.insertMethodParameter(m, m.getParameters().size() - 1, parameter) :
make.addMethodParameter(m, parameter);
AssignmentTree assign = make.Assignment(make.Identifier("this."+referenceName), make.Identifier(referenceName)); // NOI18N
BlockTree block = make.insertBlockStatement(newConstructor.getBody(), 1, make.ExpressionStatement(assign));
Set<Modifier> modifiers = new HashSet(newConstructor.getModifiers().getFlags());
modifiers.remove(Modifier.PRIVATE);
newConstructor = make.Constructor(
make.Modifiers(modifiers,newConstructor.getModifiers().getAnnotations()),
newConstructor.getTypeParameters(),
newConstructor.getParameters(),
newConstructor.getThrows(),
block);
newInnerClass = make.removeClassMember(newInnerClass, m);
genUtils.copyComments(m, newConstructor, true);
genUtils.copyComments(m, newConstructor, false);
newInnerClass = genUtils.insertClassMember(newInnerClass, newConstructor);
}
}
}
}
if(innerClass != newInnerClass) {
genUtils.copyComments(innerClass, newInnerClass, true);
genUtils.copyComments(innerClass, newInnerClass, false);
}
return newInnerClass;
}
private boolean isThisInInner() {
TreePath t=getCurrentPath();
Tree innerTree = workingCopy.getTrees().getTree(inner);
while (t!=null) {
if (t.getLeaf().equals(innerTree)) {
return true;
}
t = t.getParentPath();
}
return false;
}
}