Skip to content

Commit

Permalink
Bug 434693: [1.8][clean up] convert nested anonymous to lambdas resul…
Browse files Browse the repository at this point in the history
…ts in code with conflicting variable names
  • Loading branch information
noopur2507 authored and mkeller committed May 14, 2014
1 parent ff852ca commit e28aefb
Show file tree
Hide file tree
Showing 2 changed files with 136 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -551,6 +551,117 @@ public void testConvertToLambdaAmbiguous03() throws Exception {
assertRefactoringResultAsExpected(new ICompilationUnit[] { cu1 }, new String[] { original });
}

public void testConvertToLambdaConflictingNames() throws Exception {
IPackageFragment pack1= fSourceFolder.createPackageFragment("test", false, null);
StringBuffer buf= new StringBuffer();
buf.append("package test1;\n");
buf.append("\n");
buf.append("interface FI {\n");
buf.append(" void run(int x);\n");
buf.append("}\n");
buf.append("\n");
buf.append("public class Test {\n");
buf.append(" {\n");
buf.append(" int e;\n");
buf.append(" FI fi = new FI() {\n");
buf.append(" @Override\n");
buf.append(" public void run(int e) {\n");
buf.append(" class C1 {\n");
buf.append(" void init1() {\n");
buf.append(" m(new FI() {\n");
buf.append(" @Override\n");
buf.append(" public void run(int e) {\n");
buf.append(" FI fi = new FI() {\n");
buf.append(" @Override\n");
buf.append(" public void run(int e) {\n");
buf.append(" FI fi = new FI() {\n");
buf.append(" @Override\n");
buf.append(" public void run(int e) {\n");
buf.append(" return;\n");
buf.append(" }\n");
buf.append(" };\n");
buf.append(" }\n");
buf.append(" };\n");
buf.append(" }\n");
buf.append(" });\n");
buf.append(" }\n");
buf.append("\n");
buf.append(" void init2() {\n");
buf.append(" m(new FI() {\n");
buf.append(" @Override\n");
buf.append(" public void run(int e) {\n");
buf.append(" new FI() {\n");
buf.append(" @Override\n");
buf.append(" public void run(int e3) {\n");
buf.append(" FI fi = new FI() {\n");
buf.append(" @Override\n");
buf.append(" public void run(int e) {\n");
buf.append(" return;\n");
buf.append(" }\n");
buf.append(" };\n");
buf.append(" }\n");
buf.append(" };\n");
buf.append(" }\n");
buf.append(" });\n");
buf.append(" }\n");
buf.append(" }\n");
buf.append(" }\n");
buf.append(" };\n");
buf.append(" }\n");
buf.append("\n");
buf.append(" void m(FI fi) {\n");
buf.append(" };\n");
buf.append("}\n");
String original= buf.toString();
ICompilationUnit cu1= pack1.createCompilationUnit("Test.java", original, false, null);

enable(CleanUpConstants.CONVERT_FUNCTIONAL_INTERFACES);
enable(CleanUpConstants.USE_LAMBDA);

buf= new StringBuffer();
buf.append("package test1;\n");
buf.append("\n");
buf.append("interface FI {\n");
buf.append(" void run(int x);\n");
buf.append("}\n");
buf.append("\n");
buf.append("public class Test {\n");
buf.append(" {\n");
buf.append(" int e;\n");
buf.append(" FI fi = e1 -> {\n");
buf.append(" class C1 {\n");
buf.append(" void init1() {\n");
buf.append(" m(e2 -> {\n");
buf.append(" FI fi1 = e3 -> {\n");
buf.append(" FI fi2 = e4 -> {\n");
buf.append(" return;\n");
buf.append(" };\n");
buf.append(" };\n");
buf.append(" });\n");
buf.append(" }\n");
buf.append("\n");
buf.append(" void init2() {\n");
buf.append(" m(e2 -> new FI() {\n");
buf.append(" @Override\n");
buf.append(" public void run(int e3) {\n");
buf.append(" FI fi = e4 -> {\n");
buf.append(" return;\n");
buf.append(" };\n");
buf.append(" }\n");
buf.append(" });\n");
buf.append(" }\n");
buf.append(" }\n");
buf.append(" };\n");
buf.append(" }\n");
buf.append("\n");
buf.append(" void m(FI fi) {\n");
buf.append(" };\n");
buf.append("}\n");
String expected1= buf.toString();

assertRefactoringResultAsExpected(new ICompilationUnit[] { cu1 }, new String[] { expected1 });
}

public void testConvertToAnonymousWithWildcards() throws Exception {
IPackageFragment pack1= fSourceFolder.createPackageFragment("test", false, null);
StringBuffer buf= new StringBuffer();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;

Expand Down Expand Up @@ -199,8 +201,9 @@ public void rewriteAST(CompilationUnitRewrite cuRewrite, LinkedProposalModel mod
ImportRemover importRemover= cuRewrite.getImportRemover();
AST ast= rewrite.getAST();

for (Iterator<ClassInstanceCreation> iterator= fExpressions.iterator(); iterator.hasNext();) {
ClassInstanceCreation classInstanceCreation= iterator.next();
HashMap<ClassInstanceCreation, HashSet<String>> cicToNewNames= new HashMap<ClassInstanceCreation, HashSet<String>>();
for (int i= 0; i < fExpressions.size(); i++) {
ClassInstanceCreation classInstanceCreation= fExpressions.get(i);
TextEditGroup group= createTextEditGroup(FixMessages.LambdaExpressionsFix_convert_to_lambda_expression, cuRewrite);

AnonymousClassDeclaration anonymTypeDecl= classInstanceCreation.getAnonymousClassDeclaration();
Expand All @@ -210,7 +213,16 @@ public void rewriteAST(CompilationUnitRewrite cuRewrite, LinkedProposalModel mod
if (!(object instanceof MethodDeclaration))
continue;
MethodDeclaration methodDeclaration= (MethodDeclaration) object;
makeNamesUnique(methodDeclaration, rewrite, group);
HashSet<String> excludedNames= new HashSet<String>();
if (i != 0) {
for (ClassInstanceCreation convertedCic : fExpressions.subList(0, i)) {
if (ASTNodes.isParent(classInstanceCreation, convertedCic)) {
excludedNames.addAll(cicToNewNames.get(convertedCic));
}
}
}
HashSet<String> newNames= makeNamesUnique(excludedNames, methodDeclaration, rewrite, group);
cicToNewNames.put(classInstanceCreation, new HashSet<String>(newNames));
List<SingleVariableDeclaration> methodParameters= methodDeclaration.parameters();

// use short form with inferred parameter types and without parentheses if possible
Expand Down Expand Up @@ -260,8 +272,9 @@ public void rewriteAST(CompilationUnitRewrite cuRewrite, LinkedProposalModel mod
}
}

private void makeNamesUnique(MethodDeclaration methodDeclaration, ASTRewrite rewrite, TextEditGroup group) {
List<String> excludedNames= ASTNodes.getVisibleLocalVariablesInScope(methodDeclaration);
private HashSet<String> makeNamesUnique(HashSet<String> excludedNames, MethodDeclaration methodDeclaration, ASTRewrite rewrite, TextEditGroup group) {
HashSet<String> newNames= new HashSet<String>();
excludedNames.addAll(ASTNodes.getVisibleLocalVariablesInScope(methodDeclaration));
List<SimpleName> simpleNamesInMethod= getNamesInMethod(methodDeclaration);
List<String> namesInMethod= new ArrayList<String>();
for (SimpleName name : simpleNamesInMethod) {
Expand All @@ -271,20 +284,23 @@ private void makeNamesUnique(MethodDeclaration methodDeclaration, ASTRewrite rew
for (int i= 0; i < simpleNamesInMethod.size(); i++) {
SimpleName name= simpleNamesInMethod.get(i);
String identifier= namesInMethod.get(i);
List<String> allNamesToExclude= getNamesToExclude(excludedNames, namesInMethod, i);
HashSet<String> allNamesToExclude= getNamesToExclude(excludedNames, namesInMethod, i);
if (allNamesToExclude.contains(identifier)) {
String newIdentifier= createName(identifier, allNamesToExclude);
excludedNames.add(newIdentifier);
newNames.add(newIdentifier);
SimpleName[] references= LinkedNodeFinder.findByNode(name.getRoot(), name);
for (SimpleName ref : references) {
rewrite.set(ref, SimpleName.IDENTIFIER_PROPERTY, newIdentifier, group);
}
}
}

return newNames;
}

private List<String> getNamesToExclude(List<String> excludedNames, List<String> namesInMethod, int i) {
List<String> allNamesToExclude= new ArrayList<String>(excludedNames);
private HashSet<String> getNamesToExclude(HashSet<String> excludedNames, List<String> namesInMethod, int i) {
HashSet<String> allNamesToExclude= new HashSet<String>(excludedNames);
allNamesToExclude.addAll(namesInMethod.subList(0, i));
allNamesToExclude.addAll(namesInMethod.subList(i + 1, namesInMethod.size()));
return allNamesToExclude;
Expand Down Expand Up @@ -333,7 +349,7 @@ public boolean visit(VariableDeclaration node) {
return namesCollector.fNames;
}

private String createName(String candidate, List<String> excludedNames) {
private String createName(String candidate, HashSet<String> excludedNames) {
int i= 1;
String result= candidate;
while (excludedNames.contains(result)) {
Expand Down

0 comments on commit e28aefb

Please sign in to comment.