IDEA-247122 Variable initialization completion adds semicolon which breaks the code

GitOrigin-RevId: 61fb7454dbf3a62be2f9250e2f5e46f329b35e53
This commit is contained in:
Peter Gromov
2020-08-03 11:05:07 +00:00
committed by intellij-monorepo-bot
parent e8f3e8616b
commit e859d53975
6 changed files with 41 additions and 20 deletions
@@ -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)));
}
@@ -0,0 +1,5 @@
class C {
int x = nextInt(), <caret>y = 0;
int nextInt() {}
}
@@ -0,0 +1,5 @@
class C {
int x = nex<caret>, y = 0;
int nextInt() {}
}
@@ -1476,4 +1476,7 @@ public class SmartTypeCompletionTest extends LightFixtureCompletionTestCase {
myFixture.complete(CompletionType.SMART);
checkResultByFile("second/MethodAsQualifier-out.java");
}
public void testNoSemicolonAfterNonLastVariableInitializer() { doTest(); }
}
@@ -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);
@@ -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);
}
}