PY-19292 PY-14176 Optimize Imports doesn't re-create unaffected import statements

For instance, "from" import statements where imported names are already
ordered. Otherwise even when all imports are well formed, the whole
import block will be inserted anew and reformatted.
This commit is contained in:
Mikhail Golubev
2016-06-15 19:34:12 +03:00
parent 84381c7273
commit a9ea4677bc
6 changed files with 57 additions and 18 deletions
@@ -147,27 +147,30 @@ public class PyImportOptimizer implements ImportOptimizer {
final PyFromImportStatement fromImportStatement = (PyFromImportStatement)statement;
final QualifiedName source = fromImportStatement.getImportSourceQName();
final String sourceText = Objects.toString(source, "");
if (myPySettings.OPTIMIZE_IMPORTS_JOIN_FROM_IMPORTS_WITH_SAME_SOURCE) {
final Collection<PyFromImportStatement> sameSourceImports = fromImportSources.get(source);
if (!sameSourceImports.isEmpty()) {
final List<PyImportElement> allImportElements = new ArrayList<>();
for (PyFromImportStatement sameSourceImport : sameSourceImports) {
ContainerUtil.addAll(allImportElements, sameSourceImport.getImportElements());
}
if (myPySettings.OPTIMIZE_IMPORTS_SORT_NAMES_IN_FROM_IMPORTS) {
Collections.sort(allImportElements, IMPORT_ELEMENT_COMPARATOR);
}
final String importedNames = StringUtil.join(allImportElements, PsiElement::getText, ", ");
result.add(generator.createFromImportStatement(langLevel, sourceText, importedNames, null));
// remember that we have checked imports from this source already
fromImportSources.remove(source);
final Collection<PyFromImportStatement> sameSourceImports = fromImportSources.get(source);
if (sameSourceImports.isEmpty()) continue;
final List<PyImportElement> newStatementElements = new ArrayList<>();
// Join multiple "from" imports with the same source, like "from module import foo; from module import bar as b"
if (myPySettings.OPTIMIZE_IMPORTS_JOIN_FROM_IMPORTS_WITH_SAME_SOURCE && sameSourceImports.size() > 1) {
for (PyFromImportStatement sameSourceImport : sameSourceImports) {
ContainerUtil.addAll(newStatementElements, sameSourceImport.getImportElements());
}
// Remember that we have checked imports with this source already
fromImportSources.remove(source);
}
else if (myPySettings.OPTIMIZE_IMPORTS_SORT_NAMES_IN_FROM_IMPORTS) {
final PyImportElement[] importElements = fromImportStatement.getImportElements();
Arrays.sort(importElements, IMPORT_ELEMENT_COMPARATOR);
final String importedNames = StringUtil.join(importElements, PsiElement::getText, ", ");
final List<PyImportElement> originalElements = Arrays.asList(fromImportStatement.getImportElements());
if (!Ordering.from(IMPORT_ELEMENT_COMPARATOR).isOrdered(originalElements)) {
ContainerUtil.addAll(newStatementElements, originalElements);
}
}
if (!newStatementElements.isEmpty()) {
if (myPySettings.OPTIMIZE_IMPORTS_SORT_NAMES_IN_FROM_IMPORTS) {
Collections.sort(newStatementElements, IMPORT_ELEMENT_COMPARATOR);
}
final String importedNames = StringUtil.join(newStatementElements, PsiElement::getText, ", ");
result.add(generator.createFromImportStatement(langLevel, sourceText, importedNames, null));
}
else {
@@ -0,0 +1,6 @@
# Optimize imports should not reformat unaffected statements
from module1 import a, b
from module2 import A, B
print(A, B, a, b)
@@ -0,0 +1,6 @@
# Optimize imports should not reformat unaffected statements
from module1 import a, b
from module2 import A, B
print(A, B, a, b)
@@ -0,0 +1,6 @@
# Optimize Imports should not re-create imports statements that are in order
from module1 import a, b, c
from module2 import A, B, C
print(A, B, C, a, b, c)
@@ -0,0 +1,6 @@
# Optimize Imports should not re-create imports statements that are in order
from module1 import a, b, c
from module2 import A, B, C
print(A, B, C, a, b, c)
@@ -145,6 +145,12 @@ public class PyOptimizeImportsTest extends PyTestCase {
doTest();
}
// PY-18792, PY-19292
public void testOrderNamesInsightFromImportDoesntAffectAlreadyOrderedImports() {
getPythonCodeStyleSettings().OPTIMIZE_IMPORTS_SORT_NAMES_IN_FROM_IMPORTS = true;
doTest();
}
// PY-18792, PY-12926
public void testJoinFromImportsForSameSource() {
getPythonCodeStyleSettings().OPTIMIZE_IMPORTS_JOIN_FROM_IMPORTS_WITH_SAME_SOURCE = true;
@@ -158,6 +164,12 @@ public class PyOptimizeImportsTest extends PyTestCase {
doTest();
}
// PY-18792, PY-12926
public void testJoinFromImportsDoesntAffectSingleImports() {
getPythonCodeStyleSettings().OPTIMIZE_IMPORTS_JOIN_FROM_IMPORTS_WITH_SAME_SOURCE = true;
doTest();
}
private void doTest() {
myFixture.configureByFile(getTestName(true) + ".py");
OptimizeImportsAction.actionPerformedImpl(DataManager.getInstance().getDataContext(myFixture.getEditor().getContentComponent()));