KT-1426 Implement "Optimize Imports" in plugin - do not remove imports for objects
This commit is contained in:
@@ -145,49 +145,37 @@ public class JetPsiUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public static FqName getFQName(@NotNull JetClassOrObject jetClass) {
|
public static FqName getFQName(JetNamedDeclaration namedDeclaration) {
|
||||||
if (jetClass.getName() == null) {
|
if (namedDeclaration instanceof JetObjectDeclarationName) {
|
||||||
return null;
|
JetObjectDeclaration objectDeclaration = PsiTreeUtil.getParentOfType(namedDeclaration, JetObjectDeclaration.class);
|
||||||
}
|
if (objectDeclaration == null) {
|
||||||
|
return null;
|
||||||
PsiElement parent = jetClass.getParent();
|
|
||||||
if (parent instanceof JetFile) {
|
|
||||||
return makeFQName(getFQName((JetFile) parent), jetClass);
|
|
||||||
}
|
|
||||||
while (parent instanceof JetClassBody) {
|
|
||||||
parent = parent.getParent();
|
|
||||||
if (parent instanceof JetObjectDeclaration && parent.getParent() instanceof JetClassObject) {
|
|
||||||
parent = parent.getParent().getParent();
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if (parent instanceof JetClassOrObject) {
|
|
||||||
return makeFQName(getFQName(((JetClassOrObject) parent)), jetClass);
|
|
||||||
}
|
|
||||||
return new FqName(jetClass.getName());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
return getFQName(objectDeclaration);
|
||||||
public static FqName getFQName(@NotNull JetNamedFunction jetNamedFunction) {
|
}
|
||||||
|
|
||||||
String functionName = jetNamedFunction.getName();
|
String functionName = namedDeclaration.getName();
|
||||||
if (functionName == null) {
|
if (functionName == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
PsiElement parent = namedDeclaration.getParent();
|
||||||
PsiElement qualifiedElement = PsiTreeUtil.getParentOfType(
|
if (parent instanceof JetClassBody) {
|
||||||
jetNamedFunction,
|
// One nesting to JetClassBody doesn't affect to qualified name
|
||||||
JetFile.class, JetClassOrObject.class, JetNamedFunction.class);
|
parent = parent.getParent();
|
||||||
|
}
|
||||||
|
|
||||||
FqName firstPart = FqName.ROOT;
|
FqName firstPart = null;
|
||||||
if (qualifiedElement instanceof JetFile) {
|
if (parent instanceof JetFile) {
|
||||||
firstPart = getFQName((JetFile) qualifiedElement);
|
firstPart = getFQName((JetFile) parent);
|
||||||
}
|
}
|
||||||
else if (qualifiedElement instanceof JetClassOrObject) {
|
else if (parent instanceof JetNamedDeclaration) {
|
||||||
firstPart = getFQName((JetClassOrObject) qualifiedElement);
|
firstPart = getFQName((JetNamedDeclaration) parent);
|
||||||
}
|
}
|
||||||
else if (qualifiedElement instanceof JetNamedFunction) {
|
|
||||||
firstPart = getFQName((JetNamedFunction) qualifiedElement);
|
if (firstPart == null) {
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return firstPart.child(functionName);
|
return firstPart.child(functionName);
|
||||||
|
|||||||
@@ -130,7 +130,7 @@ public final class QualifiedNamesUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isImported(@NotNull ImportPath alreadyImported, @NotNull FqName fqName) {
|
public static boolean isImported(@NotNull ImportPath alreadyImported, @NotNull FqName fqName) {
|
||||||
if (alreadyImported.isAllUnder()) {
|
if (alreadyImported.isAllUnder() && !fqName.isRoot()) {
|
||||||
return alreadyImported.fqnPart().equals(fqName.parent());
|
return alreadyImported.fqnPart().equals(fqName.parent());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -83,9 +83,17 @@ public class JetImportOptimizer implements ImportOptimizer {
|
|||||||
// Remove imports
|
// Remove imports
|
||||||
List<JetImportDirective> imports = jetFile.getImportDirectives();
|
List<JetImportDirective> imports = jetFile.getImportDirectives();
|
||||||
if (!imports.isEmpty()) {
|
if (!imports.isEmpty()) {
|
||||||
jetFile.deleteChildRange(
|
PsiElement firstForDelete = getWithPreviousWhitespaces(imports.get(0));
|
||||||
getWithPreviousWhitespaces(imports.get(0)),
|
PsiElement lastForDelete = getWithFollowedWhitespaces(imports.get(imports.size() - 1));
|
||||||
getWithFollowedWhitespaces(imports.get(imports.size() - 1)));
|
|
||||||
|
// Should be found before deletion
|
||||||
|
PsiElement elementBeforeImports = firstForDelete.getPrevSibling();
|
||||||
|
|
||||||
|
jetFile.deleteChildRange(firstForDelete, lastForDelete);
|
||||||
|
|
||||||
|
if (elementBeforeImports != null) {
|
||||||
|
jetFile.addAfter(JetPsiFactory.createWhiteSpace(jetFile.getProject(), "\n"), elementBeforeImports);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Insert back only necessary imports in correct order
|
// Insert back only necessary imports in correct order
|
||||||
@@ -120,7 +128,7 @@ public class JetImportOptimizer implements ImportOptimizer {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Set<FqName> extractUsedQualifiedNames(JetFile jetFile) {
|
public static Set<FqName> extractUsedQualifiedNames(final JetFile jetFile) {
|
||||||
final Set<FqName> usedQualifiedNames = new HashSet<FqName>();
|
final Set<FqName> usedQualifiedNames = new HashSet<FqName>();
|
||||||
jetFile.accept(new JetVisitorVoid() {
|
jetFile.accept(new JetVisitorVoid() {
|
||||||
@Override
|
@Override
|
||||||
@@ -131,7 +139,9 @@ public class JetImportOptimizer implements ImportOptimizer {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visitReferenceExpression(JetReferenceExpression expression) {
|
public void visitReferenceExpression(JetReferenceExpression expression) {
|
||||||
if (PsiTreeUtil.getParentOfType(expression, JetImportDirective.class) == null) {
|
if (PsiTreeUtil.getParentOfType(expression, JetImportDirective.class) == null &&
|
||||||
|
PsiTreeUtil.getParentOfType(expression, JetNamespaceHeader.class) == null) {
|
||||||
|
|
||||||
PsiReference reference = expression.getReference();
|
PsiReference reference = expression.getReference();
|
||||||
if (reference != null) {
|
if (reference != null) {
|
||||||
List<PsiElement> references = new ArrayList<PsiElement>();
|
List<PsiElement> references = new ArrayList<PsiElement>();
|
||||||
@@ -141,7 +151,7 @@ public class JetImportOptimizer implements ImportOptimizer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (references.isEmpty() && reference instanceof PsiPolyVariantReference) {
|
if (references.isEmpty() && reference instanceof PsiPolyVariantReference) {
|
||||||
for (ResolveResult resolveResult : ((PsiPolyVariantReference) reference).multiResolve(true)) {
|
for (ResolveResult resolveResult : ((PsiPolyVariantReference)reference).multiResolve(true)) {
|
||||||
references.add(resolveResult.getElement());
|
references.add(resolveResult.getElement());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -153,7 +163,6 @@ public class JetImportOptimizer implements ImportOptimizer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
super.visitReferenceExpression(expression);
|
super.visitReferenceExpression(expression);
|
||||||
@@ -166,18 +175,22 @@ public class JetImportOptimizer implements ImportOptimizer {
|
|||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public static FqName getElementUsageFQName(PsiElement element) {
|
public static FqName getElementUsageFQName(PsiElement element) {
|
||||||
if (element instanceof JetClassOrObject) {
|
if (element instanceof JetFile) {
|
||||||
return JetPsiUtil.getFQName((JetClassOrObject) element);
|
return JetPsiUtil.getFQName((JetFile) element);
|
||||||
}
|
}
|
||||||
if (element instanceof JetNamedFunction) {
|
|
||||||
return JetPsiUtil.getFQName((JetNamedFunction) element);
|
if (element instanceof JetNamedDeclaration) {
|
||||||
|
return JetPsiUtil.getFQName((JetNamedDeclaration) element);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (element instanceof PsiClass) {
|
if (element instanceof PsiClass) {
|
||||||
String qualifiedName = ((PsiClass) element).getQualifiedName();
|
String qualifiedName = ((PsiClass) element).getQualifiedName();
|
||||||
if (qualifiedName != null) {
|
if (qualifiedName != null) {
|
||||||
return new FqName(qualifiedName);
|
return new FqName(qualifiedName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: Still problem with kotlin global properties imported from class files
|
||||||
if (element instanceof PsiMethod) {
|
if (element instanceof PsiMethod) {
|
||||||
PsiMethod method = (PsiMethod) element;
|
PsiMethod method = (PsiMethod) element;
|
||||||
|
|
||||||
@@ -201,6 +214,10 @@ public class JetImportOptimizer implements ImportOptimizer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (element instanceof PsiPackage) {
|
||||||
|
return new FqName(((PsiPackage) element).getQualifiedName());
|
||||||
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,9 +5,15 @@ import java.net.HttpRetryException
|
|||||||
import java.util.ArrayList
|
import java.util.ArrayList
|
||||||
import kotlin.util.measureTimeMillis
|
import kotlin.util.measureTimeMillis
|
||||||
import java.util.HashMap
|
import java.util.HashMap
|
||||||
|
import kotlin.test.asserter
|
||||||
|
import kotlin.test.Asserter
|
||||||
|
import kotlin.Assertions
|
||||||
|
|
||||||
class Action {
|
class Action {
|
||||||
fun test() {
|
fun test() {
|
||||||
|
// val traait : Asserter = asserter
|
||||||
|
val traait : Asserter? = null
|
||||||
|
val objectImport : Assertions? = null
|
||||||
measureTimeMillis({ println(HashMap<String, Int>().size()) })
|
measureTimeMillis({ println(HashMap<String, Int>().size()) })
|
||||||
val test : ArrayList<Int>? = null
|
val test : ArrayList<Int>? = null
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,13 @@
|
|||||||
import java.util.ArrayList
|
import java.util.ArrayList
|
||||||
import java.util.HashMap
|
import java.util.HashMap
|
||||||
|
import kotlin.test.Asserter
|
||||||
import kotlin.util.measureTimeMillis
|
import kotlin.util.measureTimeMillis
|
||||||
|
|
||||||
class Action {
|
class Action {
|
||||||
fun test() {
|
fun test() {
|
||||||
|
// val traait : Asserter = asserter
|
||||||
|
val traait : Asserter? = null
|
||||||
|
val objectImport : Assertions? = null
|
||||||
measureTimeMillis({ println(HashMap<String, Int>().size()) })
|
measureTimeMillis({ println(HashMap<String, Int>().size()) })
|
||||||
val test : ArrayList<Int>? = null
|
val test : ArrayList<Int>? = null
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user