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) 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), 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, OVERRIDE_KEYWORD to EnumSet.of(CLASS_ONLY, INNER_CLASS, LOCAL_CLASS, OBJECT, OBJECT_LITERAL,
INTERFACE, ENUM_CLASS, ENUM_ENTRY), INTERFACE, ENUM_CLASS, ENUM_ENTRY),
@@ -107,7 +107,7 @@ public object ModifierCheckerCore {
COMPANION_KEYWORD to EnumSet.of(CLASS_ONLY, ENUM_CLASS, INTERFACE) 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 // Deprecated in M15
FINAL_KEYWORD to EnumSet.of(INTERFACE), FINAL_KEYWORD to EnumSet.of(INTERFACE),
PROTECTED_KEYWORD to EnumSet.of(OBJECT) 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.filters.position.PositionElementFilter
import com.intellij.psi.tree.IElementType import com.intellij.psi.tree.IElementType
import com.intellij.psi.tree.TokenSet import com.intellij.psi.tree.TokenSet
import org.jetbrains.kotlin.descriptors.annotations.KotlinTarget
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.KotlinFunctionInsertHandler
import org.jetbrains.kotlin.idea.completion.handlers.KotlinKeywordInsertHandler import org.jetbrains.kotlin.idea.completion.handlers.KotlinKeywordInsertHandler
@@ -197,10 +198,10 @@ object KeywordCompletion {
else -> { else -> {
if (elementAt.parent !is JetModifierList) return true if (elementAt.parent !is JetModifierList) return true
val declaration = elementAt.parent.parent val container = elementAt.parent.parent
val possibleTargets = when (declaration) { val possibleTargets = when (container) {
is JetParameter -> { is JetParameter -> {
if (declaration.ownerFunction is JetPrimaryConstructor) if (container.ownerFunction is JetPrimaryConstructor)
listOf(VALUE_PARAMETER, MEMBER_PROPERTY) listOf(VALUE_PARAMETER, MEMBER_PROPERTY)
else else
listOf(VALUE_PARAMETER) listOf(VALUE_PARAMETER)
@@ -208,14 +209,43 @@ object KeywordCompletion {
is JetTypeParameter -> listOf(TYPE_PARAMETER) 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 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) 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 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: object
// EXIST: open // EXIST: open
// EXIST: private // EXIST: private
// EXIST: protected
// EXIST: public // EXIST: public
// EXIST: interface // EXIST: interface
// EXIST: val // EXIST: val
@@ -35,8 +34,4 @@ class B {
// EXIST: external // EXIST: external
// EXIST: annotation // EXIST: annotation
// EXIST: const // EXIST: const
/*TODO:*/
// EXIST: inner
/*TODO:*/
// EXIST: companion object
// NOTHING_ELSE // NOTHING_ELSE
@@ -16,18 +16,15 @@ var a : Int
// EXIST: final // EXIST: final
// EXIST: fun // EXIST: fun
// EXIST: get // EXIST: get
// EXIST: inner
// EXIST: internal // EXIST: internal
// EXIST: object // EXIST: object
// EXIST: open // EXIST: open
// EXIST: private // EXIST: private
// EXIST: protected
// EXIST: public // EXIST: public
// EXIST: set // EXIST: set
// EXIST: interface // EXIST: interface
// EXIST: val // EXIST: val
// EXIST: var // EXIST: var
// EXIST: companion object
// EXIST: operator // EXIST: operator
// EXIST: infix // EXIST: infix
// EXIST: sealed // 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: final
// EXIST: fun // EXIST: fun
// EXIST: import // EXIST: import
// EXIST: inner
// EXIST: internal // EXIST: internal
// EXIST: object // EXIST: object
// EXIST: open // EXIST: open
// EXIST: private // EXIST: private
// EXIST: protected
// EXIST: public // EXIST: public
// EXIST: interface // EXIST: interface
// EXIST: val // EXIST: val
// EXIST: var // EXIST: var
// EXIST: companion object
// EXIST: operator // EXIST: operator
// EXIST: infix // EXIST: infix
// EXIST: sealed // EXIST: sealed
@@ -4,6 +4,5 @@ p<caret>
// EXIST: package // EXIST: package
// EXIST: private // EXIST: private
// EXIST: protected
// EXIST: public // EXIST: public
// NOTHING_ELSE // NOTHING_ELSE
-3
View File
@@ -6,18 +6,15 @@
// EXIST: final // EXIST: final
// EXIST: fun // EXIST: fun
// EXIST: import // EXIST: import
// EXIST: inner
// EXIST: internal // EXIST: internal
// EXIST: object // EXIST: object
// EXIST: open // EXIST: open
// EXIST: package // EXIST: package
// EXIST: private // EXIST: private
// EXIST: protected
// EXIST: public // EXIST: public
// EXIST: interface // EXIST: interface
// EXIST: val // EXIST: val
// EXIST: var // EXIST: var
// EXIST: companion object
// EXIST: operator // EXIST: operator
// EXIST: infix // EXIST: infix
// EXIST: sealed // EXIST: sealed
@@ -119,6 +119,12 @@ public class KeywordCompletionTestGenerated extends AbstractKeywordCompletionTes
doTest(fileName); 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") @TestMetadata("InArgumentList.kt")
public void testInArgumentList() throws Exception { public void testInArgumentList() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/keywords/InArgumentList.kt"); String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/keywords/InArgumentList.kt");
@@ -173,6 +179,18 @@ public class KeywordCompletionTestGenerated extends AbstractKeywordCompletionTes
doTest(fileName); 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") @TestMetadata("InFunctionExpressionBody.kt")
public void testInFunctionExpressionBody() throws Exception { public void testInFunctionExpressionBody() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/keywords/InFunctionExpressionBody.kt"); String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/keywords/InFunctionExpressionBody.kt");
@@ -203,6 +221,12 @@ public class KeywordCompletionTestGenerated extends AbstractKeywordCompletionTes
doTest(fileName); 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") @TestMetadata("InMemberFunParametersList.kt")
public void testInMemberFunParametersList() throws Exception { public void testInMemberFunParametersList() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/keywords/InMemberFunParametersList.kt"); String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/keywords/InMemberFunParametersList.kt");
@@ -221,6 +245,12 @@ public class KeywordCompletionTestGenerated extends AbstractKeywordCompletionTes
doTest(fileName); 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") @TestMetadata("InParameterDefaultValue.kt")
public void testInParameterDefaultValue() throws Exception { public void testInParameterDefaultValue() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/keywords/InParameterDefaultValue.kt"); String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/keywords/InParameterDefaultValue.kt");