IDEA-96810 "optimize imports" removes annotations on unused imports

This commit is contained in:
Max Medvedev
2012-12-18 16:09:40 +04:00
parent b204203fd3
commit 8565b17e6b
4 changed files with 109 additions and 19 deletions
@@ -29,6 +29,7 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.groovy.codeStyle.GroovyCodeStyleSettings;
import org.jetbrains.plugins.groovy.lang.psi.GrReferenceElement;
import org.jetbrains.plugins.groovy.lang.psi.GroovyElementVisitor;
import org.jetbrains.plugins.groovy.lang.psi.GroovyFile;
import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementFactory;
import org.jetbrains.plugins.groovy.lang.psi.api.GroovyResolveResult;
@@ -73,7 +74,7 @@ public class GroovyImportOptimizer implements ImportOptimizer {
@Nullable final Map<String, String> annotations) {
if (!(file instanceof GroovyFile)) return;
((GroovyFile)file).accept(new PsiRecursiveElementWalkingVisitor() {
file.accept(new PsiRecursiveElementWalkingVisitor() {
@Override
public void visitElement(PsiElement element) {
super.visitElement(element);
@@ -135,13 +136,6 @@ public class GroovyImportOptimizer implements ImportOptimizer {
final String importRef = getImportReferenceText(importStatement);
if (annotations != null) {
if (isAnnotatedImport(importStatement)) {
annotations.put(importRef, importStatement.getAnnotationList().getText());
}
}
if (importStatement.isAliasedImport()) {
if (aliased != null) {
aliased.put(importRef, importedName);
@@ -197,6 +191,19 @@ public class GroovyImportOptimizer implements ImportOptimizer {
return true;
}
});
if (annotations != null) {
((GroovyFile)file).acceptChildren(new GroovyElementVisitor() {
@Override
public void visitImportStatement(GrImportStatement importStatement) {
final String annotationText = importStatement.getAnnotationList().getText();
if (!StringUtil.isEmptyOrSpaces(annotationText)) {
final String importRef = getImportReferenceText(importStatement);
annotations.put(importRef, annotationText);
}
}
});
}
}
@Nullable
@@ -264,11 +271,13 @@ public class GroovyImportOptimizer implements ImportOptimizer {
tempFile.addImport(newImport);
}
final int startOffset = oldImports.get(0).getTextRange().getStartOffset();
final int endOffset = oldImports.get(oldImports.size() - 1).getTextRange().getEndOffset();
String oldText = oldImports.isEmpty() ? "" : myFile.getText().substring(startOffset, endOffset);
if (tempFile.getText().trim().equals(oldText)) {
return;
if (oldImports.size() > 0) {
final int startOffset = oldImports.get(0).getTextRange().getStartOffset();
final int endOffset = oldImports.get(oldImports.size() - 1).getTextRange().getEndOffset();
String oldText = oldImports.isEmpty() ? "" : myFile.getText().substring(startOffset, endOffset);
if (tempFile.getText().trim().equals(oldText)) {
return;
}
}
for (GrImportStatement statement : tempFile.getImportStatements()) {
@@ -295,6 +304,7 @@ public class GroovyImportOptimizer implements ImportOptimizer {
TObjectIntHashMap<String> packageCountMap = new TObjectIntHashMap<String>();
TObjectIntHashMap<String> classCountMap = new TObjectIntHashMap<String>();
//init packageCountMap
for (String importedClass : importedClasses) {
if (implicitlyImported.contains(importedClass) ||
innerClasses.contains(importedClass) ||
@@ -309,6 +319,7 @@ public class GroovyImportOptimizer implements ImportOptimizer {
packageCountMap.increment(packageName);
}
//init classCountMap
for (String importedMember : staticallyImportedMembers) {
if (aliased.containsKey(importedMember) || annotations.containsKey(importedMember)) continue;
@@ -320,11 +331,12 @@ public class GroovyImportOptimizer implements ImportOptimizer {
final Set<String> onDemandImportedSimpleClassNames = new HashSet<String>();
final List<GrImportStatement> result = new ArrayList<GrImportStatement>();
packageCountMap.forEachEntry(new TObjectIntProcedure<String>() {
public boolean execute(String s, int i) {
if (i >= settings.CLASS_COUNT_TO_USE_IMPORT_ON_DEMAND || settings.PACKAGES_TO_USE_IMPORT_ON_DEMAND.contains(s)) {
final GrImportStatement imp = factory.createImportStatementFromText(s, false, true, null);
String annos = annotations.get(s + ".*");
String annos = annotations.remove(s + ".*");
if (annos != null) {
imp.getAnnotationList().replace(factory.createModifierList(annos));
}
@@ -344,7 +356,7 @@ public class GroovyImportOptimizer implements ImportOptimizer {
public boolean execute(String s, int i) {
if (i >= settings.NAMES_COUNT_TO_USE_IMPORT_ON_DEMAND) {
final GrImportStatement imp = factory.createImportStatementFromText(s, true, true, null);
String annos = annotations.get(s + ".*");
String annos = annotations.remove(s + ".*");
if (annos != null) {
imp.getAnnotationList().replace(factory.createModifierList(annos));
}
@@ -369,7 +381,7 @@ public class GroovyImportOptimizer implements ImportOptimizer {
}
final GrImportStatement imp = factory.createImportStatementFromText(importedClass, false, false, null);
String annos = annotations.get(importedClass);
String annos = annotations.remove(importedClass);
if (annos != null) {
imp.getAnnotationList().replace(factory.createModifierList(annos));
}
@@ -386,6 +398,10 @@ public class GroovyImportOptimizer implements ImportOptimizer {
for (GrImportStatement anImport : usedImports) {
if (anImport.isAliasedImport() || isAnnotatedImport(anImport)) {
if (isAnnotatedImport(anImport)) {
annotations.remove(getImportReferenceText(anImport));
}
if (anImport.isStatic()) {
result.add(anImport);
}
@@ -400,6 +416,22 @@ public class GroovyImportOptimizer implements ImportOptimizer {
Collections.sort(explicated, comparator);
explicated.addAll(result);
if (!annotations.isEmpty()) {
StringBuilder allSkippedAnnotations = new StringBuilder();
for (String anno : annotations.values()) {
allSkippedAnnotations.append(anno).append(' ');
}
if (explicated.isEmpty()) {
explicated.add(factory.createImportStatementFromText(CommonClassNames.JAVA_LANG_OBJECT, false, false, null));
}
final GrImportStatement first = explicated.get(0);
allSkippedAnnotations.append(first.getAnnotationList().getText());
first.getAnnotationList().replace(factory.createModifierList(allSkippedAnnotations));
}
return explicated.toArray(new GrImportStatement[explicated.size()]);
}
}
@@ -69,7 +69,7 @@ public abstract class GroovyPsiElementFactory implements JVMElementFactory {
public abstract GrBlockStatement createBlockStatementFromText(String text, @Nullable PsiElement context);
public abstract GrModifierList createModifierList(String text);
public abstract GrModifierList createModifierList(CharSequence text);
public abstract GrCaseSection createSwitchSection(String text);
@@ -702,7 +702,7 @@ public class GroovyPsiElementFactoryImpl extends GroovyPsiElementFactory {
}
@Override
public GrModifierList createModifierList(String text) {
public GrModifierList createModifierList(CharSequence text) {
final GrMethod method = createMethodFromText(text + " void foo()");
return method.getModifierList();
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2011 JetBrains s.r.o.
* Copyright 2000-2012 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -301,4 +301,62 @@ aliased2()
}
void testAnnotationOnUnusedImport1() {
myFixture.addClass('package groovyx.gpars; public class GParsPool{}')
myFixture.addClass('package groovyx.gpars; public class GParsExecutorsPool{}')
myFixture.configureByText('_.groovy', '''\
@Grab(group='org.codehaus.gpars', module='gpars', version='0.12')
import groovyx.gpars.GParsPool
import groovyx.gpars.GParsExecutorsPool
GParsExecutorsPool oi
''')
doOptimizeImports()
myFixture.checkResult('''\
@Grab(group = 'org.codehaus.gpars', module = 'gpars', version = '0.12')
import groovyx.gpars.GParsExecutorsPool
GParsExecutorsPool oi
''')
}
void testAnnotationOnUnusedImport2() {
myFixture.addClass('package groovyx.gpars; public class GParsPool{}')
myFixture.configureByText('_.groovy', '''\
@Grab(group='org.codehaus.gpars', module='gpars', version='0.12')
import groovyx.gpars.GParsPool
''')
doOptimizeImports()
myFixture.checkResult('''\
@Grab(group = 'org.codehaus.gpars', module = 'gpars', version = '0.12')
import java.lang.Object
''')
}
void testAnnotationOnUnusedImport3() {
myFixture.addClass('package groovyx.gpars; public class GParsPool{}')
myFixture.addClass('package groovyx.gpars; public class GParsExecutorsPool{}')
myFixture.configureByText('_.groovy', '''\
@Grab(group='org.codehaus.gpars', module='gpars', version='0.12')
@Grab(group='org.codehaus.gpars', module='gpars', version='0.12')
import groovyx.gpars.GParsPool
import groovyx.gpars.GParsExecutorsPool
GParsExecutorsPool oi
''')
doOptimizeImports()
myFixture.checkResult('''\
@Grab(group = 'org.codehaus.gpars', module = 'gpars', version = '0.12') @Grab(group = 'org.codehaus.gpars', module = 'gpars', version = '0.12')
import groovyx.gpars.GParsExecutorsPool
GParsExecutorsPool oi
''')
}
}