A bit more correct fix of KT-14665
This commit is contained in:
+40
-14
@@ -21,15 +21,13 @@ import com.intellij.codeInsight.completion.InsertionContext
|
||||
import com.intellij.codeInsight.lookup.LookupElement
|
||||
import com.intellij.codeInsight.lookup.LookupElementBuilder
|
||||
import com.intellij.openapi.module.ModuleUtilCore
|
||||
import com.intellij.psi.PsiComment
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.PsiErrorElement
|
||||
import com.intellij.psi.PsiWhiteSpace
|
||||
import com.intellij.psi.*
|
||||
import com.intellij.psi.filters.*
|
||||
import com.intellij.psi.filters.position.LeftNeighbour
|
||||
import com.intellij.psi.filters.position.PositionElementFilter
|
||||
import com.intellij.psi.tree.IElementType
|
||||
import com.intellij.psi.tree.TokenSet
|
||||
import org.jetbrains.kotlin.KtNodeTypes
|
||||
import org.jetbrains.kotlin.config.LanguageFeature
|
||||
import org.jetbrains.kotlin.config.LanguageVersionSettingsImpl
|
||||
import org.jetbrains.kotlin.descriptors.annotations.KotlinTarget
|
||||
@@ -206,18 +204,35 @@ object KeywordCompletion {
|
||||
is KtBlockExpression -> {
|
||||
var prefixText = "fun foo() { "
|
||||
if (prevParent is KtExpression) {
|
||||
// check that we are right after a try-expression without finally-block
|
||||
// check that we are right after a try-expression without finally-block or after if-expression without else
|
||||
val prevLeaf = prevParent.prevLeaf { it !is PsiWhiteSpace && it !is PsiComment && it !is PsiErrorElement }
|
||||
if (prevLeaf?.node?.elementType == KtTokens.RBRACE) {
|
||||
val blockParent = (prevLeaf?.parent as? KtBlockExpression)?.parent
|
||||
when (blockParent) {
|
||||
is KtTryExpression -> prefixText += "try {}\n"
|
||||
is KtCatchClause -> prefixText += "try {} catch (e: E) {}\n"
|
||||
}
|
||||
}
|
||||
if (prevLeaf != null) {
|
||||
val isAfterThen = prevLeaf.goUpWhileIsLastChild().any { it.node.elementType == KtNodeTypes.THEN }
|
||||
|
||||
if (prevLeaf?.getParentOfType<KtIfExpression>(strict = false) != null) {
|
||||
prefixText += "if(true){}\n"
|
||||
var isAfterTry = false
|
||||
var isAfterCatch = false
|
||||
if (prevLeaf.node.elementType == KtTokens.RBRACE) {
|
||||
val blockParent = (prevLeaf.parent as? KtBlockExpression)?.parent
|
||||
when (blockParent) {
|
||||
is KtTryExpression -> isAfterTry = true
|
||||
is KtCatchClause -> { isAfterTry = true; isAfterCatch = true }
|
||||
}
|
||||
}
|
||||
|
||||
if (isAfterThen) {
|
||||
if (isAfterTry) {
|
||||
prefixText += "if (a)\n"
|
||||
}
|
||||
else {
|
||||
prefixText += "if (a) {}\n"
|
||||
}
|
||||
}
|
||||
if (isAfterTry) {
|
||||
prefixText += "try {}\n"
|
||||
}
|
||||
if (isAfterCatch) {
|
||||
prefixText += "catch (e: E) {}\n"
|
||||
}
|
||||
}
|
||||
|
||||
return buildFilterWithContext(prefixText, prevParent, position)
|
||||
@@ -460,4 +475,15 @@ object KeywordCompletion {
|
||||
if (ancestor == this) return 0
|
||||
return parent!!.getStartOffsetInAncestor(ancestor) + startOffsetInParent
|
||||
}
|
||||
|
||||
private fun PsiElement.goUpWhileIsLastChild(): Sequence<PsiElement> {
|
||||
return generateSequence(this) {
|
||||
if (it is PsiFile)
|
||||
null
|
||||
else if (it != it.parent.lastChild)
|
||||
null
|
||||
else
|
||||
it.parent
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,9 +11,7 @@ fun some() {
|
||||
|
||||
|
||||
// EXIST: do
|
||||
// EXIST: as
|
||||
// EXIST: class
|
||||
// EXIST: else
|
||||
// EXIST: false
|
||||
// EXIST: for
|
||||
// EXIST: fun
|
||||
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
fun foo(p: Int) {
|
||||
if (p > 0) {
|
||||
|
||||
}
|
||||
<caret>
|
||||
}
|
||||
|
||||
// EXIST: else
|
||||
// EXIST: class
|
||||
// EXIST: do
|
||||
// EXIST: false
|
||||
// EXIST: for
|
||||
// EXIST: fun
|
||||
// EXIST: if
|
||||
// EXIST: null
|
||||
// EXIST: object
|
||||
// EXIST: return
|
||||
// EXIST: super
|
||||
// EXIST: throw
|
||||
// EXIST: interface
|
||||
// EXIST: true
|
||||
// EXIST: try
|
||||
// EXIST: val
|
||||
// EXIST: var
|
||||
// EXIST: when
|
||||
// EXIST: while
|
||||
// EXIST: typealias
|
||||
// EXIST: as
|
||||
// NOTHING_ELSE
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
fun foo(p: Int) {
|
||||
if (p > 0)
|
||||
foo()
|
||||
<caret>
|
||||
}
|
||||
|
||||
// EXIST: else
|
||||
// EXIST: class
|
||||
// EXIST: do
|
||||
// EXIST: false
|
||||
// EXIST: for
|
||||
// EXIST: fun
|
||||
// EXIST: if
|
||||
// EXIST: null
|
||||
// EXIST: object
|
||||
// EXIST: return
|
||||
// EXIST: super
|
||||
// EXIST: throw
|
||||
// EXIST: interface
|
||||
// EXIST: true
|
||||
// EXIST: try
|
||||
// EXIST: val
|
||||
// EXIST: var
|
||||
// EXIST: when
|
||||
// EXIST: while
|
||||
// EXIST: typealias
|
||||
// EXIST: as
|
||||
// NOTHING_ELSE
|
||||
@@ -1,8 +0,0 @@
|
||||
fun foo(p: Int) {
|
||||
var x = 0
|
||||
if (p > 0)
|
||||
x += p
|
||||
el<caret>
|
||||
}
|
||||
|
||||
//EXIST: else
|
||||
@@ -1,8 +0,0 @@
|
||||
fun foo(p: Int) {
|
||||
if (p > 0) {
|
||||
|
||||
}
|
||||
el<caret>
|
||||
}
|
||||
|
||||
//EXIST: else
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
fun foo(p: Int) {
|
||||
if (p > 0)
|
||||
try {
|
||||
}
|
||||
<caret>
|
||||
}
|
||||
|
||||
// EXIST: catch
|
||||
// EXIST: finally
|
||||
// EXIST: false
|
||||
// EXIST: null
|
||||
// EXIST: true
|
||||
// NOTHING_ELSE
|
||||
@@ -0,0 +1,33 @@
|
||||
fun foo(p: Int) {
|
||||
if (p > 0)
|
||||
try {
|
||||
}
|
||||
catch (e: Exception) {
|
||||
}
|
||||
<caret>
|
||||
}
|
||||
|
||||
// EXIST: catch
|
||||
// EXIST: finally
|
||||
// EXIST: else
|
||||
// EXIST: class
|
||||
// EXIST: do
|
||||
// EXIST: false
|
||||
// EXIST: for
|
||||
// EXIST: fun
|
||||
// EXIST: if
|
||||
// EXIST: null
|
||||
// EXIST: object
|
||||
// EXIST: return
|
||||
// EXIST: super
|
||||
// EXIST: throw
|
||||
// EXIST: interface
|
||||
// EXIST: true
|
||||
// EXIST: try
|
||||
// EXIST: val
|
||||
// EXIST: var
|
||||
// EXIST: when
|
||||
// EXIST: while
|
||||
// EXIST: typealias
|
||||
// EXIST: as
|
||||
// NOTHING_ELSE
|
||||
@@ -10,9 +10,7 @@ fun some() {
|
||||
|
||||
|
||||
// EXIST: do
|
||||
// EXIST: as
|
||||
// EXIST: class
|
||||
// EXIST: else
|
||||
// EXIST: false
|
||||
// EXIST: for
|
||||
// EXIST: fun
|
||||
|
||||
@@ -10,9 +10,7 @@ fun some() {
|
||||
|
||||
|
||||
// EXIST: do
|
||||
// EXIST: as
|
||||
// EXIST: class
|
||||
// EXIST: else
|
||||
// EXIST: false
|
||||
// EXIST: for
|
||||
// EXIST: fun
|
||||
|
||||
+18
-6
@@ -150,15 +150,15 @@ public class KeywordCompletionTestGenerated extends AbstractKeywordCompletionTes
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("ElseAfterBlocklessIf.kt")
|
||||
public void testElseAfterBlocklessIf() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/idea-completion/testData/keywords/ElseAfterBlocklessIf.kt");
|
||||
@TestMetadata("Else1.kt")
|
||||
public void testElse1() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/idea-completion/testData/keywords/Else1.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("ElseOnOtherLine.kt")
|
||||
public void testElseOnOtherLine() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/idea-completion/testData/keywords/ElseOnOtherLine.kt");
|
||||
@TestMetadata("Else2.kt")
|
||||
public void testElse2() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/idea-completion/testData/keywords/Else2.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@@ -174,6 +174,18 @@ public class KeywordCompletionTestGenerated extends AbstractKeywordCompletionTes
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("IfTry.kt")
|
||||
public void testIfTry() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/idea-completion/testData/keywords/IfTry.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("IfTryCatch.kt")
|
||||
public void testIfTryCatch() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/idea-completion/testData/keywords/IfTryCatch.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("InAnnotationClassScope.kt")
|
||||
public void testInAnnotationClassScope() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/idea-completion/testData/keywords/InAnnotationClassScope.kt");
|
||||
|
||||
Reference in New Issue
Block a user