### Eclipse Workspace Patch 1.0 #P org.eclipse.jdt.core Index: dom/org/eclipse/jdt/internal/core/dom/rewrite/ImportRewriteAnalyzer.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/ImportRewriteAnalyzer.java,v retrieving revision 1.15 diff -u -r1.15 ImportRewriteAnalyzer.java --- dom/org/eclipse/jdt/internal/core/dom/rewrite/ImportRewriteAnalyzer.java 7 Mar 2009 00:59:06 -0000 1.15 +++ dom/org/eclipse/jdt/internal/core/dom/rewrite/ImportRewriteAnalyzer.java 5 Nov 2009 10:30:15 -0000 @@ -24,6 +24,7 @@ import org.eclipse.jdt.core.JavaCore; import org.eclipse.jdt.core.JavaModelException; import org.eclipse.jdt.core.Signature; +import org.eclipse.jdt.core.compiler.CharOperation; import org.eclipse.jdt.core.dom.ASTNode; import org.eclipse.jdt.core.dom.CompilationUnit; import org.eclipse.jdt.core.dom.ImportDeclaration; @@ -33,6 +34,7 @@ import org.eclipse.jdt.core.search.IJavaSearchScope; import org.eclipse.jdt.core.search.SearchEngine; import org.eclipse.jdt.core.search.TypeNameRequestor; +import org.eclipse.jdt.internal.core.JavaProject; import org.eclipse.jface.text.IRegion; import org.eclipse.jface.text.Region; import org.eclipse.text.edits.DeleteEdit; @@ -168,9 +170,33 @@ } } - private static String getQualifier(ImportDeclaration decl) { + private String getQualifier(ImportDeclaration decl) { String name= decl.getName().getFullyQualifiedName(); - return decl.isOnDemand() ? name : Signature.getQualifier(name); + if (decl.isOnDemand()) { + return name; + } + return getQualifier(name, decl.isStatic()); + } + + private String getQualifier(String name, boolean isStatic) { + // For static imports, return the Type name as well as part of the qualifier + if (isStatic) { + return Signature.getQualifier(name); + } + do { + IJavaElement fragment = null; + try { + fragment = ((JavaProject) this.compilationUnit.getJavaProject()).findPackageFragment(name); + } catch (JavaModelException e) { + // Should never happen + } + // If it's the last fragment, return as Types in default packages aren't allowed in imports + if (fragment != null || CharOperation.indexOf(Signature.C_DOT, name.toCharArray()) == -1 ) { + break; + } + name = Signature.getQualifier(name); + } while (true); + return name; } private static String getFullName(ImportDeclaration decl) { @@ -401,13 +427,13 @@ } public void addImport(String fullTypeName, boolean isStatic) { - String typeContainerName= Signature.getQualifier(fullTypeName); + String typeContainerName= getQualifier(fullTypeName, isStatic); ImportDeclEntry decl= new ImportDeclEntry(fullTypeName, isStatic, null); sortIn(typeContainerName, decl, isStatic); } public boolean removeImport(String qualifiedName, boolean isStatic) { - String containerName= Signature.getQualifier(qualifiedName); + String containerName= getQualifier(qualifiedName, isStatic); int nPackages= this.packageEntries.size(); for (int i= 0; i < nPackages; i++) { @@ -525,7 +551,7 @@ int nImports= pack.getNumberOfImports(); if (this.filterImplicitImports && !pack.isStatic() && isImplicitImport(pack.getName(), this.compilationUnit)) { - pack.removeAllNew(onDemandConflicts); + pack.filterImplicitImports(this.compilationUnit); nImports= pack.getNumberOfImports(); } if (nImports == 0) { @@ -930,16 +956,17 @@ return false; } - public void removeAllNew(Set onDemandConflicts) { + public void filterImplicitImports(ICompilationUnit compilationUnit) { int nInports= this.importEntries.size(); for (int i= nInports - 1; i >= 0; i--) { ImportDeclEntry curr= getImportAt(i); - if (curr.isNew() /*&& (onDemandConflicts == null || onDemandConflicts.contains(curr.getSimpleName()))*/) { + boolean internalClassImport = curr.getElementName().lastIndexOf('.') > getName().length(); + if (curr.isNew() && !internalClassImport) { this.importEntries.remove(i); } } } - + public ImportDeclEntry getImportAt(int index) { return (ImportDeclEntry) this.importEntries.get(index); } #P org.eclipse.jdt.core.tests.model Index: src/org/eclipse/jdt/core/tests/rewrite/describing/ImportRewriteTest.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/rewrite/describing/ImportRewriteTest.java,v retrieving revision 1.12 diff -u -r1.12 ImportRewriteTest.java --- src/org/eclipse/jdt/core/tests/rewrite/describing/ImportRewriteTest.java 24 Oct 2008 10:40:41 -0000 1.12 +++ src/org/eclipse/jdt/core/tests/rewrite/describing/ImportRewriteTest.java 5 Nov 2009 10:30:19 -0000 @@ -75,7 +75,10 @@ this.sourceFolder = getPackageFragmentRoot("P", "src"); - + this.sourceFolder.createPackageFragment("java.util", false, null); + this.sourceFolder.createPackageFragment("java.net", false, null); + this.sourceFolder.createPackageFragment("java.awt", false, null); + waitUntilIndexesReady(); } @@ -572,6 +575,101 @@ assertEqualString(cu.getSource(), buf.toString()); } + /** + * Test that the Inner class import comes in the right order (i.e. after the enclosing type's import) when re-organized + * + * @see "https://bugs.eclipse.org/bugs/show_bug.cgi?id=194358" + */ + public void testAddImports_bug194358() throws Exception { + + StringBuffer buf= new StringBuffer(); + buf.append("package pack1;\n"); + buf.append("\n"); + buf.append("import pack2.A;\n"); + buf.append("import pack2.A.Inner;\n"); + buf.append("import pack2.B;\n"); + buf.append("\n"); + buf.append("public class C {\n"); + buf.append("}\n"); + + IPackageFragment pack1= this.sourceFolder.createPackageFragment("pack1", false, null); + ICompilationUnit cu= pack1.createCompilationUnit("C.java", buf.toString(), false, null); + + // We need to actually make some state in the AST for the classes, to test that we can + // disambiguate between packages and inner classes (see the bug for details). + IPackageFragment pack2= this.sourceFolder.createPackageFragment("pack2", false, null); + ICompilationUnit aUnit= pack2.createCompilationUnit("A.java", "", false, null); + ICompilationUnit bUnit= pack2.createCompilationUnit("B.java", "", false, null); + bUnit.createType("class B {}", null, false, null); + + IType aType= aUnit.createType("class A {}", null, false, null); + aType.createType("class Inner {}", null, false, null); + String[] order= new String[] { "java" }; + + ImportRewrite imports= newImportsRewrite(cu, order, 99, 99, false); + imports.addImport("pack2.A"); + imports.addImport("pack2.A.Inner"); + imports.addImport("pack2.B"); + + apply(imports); + + buf= new StringBuffer(); + buf.append("package pack1;\n"); + buf.append("\n"); + buf.append("import pack2.A;\n"); + buf.append("import pack2.A.Inner;\n"); + buf.append("import pack2.B;\n"); + buf.append("\n"); + buf.append("public class C {\n"); + buf.append("}\n"); + assertEqualString(cu.getSource(), buf.toString()); + } + + /** + * Test that a valid inner class import is not removed even if it's in the same package. + * + * @see "https://bugs.eclipse.org/bugs/show_bug.cgi?id=235253" + */ + public void testAddImports_bug235253() throws Exception { + StringBuffer buf= new StringBuffer(); + buf.append("package com.pack1;\n"); + buf.append("\n"); + buf.append("import com.pack1.A;\n"); + buf.append("import com.pack1.A.Inner;\n"); + buf.append("import com.pack2.B;\n"); + buf.append("\n"); + buf.append("public class C {\n"); + buf.append("}\n"); + + IPackageFragment pack1= this.sourceFolder.createPackageFragment("com.pack1", false, null); + ICompilationUnit cu= pack1.createCompilationUnit("C.java", buf.toString(), false, null); + ICompilationUnit aUnit= pack1.createCompilationUnit("A.java", "", false, null); + + IPackageFragment pack2= this.sourceFolder.createPackageFragment("com.pack2", false, null); + ICompilationUnit bUnit= pack2.createCompilationUnit("B.java", "", false, null); + bUnit.createType("class B {}", null, false, null); + IType aType= aUnit.createType("class A {}", null, false, null); + aType.createType("class Inner {}", null, false, null); + String[] order= new String[] { "java" }; + + ImportRewrite imports= newImportsRewrite(cu, order, 99, 99, false); + imports.addImport("com.pack1.A"); + imports.addImport("com.pack1.A.Inner"); + imports.addImport("com.pack2.B"); + + apply(imports); + + buf= new StringBuffer(); + buf.append("package com.pack1;\n"); + buf.append("\n"); + buf.append("import com.pack1.A.Inner;\n"); + buf.append("import com.pack2.B;\n"); + buf.append("\n"); + buf.append("public class C {\n"); + buf.append("}\n"); + assertEqualString(cu.getSource(), buf.toString()); + } + public void testAddStaticImports1() throws Exception { IPackageFragment pack1= this.sourceFolder.createPackageFragment("pack1", false, null); #P org.eclipse.jdt.core.tests.performance Index: src/org/eclipse/jdt/core/tests/performance/FullSourceWorkspaceASTTests.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core.tests.performance/src/org/eclipse/jdt/core/tests/performance/FullSourceWorkspaceASTTests.java,v retrieving revision 1.26 diff -u -r1.26 FullSourceWorkspaceASTTests.java --- src/org/eclipse/jdt/core/tests/performance/FullSourceWorkspaceASTTests.java 7 Mar 2009 02:04:23 -0000 1.26 +++ src/org/eclipse/jdt/core/tests/performance/FullSourceWorkspaceASTTests.java 5 Nov 2009 10:30:23 -0000 @@ -19,10 +19,15 @@ import junit.framework.*; +import org.eclipse.core.runtime.CoreException; import org.eclipse.jdt.core.*; import org.eclipse.jdt.core.compiler.IProblem; import org.eclipse.jdt.core.dom.*; +import org.eclipse.jdt.core.dom.rewrite.ImportRewrite; import org.eclipse.jdt.core.tests.model.AbstractJavaModelTests; +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.text.edits.MalformedTreeException; +import org.osgi.service.prefs.BackingStoreException; /** */ @@ -733,4 +738,39 @@ tagAsSummary("DOM AST tree for project files (JLS3)", true); // put in fingerprint runAstCreation(getProject("org.eclipse.search")); } + + private void rewriteImport(ICompilationUnit cu, String[] order, + int normalThreshold, int staticThreshold, + boolean restoreExistingImports) throws CoreException, + BackingStoreException, MalformedTreeException, BadLocationException { + + ImportRewrite rewrite = ImportRewrite + .create(cu, restoreExistingImports); + rewrite.setImportOrder(order); + rewrite.setOnDemandImportThreshold(normalThreshold); + rewrite.setStaticOnDemandImportThreshold(staticThreshold); + rewrite.rewriteImports(null); + } + + public void testPerfImportRewrite() throws MalformedTreeException, CoreException, BackingStoreException, BadLocationException { + tagAsSummary("testPerfImportRewrite", false); // do NOT put in fingerprint + + String[] order= new String[] {"org", "javax", "java"}; + ICompilationUnit unit = getCompilationUnit("org.eclipse.jdt.core", "org.eclipse.jdt.internal.core", "JavaProject.java"); + + int measures = MEASURES_COUNT; + int internalLoop = 10; + for (int i = 0; i < measures; i++) { + runGc(); + startMeasuring(); + for (int index = 0; index < internalLoop; index++ ) { + rewriteImport(unit, order, 99, 99, false); + } + stopMeasuring(); + } + commitMeasurements(); + assertPerformance(); + + } + }