From e859d53975f6f28d784ebbf1e9261d6972bc571c Mon Sep 17 00:00:00 2001 From: Peter Gromov Date: Mon, 3 Aug 2020 13:04:15 +0200 Subject: [PATCH] IDEA-247122 Variable initialization completion adds semicolon which breaks the code GitOrigin-RevId: 61fb7454dbf3a62be2f9250e2f5e46f329b35e53 --- .../codeInsight/ExpectedTypesProvider.java | 4 +++- ...onAfterNonLastVariableInitializer-out.java | 5 ++++ ...icolonAfterNonLastVariableInitializer.java | 5 ++++ .../completion/SmartTypeCompletionTest.java | 3 +++ .../com/intellij/psi/util/PsiTreeUtil.java | 24 +++++++++++++++++++ .../psi/filters/FilterPositionUtil.java | 20 +--------------- 6 files changed, 41 insertions(+), 20 deletions(-) create mode 100644 java/java-tests/testData/codeInsight/completion/smartType/NoSemicolonAfterNonLastVariableInitializer-out.java create mode 100644 java/java-tests/testData/codeInsight/completion/smartType/NoSemicolonAfterNonLastVariableInitializer.java diff --git a/java/java-impl/src/com/intellij/codeInsight/ExpectedTypesProvider.java b/java/java-impl/src/com/intellij/codeInsight/ExpectedTypesProvider.java index fec5a4cc95b3..a615906efbb2 100644 --- a/java/java-impl/src/com/intellij/codeInsight/ExpectedTypesProvider.java +++ b/java/java-impl/src/com/intellij/codeInsight/ExpectedTypesProvider.java @@ -552,7 +552,9 @@ public final class ExpectedTypesProvider { @Override public void visitVariable(@NotNull PsiVariable variable) { PsiType type = variable.getType(); - TailType tail = variable instanceof PsiResourceVariable ? TailType.NONE : TailType.SEMICOLON; + TailType tail = variable instanceof PsiResourceVariable ? TailType.NONE : + PsiUtilCore.getElementType(PsiTreeUtil.nextCodeLeaf(variable)) == JavaTokenType.COMMA ? CommaTailType.INSTANCE : + TailType.SEMICOLON; myResult.add(createInfoImpl(type, ExpectedTypeInfo.TYPE_OR_SUBTYPE, type, tail, null, getPropertyName(variable))); } diff --git a/java/java-tests/testData/codeInsight/completion/smartType/NoSemicolonAfterNonLastVariableInitializer-out.java b/java/java-tests/testData/codeInsight/completion/smartType/NoSemicolonAfterNonLastVariableInitializer-out.java new file mode 100644 index 000000000000..c32f5bc59fa0 --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/smartType/NoSemicolonAfterNonLastVariableInitializer-out.java @@ -0,0 +1,5 @@ +class C { + int x = nextInt(), y = 0; + + int nextInt() {} +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/completion/smartType/NoSemicolonAfterNonLastVariableInitializer.java b/java/java-tests/testData/codeInsight/completion/smartType/NoSemicolonAfterNonLastVariableInitializer.java new file mode 100644 index 000000000000..238046b4b695 --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/smartType/NoSemicolonAfterNonLastVariableInitializer.java @@ -0,0 +1,5 @@ +class C { + int x = nex, y = 0; + + int nextInt() {} +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/java/codeInsight/completion/SmartTypeCompletionTest.java b/java/java-tests/testSrc/com/intellij/java/codeInsight/completion/SmartTypeCompletionTest.java index 432fd992a06b..914e27077c26 100644 --- a/java/java-tests/testSrc/com/intellij/java/codeInsight/completion/SmartTypeCompletionTest.java +++ b/java/java-tests/testSrc/com/intellij/java/codeInsight/completion/SmartTypeCompletionTest.java @@ -1476,4 +1476,7 @@ public class SmartTypeCompletionTest extends LightFixtureCompletionTestCase { myFixture.complete(CompletionType.SMART); checkResultByFile("second/MethodAsQualifier-out.java"); } + + public void testNoSemicolonAfterNonLastVariableInitializer() { doTest(); } + } diff --git a/platform/core-api/src/com/intellij/psi/util/PsiTreeUtil.java b/platform/core-api/src/com/intellij/psi/util/PsiTreeUtil.java index 2cb3cb35173b..8292266f590b 100644 --- a/platform/core-api/src/com/intellij/psi/util/PsiTreeUtil.java +++ b/platform/core-api/src/com/intellij/psi/util/PsiTreeUtil.java @@ -1103,6 +1103,30 @@ public class PsiTreeUtil { return nextLeaf; } + /** + * @return closest leaf (not necessarily a sibling) before the given element + * which has non-empty range and is neither a whitespace nor a comment + */ + public static @Nullable PsiElement prevCodeLeaf(@NotNull PsiElement element) { + PsiElement prevLeaf = prevLeaf(element, true); + while (prevLeaf != null && isNonCodeLeaf(prevLeaf)) prevLeaf = prevLeaf(prevLeaf, true); + return prevLeaf; + } + + /** + * @return closest leaf (not necessarily a sibling) after the given element + * which has non-empty range and is neither a whitespace nor a comment + */ + public static @Nullable PsiElement nextCodeLeaf(@NotNull PsiElement element) { + PsiElement nextLeaf = nextLeaf(element, true); + while (nextLeaf != null && isNonCodeLeaf(nextLeaf)) nextLeaf = nextLeaf(nextLeaf, true); + return nextLeaf; + } + + private static boolean isNonCodeLeaf(PsiElement leaf) { + return StringUtil.isEmptyOrSpaces(leaf.getText()) || getNonStrictParentOfType(leaf, PsiComment.class) != null; + } + public static @Nullable PsiElement nextLeaf(@NotNull PsiElement element, final boolean skipEmptyElements) { PsiElement nextLeaf = nextLeaf(element); while (skipEmptyElements && nextLeaf != null && nextLeaf.getTextLength() == 0) nextLeaf = nextLeaf(nextLeaf); diff --git a/platform/lang-impl/src/com/intellij/psi/filters/FilterPositionUtil.java b/platform/lang-impl/src/com/intellij/psi/filters/FilterPositionUtil.java index 5a1ecec1a1c7..1b68a94ade20 100644 --- a/platform/lang-impl/src/com/intellij/psi/filters/FilterPositionUtil.java +++ b/platform/lang-impl/src/com/intellij/psi/filters/FilterPositionUtil.java @@ -1,11 +1,7 @@ // Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.psi.filters; -import com.intellij.lang.ASTNode; -import com.intellij.psi.PsiComment; import com.intellij.psi.PsiElement; -import com.intellij.psi.TokenType; -import com.intellij.psi.impl.source.tree.TreeUtil; import com.intellij.psi.util.PsiTreeUtil; import org.jetbrains.annotations.Nullable; @@ -15,20 +11,6 @@ import org.jetbrains.annotations.Nullable; public final class FilterPositionUtil { @Nullable public static PsiElement searchNonSpaceNonCommentBack(PsiElement element) { - return searchNonSpaceNonCommentBack(element, false); - } - - @Nullable - public static PsiElement searchNonSpaceNonCommentBack(PsiElement element, final boolean strict) { - if (element == null || element.getNode() == null) return null; - ASTNode leftNeighbour = TreeUtil.prevLeaf(element.getNode()); - if (!strict) { - while (leftNeighbour != null && - (leftNeighbour.getElementType() == TokenType.WHITE_SPACE || - PsiTreeUtil.getNonStrictParentOfType(leftNeighbour.getPsi(), PsiComment.class) != null)) { - leftNeighbour = TreeUtil.prevLeaf(leftNeighbour); - } - } - return leftNeighbour != null ? leftNeighbour.getPsi() : null; + return element == null ? null : PsiTreeUtil.prevCodeLeaf(element); } } \ No newline at end of file