blob: 275d74d2ca28eda4579580dd73deb8ab0d2cd94e [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2015 Google Inc and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* John Glassmyer <jogl@google.com> - import group sorting is broken - https://bugs.eclipse.org/430303
*******************************************************************************/
package org.eclipse.jdt.internal.core.dom.rewrite.imports;
import java.util.Comparator;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.Signature;
import org.eclipse.jdt.internal.core.JavaProject;
/**
* Sorts imports according to a lexicographic comparison of their containing package names.
* <p>
* This requires use of the JavaProject to look up packages and/or types by name in order to
* distinguish segments of the import's container name as containing package name vs. containing
* type name.
* <p>
* The alternative is {@link PackageAndContainingTypeImportComparator}. See
* https://bugs.eclipse.org/194358.
*/
final class PackageImportComparator implements Comparator<ImportName> {
private final JavaProject javaProject;
PackageImportComparator(JavaProject javaProject) {
this.javaProject = javaProject;
}
@Override
public int compare(ImportName o1, ImportName o2) {
return determinePackageName(o1).compareTo(determinePackageName(o2));
}
private String determinePackageName(ImportName importName) {
String containerName = importName.containerName;
try {
// Loop from longest to shortest prefix (of dot-separated name segments) of the
// container name until a package name is found.
String containerNamePrefix = containerName;
while (true) {
// Try to find a package named with this prefix.
if (this.javaProject.findPackageFragment(containerNamePrefix) != null) {
return containerNamePrefix;
}
int lastSegmentStart = containerNamePrefix.lastIndexOf(Signature.C_DOT) + 1;
// Use the heuristic that a prefix whose last segment starts with a lowercase letter
// is a package name, if we don't recognize the prefix as the name of a type.
if (this.javaProject.findType(containerNamePrefix) == null) {
if (Character.isLowerCase(containerNamePrefix.charAt(lastSegmentStart))) {
return containerNamePrefix;
}
}
if (lastSegmentStart == 0) {
// No prefix of containerName could be resolved to a package name.
break;
}
containerNamePrefix = containerNamePrefix.substring(0, lastSegmentStart - 1);
}
} catch (JavaModelException e) {
// An error occurred when we asked the JavaProject to resolve a name,
// so there is no point in proceeding with the loop.
}
return containerName;
}
}