Adapted keyword completion to changed parser + more precise completion for modifier keywords

This commit is contained in:
Valentin Kipyatkov
2015-10-10 18:47:48 +03:00
parent f90ff31507
commit 434be3be21
18 changed files with 48 additions and 143 deletions
@@ -19,15 +19,20 @@ package org.jetbrains.kotlin.resolve
import com.intellij.lang.ASTNode
import com.intellij.psi.PsiElement
import com.intellij.psi.tree.TokenSet
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.descriptors.annotations.KotlinTarget
import org.jetbrains.kotlin.descriptors.annotations.KotlinTarget.*
import org.jetbrains.kotlin.diagnostics.Errors
import org.jetbrains.kotlin.lexer.JetModifierKeywordToken
import java.util.*
import org.jetbrains.kotlin.lexer.JetTokens.*
import org.jetbrains.kotlin.descriptors.annotations.KotlinTarget.*
import org.jetbrains.kotlin.lexer.JetTokens
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.lexer.JetTokens.*
import org.jetbrains.kotlin.psi.JetClassOrObject
import org.jetbrains.kotlin.psi.JetDeclarationWithBody
import org.jetbrains.kotlin.psi.JetModifierList
import org.jetbrains.kotlin.psi.JetModifierListOwner
import java.util.*
public object ModifierCheckerCore {
private enum class Compatibility {
@@ -51,7 +56,7 @@ public object ModifierCheckerCore {
MEMBER_FUNCTION, TOP_LEVEL_FUNCTION, PROPERTY_GETTER, PROPERTY_SETTER,
MEMBER_PROPERTY, TOP_LEVEL_PROPERTY, CONSTRUCTOR)
private val possibleTargetMap = mapOf<JetModifierKeywordToken, Set<KotlinTarget>>(
val possibleTargetMap = mapOf<JetModifierKeywordToken, Set<KotlinTarget>>(
ENUM_KEYWORD to EnumSet.of(ENUM_CLASS),
ABSTRACT_KEYWORD to EnumSet.of(CLASS_ONLY, LOCAL_CLASS, INNER_CLASS, INTERFACE, MEMBER_PROPERTY, MEMBER_FUNCTION),
OPEN_KEYWORD to EnumSet.of(CLASS_ONLY, LOCAL_CLASS, INNER_CLASS, INTERFACE, MEMBER_PROPERTY, MEMBER_FUNCTION),
@@ -28,15 +28,18 @@ 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.descriptors.annotations.KotlinTarget.*
import org.jetbrains.kotlin.idea.completion.handlers.KotlinFunctionInsertHandler
import org.jetbrains.kotlin.idea.completion.handlers.KotlinKeywordInsertHandler
import org.jetbrains.kotlin.lexer.JetKeywordToken
import org.jetbrains.kotlin.lexer.JetModifierKeywordToken
import org.jetbrains.kotlin.lexer.JetTokens.*
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType
import org.jetbrains.kotlin.psi.psiUtil.nextLeaf
import org.jetbrains.kotlin.psi.psiUtil.prevLeaf
import org.jetbrains.kotlin.psi.psiUtil.siblings
import org.jetbrains.kotlin.resolve.ModifierCheckerCore
open class KeywordLookupObject
@@ -47,10 +50,8 @@ object KeywordCompletion {
.filter { it !in NON_ACTUAL_KEYWORDS }
.map { it as JetKeywordToken }
private val KEYWORD_TO_DUMMY_POSTFIX = mapOf(
OUT_KEYWORD to " X",
FILE_KEYWORD to ":"
)
private val DEFAULT_DUMMY_POSTFIX = " X"
private val KEYWORD_TO_DUMMY_POSTFIX = mapOf(FILE_KEYWORD to ":")
private val KEYWORDS_TO_IGNORE_PREFIX = TokenSet.create(OVERRIDE_KEYWORD /* it's needed to complete overrides that should be work by member name too */)
@@ -176,19 +177,32 @@ object KeywordCompletion {
private fun buildFilterByText(prefixText: String, project: Project): (JetKeywordToken) -> Boolean {
val psiFactory = JetPsiFactory(project)
return { keywordTokenType ->
val postfix = KEYWORD_TO_DUMMY_POSTFIX[keywordTokenType] ?: ""
return fun (keywordTokenType): Boolean {
val postfix = KEYWORD_TO_DUMMY_POSTFIX[keywordTokenType] ?: DEFAULT_DUMMY_POSTFIX
val file = psiFactory.createFile(prefixText + keywordTokenType.getValue() + postfix)
val elementAt = file.findElementAt(prefixText.length())!!
when {
!elementAt.getNode()!!.getElementType().matchesKeyword(keywordTokenType) -> false
!elementAt.getNode()!!.getElementType().matchesKeyword(keywordTokenType) -> return false
elementAt.getNonStrictParentOfType<PsiErrorElement>() != null -> false
elementAt.getNonStrictParentOfType<PsiErrorElement>() != null -> return false
elementAt.prevLeaf { it !is PsiWhiteSpace && it !is PsiComment } is PsiErrorElement -> false
elementAt.prevLeaf { it !is PsiWhiteSpace && it !is PsiComment } is PsiErrorElement -> return false
else -> true
keywordTokenType !is JetModifierKeywordToken -> return true
else -> {
if (elementAt.parent !is JetModifierList) return true
val possibleTargets = when (elementAt.parent.parent) {
is JetParameter -> listOf(VALUE_PARAMETER)
is JetTypeParameter -> listOf(TYPE_PARAMETER)
is JetClassBody -> listOf(CLASS_ONLY, INTERFACE, OBJECT, ENUM_CLASS, ANNOTATION_CLASS, INNER_CLASS, MEMBER_FUNCTION, MEMBER_PROPERTY, FUNCTION, PROPERTY)
is JetFile -> listOf(CLASS_ONLY, INTERFACE, OBJECT, ENUM_CLASS, ANNOTATION_CLASS, TOP_LEVEL_FUNCTION, TOP_LEVEL_PROPERTY, FUNCTION, PROPERTY)
else -> return true
}
val modifierTargets = ModifierCheckerCore.possibleTargetMap[keywordTokenType] ?: return true
return possibleTargets.any { it in modifierTargets }
}
}
}
}
@@ -11,16 +11,10 @@ class MouseMovedEventArgs
// EXIST: final
// EXIST: fun
// EXIST: get
// EXIST: in
/*why?*/
// EXIST: inner
// EXIST: internal
// EXIST: object
// EXIST: open
// EXIST: out
/*why?*/
// EXIST: reified
/*why?*/
// EXIST: override
// EXIST: private
// EXIST: protected
@@ -29,7 +23,6 @@ class MouseMovedEventArgs
// EXIST: interface
// EXIST: val
// EXIST: var
// EXIST: vararg
// EXIST: constructor
// EXIST: init
/*why?*/
@@ -40,10 +33,8 @@ class MouseMovedEventArgs
// EXIST: lateinit
// EXIST: data
// EXIST: inline
// EXIST: noinline
// EXIST: tailrec
// EXIST: external
// EXIST: annotation
// EXIST: crossinline
// EXIST: const
// NOTHING_ELSE
+4 -15
View File
@@ -17,37 +17,26 @@ class B {
// EXIST: enum
// EXIST: final
// EXIST: fun
// EXIST: in
/*why?*/
// EXIST: inner
// EXIST: internal
// EXIST: object
// EXIST: open
// EXIST: out
/*why?*/
// EXIST: reified
/*why?*/
// EXIST: override
// EXIST: private
// EXIST: protected
// EXIST: public
// EXIST: interface
// EXIST: val
// EXIST: var
// EXIST: vararg
/*why?*/
// EXIST: companion object
// EXIST: operator
// EXIST: infix
// EXIST: sealed
// EXIST: lateinit
// EXIST: data
// EXIST: inline
// EXIST: noinline
// EXIST: tailrec
// EXIST: external
// EXIST: annotation
// EXIST: crossinline
// EXIST: const
/*TODO*/
/*TODO:*/
// EXIST: inner
/*TODO:*/
// EXIST: companion object
// NOTHING_ELSE
-9
View File
@@ -15,16 +15,10 @@ class A {
// EXIST: enum
// EXIST: final
// EXIST: fun
// EXIST: in
/*why?*/
// EXIST: inner
// EXIST: internal
// EXIST: object
// EXIST: open
// EXIST: out
/*why?*/
// EXIST: reified
/*why?*/
// EXIST: override
// EXIST: private
// EXIST: protected
@@ -32,7 +26,6 @@ class A {
// EXIST: interface
// EXIST: val
// EXIST: var
// EXIST: vararg
// EXIST: constructor
// EXIST: init
/*why?*/
@@ -43,10 +36,8 @@ class A {
// EXIST: lateinit
// EXIST: data
// EXIST: inline
// EXIST: noinline
// EXIST: tailrec
// EXIST: external
// EXIST: annotation
// EXIST: crossinline
// EXIST: const
// NOTHING_ELSE
-1
View File
@@ -2,7 +2,6 @@
// EXIST: {"lookupString":"class","itemText":"class","attributes":"bold"}
// EXIST: {"lookupString":"fun","itemText":"fun","attributes":"bold"}
// EXIST: {"lookupString":"in","itemText":"in","attributes":"bold"}
// EXIST: {"lookupString":"interface","itemText":"interface","attributes":"bold"}
// EXIST: {"lookupString":"object","itemText":"object","attributes":"bold"}
// EXIST: {"lookupString":"package","itemText":"package","attributes":"bold"}
@@ -16,17 +16,10 @@ var a : Int
// EXIST: final
// EXIST: fun
// EXIST: get
// EXIST: in
/*why?*/
// EXIST: inner
// EXIST: internal
// EXIST: object
// EXIST: open
// EXIST: out
/*why?*/
// EXIST: reified
/*why?*/
// EXIST: override
// EXIST: private
// EXIST: protected
// EXIST: public
@@ -34,20 +27,14 @@ var a : Int
// EXIST: interface
// EXIST: val
// EXIST: var
// EXIST: vararg
/*why?*/
// EXIST: companion object
// EXIST: operator
// EXIST: infix
// EXIST: sealed
// EXIST: lateinit
// EXIST: data
// EXIST: inline
// EXIST: noinline
// EXIST: tailrec
// EXIST: external
// EXIST: annotation
// EXIST: crossinline
// EXIST: const
/*TODO*/
// NOTHING_ELSE
@@ -13,16 +13,10 @@ public class Test {
// EXIST: enum
// EXIST: final
// EXIST: fun
// EXIST: in
/*why?*/
// EXIST: inner
// EXIST: internal
// EXIST: object
// EXIST: open
// EXIST: out
/*why?*/
// EXIST: reified
/*why?*/
// EXIST: override
// EXIST: private
// EXIST: protected
@@ -30,7 +24,6 @@ public class Test {
// EXIST: interface
// EXIST: val
// EXIST: var
// EXIST: vararg
// EXIST: constructor
// EXIST: init
/*why?*/
@@ -41,10 +34,8 @@ public class Test {
// EXIST: lateinit
// EXIST: data
// EXIST: inline
// EXIST: noinline
// EXIST: tailrec
// EXIST: external
// EXIST: annotation
// EXIST: crossinline
// EXIST: const
// NOTHING_ELSE
-10
View File
@@ -7,16 +7,10 @@ class TestClass {
// EXIST: enum
// EXIST: final
// EXIST: fun
// EXIST: in
/*why?*/
// EXIST: inner
// EXIST: internal
// EXIST: object
// EXIST: open
// EXIST: out
/*why?*/
// EXIST: reified
/*why?*/
// EXIST: override
// EXIST: private
// EXIST: protected
@@ -24,8 +18,6 @@ class TestClass {
// EXIST: interface
// EXIST: val
// EXIST: var
// EXIST: vararg
/*why?*/
// EXIST: constructor
// EXIST: init
// EXIST: companion object
@@ -35,10 +27,8 @@ class TestClass {
// EXIST: lateinit
// EXIST: data
// EXIST: inline
// EXIST: noinline
// EXIST: tailrec
// EXIST: external
// EXIST: annotation
// EXIST: crossinline
// EXIST: const
// NOTHING_ELSE
@@ -2,4 +2,5 @@ class T<<caret>>
// EXIST: in
// EXIST: out
// EXIST: reified
// NOTHING_ELSE
@@ -5,9 +5,10 @@ class TestSample() {
}
}
/* TODO: they all are not correct */
// EXIST: vararg
// EXIST: noinline
// EXIST: crossinline
/* TODO: val&var are not correct */
// EXIST: val
// EXIST: var
// EXIST: in
// EXIST: out
// NOTHING_ELSE
@@ -4,4 +4,5 @@ fun testing() {}
// EXIST: in
// EXIST: out
// EXIST: reified
// NOTHING_ELSE
@@ -2,9 +2,10 @@ fun test(<caret>) {
}
// EXIST: vararg
// EXIST: noinline
// EXIST: crossinline
/* TODO: they all are not correct */
// EXIST: val
// EXIST: var
// EXIST: in
// EXIST: out
// NOTHING_ELSE
@@ -8,37 +8,24 @@ package Test
// EXIST: final
// EXIST: fun
// EXIST: import
// EXIST: in
/*why?*/
// EXIST: inner
// EXIST: internal
// EXIST: object
// EXIST: open
// EXIST: out
/*why?*/
// EXIST: reified
/*why?*/
// EXIST: override
// EXIST: private
// EXIST: protected
// EXIST: public
// EXIST: interface
// EXIST: val
// EXIST: var
// EXIST: vararg
/*why?*/
// EXIST: companion object
// EXIST: operator
// EXIST: infix
// EXIST: sealed
// EXIST: lateinit
// EXIST: data
// EXIST: inline
// EXIST: noinline
// EXIST: tailrec
// EXIST: external
// EXIST: annotation
// EXIST: crossinline
// EXIST: const
/*TODO*/
// NOTHING_ELSE
@@ -10,16 +10,10 @@ class Some {
// EXIST: final
// EXIST: fun
// EXIST: get
// EXIST: in
/*why?*/
// EXIST: inner
// EXIST: internal
// EXIST: object
// EXIST: open
// EXIST: out
/*why?*/
// EXIST: reified
/*why?*/
// EXIST: override
// EXIST: private
// EXIST: protected
@@ -28,8 +22,6 @@ class Some {
// EXIST: interface
// EXIST: val
// EXIST: var
// EXIST: vararg
/*why?*/
// EXIST: constructor
// EXIST: init
// EXIST: companion object
@@ -39,10 +31,8 @@ class Some {
// EXIST: lateinit
// EXIST: data
// EXIST: inline
// EXIST: noinline
// EXIST: tailrec
// EXIST: external
// EXIST: annotation
// EXIST: crossinline
// EXIST: const
// NOTHING_ELSE
@@ -10,16 +10,10 @@ class Some {
// EXIST: final
// EXIST: fun
// EXIST: get
// EXIST: in
/*why?*/
// EXIST: inner
// EXIST: internal
// EXIST: object
// EXIST: open
// EXIST: out
/*why?*/
// EXIST: reified
/*why?*/
// EXIST: override
// EXIST: private
// EXIST: protected
@@ -28,8 +22,6 @@ class Some {
// EXIST: interface
// EXIST: val
// EXIST: var
// EXIST: vararg
/*why?*/
// EXIST: constructor
// EXIST: init
// EXIST: companion object
@@ -39,10 +31,8 @@ class Some {
// EXIST: lateinit
// EXIST: data
// EXIST: inline
// EXIST: noinline
// EXIST: tailrec
// EXIST: external
// EXIST: annotation
// EXIST: crossinline
// EXIST: const
// NOTHING_ELSE
@@ -12,16 +12,10 @@ class Some {
// EXIST: fun
// EXIST: get
/*TODO*/
// EXIST: in
/*why?*/
// EXIST: inner
// EXIST: internal
// EXIST: object
// EXIST: open
// EXIST: out
/*why?*/
// EXIST: reified
/*why?*/
// EXIST: override
// EXIST: private
// EXIST: protected
@@ -30,8 +24,6 @@ class Some {
// EXIST: interface
// EXIST: val
// EXIST: var
// EXIST: vararg
/*why?*/
// EXIST: constructor
// EXIST: init
// EXIST: companion object
@@ -41,10 +33,8 @@ class Some {
// EXIST: lateinit
// EXIST: data
// EXIST: inline
// EXIST: noinline
// EXIST: tailrec
// EXIST: external
// EXIST: annotation
// EXIST: crossinline
// EXIST: const
// NOTHING_ELSE
-13
View File
@@ -6,17 +6,10 @@
// EXIST: final
// EXIST: fun
// EXIST: import
// EXIST: in
/*why?*/
// EXIST: inner
// EXIST: internal
// EXIST: object
// EXIST: open
// EXIST: out
/*why?*/
// EXIST: reified
/*why?*/
// EXIST: override
// EXIST: package
// EXIST: private
// EXIST: protected
@@ -24,20 +17,14 @@
// EXIST: interface
// EXIST: val
// EXIST: var
// EXIST: vararg
/*why?*/
// EXIST: companion object
// EXIST: operator
// EXIST: infix
// EXIST: sealed
// EXIST: lateinit
// EXIST: data
// EXIST: inline
// EXIST: noinline
// EXIST: tailrec
// EXIST: external
// EXIST: annotation
// EXIST: crossinline
// EXIST: const
/*TODO*/
// NOTHING_ELSE