Completion of parameter name+type works for val/var parameters
This commit is contained in:
+18
-18
@@ -263,13 +263,14 @@ class BasicCompletionSession(configuration: CompletionSessionConfiguration,
|
|||||||
resultSet: CompletionResultSet)
|
resultSet: CompletionResultSet)
|
||||||
: CompletionSessionBase(configuration, parameters, resultSet) {
|
: CompletionSessionBase(configuration, parameters, resultSet) {
|
||||||
|
|
||||||
public enum class CompletionKind {
|
public enum class CompletionKind(val classKindFilter: ((ClassKind) -> Boolean)?) {
|
||||||
KEYWORDS_ONLY,
|
KEYWORDS_ONLY(classKindFilter = null),
|
||||||
NAMED_ARGUMENTS_ONLY,
|
NAMED_ARGUMENTS_ONLY(classKindFilter = null),
|
||||||
ALL,
|
ALL(classKindFilter = { it != ClassKind.ENUM_ENTRY }),
|
||||||
TYPES,
|
TYPES(classKindFilter = { it != ClassKind.ENUM_ENTRY }),
|
||||||
ANNOTATION_TYPES,
|
ANNOTATION_TYPES(classKindFilter = { it == ClassKind.ANNOTATION_CLASS }),
|
||||||
ANNOTATION_TYPES_OR_PARAMETER_NAME
|
ANNOTATION_TYPES_OR_PARAMETER_NAME(classKindFilter = { it == ClassKind.ANNOTATION_CLASS }),
|
||||||
|
PARAMETER_NAME(classKindFilter = null)
|
||||||
}
|
}
|
||||||
|
|
||||||
public val completionKind: CompletionKind = calcCompletionKind()
|
public val completionKind: CompletionKind = calcCompletionKind()
|
||||||
@@ -284,12 +285,12 @@ class BasicCompletionSession(configuration: CompletionSessionConfiguration,
|
|||||||
CompletionKind.ALL ->
|
CompletionKind.ALL ->
|
||||||
DescriptorKindFilter(DescriptorKindFilter.ALL_KINDS_MASK)
|
DescriptorKindFilter(DescriptorKindFilter.ALL_KINDS_MASK)
|
||||||
|
|
||||||
CompletionKind.NAMED_ARGUMENTS_ONLY, CompletionKind.KEYWORDS_ONLY ->
|
CompletionKind.NAMED_ARGUMENTS_ONLY, CompletionKind.KEYWORDS_ONLY, CompletionKind.PARAMETER_NAME ->
|
||||||
null
|
null
|
||||||
}
|
}
|
||||||
|
|
||||||
private val parameterNameAndTypeCompletion = if (completionKind == CompletionKind.ANNOTATION_TYPES_OR_PARAMETER_NAME)
|
private val parameterNameAndTypeCompletion = if (completionKind == CompletionKind.PARAMETER_NAME || completionKind == CompletionKind.ANNOTATION_TYPES_OR_PARAMETER_NAME)
|
||||||
ParameterNameAndTypeCompletion(collector, lookupElementFactory, prefixMatcher)
|
ParameterNameAndTypeCompletion(collector, lookupElementFactory, prefixMatcher, resolutionFacade)
|
||||||
else
|
else
|
||||||
null
|
null
|
||||||
|
|
||||||
@@ -299,7 +300,11 @@ class BasicCompletionSession(configuration: CompletionSessionConfiguration,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (reference == null) {
|
if (reference == null) {
|
||||||
return CompletionKind.KEYWORDS_ONLY
|
val parameter = position.getParent() as? JetParameter
|
||||||
|
return if (parameter != null && position == parameter.getNameIdentifier())
|
||||||
|
CompletionKind.PARAMETER_NAME
|
||||||
|
else
|
||||||
|
CompletionKind.KEYWORDS_ONLY
|
||||||
}
|
}
|
||||||
|
|
||||||
val annotationEntry = position.getStrictParentOfType<JetAnnotationEntry>()
|
val annotationEntry = position.getStrictParentOfType<JetAnnotationEntry>()
|
||||||
@@ -333,7 +338,7 @@ class BasicCompletionSession(configuration: CompletionSessionConfiguration,
|
|||||||
if (completionKind != CompletionKind.NAMED_ARGUMENTS_ONLY) {
|
if (completionKind != CompletionKind.NAMED_ARGUMENTS_ONLY) {
|
||||||
collector.addDescriptorElements(referenceVariants, suppressAutoInsertion = false)
|
collector.addDescriptorElements(referenceVariants, suppressAutoInsertion = false)
|
||||||
|
|
||||||
parameterNameAndTypeCompletion?.addFromImports(reference!!.expression, bindingContext, { isVisibleDescriptor(it) })
|
parameterNameAndTypeCompletion?.addFromImports(position, bindingContext, { isVisibleDescriptor(it) })
|
||||||
|
|
||||||
val keywordsPrefix = prefix.substringBefore('@') // if there is '@' in the prefix - use shorter prefix to not loose 'this' etc
|
val keywordsPrefix = prefix.substringBefore('@') // if there is '@' in the prefix - use shorter prefix to not loose 'this' etc
|
||||||
KeywordCompletion.complete(expression ?: parameters.getPosition(), keywordsPrefix) { lookupElement ->
|
KeywordCompletion.complete(expression ?: parameters.getPosition(), keywordsPrefix) { lookupElement ->
|
||||||
@@ -402,12 +407,7 @@ class BasicCompletionSession(configuration: CompletionSessionConfiguration,
|
|||||||
flushToResultSet()
|
flushToResultSet()
|
||||||
|
|
||||||
if (shouldRunTopLevelCompletion()) {
|
if (shouldRunTopLevelCompletion()) {
|
||||||
addAllClasses {
|
completionKind.classKindFilter?.let { addAllClasses(it) }
|
||||||
if (completionKind != CompletionKind.ANNOTATION_TYPES && completionKind != CompletionKind.ANNOTATION_TYPES_OR_PARAMETER_NAME)
|
|
||||||
it != ClassKind.ENUM_ENTRY
|
|
||||||
else
|
|
||||||
it == ClassKind.ANNOTATION_CLASS
|
|
||||||
}
|
|
||||||
|
|
||||||
if (completionKind == CompletionKind.ALL) {
|
if (completionKind == CompletionKind.ALL) {
|
||||||
collector.addDescriptorElements(getTopLevelCallables(), suppressAutoInsertion = true)
|
collector.addDescriptorElements(getTopLevelCallables(), suppressAutoInsertion = true)
|
||||||
|
|||||||
+33
-4
@@ -23,29 +23,37 @@ import com.intellij.codeInsight.lookup.LookupElement
|
|||||||
import com.intellij.codeInsight.lookup.LookupElementDecorator
|
import com.intellij.codeInsight.lookup.LookupElementDecorator
|
||||||
import com.intellij.codeInsight.lookup.LookupElementPresentation
|
import com.intellij.codeInsight.lookup.LookupElementPresentation
|
||||||
import com.intellij.psi.PsiClass
|
import com.intellij.psi.PsiClass
|
||||||
|
import com.intellij.psi.PsiElement
|
||||||
import com.intellij.psi.codeStyle.CodeStyleSettingsManager
|
import com.intellij.psi.codeStyle.CodeStyleSettingsManager
|
||||||
|
import org.jetbrains.kotlin.descriptors.ClassDescriptorWithResolutionScopes
|
||||||
import org.jetbrains.kotlin.descriptors.ClassifierDescriptor
|
import org.jetbrains.kotlin.descriptors.ClassifierDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||||
|
import org.jetbrains.kotlin.idea.caches.resolve.ResolutionFacade
|
||||||
import org.jetbrains.kotlin.idea.core.KotlinIndicesHelper
|
import org.jetbrains.kotlin.idea.core.KotlinIndicesHelper
|
||||||
import org.jetbrains.kotlin.idea.core.formatter.JetCodeStyleSettings
|
import org.jetbrains.kotlin.idea.core.formatter.JetCodeStyleSettings
|
||||||
import org.jetbrains.kotlin.idea.core.refactoring.EmptyValidator
|
import org.jetbrains.kotlin.idea.core.refactoring.EmptyValidator
|
||||||
import org.jetbrains.kotlin.idea.core.refactoring.JetNameSuggester
|
import org.jetbrains.kotlin.idea.core.refactoring.JetNameSuggester
|
||||||
import org.jetbrains.kotlin.psi.JetSimpleNameExpression
|
import org.jetbrains.kotlin.psi.JetClassOrObject
|
||||||
|
import org.jetbrains.kotlin.psi.JetExpression
|
||||||
|
import org.jetbrains.kotlin.psi.JetFile
|
||||||
|
import org.jetbrains.kotlin.psi.psiUtil.parentsWithSelf
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
|
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
|
||||||
|
import org.jetbrains.kotlin.resolve.scopes.JetScope
|
||||||
import org.jetbrains.kotlin.resolve.scopes.getDescriptorsFiltered
|
import org.jetbrains.kotlin.resolve.scopes.getDescriptorsFiltered
|
||||||
|
|
||||||
class ParameterNameAndTypeCompletion(
|
class ParameterNameAndTypeCompletion(
|
||||||
private val collector: LookupElementsCollector,
|
private val collector: LookupElementsCollector,
|
||||||
private val lookupElementFactory: LookupElementFactory,
|
private val lookupElementFactory: LookupElementFactory,
|
||||||
private val prefixMatcher: PrefixMatcher
|
private val prefixMatcher: PrefixMatcher,
|
||||||
|
private val resolutionFacade: ResolutionFacade
|
||||||
) {
|
) {
|
||||||
private val modifiedPrefixMatcher = prefixMatcher.cloneWithPrefix(prefixMatcher.getPrefix().capitalize())
|
private val modifiedPrefixMatcher = prefixMatcher.cloneWithPrefix(prefixMatcher.getPrefix().capitalize())
|
||||||
|
|
||||||
public fun addFromImports(nameExpression: JetSimpleNameExpression, bindingContext: BindingContext, visibilityFilter: (DeclarationDescriptor) -> Boolean) {
|
public fun addFromImports(context: PsiElement, bindingContext: BindingContext, visibilityFilter: (DeclarationDescriptor) -> Boolean) {
|
||||||
if (prefixMatcher.getPrefix().isEmpty()) return
|
if (prefixMatcher.getPrefix().isEmpty()) return
|
||||||
|
|
||||||
val resolutionScope = bindingContext[BindingContext.RESOLUTION_SCOPE, nameExpression] ?: return
|
val resolutionScope = context.getResolutionScope(bindingContext)
|
||||||
val classifiers = resolutionScope.getDescriptorsFiltered(DescriptorKindFilter.NON_SINGLETON_CLASSIFIERS, modifiedPrefixMatcher.asNameFilter())
|
val classifiers = resolutionScope.getDescriptorsFiltered(DescriptorKindFilter.NON_SINGLETON_CLASSIFIERS, modifiedPrefixMatcher.asNameFilter())
|
||||||
|
|
||||||
for (classifier in classifiers) {
|
for (classifier in classifiers) {
|
||||||
@@ -55,6 +63,27 @@ class ParameterNameAndTypeCompletion(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun PsiElement.getResolutionScope(bindingContext: BindingContext): JetScope {
|
||||||
|
for (parent in parentsWithSelf) {
|
||||||
|
if (parent is JetExpression) {
|
||||||
|
val scope = bindingContext[BindingContext.RESOLUTION_SCOPE, parent]
|
||||||
|
if (scope != null) return scope
|
||||||
|
}
|
||||||
|
|
||||||
|
if (parent is JetClassOrObject) {
|
||||||
|
val classDescriptor = bindingContext[BindingContext.CLASS, parent] as? ClassDescriptorWithResolutionScopes
|
||||||
|
if (classDescriptor != null) {
|
||||||
|
return classDescriptor.getScopeForMemberDeclarationResolution()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (parent is JetFile) {
|
||||||
|
return resolutionFacade.getFileTopLevelScope(parent)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
error("Not in JetFile")
|
||||||
|
}
|
||||||
|
|
||||||
public fun addAll(parameters: CompletionParameters, indicesHelper: KotlinIndicesHelper) {
|
public fun addAll(parameters: CompletionParameters, indicesHelper: KotlinIndicesHelper) {
|
||||||
if (prefixMatcher.getPrefix().isEmpty()) return
|
if (prefixMatcher.getPrefix().isEmpty()) return
|
||||||
|
|
||||||
|
|||||||
+11
@@ -0,0 +1,11 @@
|
|||||||
|
package pack
|
||||||
|
|
||||||
|
class FooBar
|
||||||
|
|
||||||
|
class Boo
|
||||||
|
|
||||||
|
class C(val b<caret>)
|
||||||
|
|
||||||
|
// EXIST: { lookupString: "bar", itemText: "bar: FooBar", tailText: " (pack)" }
|
||||||
|
// EXIST: { lookupString: "fooBar", itemText: "fooBar: FooBar", tailText: " (pack)" }
|
||||||
|
// EXIST: { lookupString: "boo", itemText: "boo: Boo", tailText: " (pack)" }
|
||||||
+11
@@ -0,0 +1,11 @@
|
|||||||
|
package pack
|
||||||
|
|
||||||
|
class FooBar
|
||||||
|
|
||||||
|
class C(private var b<caret>) {
|
||||||
|
class Boo
|
||||||
|
}
|
||||||
|
|
||||||
|
// EXIST: { lookupString: "bar", itemText: "bar: FooBar", tailText: " (pack)" }
|
||||||
|
// EXIST: { lookupString: "fooBar", itemText: "fooBar: FooBar", tailText: " (pack)" }
|
||||||
|
// EXIST: { lookupString: "boo", itemText: "boo: Boo", tailText: " (pack.C)" }
|
||||||
+12
@@ -1427,6 +1427,18 @@ public class JSBasicCompletionTestGenerated extends AbstractJSBasicCompletionTes
|
|||||||
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/parameterNameAndType/Simple.kt");
|
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/parameterNameAndType/Simple.kt");
|
||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("ValParameter.kt")
|
||||||
|
public void testValParameter() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/parameterNameAndType/ValParameter.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("VarParameter.kt")
|
||||||
|
public void testVarParameter() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/parameterNameAndType/VarParameter.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@TestMetadata("idea/idea-completion/testData/basic/common/shadowing")
|
@TestMetadata("idea/idea-completion/testData/basic/common/shadowing")
|
||||||
|
|||||||
+12
@@ -1427,6 +1427,18 @@ public class JvmBasicCompletionTestGenerated extends AbstractJvmBasicCompletionT
|
|||||||
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/parameterNameAndType/Simple.kt");
|
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/parameterNameAndType/Simple.kt");
|
||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("ValParameter.kt")
|
||||||
|
public void testValParameter() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/parameterNameAndType/ValParameter.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("VarParameter.kt")
|
||||||
|
public void testVarParameter() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/parameterNameAndType/VarParameter.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@TestMetadata("idea/idea-completion/testData/basic/common/shadowing")
|
@TestMetadata("idea/idea-completion/testData/basic/common/shadowing")
|
||||||
|
|||||||
Reference in New Issue
Block a user