A bit more correct fix of KT-14665

This commit is contained in:
Valentin Kipyatkov
2017-07-26 17:04:04 +03:00
parent 3ff5c95419
commit 44dafc38e5
11 changed files with 161 additions and 42 deletions
@@ -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
}
}
}
-2
View File
@@ -11,9 +11,7 @@ fun some() {
// EXIST: do
// EXIST: as
// EXIST: class
// EXIST: else
// EXIST: false
// EXIST: for
// EXIST: fun
+29
View File
@@ -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
View File
@@ -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
View File
@@ -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
+33
View File
@@ -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
-2
View File
@@ -10,9 +10,7 @@ fun some() {
// EXIST: do
// EXIST: as
// EXIST: class
// EXIST: else
// EXIST: false
// EXIST: for
// EXIST: fun
-2
View File
@@ -10,9 +10,7 @@ fun some() {
// EXIST: do
// EXIST: as
// EXIST: class
// EXIST: else
// EXIST: false
// EXIST: for
// EXIST: fun
@@ -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");