mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
PY-23125 Preserve blank lines before the first comment in optimize imports
I tweaked Python import optimizer so that it inserts new imports and their comments after the last of original imports, not before the first of them (and then deletes the old ones). The reason is that it turned out to be practically impossible to use PsiComment as the anchor for PsiElement#addRangeBefore(), because of the hardcoded behavior of CodeEditUtil.addChildren() which skips preceding whitespaces in this scenario. Otherwise, if the blank line before "# noinspection" comment preceding the first imports statement gets removed, next time this comment will be left in place, considered part of the top-level module comment e.g. license.
This commit is contained in:
@@ -282,15 +282,14 @@ public class PyImportOptimizer implements ImportOptimizer {
|
||||
}
|
||||
final PyImportStatementBase firstImport = myImportBlock.get(0);
|
||||
final List<PsiComment> boundComments = collectPrecedingLineComments(firstImport).getFirst();
|
||||
final PsiElement insertionAnchor = boundComments.isEmpty() ? firstImport : boundComments.get(0);
|
||||
addImportsBefore(insertionAnchor);
|
||||
// Remove together with extra whitespaces preceding
|
||||
final PsiElement nonWhitespaceBefore = PyPsiUtils.getPrevNonWhitespaceSibling(insertionAnchor);
|
||||
myFile.deleteChildRange(nonWhitespaceBefore != null ? nonWhitespaceBefore.getNextSibling() : insertionAnchor,
|
||||
ContainerUtil.getLastItem(myImportBlock));
|
||||
final PsiElement firstElementToRemove = boundComments.isEmpty() ? firstImport : boundComments.get(0);
|
||||
final PyImportStatementBase lastImport = ContainerUtil.getLastItem(myImportBlock);
|
||||
assert lastImport != null;
|
||||
addImportsAfter(lastImport);
|
||||
myFile.deleteChildRange(firstElementToRemove, PyPsiUtils.getNextNonWhitespaceSibling(lastImport).getPrevSibling());
|
||||
}
|
||||
|
||||
private void addImportsBefore(@NotNull PsiElement anchor) {
|
||||
private void addImportsAfter(@NotNull PsiElement anchor) {
|
||||
final StringBuilder content = new StringBuilder();
|
||||
|
||||
for (List<PyImportStatementBase> imports : myGroups.values()) {
|
||||
@@ -325,14 +324,12 @@ public class PyImportOptimizer implements ImportOptimizer {
|
||||
|
||||
final Project project = anchor.getProject();
|
||||
final PyElementGenerator generator = PyElementGenerator.getInstance(project);
|
||||
PyFile file = (PyFile)generator.createDummyFile(LanguageLevel.forElement(anchor), content.toString());
|
||||
file = (PyFile)CodeStyleManager.getInstance(project).reformat(file);
|
||||
final List<PyImportStatementBase> newImportBlock = file.getImportBlock();
|
||||
final PyFile file = (PyFile)generator.createDummyFile(LanguageLevel.forElement(anchor), content.toString());
|
||||
final PyFile reformattedFile = (PyFile)CodeStyleManager.getInstance(project).reformat(file);
|
||||
final List<PyImportStatementBase> newImportBlock = reformattedFile.getImportBlock();
|
||||
assert newImportBlock != null;
|
||||
|
||||
final PyImportStatementBase lastImport = ContainerUtil.getLastItem(newImportBlock);
|
||||
assert lastImport != null;
|
||||
myFile.addRangeBefore(file.getFirstChild(), file.getLastChild(), anchor);
|
||||
myFile.addRangeAfter(reformattedFile.getFirstChild(), reformattedFile.getLastChild(), anchor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
|
||||
# comment after the top-level one
|
||||
|
||||
|
||||
|
||||
# comment for abc
|
||||
import abc
|
||||
# comment for sys
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
|
||||
# comment after the top-level one
|
||||
|
||||
|
||||
|
||||
# comment for b
|
||||
import b
|
||||
|
||||
|
||||
@@ -273,6 +273,7 @@ public class PyOptimizeImportsTest extends PyTestCase {
|
||||
doTest();
|
||||
}
|
||||
|
||||
// PY-23125
|
||||
public void testStackDanglingCommentsAtEnd() {
|
||||
doTest();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user