Adapted completion in lambda signatures to modern syntax

This commit is contained in:
Valentin Kipyatkov
2015-07-06 21:07:33 +03:00
parent 60ea98f870
commit 75d668bc19
11 changed files with 33 additions and 74 deletions
@@ -22,10 +22,7 @@ import com.intellij.openapi.progress.ProcessCanceledException
import com.intellij.patterns.PlatformPatterns
import com.intellij.patterns.PsiJavaPatterns.elementType
import com.intellij.patterns.PsiJavaPatterns.psiElement
import com.intellij.psi.PsiComment
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiErrorElement
import com.intellij.psi.TokenType
import com.intellij.psi.*
import com.intellij.psi.search.PsiElementProcessor
import com.intellij.psi.tree.TokenSet
import com.intellij.psi.util.PsiTreeUtil
@@ -73,11 +70,10 @@ public class KotlinCompletionContributor : CompletionContributor() {
PackageDirectiveCompletion.ACTIVATION_PATTERN.accepts(tokenBefore) -> PackageDirectiveCompletion.DUMMY_IDENTIFIER
isInFunctionLiteralParameterList(tokenBefore) -> CompletionUtilCore.DUMMY_IDENTIFIER_TRIMMED
isInClassHeader(tokenBefore) -> CompletionUtilCore.DUMMY_IDENTIFIER // do not add '$' to not interrupt class declaration parsing
else -> specialExtensionReceiverDummyIdentifier(tokenBefore)
else -> specialLambdaSignatureDummyIdentifier(tokenBefore)
?: specialExtensionReceiverDummyIdentifier(tokenBefore)
?: specialInTypeArgsDummyIdentifier(tokenBefore)
?: specialInParameterListDummyIdentifier(tokenBefore)
?: specialInArgumentListDummyIdentifier(tokenBefore)
@@ -137,12 +133,6 @@ public class KotlinCompletionContributor : CompletionContributor() {
return expression.getTextRange()!!.getEndOffset()
}
private fun isInFunctionLiteralParameterList(tokenBefore: PsiElement?): Boolean {
val parameterList = tokenBefore?.parents?.firstOrNull { it is JetParameterList } ?: return false
val parent = parameterList.getParent()
return parent is JetFunctionLiteral && parent.getValueParameterList() == parameterList
}
private fun isInClassHeader(tokenBefore: PsiElement?): Boolean {
val classOrObject = tokenBefore?.parents?.firstIsInstanceOrNull<JetClassOrObject>() ?: return false
val name = classOrObject.getNameIdentifier() ?: return false
@@ -151,6 +141,31 @@ public class KotlinCompletionContributor : CompletionContributor() {
return name.endOffset <= offset && offset <= body.startOffset
}
private fun specialLambdaSignatureDummyIdentifier(tokenBefore: PsiElement?): String? {
var leaf = tokenBefore
while (leaf is PsiWhiteSpace || leaf is PsiComment) {
leaf = leaf.prevLeaf(true)
}
val lambda = leaf?.parents?.firstOrNull { it is JetFunctionLiteral } ?: return null
val lambdaChild = leaf!!.parents.takeWhile { it != lambda }.lastOrNull() ?: return null
if (lambdaChild is JetParameterList) return CompletionUtilCore.DUMMY_IDENTIFIER_TRIMMED
if (lambdaChild !is JetBlockExpression) return null
val blockChild = leaf.parents.takeWhile { it != lambdaChild }.lastOrNull()
if (blockChild !is PsiErrorElement) return null
val inIncompleteSignature = blockChild.siblings(forward = false, withItself = false).all {
when (it) {
is PsiWhiteSpace, is PsiComment -> true
is JetBinaryExpressionWithTypeRHS -> it.getOperationReference().getReferencedNameElementType() == JetTokens.COLON
else -> false
}
}
return if (inIncompleteSignature) CompletionUtilCore.DUMMY_IDENTIFIER_TRIMMED + "->" else null
}
private val declarationKeywords = TokenSet.create(JetTokens.FUN_KEYWORD, JetTokens.VAL_KEYWORD, JetTokens.VAR_KEYWORD)
private val declarationTokens = TokenSet.orSet(TokenSet.create(JetTokens.IDENTIFIER, JetTokens.LT, JetTokens.GT,
JetTokens.COMMA, JetTokens.DOT, JetTokens.QUEST, JetTokens.COLON,
@@ -1,7 +0,0 @@
fun bar() {
val handler = { (<caret>) }
}
// INVOCATION_COUNT: 0
// EXIST: bar
// EXIST: null
@@ -1,5 +1,5 @@
fun bar() {
val handler = { (i: Int, <caret>) }
val handler = { i: Int, <caret> }
}
// NUMBER: 0
@@ -1,5 +0,0 @@
fun bar() {
val handler = { (i, <caret>) }
}
// NUMBER: 0
@@ -1,5 +1,5 @@
fun bar() {
val handler = { (i: <caret>) }
val handler = { i: <caret> }
}
// EXIST: Int
@@ -1,8 +0,0 @@
fun bar() {
val handler = { (i: <caret> }
}
// EXIST: Int
// EXIST: String
// ABSENT: bar
// ABSENT: handler
@@ -1,5 +1,5 @@
fun bar() {
val handler = { (i: Int, s: <caret> }
val handler = { i: Int, s: <caret> }
}
// EXIST: Int
@@ -1,5 +1,5 @@
fun bar() {
val handler = { (i: List<<caret>>) }
val handler = { i: List<<caret>> }
}
// EXIST: Int
@@ -1,5 +1,5 @@
fun bar() {
val handler = { (i: Map<String, <caret> }
val handler = { i: Map<String, <caret> }
}
// EXIST: Int
@@ -1281,24 +1281,12 @@ public class JSBasicCompletionTestGenerated extends AbstractJSBasicCompletionTes
doTest(fileName);
}
@TestMetadata("ParameterName1.kt")
public void testParameterName1() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/lambdaSignature/ParameterName1.kt");
doTest(fileName);
}
@TestMetadata("ParameterName2.kt")
public void testParameterName2() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/lambdaSignature/ParameterName2.kt");
doTest(fileName);
}
@TestMetadata("ParameterName3.kt")
public void testParameterName3() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/lambdaSignature/ParameterName3.kt");
doTest(fileName);
}
@TestMetadata("ParameterName4.kt")
public void testParameterName4() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/lambdaSignature/ParameterName4.kt");
@@ -1317,12 +1305,6 @@ public class JSBasicCompletionTestGenerated extends AbstractJSBasicCompletionTes
doTest(fileName);
}
@TestMetadata("ParameterType2.kt")
public void testParameterType2() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/lambdaSignature/ParameterType2.kt");
doTest(fileName);
}
@TestMetadata("ParameterType3.kt")
public void testParameterType3() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/lambdaSignature/ParameterType3.kt");
@@ -1281,24 +1281,12 @@ public class JvmBasicCompletionTestGenerated extends AbstractJvmBasicCompletionT
doTest(fileName);
}
@TestMetadata("ParameterName1.kt")
public void testParameterName1() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/lambdaSignature/ParameterName1.kt");
doTest(fileName);
}
@TestMetadata("ParameterName2.kt")
public void testParameterName2() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/lambdaSignature/ParameterName2.kt");
doTest(fileName);
}
@TestMetadata("ParameterName3.kt")
public void testParameterName3() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/lambdaSignature/ParameterName3.kt");
doTest(fileName);
}
@TestMetadata("ParameterName4.kt")
public void testParameterName4() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/lambdaSignature/ParameterName4.kt");
@@ -1317,12 +1305,6 @@ public class JvmBasicCompletionTestGenerated extends AbstractJvmBasicCompletionT
doTest(fileName);
}
@TestMetadata("ParameterType2.kt")
public void testParameterType2() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/lambdaSignature/ParameterType2.kt");
doTest(fileName);
}
@TestMetadata("ParameterType3.kt")
public void testParameterType3() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/lambdaSignature/ParameterType3.kt");