Even more precise keyword completion for modifiers

This commit is contained in:
Valentin Kipyatkov
2015-10-13 18:15:13 +03:00
parent 15d507bf47
commit f67bd8c13f
13 changed files with 200 additions and 22 deletions
@@ -95,7 +95,7 @@ public object ModifierCheckerCore {
FINAL_KEYWORD to EnumSet.of(ENUM_CLASS, OBJECT)
)
private val possibleParentTargetMap = mapOf<JetModifierKeywordToken, Set<KotlinTarget>>(
val possibleParentTargetMap = mapOf<JetModifierKeywordToken, Set<KotlinTarget>>(
INNER_KEYWORD to EnumSet.of(CLASS_ONLY, INNER_CLASS, LOCAL_CLASS, ENUM_CLASS, ENUM_ENTRY),
OVERRIDE_KEYWORD to EnumSet.of(CLASS_ONLY, INNER_CLASS, LOCAL_CLASS, OBJECT, OBJECT_LITERAL,
INTERFACE, ENUM_CLASS, ENUM_ENTRY),
@@ -107,7 +107,7 @@ public object ModifierCheckerCore {
COMPANION_KEYWORD to EnumSet.of(CLASS_ONLY, ENUM_CLASS, INTERFACE)
)
private val deprecatedParentTargetMap = mapOf<JetModifierKeywordToken, Set<KotlinTarget>>(
val deprecatedParentTargetMap = mapOf<JetModifierKeywordToken, Set<KotlinTarget>>(
// Deprecated in M15
FINAL_KEYWORD to EnumSet.of(INTERFACE),
PROTECTED_KEYWORD to EnumSet.of(OBJECT)
@@ -28,6 +28,7 @@ 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.descriptors.annotations.KotlinTarget.*
import org.jetbrains.kotlin.idea.completion.handlers.KotlinFunctionInsertHandler
import org.jetbrains.kotlin.idea.completion.handlers.KotlinKeywordInsertHandler
@@ -197,10 +198,10 @@ object KeywordCompletion {
else -> {
if (elementAt.parent !is JetModifierList) return true
val declaration = elementAt.parent.parent
val possibleTargets = when (declaration) {
val container = elementAt.parent.parent
val possibleTargets = when (container) {
is JetParameter -> {
if (declaration.ownerFunction is JetPrimaryConstructor)
if (container.ownerFunction is JetPrimaryConstructor)
listOf(VALUE_PARAMETER, MEMBER_PROPERTY)
else
listOf(VALUE_PARAMETER)
@@ -208,14 +209,43 @@ object KeywordCompletion {
is JetTypeParameter -> listOf(TYPE_PARAMETER)
is JetEnumEntry -> listOf(ENUM_ENTRY)
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 -> null
}
val modifierTargets = ModifierCheckerCore.possibleTargetMap[keywordTokenType]
if (modifierTargets != null && possibleTargets != null && possibleTargets.none { it in modifierTargets }) return false
val ownerDeclaration = container?.getParentOfType<JetDeclaration>(strict = true)
val parentTarget = when (ownerDeclaration) {
null -> KotlinTarget.FILE
is JetClass -> {
when {
ownerDeclaration.isInterface() -> KotlinTarget.INTERFACE
ownerDeclaration.isEnum() -> KotlinTarget.ENUM_CLASS
ownerDeclaration.isAnnotation() -> KotlinTarget.ANNOTATION_CLASS
ownerDeclaration.isInner() -> KotlinTarget.INNER_CLASS
else -> KotlinTarget.CLASS_ONLY
}
}
is JetObjectDeclaration -> if (ownerDeclaration.isObjectLiteral()) KotlinTarget.OBJECT_LITERAL else KotlinTarget.OBJECT
else -> return true
}
val modifierTargets = ModifierCheckerCore.possibleTargetMap[keywordTokenType] ?: return true
return possibleTargets.any { it in modifierTargets }
val modifierParents = ModifierCheckerCore.possibleParentTargetMap[keywordTokenType]
if (modifierParents != null && parentTarget !in modifierParents) return false
val deprecatedParents = ModifierCheckerCore.deprecatedParentTargetMap[keywordTokenType]
if (deprecatedParents != null && parentTarget in deprecatedParents) return false
return true
}
}
}
@@ -21,7 +21,6 @@ class B {
// EXIST: object
// EXIST: open
// EXIST: private
// EXIST: protected
// EXIST: public
// EXIST: interface
// EXIST: val
@@ -35,8 +34,4 @@ class B {
// EXIST: external
// EXIST: annotation
// EXIST: const
/*TODO:*/
// EXIST: inner
/*TODO:*/
// EXIST: companion object
// NOTHING_ELSE
@@ -16,18 +16,15 @@ var a : Int
// EXIST: final
// EXIST: fun
// EXIST: get
// EXIST: inner
// EXIST: internal
// EXIST: object
// EXIST: open
// EXIST: private
// EXIST: protected
// EXIST: public
// EXIST: set
// EXIST: interface
// EXIST: val
// EXIST: var
// EXIST: companion object
// EXIST: operator
// EXIST: infix
// EXIST: sealed
@@ -0,0 +1,28 @@
annotation class Test {
<caret>
}
// EXIST: abstract
// EXIST: class
// EXIST: enum
// EXIST: final
// EXIST: fun
// EXIST: object
// EXIST: open
// EXIST: public
// EXIST: interface
// EXIST: val
// EXIST: var
// EXIST: constructor
// EXIST: init
// EXIST: operator
// EXIST: infix
// EXIST: sealed
// EXIST: lateinit
// EXIST: data
// EXIST: inline
// EXIST: tailrec
// EXIST: external
// EXIST: annotation
// EXIST: const
// NOTHING_ELSE
@@ -0,0 +1,5 @@
enum class Test {
<caret>
}
// NUMBER: 0
+39
View File
@@ -0,0 +1,39 @@
enum class Test {
;
<caret>
}
// EXIST: abstract
// EXIST: enum
// EXIST: final
// EXIST: inner
// EXIST: internal
// EXIST: open
// EXIST: override
// EXIST: private
// EXIST: protected
// EXIST: public
// EXIST: companion object
// EXIST: operator
// EXIST: infix
// EXIST: sealed
// EXIST: lateinit
// EXIST: data
// EXIST: inline
// EXIST: tailrec
// EXIST: external
// EXIST: annotation
// EXIST: const
// EXIST: fun
/* TODO: items below are not valid here */
// EXIST: class
// EXIST: constructor
// EXIST: init
// EXIST: interface
// EXIST: object
// EXIST: val
// EXIST: var
// NOTHING_ELSE
@@ -0,0 +1,30 @@
interface Test {
<caret>
}
// EXIST: abstract
// EXIST: class
// EXIST: enum
// EXIST: fun
// EXIST: object
// EXIST: open
// EXIST: override
// EXIST: private
// EXIST: public
// EXIST: interface
// EXIST: val
// EXIST: var
// EXIST: constructor
// EXIST: init
// EXIST: companion object
// EXIST: operator
// EXIST: infix
// EXIST: sealed
// EXIST: lateinit
// EXIST: data
// EXIST: inline
// EXIST: tailrec
// EXIST: external
// EXIST: annotation
// EXIST: const
// NOTHING_ELSE
+31
View File
@@ -0,0 +1,31 @@
object Test {
<caret>
}
// EXIST: abstract
// EXIST: class
// EXIST: enum
// EXIST: final
// EXIST: fun
// EXIST: internal
// EXIST: object
// EXIST: open
// EXIST: override
// EXIST: private
// EXIST: public
// EXIST: interface
// EXIST: val
// EXIST: var
// EXIST: constructor
// EXIST: init
// EXIST: operator
// EXIST: infix
// EXIST: sealed
// EXIST: lateinit
// EXIST: data
// EXIST: inline
// EXIST: tailrec
// EXIST: external
// EXIST: annotation
// EXIST: const
// NOTHING_ELSE
@@ -8,17 +8,14 @@ package Test
// EXIST: final
// EXIST: fun
// EXIST: import
// EXIST: inner
// EXIST: internal
// EXIST: object
// EXIST: open
// EXIST: private
// EXIST: protected
// EXIST: public
// EXIST: interface
// EXIST: val
// EXIST: var
// EXIST: companion object
// EXIST: operator
// EXIST: infix
// EXIST: sealed
@@ -4,6 +4,5 @@ p<caret>
// EXIST: package
// EXIST: private
// EXIST: protected
// EXIST: public
// NOTHING_ELSE
-3
View File
@@ -6,18 +6,15 @@
// EXIST: final
// EXIST: fun
// EXIST: import
// EXIST: inner
// EXIST: internal
// EXIST: object
// EXIST: open
// EXIST: package
// EXIST: private
// EXIST: protected
// EXIST: public
// EXIST: interface
// EXIST: val
// EXIST: var
// EXIST: companion object
// EXIST: operator
// EXIST: infix
// EXIST: sealed
@@ -119,6 +119,12 @@ public class KeywordCompletionTestGenerated extends AbstractKeywordCompletionTes
doTest(fileName);
}
@TestMetadata("InAnnotationClassScope.kt")
public void testInAnnotationClassScope() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/keywords/InAnnotationClassScope.kt");
doTest(fileName);
}
@TestMetadata("InArgumentList.kt")
public void testInArgumentList() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/keywords/InArgumentList.kt");
@@ -173,6 +179,18 @@ public class KeywordCompletionTestGenerated extends AbstractKeywordCompletionTes
doTest(fileName);
}
@TestMetadata("InEnumScope1.kt")
public void testInEnumScope1() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/keywords/InEnumScope1.kt");
doTest(fileName);
}
@TestMetadata("InEnumScope2.kt")
public void testInEnumScope2() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/keywords/InEnumScope2.kt");
doTest(fileName);
}
@TestMetadata("InFunctionExpressionBody.kt")
public void testInFunctionExpressionBody() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/keywords/InFunctionExpressionBody.kt");
@@ -203,6 +221,12 @@ public class KeywordCompletionTestGenerated extends AbstractKeywordCompletionTes
doTest(fileName);
}
@TestMetadata("InInterfaceScope.kt")
public void testInInterfaceScope() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/keywords/InInterfaceScope.kt");
doTest(fileName);
}
@TestMetadata("InMemberFunParametersList.kt")
public void testInMemberFunParametersList() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/keywords/InMemberFunParametersList.kt");
@@ -221,6 +245,12 @@ public class KeywordCompletionTestGenerated extends AbstractKeywordCompletionTes
doTest(fileName);
}
@TestMetadata("InObjectScope.kt")
public void testInObjectScope() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/keywords/InObjectScope.kt");
doTest(fileName);
}
@TestMetadata("InParameterDefaultValue.kt")
public void testInParameterDefaultValue() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/keywords/InParameterDefaultValue.kt");