diff options
author | Lukas Hanke | 2013-11-12 05:15:00 +0000 |
---|---|---|
committer | Manju Mathew | 2013-11-12 05:15:00 +0000 |
commit | 06d69b4e9a453b31a9617a2d5c681e762376d562 (patch) | |
tree | 6ad481fb65268c3126bc98b55399797c1a4996b5 | |
parent | fc5db860cde9862df43b16821dd6c29a092bace8 (diff) | |
download | eclipse.jdt.ui-06d69b4e9a453b31a9617a2d5c681e762376d562.tar.gz eclipse.jdt.ui-06d69b4e9a453b31a9617a2d5c681e762376d562.tar.xz eclipse.jdt.ui-06d69b4e9a453b31a9617a2d5c681e762376d562.zip |
Fixed Bug 241696: [quick fix] quickfix to iterate over a collectionI20131112-0800
Signed-off-by: Lukas Hanke <hanke@yatta.de>
4 files changed, 328 insertions, 68 deletions
diff --git a/org.eclipse.jdt.ui.tests/ui/org/eclipse/jdt/ui/tests/quickfix/AssistQuickFixTest.java b/org.eclipse.jdt.ui.tests/ui/org/eclipse/jdt/ui/tests/quickfix/AssistQuickFixTest.java index 40a4d85623..0f9cd4f941 100644 --- a/org.eclipse.jdt.ui.tests/ui/org/eclipse/jdt/ui/tests/quickfix/AssistQuickFixTest.java +++ b/org.eclipse.jdt.ui.tests/ui/org/eclipse/jdt/ui/tests/quickfix/AssistQuickFixTest.java @@ -8514,8 +8514,7 @@ public class AssistQuickFixTest extends QuickFixTest { buf.append("import java.util.Iterator;\n"); buf.append("public class E {\n"); buf.append(" void foo(Collection<String> collection) {\n"); - buf.append(" for (Iterator<String> iterator = collection.iterator(); iterator\n"); - buf.append(" .hasNext();) {\n"); + buf.append(" for (Iterator<String> iterator = collection.iterator(); iterator.hasNext();) {\n"); buf.append(" String string = iterator.next();\n"); buf.append(" \n"); buf.append(" }\n"); @@ -8651,6 +8650,67 @@ public class AssistQuickFixTest extends QuickFixTest { fJProject1.setOptions(saveOptions); } } + + public void testGenerateForGenerics() throws Exception { + IPackageFragment pack1= fSourceFolder.createPackageFragment("test1", false, null); + StringBuffer buf= new StringBuffer(); + buf.append("package test1;\n"); + buf.append("import java.util.Collection;\n"); + buf.append("import java.util.Date;\n"); + buf.append("public class E {\n"); + buf.append(" void <T extends Date> foo(Collection<T> collection) {\n"); + buf.append(" collection\n"); + buf.append(" }\n"); + buf.append("}\n"); + ICompilationUnit cu= pack1.createCompilationUnit("E.java", buf.toString(), false, null); + + Map saveOptions= fJProject1.getOptions(false); + Map newOptions= new HashMap(saveOptions); + newOptions.put(DefaultCodeFormatterConstants.FORMATTER_PUT_EMPTY_STATEMENT_ON_NEW_LINE, "true"); + try { + fJProject1.setOptions(newOptions); + String selection= "collection"; + AssistContext context= getCorrectionContext(cu, buf.toString().lastIndexOf(selection) + selection.length(), 0); + List proposals= collectAssists(context, false); + + assertNumberOfProposals(proposals, 2); + assertCorrectLabels(proposals); + + String[] expected= new String[2]; + buf= new StringBuffer(); + buf.append("package test1;\n"); + buf.append("import java.util.Collection;\n"); + buf.append("import java.util.Date;\n"); + buf.append("public class E {\n"); + buf.append(" void <T extends Date> foo(Collection<T> collection) {\n"); + buf.append(" for (T t : collection) {\n"); + buf.append(" \n"); + buf.append(" }\n"); + buf.append(" }\n"); + buf.append("}\n"); + expected[0]= buf.toString(); + + buf= new StringBuffer(); + buf.append("package test1;\n"); + buf.append("import java.util.Collection;\n"); + buf.append("import java.util.Date;\n"); + buf.append("import java.util.Iterator;\n"); + buf.append("public class E {\n"); + buf.append(" void <T extends Date> foo(Collection<T> collection) {\n"); + buf.append(" for (Iterator<T> iterator = collection.iterator(); iterator\n"); + buf.append(" .hasNext();) {\n"); + buf.append(" T t = iterator.next();\n"); + buf.append(" \n"); + buf.append(" }\n"); + buf.append(" }\n"); + buf.append("}\n"); + expected[1]= buf.toString(); + + assertExpectedExistInProposals(proposals, expected); + } finally { + fJProject1.setOptions(saveOptions); + } + } public void testGenerateForMissingParametrization() throws Exception { IPackageFragment pack1= fSourceFolder.createPackageFragment("test1", false, null); @@ -8695,7 +8755,7 @@ public class AssistQuickFixTest extends QuickFixTest { buf.append("import java.util.Iterator;\n"); buf.append("public class E {\n"); buf.append(" void foo(Collection collection) {\n"); - buf.append(" for (Iterator<Object> iterator = collection.iterator(); iterator\n"); + buf.append(" for (Iterator iterator = collection.iterator(); iterator\n"); buf.append(" .hasNext();) {\n"); buf.append(" Object object = iterator.next();\n"); buf.append(" \n"); @@ -8746,7 +8806,8 @@ public class AssistQuickFixTest extends QuickFixTest { buf.append("import java.util.Iterator;\n"); buf.append("public class E {\n"); buf.append(" void foo(Collection collection) {\n"); - buf.append(" for (Iterator iterator = collection.iterator(); iterator.hasNext();) {\n"); + buf.append(" for (Iterator iterator = collection.iterator(); iterator\n"); + buf.append(" .hasNext();) {\n"); buf.append(" Object object = iterator.next();\n"); buf.append(" \n"); buf.append(" }\n"); @@ -8778,7 +8839,7 @@ public class AssistQuickFixTest extends QuickFixTest { assertNumberOfProposals(proposals, 2); assertCorrectLabels(proposals); - String[] expected= new String[1]; + String[] expected= new String[2]; buf= new StringBuffer(); buf.append("package test1;\n"); buf.append("public class E {\n"); @@ -8799,7 +8860,224 @@ public class AssistQuickFixTest extends QuickFixTest { buf.append(" }\n"); buf.append(" }\n"); buf.append("}\n"); + expected[1]= buf.toString(); assertExpectedExistInProposals(proposals, expected); } + + public void testGenerateForImportsAndFormat1() throws Exception { + IPackageFragment pack1= fSourceFolder.createPackageFragment("test1", false, null); + StringBuffer buf= new StringBuffer(); + buf.append("package test1;\n"); + buf.append("public class A {\n"); + buf.append(" class Iterator {}\n"); + buf.append(" void foo() {\n"); + buf.append(" B.get( /*important: empty*/ );\n"); + buf.append(" }\n"); + buf.append("}\n"); + + StringBuffer buf2= new StringBuffer(); + buf2.append("package test1;\n"); + buf2.append("import java.util.ArrayList;\n"); + buf2.append("import java.util.Date;\n"); + buf2.append("import java.util.Set;\n"); + buf2.append("public class B {\n"); + buf2.append(" static ArrayList<Date> get() {\n"); + buf2.append(" return new ArrayList<Date>();\n"); + buf2.append(" }\n"); + buf2.append(" static Set raw(int i) {\n"); + buf2.append(" return java.util.Collections.emptySet();\n"); + buf2.append(" }\n"); + buf2.append("}"); + + ICompilationUnit cu= pack1.createCompilationUnit("A.java", buf.toString(), false, null); + pack1.createCompilationUnit("B.java", buf2.toString(), false, null); + + Map saveOptions= fJProject1.getOptions(false); + Map newOptions= new HashMap(); + JavaCore.setComplianceOptions(JavaCore.VERSION_1_5, newOptions); + newOptions.put(DefaultCodeFormatterConstants.FORMATTER_PUT_EMPTY_STATEMENT_ON_NEW_LINE, "true"); + try { + fJProject1.setOptions(newOptions); + + String selection= "B.get( /*important: empty*/ );"; + AssistContext context= getCorrectionContext(cu, buf.toString().lastIndexOf(selection) + selection.length(), 0); + List proposals= collectAssists(context, false); + + assertNumberOfProposals(proposals, 4); + assertCorrectLabels(proposals); + + String[] expected= new String[2]; + buf= new StringBuffer(); + buf.append("package test1;\n"); + buf.append("\n"); + buf.append("import java.util.Date;\n"); + buf.append("\n"); + buf.append("public class A {\n"); + buf.append(" class Iterator {}\n"); + buf.append(" void foo() {\n"); + buf.append(" for (Date date : B.get( /*important: empty*/ )) {\n"); + buf.append(" \n"); + buf.append(" }\n"); + buf.append(" }\n"); + buf.append("}\n"); + expected[0]= buf.toString(); + + buf= new StringBuffer(); + buf.append("package test1;\n"); + buf.append("\n"); + buf.append("import java.util.Date;\n"); + buf.append("\n"); + buf.append("public class A {\n"); + buf.append(" class Iterator {}\n"); + buf.append(" void foo() {\n"); + buf.append(" for (java.util.Iterator<Date> iterator = B.get( /*important: empty*/ ).iterator(); iterator\n"); + buf.append(" .hasNext();) {\n"); + buf.append(" Date date = iterator.next();\n"); + buf.append(" \n"); + buf.append(" }\n"); + buf.append(" }\n"); + buf.append("}\n"); + expected[1]= buf.toString(); + + assertExpectedExistInProposals(proposals, expected); + } finally { + fJProject1.setOptions(saveOptions); + } + } + + public void testGenerateForImportsAndFormat2() throws Exception { + IPackageFragment pack1= fSourceFolder.createPackageFragment("test1", false, null); + StringBuffer buf= new StringBuffer(); + buf.append("package test1;\n"); + buf.append("public class A {\n"); + buf.append(" class Object {}\n"); + buf.append(" class Iterator {}\n"); + buf.append(" void foo() {\n"); + buf.append(" B.raw(1+ 2);\n"); + buf.append(" }\n"); + buf.append("}\n"); + + StringBuffer buf2= new StringBuffer(); + buf2.append("package test1;\n"); + buf2.append("import java.util.ArrayList;\n"); + buf2.append("import java.util.Date;\n"); + buf2.append("import java.util.Set;\n"); + buf2.append("public class B {\n"); + buf2.append(" static ArrayList<Date> get() {\n"); + buf2.append(" return new ArrayList<Date>();\n"); + buf2.append(" }\n"); + buf2.append(" static Set raw(int i) {\n"); + buf2.append(" return java.util.Collections.emptySet();\n"); + buf2.append(" }\n"); + buf2.append("}"); + + ICompilationUnit cu= pack1.createCompilationUnit("A.java", buf.toString(), false, null); + pack1.createCompilationUnit("B.java", buf2.toString(), false, null); + + Map saveOptions= fJProject1.getOptions(false); + Map newOptions= new HashMap(); + JavaCore.setComplianceOptions(JavaCore.VERSION_1_5, newOptions); + newOptions.put(DefaultCodeFormatterConstants.FORMATTER_PUT_EMPTY_STATEMENT_ON_NEW_LINE, "true"); + try { + fJProject1.setOptions(newOptions); + + String selection= "B.raw(1+ 2);"; + AssistContext context= getCorrectionContext(cu, buf.toString().lastIndexOf(selection) + selection.length(), 0); + List proposals= collectAssists(context, false); + + assertNumberOfProposals(proposals, 4); + assertCorrectLabels(proposals); + + String[] expected= new String[2]; + buf= new StringBuffer(); + buf.append("package test1;\n"); + buf.append("public class A {\n"); + buf.append(" class Object {}\n"); + buf.append(" class Iterator {}\n"); + buf.append(" void foo() {\n"); + buf.append(" for (java.lang.Object object : B.raw(1+ 2)) {\n"); + buf.append(" \n"); + buf.append(" }\n"); + buf.append(" }\n"); + buf.append("}\n"); + expected[0]= buf.toString(); + + buf= new StringBuffer(); + buf.append("package test1;\n"); + buf.append("public class A {\n"); + buf.append(" class Object {}\n"); + buf.append(" class Iterator {}\n"); + buf.append(" void foo() {\n"); + buf.append(" for (java.util.Iterator iterator = B.raw(1+ 2).iterator(); iterator\n"); + buf.append(" .hasNext();) {\n"); + buf.append(" java.lang.Object object = iterator.next();\n"); + buf.append(" \n"); + buf.append(" }\n"); + buf.append(" }\n"); + buf.append("}\n"); + expected[1]= buf.toString(); + + assertExpectedExistInProposals(proposals, expected); + } finally { + fJProject1.setOptions(saveOptions); + } + } + + public void testGenerateForImportsArray() throws Exception { + IPackageFragment pack1= fSourceFolder.createPackageFragment("test1", false, null); + StringBuffer buf= new StringBuffer(); + buf.append("package test1;\n"); + buf.append("public class A {\n"); + buf.append(" class Date {}\n"); + buf.append(" void foo() {\n"); + buf.append(" B.get();\n"); + buf.append(" }\n"); + buf.append("}\n"); + + StringBuffer buf2= new StringBuffer(); + buf2.append("package test1;\n"); + buf2.append("import java.util.Date;\n"); + buf2.append("public class B {\n"); + buf2.append(" static Date[] get() {\n"); + buf2.append(" return new Date[1];\n"); + buf2.append(" }\n"); + buf2.append("}"); + + ICompilationUnit cu= pack1.createCompilationUnit("A.java", buf.toString(), false, null); + pack1.createCompilationUnit("B.java", buf2.toString(), false, null); + + Map saveOptions= fJProject1.getOptions(false); + Map newOptions= new HashMap(); + JavaCore.setComplianceOptions(JavaCore.VERSION_1_5, newOptions); + newOptions.put(DefaultCodeFormatterConstants.FORMATTER_PUT_EMPTY_STATEMENT_ON_NEW_LINE, "true"); + try { + fJProject1.setOptions(newOptions); + + String selection= "B.get();"; + AssistContext context= getCorrectionContext(cu, buf.toString().lastIndexOf(selection) + selection.length(), 0); + List proposals= collectAssists(context, false); + + assertNumberOfProposals(proposals, 4); + assertCorrectLabels(proposals); + + String[] expected= new String[1]; + buf= new StringBuffer(); + buf.append("package test1;\n"); + buf.append("public class A {\n"); + buf.append(" class Date {}\n"); + buf.append(" void foo() {\n"); + buf.append(" for (java.util.Date date : B.get()) {\n"); + buf.append(" \n"); + buf.append(" }\n"); + buf.append(" }\n"); + buf.append("}\n"); + expected[0]= buf.toString(); + + assertExpectedExistInProposals(proposals, expected); + } finally { + fJProject1.setOptions(saveOptions); + } + } + } diff --git a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/correction/CorrectionMessages.properties b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/correction/CorrectionMessages.properties index d1fdaaa764..8a33e69aad 100644 --- a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/correction/CorrectionMessages.properties +++ b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/correction/CorrectionMessages.properties @@ -345,8 +345,8 @@ QuickAssistProcessor_typetoarrayInitializer_description=Add type to initializer QuickAssistProcessor_convert_local_to_field_description=Convert local variable to field QuickAssistProcessor_convert_to_indexed_for_loop=Convert to indexed 'for' loop QuickAssistProcessor_convert_to_iterator_for_loop=Convert to Iterator-based 'for' loop -QuickAssistProcessor_generate_enhanced_for_loop=Iterate over collection using foreach -QuickAssistProcessor_generate_iterator_for_loop=Iterate over collection using iterator +QuickAssistProcessor_generate_enhanced_for_loop=Iterate over array or iterable using foreach +QuickAssistProcessor_generate_iterator_for_loop=Iterate over iterable using iterator QuickAssistProcessor_generate_iterate_array_for_loop=Iterate over array using for QuickAssistProcessor_convert_to_message_format=Use 'MessageFormat' for string concatenation QuickAssistProcessor_convert_to_multiple_singletype_catch_blocks=Use separate catch blocks diff --git a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/correction/QuickAssistProcessor.java b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/correction/QuickAssistProcessor.java index 45b106ecc5..175444a860 100644 --- a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/correction/QuickAssistProcessor.java +++ b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/correction/QuickAssistProcessor.java @@ -2556,7 +2556,7 @@ public class QuickAssistProcessor implements IQuickAssistProcessor { return true; } - private boolean getGenerateForLoopProposals(IInvocationContext context, ASTNode coveringNode, Collection<ICommandAccess> resultingCollections) { + private static boolean getGenerateForLoopProposals(IInvocationContext context, ASTNode coveringNode, Collection<ICommandAccess> resultingCollections) { Statement statement= ASTResolving.findParentStatement(coveringNode); if (!(statement instanceof ExpressionStatement)) { return false; diff --git a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/correction/proposals/GenerateForLoopAssistProposal.java b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/correction/proposals/GenerateForLoopAssistProposal.java index 4b57444afa..d0e27aa4ad 100644 --- a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/correction/proposals/GenerateForLoopAssistProposal.java +++ b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/correction/proposals/GenerateForLoopAssistProposal.java @@ -27,26 +27,24 @@ import org.eclipse.jdt.core.dom.EnhancedForStatement; import org.eclipse.jdt.core.dom.Expression; import org.eclipse.jdt.core.dom.FieldAccess; import org.eclipse.jdt.core.dom.ForStatement; +import org.eclipse.jdt.core.dom.IMethodBinding; import org.eclipse.jdt.core.dom.ITypeBinding; import org.eclipse.jdt.core.dom.InfixExpression; import org.eclipse.jdt.core.dom.MethodInvocation; import org.eclipse.jdt.core.dom.NumberLiteral; -import org.eclipse.jdt.core.dom.ParameterizedType; import org.eclipse.jdt.core.dom.PostfixExpression; import org.eclipse.jdt.core.dom.PrimitiveType; import org.eclipse.jdt.core.dom.SimpleName; -import org.eclipse.jdt.core.dom.SimpleType; import org.eclipse.jdt.core.dom.SingleVariableDeclaration; import org.eclipse.jdt.core.dom.Statement; import org.eclipse.jdt.core.dom.VariableDeclarationExpression; import org.eclipse.jdt.core.dom.VariableDeclarationFragment; import org.eclipse.jdt.core.dom.rewrite.ASTRewrite; -import org.eclipse.jdt.core.dom.rewrite.ImportRewrite; +import org.eclipse.jdt.internal.corext.codemanipulation.ContextSensitiveImportRewriteContext; import org.eclipse.jdt.internal.corext.codemanipulation.StubUtility; import org.eclipse.jdt.internal.corext.dom.Bindings; import org.eclipse.jdt.internal.corext.dom.ScopeAnalyzer; -import org.eclipse.jdt.internal.corext.util.JavaModelUtil; import org.eclipse.jdt.internal.ui.JavaPluginImages; import org.eclipse.jdt.internal.ui.text.correction.CorrectionMessages; @@ -113,6 +111,7 @@ public class GenerateForLoopAssistProposal extends LinkedCorrectionProposal { protected ASTRewrite getRewrite() throws CoreException { AST ast= fCurrentNode.getAST(); + createImportRewrite((CompilationUnit) fCurrentExpression.getRoot()); // generate the subexpression which represents the expression to iterate over if (fCurrentExpression instanceof Assignment) { @@ -144,19 +143,17 @@ public class GenerateForLoopAssistProposal extends LinkedCorrectionProposal { EnhancedForStatement loopStatement= ast.newEnhancedForStatement(); ASTRewrite rewrite= ASTRewrite.create(ast); - String loopOverTypename= extractElementTypeName(ast); - if (loopOverTypename == null) { - loopOverTypename= Object.class.getSimpleName(); - } + ITypeBinding loopOverType= extractElementType(ast); + // generate name proposals and add them to the variable declaration - SimpleName forDeclarationName= resolveLinkedVariableNameWithProposals(ast, rewrite, loopOverTypename, true); + SimpleName forDeclarationName= resolveLinkedVariableNameWithProposals(rewrite, loopOverType.getName(), true); SingleVariableDeclaration forLoopInitializer= ast.newSingleVariableDeclaration(); - forLoopInitializer.setType(ast.newSimpleType(ast.newSimpleName(loopOverTypename))); + forLoopInitializer.setType(getImportRewrite().addImport(loopOverType, ast, new ContextSensitiveImportRewriteContext(fCurrentNode, getImportRewrite()))); forLoopInitializer.setName(forDeclarationName); loopStatement.setParameter(forLoopInitializer); - loopStatement.setExpression((Expression) ASTNode.copySubtree(ast, fSubExpression)); + loopStatement.setExpression((Expression) rewrite.createCopyTarget(fSubExpression)); Block forLoopBody= ast.newBlock(); forLoopBody.statements().add(createBlankLineStatementWithCursorPosition(rewrite)); @@ -179,13 +176,10 @@ public class GenerateForLoopAssistProposal extends LinkedCorrectionProposal { ASTRewrite rewrite= ASTRewrite.create(ast); ForStatement loopStatement= ast.newForStatement(); - String loopOverTypename= extractElementTypeName(ast); - if (loopOverTypename == null && JavaModelUtil.is50OrHigher(getCompilationUnit().getJavaProject())) { - loopOverTypename= Object.class.getSimpleName(); - } + ITypeBinding loopOverType= extractElementType(ast); - SimpleName loopVariableName= resolveLinkedVariableNameWithProposals(ast, rewrite, "iterator", true); //$NON-NLS-1$ - loopStatement.initializers().add(getIteratorBasedForInitializer(ast, rewrite, loopOverTypename, loopVariableName)); + SimpleName loopVariableName= resolveLinkedVariableNameWithProposals(rewrite, "iterator", true); //$NON-NLS-1$ + loopStatement.initializers().add(getIteratorBasedForInitializer(rewrite, loopVariableName)); MethodInvocation loopExpression= ast.newMethodInvocation(); loopExpression.setName(ast.newSimpleName("hasNext")); //$NON-NLS-1$ @@ -196,15 +190,12 @@ public class GenerateForLoopAssistProposal extends LinkedCorrectionProposal { loopStatement.setExpression(loopExpression); Block forLoopBody= ast.newBlock(); - Assignment assignResolvedVariable= getIteratorBasedForBodyAssignment(ast, rewrite, loopOverTypename, loopVariableName); + Assignment assignResolvedVariable= getIteratorBasedForBodyAssignment(rewrite, loopOverType, loopVariableName); forLoopBody.statements().add(ast.newExpressionStatement(assignResolvedVariable)); forLoopBody.statements().add(createBlankLineStatementWithCursorPosition(rewrite)); loopStatement.setBody(forLoopBody); - ImportRewrite fixImports= createImportRewrite((CompilationUnit) fCurrentExpression.getRoot()); - fixImports.addImport("java.util.Iterator"); //$NON-NLS-1$ - rewrite.replace(fCurrentNode, loopStatement, null); return rewrite; @@ -214,31 +205,24 @@ public class GenerateForLoopAssistProposal extends LinkedCorrectionProposal { * Generates the initializer for an iterator based <code>for</code> loop, which declares and * initializes the variable to loop over. * - * @param ast the current {@link AST} * @param rewrite the instance of {@link ASTRewrite} - * @param loopOverTypename the type of the loop variable represented as {@link String} * @param loopVariableName the proposed name of the loop variable * @return a {@link VariableDeclarationExpression} to use as initializer */ - private VariableDeclarationExpression getIteratorBasedForInitializer(AST ast, ASTRewrite rewrite, String loopOverTypename, SimpleName loopVariableName) { + private VariableDeclarationExpression getIteratorBasedForInitializer(ASTRewrite rewrite, SimpleName loopVariableName) { + AST ast= rewrite.getAST(); + IMethodBinding iteratorMethodBinding= Bindings.findMethodInHierarchy(fCurrentExpression.resolveTypeBinding(), "iterator", new ITypeBinding[] {}); //$NON-NLS-1$ // initializing fragment VariableDeclarationFragment varDeclarationFragment= ast.newVariableDeclarationFragment(); varDeclarationFragment.setName(loopVariableName); MethodInvocation iteratorExpression= ast.newMethodInvocation(); - iteratorExpression.setName(ast.newSimpleName("iterator")); //$NON-NLS-1$ - iteratorExpression.setExpression((Expression) ASTNode.copySubtree(ast, fSubExpression)); + iteratorExpression.setName(ast.newSimpleName(iteratorMethodBinding.getName())); + iteratorExpression.setExpression((Expression) rewrite.createCopyTarget(fCurrentExpression)); varDeclarationFragment.setInitializer(iteratorExpression); // declaration VariableDeclarationExpression varDeclarationExpression= ast.newVariableDeclarationExpression(varDeclarationFragment); - SimpleType type= ast.newSimpleType(ast.newSimpleName("Iterator")); //$NON-NLS-1$ - if (loopOverTypename != null) { - ParameterizedType parameterizedType= ast.newParameterizedType(type); - parameterizedType.typeArguments().add(ast.newSimpleType(ast.newSimpleName(loopOverTypename))); - varDeclarationExpression.setType(parameterizedType); - } else { - varDeclarationExpression.setType(type); - } + varDeclarationExpression.setType(getImportRewrite().addImport(iteratorMethodBinding.getReturnType(), ast, new ContextSensitiveImportRewriteContext(fCurrentNode, getImportRewrite()))); return varDeclarationExpression; } @@ -248,24 +232,22 @@ public class GenerateForLoopAssistProposal extends LinkedCorrectionProposal { * based <code>for</code> loop body, to retrieve the next element of the {@link Iterable} * instance. * - * @param ast the current {@link AST} * @param rewrite the current instance of {@link ASTRewrite} - * @param loopOverTypename the type of the loop variable in string representation + * @param loopOverType the {@link ITypeBinding} of the loop variable * @param loopVariableName the name of the loop variable * @return an {@link Assignment}, which retrieves the next element of the {@link Iterable} using * the active {@link Iterator} */ - private Assignment getIteratorBasedForBodyAssignment(AST ast, ASTRewrite rewrite, String loopOverTypename, SimpleName loopVariableName) { + private Assignment getIteratorBasedForBodyAssignment(ASTRewrite rewrite, ITypeBinding loopOverType, SimpleName loopVariableName) { + AST ast= rewrite.getAST(); Assignment assignResolvedVariable= ast.newAssignment(); - // in case no generics were given we get instances of Object.class using iterator.next() - String elementTypename= (loopOverTypename == null ? Object.class.getSimpleName() : loopOverTypename); // left hand side - SimpleName resolvedVariableName= resolveLinkedVariableNameWithProposals(ast, rewrite, elementTypename, false); + SimpleName resolvedVariableName= resolveLinkedVariableNameWithProposals(rewrite, loopOverType.getName(), false); VariableDeclarationFragment resolvedVariableDeclarationFragment= ast.newVariableDeclarationFragment(); resolvedVariableDeclarationFragment.setName(resolvedVariableName); VariableDeclarationExpression resolvedVariableDeclaration= ast.newVariableDeclarationExpression(resolvedVariableDeclarationFragment); - resolvedVariableDeclaration.setType(ast.newSimpleType(ast.newSimpleName(elementTypename))); + resolvedVariableDeclaration.setType(getImportRewrite().addImport(loopOverType, ast, new ContextSensitiveImportRewriteContext(fCurrentNode, getImportRewrite()))); assignResolvedVariable.setLeftHandSide(resolvedVariableDeclaration); // right hand side @@ -291,10 +273,10 @@ public class GenerateForLoopAssistProposal extends LinkedCorrectionProposal { ASTRewrite rewrite= ASTRewrite.create(ast); ForStatement loopStatement= ast.newForStatement(); - SimpleName loopVariableName= resolveLinkedVariableNameWithProposals(ast, rewrite, "i", true); //$NON-NLS-1$ + SimpleName loopVariableName= resolveLinkedVariableNameWithProposals(rewrite, "i", true); //$NON-NLS-1$ loopStatement.initializers().add(getIndexBasedForInitializer(ast, loopVariableName)); - loopStatement.setExpression(getLinkedInfixExpression(ast, rewrite, loopVariableName.getIdentifier())); - loopStatement.updaters().add(getLinkedIncrementExpression(ast, rewrite, loopVariableName.getIdentifier())); + loopStatement.setExpression(getLinkedInfixExpression(rewrite, loopVariableName.getIdentifier())); + loopStatement.updaters().add(getLinkedIncrementExpression(rewrite, loopVariableName.getIdentifier())); Block forLoopBody= ast.newBlock(); forLoopBody.statements().add(createBlankLineStatementWithCursorPosition(rewrite)); @@ -307,13 +289,13 @@ public class GenerateForLoopAssistProposal extends LinkedCorrectionProposal { /** * Creates an {@link InfixExpression} which is linked to the group of the variableToIncrement. * - * @param ast the current {@link AST} instance * @param rewrite the current {@link ASTRewrite} instance * @param variableToIncrement the name of the variable to generate the {@link InfixExpression} * for * @return a filled, new {@link InfixExpression} instance */ - private InfixExpression getLinkedInfixExpression(AST ast, ASTRewrite rewrite, String variableToIncrement) { + private InfixExpression getLinkedInfixExpression(ASTRewrite rewrite, String variableToIncrement) { + AST ast= rewrite.getAST(); InfixExpression loopExpression= ast.newInfixExpression(); SimpleName name= ast.newSimpleName(variableToIncrement); addLinkedPosition(rewrite.track(name), false, name.getIdentifier()); @@ -321,7 +303,7 @@ public class GenerateForLoopAssistProposal extends LinkedCorrectionProposal { loopExpression.setOperator(InfixExpression.Operator.LESS); FieldAccess getArrayLengthExpression= ast.newFieldAccess(); - getArrayLengthExpression.setExpression((Expression) ASTNode.copySubtree(ast, fSubExpression)); + getArrayLengthExpression.setExpression((Expression) rewrite.createCopyTarget(fSubExpression)); getArrayLengthExpression.setName(ast.newSimpleName("length")); //$NON-NLS-1$ loopExpression.setRightOperand(getArrayLengthExpression); @@ -332,13 +314,13 @@ public class GenerateForLoopAssistProposal extends LinkedCorrectionProposal { * Creates a {@link PostfixExpression} used to increment the loop variable of a <code>for</code> * loop to iterate over an array. * - * @param ast the current {@link AST} instance * @param rewrite the current {@link ASTRewrite} instance * @param variableToIncrement the name of the variable to increment * @return a filled {@link PostfixExpression} realizing an incrementation of the specified * variable */ - private Expression getLinkedIncrementExpression(AST ast, ASTRewrite rewrite, String variableToIncrement) { + private Expression getLinkedIncrementExpression(ASTRewrite rewrite, String variableToIncrement) { + AST ast= rewrite.getAST(); PostfixExpression incrementLoopVariable= ast.newPostfixExpression(); SimpleName name= ast.newSimpleName(variableToIncrement); addLinkedPosition(rewrite.track(name), false, name.getIdentifier()); @@ -348,7 +330,7 @@ public class GenerateForLoopAssistProposal extends LinkedCorrectionProposal { } /** - * Generates an {@link VariableDeclarationExpression}, which initializes the loop variable to + * Generates a {@link VariableDeclarationExpression}, which initializes the loop variable to * iterate over an array. * * @param ast the current {@link AST} instance @@ -375,14 +357,14 @@ public class GenerateForLoopAssistProposal extends LinkedCorrectionProposal { * Resolves name proposals by the given basename and adds a {@link LinkedPosition} to the * returned {@link SimpleName} expression. * - * @param ast the current {@link AST} * @param rewrite the current instance of an {@link ASTRewrite} * @param basename the base string to use for proposal calculation * @param firstLinkedProposal true if the generated name is the first {@link LinkedPosition} to * edit in the current {@link CompilationUnit}, false otherwise * @return the linked {@link SimpleName} instance based on the name proposals */ - private SimpleName resolveLinkedVariableNameWithProposals(AST ast, ASTRewrite rewrite, String basename, boolean firstLinkedProposal) { + private SimpleName resolveLinkedVariableNameWithProposals(ASTRewrite rewrite, String basename, boolean firstLinkedProposal) { + AST ast= rewrite.getAST(); String[] nameProposals= getVariableNameProposals(basename); SimpleName forDeclarationName= (nameProposals.length > 0 ? ast.newSimpleName(nameProposals[0]) : ast.newSimpleName(basename)); for (int i= 0; i < nameProposals.length; i++) { @@ -430,19 +412,19 @@ public class GenerateForLoopAssistProposal extends LinkedCorrectionProposal { * to iterate over an array using <code>foreach</code>. * * @param ast the current {@link AST} instance - * @return the string representation of the type's unqualified name + * @return the {@link ITypeBinding} of the elements to iterate over */ - private String extractElementTypeName(AST ast) { + private ITypeBinding extractElementType(AST ast) { ITypeBinding binding= fSubExpression.resolveTypeBinding(); if (binding.isArray()) { - return Bindings.normalizeForDeclarationUse(binding.getElementType(), ast).getName(); - } - ITypeBinding[] typeArguments= Bindings.findTypeInHierarchy(binding, "java.lang.Iterable").getTypeArguments(); //$NON-NLS-1$ - if (typeArguments != null && typeArguments.length > 0) { - return Bindings.normalizeForDeclarationUse(typeArguments[0], ast).getName(); + return Bindings.normalizeForDeclarationUse(binding.getElementType(), ast); } - return null; + // extract elements type directly out of the bindings + IMethodBinding iteratorMethodBinding= Bindings.findMethodInHierarchy(fCurrentExpression.resolveTypeBinding(), "iterator", new ITypeBinding[] {}); //$NON-NLS-1$ + IMethodBinding iteratorNextMethodBinding= Bindings.findMethodInHierarchy(iteratorMethodBinding.getReturnType(), "next", new ITypeBinding[] {}); //$NON-NLS-1$ + + return iteratorNextMethodBinding.getReturnType(); } } |