Completion of parameter name/types from the current file

This commit is contained in:
Valentin Kipyatkov
2015-06-18 17:51:47 +03:00
parent 22ad1389f5
commit 17500cef98
15 changed files with 233 additions and 69 deletions
@@ -125,7 +125,9 @@ abstract class CompletionSessionBase(protected val configuration: CompletionSess
protected val prefixMatcher: PrefixMatcher = this.resultSet.getPrefixMatcher() protected val prefixMatcher: PrefixMatcher = this.resultSet.getPrefixMatcher()
protected val referenceVariantsHelper: ReferenceVariantsHelper = ReferenceVariantsHelper(bindingContext, moduleDescriptor, project, { isVisibleDescriptor(it) }) protected val isVisibleFilter: (DeclarationDescriptor) -> Boolean = { isVisibleDescriptor(it) }
protected val referenceVariantsHelper: ReferenceVariantsHelper = ReferenceVariantsHelper(bindingContext, moduleDescriptor, project, isVisibleFilter)
protected val receiversData: ReferenceVariantsHelper.ReceiversData? = reference?.let { referenceVariantsHelper.getReferenceVariantsReceivers(it.expression) } protected val receiversData: ReferenceVariantsHelper.ReceiversData? = reference?.let { referenceVariantsHelper.getReferenceVariantsReceivers(it.expression) }
@@ -165,7 +167,7 @@ abstract class CompletionSessionBase(protected val configuration: CompletionSess
} }
protected val indicesHelper: KotlinIndicesHelper protected val indicesHelper: KotlinIndicesHelper
get() = KotlinIndicesHelper(project, resolutionFacade, searchScope, moduleDescriptor, { isVisibleDescriptor(it) }) get() = KotlinIndicesHelper(project, resolutionFacade, searchScope, moduleDescriptor, isVisibleFilter)
protected fun isVisibleDescriptor(descriptor: DeclarationDescriptor): Boolean { protected fun isVisibleDescriptor(descriptor: DeclarationDescriptor): Boolean {
if (descriptor is DeclarationDescriptorWithVisibility && inDescriptor != null) { if (descriptor is DeclarationDescriptorWithVisibility && inDescriptor != null) {
@@ -356,9 +358,13 @@ class BasicCompletionSession(configuration: CompletionSessionConfiguration,
} }
if (completionKind != CompletionKind.NAMED_ARGUMENTS_ONLY) { if (completionKind != CompletionKind.NAMED_ARGUMENTS_ONLY) {
collector.addDescriptorElements(referenceVariants, suppressAutoInsertion = false) parameterNameAndTypeCompletion?.addFromParametersInFile(position, resolutionFacade, isVisibleFilter)
flushToResultSet()
parameterNameAndTypeCompletion?.addFromImports(position, bindingContext, { isVisibleDescriptor(it) }) parameterNameAndTypeCompletion?.addFromImportedClasses(position, bindingContext, isVisibleFilter)
flushToResultSet()
collector.addDescriptorElements(referenceVariants, suppressAutoInsertion = false)
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 ->
@@ -434,7 +440,7 @@ class BasicCompletionSession(configuration: CompletionSessionConfiguration,
} }
} }
parameterNameAndTypeCompletion?.addAll(parameters, indicesHelper) parameterNameAndTypeCompletion?.addFromAllClasses(parameters, indicesHelper)
} }
} }
@@ -456,7 +462,7 @@ class SmartCompletionSession(configuration: CompletionSessionConfiguration, para
addFunctionLiteralArgumentCompletions() addFunctionLiteralArgumentCompletions()
val completion = SmartCompletion(expression, resolutionFacade, moduleDescriptor, val completion = SmartCompletion(expression, resolutionFacade, moduleDescriptor,
bindingContext, { isVisibleDescriptor(it) }, inDescriptor, prefixMatcher, originalSearchScope, bindingContext, isVisibleFilter, inDescriptor, prefixMatcher, originalSearchScope,
mapper, lookupElementFactory) mapper, lookupElementFactory)
val result = completion.execute() val result = completion.execute()
if (result != null) { if (result != null) {
@@ -22,6 +22,7 @@ import com.intellij.openapi.progress.ProcessCanceledException
import com.intellij.openapi.util.Key import com.intellij.openapi.util.Key
import com.intellij.patterns.ElementPattern import com.intellij.patterns.ElementPattern
import com.intellij.patterns.StandardPatterns import com.intellij.patterns.StandardPatterns
import com.intellij.psi.PsiDocumentManager
import com.intellij.util.PlatformIcons import com.intellij.util.PlatformIcons
import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.*
@@ -29,9 +30,9 @@ import org.jetbrains.kotlin.idea.caches.resolve.ResolutionFacade
import org.jetbrains.kotlin.idea.completion.handlers.CastReceiverInsertHandler import org.jetbrains.kotlin.idea.completion.handlers.CastReceiverInsertHandler
import org.jetbrains.kotlin.idea.completion.handlers.WithTailInsertHandler import org.jetbrains.kotlin.idea.completion.handlers.WithTailInsertHandler
import org.jetbrains.kotlin.idea.util.* import org.jetbrains.kotlin.idea.util.*
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.parents
import org.jetbrains.kotlin.psi.psiUtil.parentsWithSelf import org.jetbrains.kotlin.psi.psiUtil.parentsWithSelf
import org.jetbrains.kotlin.renderer.DescriptorRenderer import org.jetbrains.kotlin.renderer.DescriptorRenderer
import org.jetbrains.kotlin.renderer.render import org.jetbrains.kotlin.renderer.render
@@ -339,6 +340,62 @@ fun LookupElementFactory.createBackingFieldLookupElement(
}.assignPriority(ItemPriority.BACKING_FIELD) }.assignPriority(ItemPriority.BACKING_FIELD)
} }
fun LookupElementFactory.createLookupElementForType(type: JetType): LookupElement? {
if (type.isError()) return null
val classifier = type.getConstructor().getDeclarationDescriptor() ?: return null
val lookupElement = createLookupElement(classifier, false)
var itemText = IdeDescriptorRenderers.SOURCE_CODE_SHORT_NAMES_IN_TYPES.renderType(type)
val typeText = IdeDescriptorRenderers.SOURCE_CODE.renderType(type)
var packageName: FqName? = null
if (!KotlinBuiltIns.isExactFunctionOrExtensionFunctionType(type)) {
var container = classifier.getContainingDeclaration()
while (container is ClassDescriptor) {
container = container.getContainingDeclaration()
}
if (container is PackageFragmentDescriptor) {
packageName = container.fqName
}
}
val insertHandler: InsertHandler<LookupElement> = object : InsertHandler<LookupElement> {
override fun handleInsert(context: InsertionContext, item: LookupElement) {
context.getDocument().replaceString(context.getStartOffset(), context.getTailOffset(), typeText)
context.setTailOffset(context.getStartOffset() + typeText.length())
shortenReferences(context, context.getStartOffset(), context.getTailOffset())
}
}
class TypeLookupElement : LookupElementDecorator<LookupElement>(lookupElement) {
val typeText = typeText
override fun equals(other: Any?) = other is TypeLookupElement && typeText == other.typeText
override fun hashCode() = typeText.hashCode()
override fun renderElement(presentation: LookupElementPresentation) {
getDelegate().renderElement(presentation)
presentation.setItemText(itemText)
presentation.clearTail()
if (packageName != null) {
presentation.appendTailText(" ($packageName)", true)
}
}
override fun handleInsert(context: InsertionContext) {
insertHandler.handleInsert(context, getDelegate())
}
}
return TypeLookupElement()
}
fun shortenReferences(context: InsertionContext, startOffset: Int, endOffset: Int) {
PsiDocumentManager.getInstance(context.getProject()).commitAllDocuments();
ShortenReferences.DEFAULT.process(context.getFile() as JetFile, startOffset, endOffset)
}
fun <T> ElementPattern<T>.and(rhs: ElementPattern<T>) = StandardPatterns.and(this, rhs) fun <T> ElementPattern<T>.and(rhs: ElementPattern<T>) = StandardPatterns.and(this, rhs)
fun <T> ElementPattern<T>.andNot(rhs: ElementPattern<T>) = StandardPatterns.and(this, StandardPatterns.not(rhs)) fun <T> ElementPattern<T>.andNot(rhs: ElementPattern<T>) = StandardPatterns.and(this, StandardPatterns.not(rhs))
fun <T> ElementPattern<T>.or(rhs: ElementPattern<T>) = StandardPatterns.or(this, rhs) fun <T> ElementPattern<T>.or(rhs: ElementPattern<T>) = StandardPatterns.or(this, rhs)
@@ -23,8 +23,10 @@ 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.PsiDocumentManager
import com.intellij.psi.PsiElement import com.intellij.psi.PsiElement
import com.intellij.psi.codeStyle.CodeStyleSettingsManager import com.intellij.psi.codeStyle.CodeStyleSettingsManager
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.descriptors.ClassDescriptorWithResolutionScopes 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
@@ -33,14 +35,15 @@ 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.JetClassOrObject import org.jetbrains.kotlin.idea.util.approximateFlexibleTypes
import org.jetbrains.kotlin.psi.JetExpression import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.JetFile import org.jetbrains.kotlin.psi.psiUtil.forEachDescendantOfType
import org.jetbrains.kotlin.psi.psiUtil.parentsWithSelf 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.JetScope
import org.jetbrains.kotlin.resolve.scopes.getDescriptorsFiltered import org.jetbrains.kotlin.resolve.scopes.getDescriptorsFiltered
import org.jetbrains.kotlin.types.JetType
class ParameterNameAndTypeCompletion( class ParameterNameAndTypeCompletion(
private val collector: LookupElementsCollector, private val collector: LookupElementsCollector,
@@ -50,10 +53,10 @@ class ParameterNameAndTypeCompletion(
) { ) {
private val modifiedPrefixMatcher = prefixMatcher.cloneWithPrefix(prefixMatcher.getPrefix().capitalize()) private val modifiedPrefixMatcher = prefixMatcher.cloneWithPrefix(prefixMatcher.getPrefix().capitalize())
public fun addFromImports(context: PsiElement, bindingContext: BindingContext, visibilityFilter: (DeclarationDescriptor) -> Boolean) { public fun addFromImportedClasses(position: PsiElement, bindingContext: BindingContext, visibilityFilter: (DeclarationDescriptor) -> Boolean) {
if (prefixMatcher.getPrefix().isEmpty()) return if (prefixMatcher.getPrefix().isEmpty()) return
val resolutionScope = context.getResolutionScope(bindingContext) val resolutionScope = position.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) {
@@ -84,13 +87,30 @@ class ParameterNameAndTypeCompletion(
error("Not in JetFile") error("Not in JetFile")
} }
public fun addAll(parameters: CompletionParameters, indicesHelper: KotlinIndicesHelper) { public fun addFromAllClasses(parameters: CompletionParameters, indicesHelper: KotlinIndicesHelper) {
if (prefixMatcher.getPrefix().isEmpty()) return if (prefixMatcher.getPrefix().isEmpty()) return
AllClassesCompletion(parameters, indicesHelper, modifiedPrefixMatcher, { !it.isSingleton() }) AllClassesCompletion(parameters, indicesHelper, modifiedPrefixMatcher, { !it.isSingleton() })
.collect({ addSuggestionsForClassifier(it) }, { addSuggestionsForJavaClass(it) }) .collect({ addSuggestionsForClassifier(it) }, { addSuggestionsForJavaClass(it) })
} }
public fun addFromParametersInFile(position: PsiElement, resolutionFacade: ResolutionFacade, visibilityFilter: (DeclarationDescriptor) -> Boolean) {
position.getContainingFile().forEachDescendantOfType<JetParameter>(
canGoInside = { it !is JetExpression || it is JetDeclaration } // we analyze parameters inside bodies to not resolve too much
) { declaration ->
val name = declaration.getName()
if (name != null && prefixMatcher.prefixMatches(name)) {
val parameter = resolutionFacade.analyze(declaration)[BindingContext.VALUE_PARAMETER, declaration]
if (parameter != null) {
val parameterType = parameter.getType()
if (parameterType.isVisible(visibilityFilter)) {
addLookupElement(NameAndArbitraryType(name, parameterType))
}
}
}
}
}
private fun addSuggestionsForClassifier(classifier: DeclarationDescriptor) { private fun addSuggestionsForClassifier(classifier: DeclarationDescriptor) {
addSuggestions(classifier.getName().asString()) { name -> NameAndDescriptorType(name, classifier as ClassifierDescriptor) } addSuggestions(classifier.getName().asString()) { name -> NameAndDescriptorType(name, classifier as ClassifierDescriptor) }
} }
@@ -103,52 +123,76 @@ class ParameterNameAndTypeCompletion(
val parameterNames = JetNameSuggester.getCamelNames(className, EmptyValidator) val parameterNames = JetNameSuggester.getCamelNames(className, EmptyValidator)
for (parameterName in parameterNames) { for (parameterName in parameterNames) {
if (prefixMatcher.prefixMatches(parameterName)) { if (prefixMatcher.prefixMatches(parameterName)) {
val nameAndType = nameAndTypeFactory(parameterName) addLookupElement(nameAndTypeFactory(parameterName))
collector.addElement(MyLookupElement(nameAndType, lookupElementFactory).suppressAutoInsertion())
} }
} }
} }
private interface NameAndType { private fun addLookupElement(nameAndType: NameAndType) {
val parameterName: String val lookupElement = MyLookupElement.create(nameAndType, lookupElementFactory)
if (lookupElement != null) {
fun createTypeLookupElement(lookupElementFactory: LookupElementFactory): LookupElement collector.addElement(lookupElement)
}
} }
private data class NameAndDescriptorType(override val parameterName: String, val type: ClassifierDescriptor) : NameAndType { private fun JetType.isVisible(visibilityFilter: (DeclarationDescriptor) -> Boolean): Boolean {
if (isError()) return false
val classifier = getConstructor().getDeclarationDescriptor() ?: return false
return visibilityFilter(classifier) && getArguments().all { it.getType().isVisible(visibilityFilter) }
}
private abstract class NameAndType(val parameterName: String) {
abstract fun createTypeLookupElement(lookupElementFactory: LookupElementFactory): LookupElement?
}
private class NameAndDescriptorType(parameterName: String, private val type: ClassifierDescriptor) : NameAndType(parameterName) {
override fun createTypeLookupElement(lookupElementFactory: LookupElementFactory) override fun createTypeLookupElement(lookupElementFactory: LookupElementFactory)
= lookupElementFactory.createLookupElement(type, false) = lookupElementFactory.createLookupElement(type, false)
} }
private data class NameAndJavaType(override val parameterName: String, val type: PsiClass) : NameAndType { private class NameAndJavaType(parameterName: String, private val type: PsiClass) : NameAndType(parameterName) {
override fun createTypeLookupElement(lookupElementFactory: LookupElementFactory) override fun createTypeLookupElement(lookupElementFactory: LookupElementFactory)
= lookupElementFactory.createLookupElementForJavaClass(type) = lookupElementFactory.createLookupElementForJavaClass(type)
} }
private class MyLookupElement( private class NameAndArbitraryType(parameterName: String, private val type: JetType) : NameAndType(parameterName) {
val nameAndType: NameAndType, override fun createTypeLookupElement(lookupElementFactory: LookupElementFactory)
factory: LookupElementFactory = lookupElementFactory.createLookupElementForType(type)
) : LookupElementDecorator<LookupElement>(nameAndType.createTypeLookupElement(factory)) { }
private class MyLookupElement private constructor(
private val parameterName: String,
typeLookupElement: LookupElement
) : LookupElementDecorator<LookupElement>(typeLookupElement) {
companion object {
fun create(nameAndType: NameAndType, factory: LookupElementFactory): LookupElement? {
val lookupElement = nameAndType.createTypeLookupElement(factory) ?: return null
return MyLookupElement(nameAndType.parameterName, lookupElement).suppressAutoInsertion()
}
}
override fun equals(other: Any?) override fun equals(other: Any?)
= other is MyLookupElement && nameAndType.parameterName == other.nameAndType.parameterName && getDelegate() == other.getDelegate() = other is MyLookupElement && parameterName == other.parameterName && getDelegate() == other.getDelegate()
override fun hashCode() = nameAndType.parameterName.hashCode() override fun hashCode() = parameterName.hashCode()
override fun getLookupString() = nameAndType.parameterName override fun getLookupString() = parameterName
override fun getAllLookupStrings() = setOf(nameAndType.parameterName) override fun getAllLookupStrings() = setOf(parameterName)
override fun renderElement(presentation: LookupElementPresentation) { override fun renderElement(presentation: LookupElementPresentation) {
super.renderElement(presentation) super.renderElement(presentation)
presentation.setItemText(nameAndType.parameterName + ": " + presentation.getItemText()) presentation.setItemText(parameterName + ": " + presentation.getItemText())
} }
override fun handleInsert(context: InsertionContext) { override fun handleInsert(context: InsertionContext) {
super.handleInsert(context) super.handleInsert(context)
PsiDocumentManager.getInstance(context.getProject()).doPostponedOperationsAndUnblockDocument(context.getDocument())
val settings = CodeStyleSettingsManager.getInstance(context.getProject()).getCurrentSettings().getCustomSettings(javaClass<JetCodeStyleSettings>()) val settings = CodeStyleSettingsManager.getInstance(context.getProject()).getCurrentSettings().getCustomSettings(javaClass<JetCodeStyleSettings>())
val spaceBefore = if (settings.SPACE_BEFORE_TYPE_COLON) " " else "" val spaceBefore = if (settings.SPACE_BEFORE_TYPE_COLON) " " else ""
val spaceAfter = if (settings.SPACE_AFTER_TYPE_COLON) " " else "" val spaceAfter = if (settings.SPACE_AFTER_TYPE_COLON) " " else ""
val text = nameAndType.parameterName + spaceBefore + ":" + spaceAfter val text = parameterName + spaceBefore + ":" + spaceAfter
context.getDocument().insertString(context.getStartOffset(), text) context.getDocument().insertString(context.getStartOffset(), text)
} }
} }
@@ -371,7 +371,7 @@ class SmartCompletion(
val items = ArrayList<LookupElement>() val items = ArrayList<LookupElement>()
for ((type, infos) in expectedInfosGrouped) { for ((type, infos) in expectedInfosGrouped) {
val lookupElement = lookupElementForType(type) ?: continue val lookupElement = lookupElementFactory.createLookupElementForType(type) ?: continue
items.add(lookupElement.addTailAndNameSimilarity(infos)) items.add(lookupElement.addTailAndNameSimilarity(infos))
} }
return Result(null, items, null) return Result(null, items, null)
@@ -439,34 +439,6 @@ class SmartCompletion(
return Result(::filterDeclaration, listOf(), null) return Result(::filterDeclaration, listOf(), null)
} }
private fun lookupElementForType(type: JetType): LookupElement? {
if (type.isError()) return null
val classifier = type.getConstructor().getDeclarationDescriptor() ?: return null
val lookupElement = lookupElementFactory.createLookupElement(classifier, bindingContext, false)
var itemText = IdeDescriptorRenderers.SOURCE_CODE_SHORT_NAMES_IN_TYPES.renderType(type)
val typeText = IdeDescriptorRenderers.SOURCE_CODE.renderType(type)
val insertHandler: InsertHandler<LookupElement> = object : InsertHandler<LookupElement> {
override fun handleInsert(context: InsertionContext, item: LookupElement) {
context.getDocument().replaceString(context.getStartOffset(), context.getTailOffset(), typeText)
context.setTailOffset(context.getStartOffset() + typeText.length())
shortenReferences(context, context.getStartOffset(), context.getTailOffset())
}
}
return object: LookupElementDecorator<LookupElement>(lookupElement) {
override fun renderElement(presentation: LookupElementPresentation) {
getDelegate().renderElement(presentation)
presentation.setItemText(itemText)
}
override fun handleInsert(context: InsertionContext) {
insertHandler.handleInsert(context, getDelegate())
}
}
}
companion object { companion object {
public val OLD_ARGUMENTS_REPLACEMENT_OFFSET: OffsetKey = OffsetKey.create("nonFunctionReplacementOffset") public val OLD_ARGUMENTS_REPLACEMENT_OFFSET: OffsetKey = OffsetKey.create("nonFunctionReplacementOffset")
public val MULTIPLE_ARGUMENTS_REPLACEMENT_OFFSET: OffsetKey = OffsetKey.create("multipleArgumentsReplacementOffset") public val MULTIPLE_ARGUMENTS_REPLACEMENT_OFFSET: OffsetKey = OffsetKey.create("multipleArgumentsReplacementOffset")
@@ -23,6 +23,7 @@ import com.intellij.codeInsight.lookup.LookupElementPresentation
import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.idea.completion.ExpectedInfo import org.jetbrains.kotlin.idea.completion.ExpectedInfo
import org.jetbrains.kotlin.idea.completion.LookupElementFactory import org.jetbrains.kotlin.idea.completion.LookupElementFactory
import org.jetbrains.kotlin.idea.completion.shortenReferences
import org.jetbrains.kotlin.idea.core.isVisible import org.jetbrains.kotlin.idea.core.isVisible
import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers
import org.jetbrains.kotlin.idea.util.fuzzyReturnType import org.jetbrains.kotlin.idea.util.fuzzyReturnType
@@ -52,11 +52,6 @@ class ArtificialElementInsertHandler(
} }
} }
fun shortenReferences(context: InsertionContext, startOffset: Int, endOffset: Int) {
PsiDocumentManager.getInstance(context.getProject()).commitAllDocuments();
ShortenReferences.DEFAULT.process(context.getFile() as JetFile, startOffset, endOffset)
}
fun mergeTails(tails: Collection<Tail?>): Tail? { fun mergeTails(tails: Collection<Tail?>): Tail? {
if (tails.size() == 1) return tails.single() if (tails.size() == 1) return tails.single()
return if (HashSet(tails).size() == 1) tails.first() else null return if (HashSet(tails).size() == 1) tails.first() else null
@@ -0,0 +1,28 @@
import java.io.*
class X {
fun f1(strings: List<String>) { }
fun f2(numbers: List<Int>) { }
}
fun f3(strings: List<String>) { }
fun f4(value: Any?) { }
fun f5(value: File) { }
fun f6(handler: (() -> String)?) { }
class C(val handler: () -> Unit) {
companion object {
fun foo(<caret>) {
fun local(localParam: String/* it should not be included by performance reasons*/){}
}
}
}
// EXIST: { lookupString: "strings", itemText: "strings: List<String>", tailText: " (kotlin)" }
// EXIST: { lookupString: "numbers", itemText: "numbers: List<Int>", tailText: " (kotlin)" }
// EXIST: { lookupString: "value", itemText: "value: Any?", tailText: " (kotlin)" }
// EXIST_JAVA_ONLY: { lookupString: "value", itemText: "value: File", tailText: " (java.io)" }
// EXIST: { lookupString: "handler", itemText: "handler: (() -> String)?", tailText: null }
// EXIST: { lookupString: "handler", itemText: "handler: () -> Unit", tailText: null }
// ABSENT: "localParam"
// ABSENT: "file"
@@ -0,0 +1,19 @@
package ppp
import java.io.*
class X {
public class PublicNested
private class PrivateNested
fun f1(nested: PublicNested) { }
fun f2(nested: PrivateNested) { }
fun f3(nestedList: List<PublicNested>) { }
fun f4(nestedList: List<PrivateNested>) { }
}
fun foo(neste<caret>)
// EXIST: { lookupString: "nested", itemText: "nested: X.PublicNested", tailText: " (ppp)" }
// EXIST: { lookupString: "nestedList", itemText: "nestedList: List<X.PublicNested>", tailText: " (kotlin)" }
// NOTHING_ELSE
@@ -0,0 +1,5 @@
fun foo(xxx: ((java.io.File) -> List<String>)?)
fun bar(x<caret>)
// ELEMENT: xxx
@@ -0,0 +1,7 @@
import java.io.File
fun foo(xxx: ((java.io.File) -> List<String>)?)
fun bar(xxx: ((File) -> List<String>)?<caret>)
// ELEMENT: xxx
+2 -2
View File
@@ -6,6 +6,6 @@ fun bar(o: Any) {
foo(o as <caret>) foo(o as <caret>)
} }
// EXIST: { lookupString:"List", itemText:"List<String>" } // EXIST: { lookupString:"List", itemText:"List<String>", tailText: " (kotlin)" }
// EXIST: { lookupString:"Map", itemText:"Map<String, Int>" } // EXIST: { lookupString:"Map", itemText:"Map<String, Int>", tailText: " (kotlin)" }
// NOTHING_ELSE // NOTHING_ELSE
+2 -2
View File
@@ -7,6 +7,6 @@ fun bar(o: Any) {
foo(o as <caret>) foo(o as <caret>)
} }
// EXIST: { lookupString:"List", itemText:"List<String>" } // EXIST: { lookupString:"List", itemText:"List<String>", tailText: " (kotlin)" }
// EXIST: { lookupString:"String", itemText:"String" } // EXIST: { lookupString:"String", itemText:"String", tailText: " (kotlin)" }
// NOTHING_ELSE // NOTHING_ELSE
@@ -1458,6 +1458,18 @@ public class JSBasicCompletionTestGenerated extends AbstractJSBasicCompletionTes
doTest(fileName); doTest(fileName);
} }
@TestMetadata("ParametersInFile.kt")
public void testParametersInFile() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/parameterNameAndType/ParametersInFile.kt");
doTest(fileName);
}
@TestMetadata("ParametersInFileInaccessibleType.kt")
public void testParametersInFileInaccessibleType() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/parameterNameAndType/ParametersInFileInaccessibleType.kt");
doTest(fileName);
}
@TestMetadata("Simple.kt") @TestMetadata("Simple.kt")
public void testSimple() throws Exception { public void testSimple() throws Exception {
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");
@@ -1458,6 +1458,18 @@ public class JvmBasicCompletionTestGenerated extends AbstractJvmBasicCompletionT
doTest(fileName); doTest(fileName);
} }
@TestMetadata("ParametersInFile.kt")
public void testParametersInFile() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/parameterNameAndType/ParametersInFile.kt");
doTest(fileName);
}
@TestMetadata("ParametersInFileInaccessibleType.kt")
public void testParametersInFileInaccessibleType() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/parameterNameAndType/ParametersInFileInaccessibleType.kt");
doTest(fileName);
}
@TestMetadata("Simple.kt") @TestMetadata("Simple.kt")
public void testSimple() throws Exception { public void testSimple() throws Exception {
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");
@@ -277,6 +277,12 @@ public class BasicCompletionHandlerTestGenerated extends AbstractBasicCompletion
doTest(fileName); doTest(fileName);
} }
@TestMetadata("ParameterInFile.kt")
public void testParameterInFile() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/handlers/basic/parameterNameAndType/ParameterInFile.kt");
doTest(fileName);
}
@TestMetadata("Simple.kt") @TestMetadata("Simple.kt")
public void testSimple() throws Exception { public void testSimple() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/handlers/basic/parameterNameAndType/Simple.kt"); String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/handlers/basic/parameterNameAndType/Simple.kt");