Completion of parameter name+type works for val/var parameters

This commit is contained in:
Valentin Kipyatkov
2015-06-17 18:53:25 +03:00
parent 0e4ac7108a
commit 0e045b9478
6 changed files with 97 additions and 22 deletions
@@ -263,13 +263,14 @@ class BasicCompletionSession(configuration: CompletionSessionConfiguration,
resultSet: CompletionResultSet)
: CompletionSessionBase(configuration, parameters, resultSet) {
public enum class CompletionKind {
KEYWORDS_ONLY,
NAMED_ARGUMENTS_ONLY,
ALL,
TYPES,
ANNOTATION_TYPES,
ANNOTATION_TYPES_OR_PARAMETER_NAME
public enum class CompletionKind(val classKindFilter: ((ClassKind) -> Boolean)?) {
KEYWORDS_ONLY(classKindFilter = null),
NAMED_ARGUMENTS_ONLY(classKindFilter = null),
ALL(classKindFilter = { it != ClassKind.ENUM_ENTRY }),
TYPES(classKindFilter = { it != ClassKind.ENUM_ENTRY }),
ANNOTATION_TYPES(classKindFilter = { it == ClassKind.ANNOTATION_CLASS }),
ANNOTATION_TYPES_OR_PARAMETER_NAME(classKindFilter = { it == ClassKind.ANNOTATION_CLASS }),
PARAMETER_NAME(classKindFilter = null)
}
public val completionKind: CompletionKind = calcCompletionKind()
@@ -284,12 +285,12 @@ class BasicCompletionSession(configuration: CompletionSessionConfiguration,
CompletionKind.ALL ->
DescriptorKindFilter(DescriptorKindFilter.ALL_KINDS_MASK)
CompletionKind.NAMED_ARGUMENTS_ONLY, CompletionKind.KEYWORDS_ONLY ->
CompletionKind.NAMED_ARGUMENTS_ONLY, CompletionKind.KEYWORDS_ONLY, CompletionKind.PARAMETER_NAME ->
null
}
private val parameterNameAndTypeCompletion = if (completionKind == CompletionKind.ANNOTATION_TYPES_OR_PARAMETER_NAME)
ParameterNameAndTypeCompletion(collector, lookupElementFactory, prefixMatcher)
private val parameterNameAndTypeCompletion = if (completionKind == CompletionKind.PARAMETER_NAME || completionKind == CompletionKind.ANNOTATION_TYPES_OR_PARAMETER_NAME)
ParameterNameAndTypeCompletion(collector, lookupElementFactory, prefixMatcher, resolutionFacade)
else
null
@@ -299,7 +300,11 @@ class BasicCompletionSession(configuration: CompletionSessionConfiguration,
}
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>()
@@ -333,7 +338,7 @@ class BasicCompletionSession(configuration: CompletionSessionConfiguration,
if (completionKind != CompletionKind.NAMED_ARGUMENTS_ONLY) {
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
KeywordCompletion.complete(expression ?: parameters.getPosition(), keywordsPrefix) { lookupElement ->
@@ -402,12 +407,7 @@ class BasicCompletionSession(configuration: CompletionSessionConfiguration,
flushToResultSet()
if (shouldRunTopLevelCompletion()) {
addAllClasses {
if (completionKind != CompletionKind.ANNOTATION_TYPES && completionKind != CompletionKind.ANNOTATION_TYPES_OR_PARAMETER_NAME)
it != ClassKind.ENUM_ENTRY
else
it == ClassKind.ANNOTATION_CLASS
}
completionKind.classKindFilter?.let { addAllClasses(it) }
if (completionKind == CompletionKind.ALL) {
collector.addDescriptorElements(getTopLevelCallables(), suppressAutoInsertion = true)
@@ -23,29 +23,37 @@ import com.intellij.codeInsight.lookup.LookupElement
import com.intellij.codeInsight.lookup.LookupElementDecorator
import com.intellij.codeInsight.lookup.LookupElementPresentation
import com.intellij.psi.PsiClass
import com.intellij.psi.PsiElement
import com.intellij.psi.codeStyle.CodeStyleSettingsManager
import org.jetbrains.kotlin.descriptors.ClassDescriptorWithResolutionScopes
import org.jetbrains.kotlin.descriptors.ClassifierDescriptor
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.formatter.JetCodeStyleSettings
import org.jetbrains.kotlin.idea.core.refactoring.EmptyValidator
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.scopes.DescriptorKindFilter
import org.jetbrains.kotlin.resolve.scopes.JetScope
import org.jetbrains.kotlin.resolve.scopes.getDescriptorsFiltered
class ParameterNameAndTypeCompletion(
private val collector: LookupElementsCollector,
private val lookupElementFactory: LookupElementFactory,
private val prefixMatcher: PrefixMatcher
private val prefixMatcher: PrefixMatcher,
private val resolutionFacade: ResolutionFacade
) {
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
val resolutionScope = bindingContext[BindingContext.RESOLUTION_SCOPE, nameExpression] ?: return
val resolutionScope = context.getResolutionScope(bindingContext)
val classifiers = resolutionScope.getDescriptorsFiltered(DescriptorKindFilter.NON_SINGLETON_CLASSIFIERS, modifiedPrefixMatcher.asNameFilter())
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) {
if (prefixMatcher.getPrefix().isEmpty()) return
@@ -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)" }
@@ -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)" }
@@ -1427,6 +1427,18 @@ public class JSBasicCompletionTestGenerated extends AbstractJSBasicCompletionTes
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/parameterNameAndType/Simple.kt");
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")
@@ -1427,6 +1427,18 @@ public class JvmBasicCompletionTestGenerated extends AbstractJvmBasicCompletionT
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/parameterNameAndType/Simple.kt");
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")