From a84f06bac6ba350faaf07678c35928351a3e6d50 Mon Sep 17 00:00:00 2001 From: m0rkeulv Date: Sat, 19 Aug 2023 16:03:19 +0200 Subject: [PATCH] Fixing "Automatic import placed after class Doc comment." (#842) --- CHANGELOG.md | 1 + .../haxe/util/HaxeAddImportHelper.java | 35 +++++++++++++++---- .../plugins/haxe/util/UsefulPsiTreeUtil.java | 23 +++++++++--- .../testData/addImportIntention/Helper.hx | 5 +++ .../testData/addImportIntention/Helper.txt | 5 +++ .../testData/addImportIntention/Module.hx | 2 ++ .../testData/addImportIntention/Module.txt | 2 ++ .../testData/addImportIntention/Simple.hx | 2 ++ .../testData/addImportIntention/Simple.txt | 2 ++ .../testData/move/moveFile1/after/Test.hx | 1 - 10 files changed, 66 insertions(+), 12 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6a7147689..331cbeded 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ## 1.4.13 * Added: Quick fix for incorrect extends and implements (#940) * Fixed: Resolving type from inline method calls (#868) +* Fixed: Automatic import was placed after class Doc comment (#842) ## 1.4.12 * Bugfix: "import class quickfix" missing in some cases (#1132) diff --git a/src/main/java/com/intellij/plugins/haxe/util/HaxeAddImportHelper.java b/src/main/java/com/intellij/plugins/haxe/util/HaxeAddImportHelper.java index 7dc255a0e..1291885bc 100644 --- a/src/main/java/com/intellij/plugins/haxe/util/HaxeAddImportHelper.java +++ b/src/main/java/com/intellij/plugins/haxe/util/HaxeAddImportHelper.java @@ -22,23 +22,44 @@ import com.intellij.plugins.haxe.lang.psi.HaxePackageStatement; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; +import com.intellij.psi.PsiParserFacade; +import lombok.CustomLog; + +import static com.intellij.plugins.haxe.util.UsefulPsiTreeUtil.isWhitespaceOrCommentButNotDocs; /** * @author: Fedor.Korotkov */ +@CustomLog public class HaxeAddImportHelper { public static HaxeImportStatement addImport(String path, PsiFile file) { int positionIndex = 0; final PsiElement[] children = file.getChildren(); - while ((children[positionIndex] instanceof HaxePackageStatement || - UsefulPsiTreeUtil.isWhitespaceOrComment(children[positionIndex]) && - positionIndex < children.length)) { - ++positionIndex; + PsiElement child = children[positionIndex]; + // find HaxePackageStatement position + while (!(child instanceof HaxePackageStatement)) { + if (++positionIndex < children.length) { + child = children[positionIndex]; + }else { + log.warn("Unable to insert Import statement"); + return null; + } + } + // find last whitespace line before docs or code and after last import + while (child instanceof HaxePackageStatement + || child instanceof HaxeImportStatement + || isWhitespaceOrCommentButNotDocs(child)) { + if (++positionIndex < children.length) { + child = children[positionIndex]; + }else { + log.warn("Unable to insert Import statement"); + return null; + } } - assert positionIndex < children.length; - return insertImportBefore(path, file, children[positionIndex]); + assert child != null; + return insertImportBefore(path, file, child); } private static HaxeImportStatement insertImportBefore(String path, PsiFile file, PsiElement child) { @@ -48,6 +69,8 @@ private static HaxeImportStatement insertImportBefore(String path, PsiFile file, return null; } + final PsiElement newLineElement = PsiParserFacade.getInstance(file.getProject()).createWhiteSpaceFromText("\n"); + file.addBefore(newLineElement, child); file.addBefore(importStatement, child); return importStatement; } diff --git a/src/main/java/com/intellij/plugins/haxe/util/UsefulPsiTreeUtil.java b/src/main/java/com/intellij/plugins/haxe/util/UsefulPsiTreeUtil.java index ffc317796..457d41401 100644 --- a/src/main/java/com/intellij/plugins/haxe/util/UsefulPsiTreeUtil.java +++ b/src/main/java/com/intellij/plugins/haxe/util/UsefulPsiTreeUtil.java @@ -26,9 +26,12 @@ import com.intellij.openapi.util.TextRange; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.plugins.haxe.HaxeFileType; +import com.intellij.plugins.haxe.lang.lexer.HaxeElementType; +import com.intellij.plugins.haxe.lang.lexer.HaxeTokenTypeSets; import com.intellij.plugins.haxe.lang.psi.HaxeClass; import com.intellij.plugins.haxe.lang.psi.HaxeParenthesizedExpression; import com.intellij.plugins.haxe.lang.psi.HaxePsiCompositeElement; +import com.intellij.plugins.haxe.lang.psi.impl.HaxePsiDocComment; import com.intellij.plugins.haxe.lang.util.HaxeAstUtil; import com.intellij.psi.*; import com.intellij.psi.tree.IElementType; @@ -79,7 +82,9 @@ public boolean value(PsiElement element) { } @Nullable - public static PsiElement getPrevSiblingSkippingCondition(@Nullable PsiElement sibling, Condition condition, boolean strictly) { + public static PsiElement getPrevSiblingSkippingCondition(@Nullable PsiElement sibling, + Condition condition, + boolean strictly) { if (sibling == null) return null; PsiElement result = strictly ? sibling.getPrevSibling() : sibling; while (result != null && condition.value(result)) { @@ -89,7 +94,9 @@ public static PsiElement getPrevSiblingSkippingCondition(@Nullable PsiElement si } @Nullable - public static PsiElement getNextSiblingSkippingCondition(@Nullable PsiElement sibling, Condition condition, boolean strictly) { + public static PsiElement getNextSiblingSkippingCondition(@Nullable PsiElement sibling, + Condition condition, + boolean strictly) { if (sibling == null) return null; PsiElement result = strictly ? sibling.getNextSibling() : sibling; while (result != null && condition.value(result)) { @@ -143,6 +150,10 @@ public static boolean isWhitespaceOrComment(ASTNode node) { public static boolean isWhitespaceOrComment(PsiElement element) { return element instanceof PsiWhiteSpace || element instanceof PsiComment; } + public static boolean isWhitespaceOrCommentButNotDocs(PsiElement element) { + return element instanceof PsiWhiteSpace + || (element instanceof PsiComment comment && comment.getTokenType() != HaxeTokenTypeSets.DOC_COMMENT); + } private static void populateClassesList(List classList, Project project, VirtualFile file) { VirtualFile[] files = file.getChildren(); @@ -170,8 +181,9 @@ public static List getClassesInDirectory(Project project, VirtualFile @Nullable public static T getParentOfType(@Nullable PsiElement element, @NotNull Class aClass) { - if (element == null || element instanceof PsiFile) + if (element == null || element instanceof PsiFile) { return null; + } // Don't start with the passed element. element = element.getParent(); @@ -187,8 +199,9 @@ public static T getParentOfType(@Nullable PsiElement element, @NotNull Class @Nullable public static PsiElement getParent(@Nullable PsiElement element, @NotNull IElementType elementType) { - if (element == null || element instanceof PsiFile) + if (element == null || element instanceof PsiFile) { return null; + } element = element.getParent(); while (element != null && !(element instanceof PsiFile)) { @@ -288,7 +301,7 @@ static public T getLastChild(PsiElement element, Class static public PsiElement getToken(PsiElement element, String token) { for (ASTNode node : element.getNode().getChildren(null)) { - if (node.getText().equals(token)) return node.getPsi(); + if (node.getText().equals(token)) return node.getPsi(); } return null; } diff --git a/src/test/resources/testData/addImportIntention/Helper.hx b/src/test/resources/testData/addImportIntention/Helper.hx index acb6d0941..955f267c5 100644 --- a/src/test/resources/testData/addImportIntention/Helper.hx +++ b/src/test/resources/testData/addImportIntention/Helper.hx @@ -1,3 +1,8 @@ +package; + +/** + helper class docs +**/ class Helper { var bar:Baz; } \ No newline at end of file diff --git a/src/test/resources/testData/addImportIntention/Helper.txt b/src/test/resources/testData/addImportIntention/Helper.txt index 389be6ba2..c3a625a4f 100644 --- a/src/test/resources/testData/addImportIntention/Helper.txt +++ b/src/test/resources/testData/addImportIntention/Helper.txt @@ -1,4 +1,9 @@ +package; import foo.Bar.Baz; + +/** + helper class docs +**/ class Helper { var bar:Baz; } \ No newline at end of file diff --git a/src/test/resources/testData/addImportIntention/Module.hx b/src/test/resources/testData/addImportIntention/Module.hx index 421240304..6e9d4360e 100644 --- a/src/test/resources/testData/addImportIntention/Module.hx +++ b/src/test/resources/testData/addImportIntention/Module.hx @@ -1,3 +1,5 @@ +package; + class Module { var t:Type1; } diff --git a/src/test/resources/testData/addImportIntention/Module.txt b/src/test/resources/testData/addImportIntention/Module.txt index 89d0a2c27..97ab83ed2 100644 --- a/src/test/resources/testData/addImportIntention/Module.txt +++ b/src/test/resources/testData/addImportIntention/Module.txt @@ -1,3 +1,5 @@ +package; + import foo.Types.Type1; class Module { var t:Type1; diff --git a/src/test/resources/testData/addImportIntention/Simple.hx b/src/test/resources/testData/addImportIntention/Simple.hx index 31ed56701..b5534b043 100644 --- a/src/test/resources/testData/addImportIntention/Simple.hx +++ b/src/test/resources/testData/addImportIntention/Simple.hx @@ -1,3 +1,5 @@ +package; + class Simple { var bar:Bar; } \ No newline at end of file diff --git a/src/test/resources/testData/addImportIntention/Simple.txt b/src/test/resources/testData/addImportIntention/Simple.txt index 08fb51ffa..c473aec71 100644 --- a/src/test/resources/testData/addImportIntention/Simple.txt +++ b/src/test/resources/testData/addImportIntention/Simple.txt @@ -1,3 +1,5 @@ +package; + import foo.Bar; class Simple { var bar:Bar; diff --git a/src/test/resources/testData/move/moveFile1/after/Test.hx b/src/test/resources/testData/move/moveFile1/after/Test.hx index d5263b5ca..445acaca8 100644 --- a/src/test/resources/testData/move/moveFile1/after/Test.hx +++ b/src/test/resources/testData/move/moveFile1/after/Test.hx @@ -1,7 +1,6 @@ package ; import bar.ArrayUtils; - class Test { static function main() { function is_c(val) { return val == "c"; }