From 8210d3091f64a3de385ce6f01314322620f82735 Mon Sep 17 00:00:00 2001 From: Valentin Kipyatkov Date: Wed, 17 Jun 2015 17:55:51 +0300 Subject: [PATCH] Initial implementation of KT-6427 Completion to use Java name suggestion to complete function parameters (+ filtered out synthetic Kotlin classes from completion) --- .../org/jetbrains/kotlin/utils/addToStdlib.kt | 10 ++ .../idea/completion/AllClassesCompletion.kt | 37 ++--- .../idea/completion/CompletionSession.kt | 24 +++- .../completion/KotlinCompletionContributor.kt | 5 - .../completion/LookupElementsCollector.kt | 2 +- .../ParameterNameAndTypeCompletion.kt | 127 ++++++++++++++++++ .../NoParameterAnnotationAutoPopup1.kt | 4 - .../NoParameterAnnotationAutoPopup2.kt | 4 - .../parameterNameAndType/NoDuplication.kt | 6 + .../parameterNameAndType/NoDuplicationJava.kt | 6 + .../parameterNameAndType/NotImported.kt | 3 + .../parameterNameAndType/NotImportedJava.kt | 3 + .../common/parameterNameAndType/Simple.kt | 11 ++ .../testData/basic/java/NoSyntheticClasses.kt | 8 ++ ...ctionLiteralInsertWhenNoSpacesForBraces.kt | 2 +- ...iteralInsertWhenNoSpacesForBraces.kt.after | 2 +- .../parameterNameAndType/CodeStyleSettings.kt | 8 ++ .../CodeStyleSettings.kt.after | 8 ++ .../basic/parameterNameAndType/Comma.kt | 6 + .../basic/parameterNameAndType/Comma.kt.after | 6 + .../parameterNameAndType/InsertImport.kt | 3 + .../InsertImport.kt.after | 5 + .../basic/parameterNameAndType/Simple.kt | 5 + .../parameterNameAndType/Simple.kt.after | 5 + .../test/JSBasicCompletionTestGenerated.java | 51 +++++-- .../test/JvmBasicCompletionTestGenerated.java | 57 ++++++-- .../AbstractCompletionHandlerTests.kt | 16 ++- .../BasicCompletionHandlerTestGenerated.java | 33 +++++ .../kotlin/idea/core/KotlinIndicesHelper.kt | 21 ++- .../core/refactoring/JetNameSuggester.java | 7 + .../kotlin/idea/quickfix/AutoImportFix.kt | 4 +- 31 files changed, 408 insertions(+), 81 deletions(-) create mode 100644 idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/ParameterNameAndTypeCompletion.kt delete mode 100644 idea/idea-completion/testData/basic/common/annotations/NoParameterAnnotationAutoPopup1.kt delete mode 100644 idea/idea-completion/testData/basic/common/annotations/NoParameterAnnotationAutoPopup2.kt create mode 100644 idea/idea-completion/testData/basic/common/parameterNameAndType/NoDuplication.kt create mode 100644 idea/idea-completion/testData/basic/common/parameterNameAndType/NoDuplicationJava.kt create mode 100644 idea/idea-completion/testData/basic/common/parameterNameAndType/NotImported.kt create mode 100644 idea/idea-completion/testData/basic/common/parameterNameAndType/NotImportedJava.kt create mode 100644 idea/idea-completion/testData/basic/common/parameterNameAndType/Simple.kt create mode 100644 idea/idea-completion/testData/basic/java/NoSyntheticClasses.kt create mode 100644 idea/idea-completion/testData/handlers/basic/parameterNameAndType/CodeStyleSettings.kt create mode 100644 idea/idea-completion/testData/handlers/basic/parameterNameAndType/CodeStyleSettings.kt.after create mode 100644 idea/idea-completion/testData/handlers/basic/parameterNameAndType/Comma.kt create mode 100644 idea/idea-completion/testData/handlers/basic/parameterNameAndType/Comma.kt.after create mode 100644 idea/idea-completion/testData/handlers/basic/parameterNameAndType/InsertImport.kt create mode 100644 idea/idea-completion/testData/handlers/basic/parameterNameAndType/InsertImport.kt.after create mode 100644 idea/idea-completion/testData/handlers/basic/parameterNameAndType/Simple.kt create mode 100644 idea/idea-completion/testData/handlers/basic/parameterNameAndType/Simple.kt.after diff --git a/core/util.runtime/src/org/jetbrains/kotlin/utils/addToStdlib.kt b/core/util.runtime/src/org/jetbrains/kotlin/utils/addToStdlib.kt index f6a66580a18..a4956fc30ae 100644 --- a/core/util.runtime/src/org/jetbrains/kotlin/utils/addToStdlib.kt +++ b/core/util.runtime/src/org/jetbrains/kotlin/utils/addToStdlib.kt @@ -95,3 +95,13 @@ public fun constant(calculator: () -> T): T { } private val constantMap = ConcurrentHashMap, Any>() + +public fun String.indexOfOrNull(char: Char, startIndex: Int = 0, ignoreCase: Boolean = false): Int? { + val index = indexOf(char, startIndex, ignoreCase) + return if (index >= 0) index else null +} + +public fun String.lastIndexOfOrNull(char: Char, startIndex: Int = 0, ignoreCase: Boolean = false): Int? { + val index = lastIndexOf(char, startIndex, ignoreCase) + return if (index >= 0) index else null +} diff --git a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/AllClassesCompletion.kt b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/AllClassesCompletion.kt index 5695484ee29..e85703308ea 100644 --- a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/AllClassesCompletion.kt +++ b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/AllClassesCompletion.kt @@ -19,8 +19,10 @@ package org.jetbrains.kotlin.idea.completion import com.intellij.codeInsight.completion.AllClassesGetter import com.intellij.codeInsight.completion.CompletionParameters import com.intellij.codeInsight.completion.PrefixMatcher +import com.intellij.psi.PsiClass import com.intellij.psi.search.GlobalSearchScope import org.jetbrains.kotlin.asJava.KotlinLightClass +import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.ClassKind import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.descriptors.ModuleDescriptor @@ -31,34 +33,28 @@ import org.jetbrains.kotlin.platform.JavaToKotlinClassMap import org.jetbrains.kotlin.psi.JetFile import org.jetbrains.kotlin.resolve.BindingContext -class AllClassesCompletion(val parameters: CompletionParameters, - val lookupElementFactory: LookupElementFactory, - val resolutionFacade: ResolutionFacade, - val bindingContext: BindingContext, - val moduleDescriptor: ModuleDescriptor, - val scope: GlobalSearchScope, - val prefixMatcher: PrefixMatcher, - val kindFilter: (ClassKind) -> Boolean, - val visibilityFilter: (DeclarationDescriptor) -> Boolean) { - fun collect(result: LookupElementsCollector) { +class AllClassesCompletion(private val parameters: CompletionParameters, + private val kotlinIndicesHelper: KotlinIndicesHelper, + private val prefixMatcher: PrefixMatcher, + private val kindFilter: (ClassKind) -> Boolean) { + fun collect(classDescriptorCollector: (ClassDescriptor) -> Unit, javaClassCollector: (PsiClass) -> Unit) { //TODO: this is a temporary hack until we have built-ins in indices val builtIns = JavaToKotlinClassMap.INSTANCE.allKotlinClasses() val filteredBuiltIns = builtIns.filter { kindFilter(it.getKind()) && prefixMatcher.prefixMatches(it.getName().asString()) } - result.addDescriptorElements(filteredBuiltIns, suppressAutoInsertion = true) + filteredBuiltIns.forEach { classDescriptorCollector(it) } - val project = parameters.getOriginalFile().getProject() - val helper = KotlinIndicesHelper(project, resolutionFacade, bindingContext, scope, moduleDescriptor, visibilityFilter) - result.addDescriptorElements(helper.getClassDescriptors({ prefixMatcher.prefixMatches(it) }, kindFilter), - suppressAutoInsertion = true) + kotlinIndicesHelper.getClassDescriptors({ prefixMatcher.prefixMatches(it) }, kindFilter).forEach { classDescriptorCollector(it) } if (!ProjectStructureUtil.isJsKotlinModule(parameters.getOriginalFile() as JetFile)) { - addAdaptedJavaCompletion(result) + addAdaptedJavaCompletion(javaClassCollector) } } - private fun addAdaptedJavaCompletion(collector: LookupElementsCollector) { + private fun addAdaptedJavaCompletion(collector: (PsiClass) -> Unit) { AllClassesGetter.processJavaClasses(parameters, prefixMatcher, true, { psiClass -> if (psiClass!! !is KotlinLightClass) { // Kotlin class should have already been added as kotlin element before + if (psiClass.isSyntheticKotlinClass()) return@processJavaClasses // filter out synthetic classes produced by Kotlin compiler + val kind = when { psiClass.isAnnotationType() -> ClassKind.ANNOTATION_CLASS psiClass.isInterface() -> ClassKind.INTERFACE @@ -66,9 +62,14 @@ class AllClassesCompletion(val parameters: CompletionParameters, else -> ClassKind.CLASS } if (kindFilter(kind)) { - collector.addElementWithAutoInsertionSuppressed(lookupElementFactory.createLookupElementForJavaClass(psiClass)) + collector(psiClass) } } }) } + + private fun PsiClass.isSyntheticKotlinClass(): Boolean { + if (!getName().contains('$')) return false // optimization to not analyze annotations of all classes + return getModifierList()?.findAnnotation(javaClass().getName()) != null + } } diff --git a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/CompletionSession.kt b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/CompletionSession.kt index bf305d55203..c8f9564bb21 100644 --- a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/CompletionSession.kt +++ b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/CompletionSession.kt @@ -128,7 +128,7 @@ abstract class CompletionSessionBase(protected val configuration: CompletionSess protected val prefixMatcher: PrefixMatcher = this.resultSet.getPrefixMatcher() - protected val referenceVariantsHelper: ReferenceVariantsHelper = ReferenceVariantsHelper(bindingContext, moduleDescriptor, project) { isVisibleDescriptor(it) } + protected val referenceVariantsHelper: ReferenceVariantsHelper = ReferenceVariantsHelper(bindingContext, moduleDescriptor, project, { isVisibleDescriptor(it) }) protected val receiversData: ReferenceVariantsHelper.ReceiversData? = reference?.let { referenceVariantsHelper.getReferenceVariantsReceivers(it.expression) } @@ -168,7 +168,7 @@ abstract class CompletionSessionBase(protected val configuration: CompletionSess } protected val indicesHelper: KotlinIndicesHelper - get() = KotlinIndicesHelper(project, resolutionFacade, bindingContext, searchScope, moduleDescriptor) { isVisibleDescriptor(it) } + get() = KotlinIndicesHelper(project, resolutionFacade, searchScope, moduleDescriptor, { isVisibleDescriptor(it) }) protected fun isVisibleDescriptor(descriptor: DeclarationDescriptor): Boolean { if (descriptor is DeclarationDescriptorWithVisibility && inDescriptor != null) { @@ -241,7 +241,7 @@ abstract class CompletionSessionBase(protected val configuration: CompletionSess } protected fun getTopLevelExtensions(): Collection { - val descriptors = indicesHelper.getCallableTopLevelExtensions({ prefixMatcher.prefixMatches(it) }, reference!!.expression) + val descriptors = indicesHelper.getCallableTopLevelExtensions({ prefixMatcher.prefixMatches(it) }, reference!!.expression, bindingContext) return filterShadowedNonImported(descriptors, reference) } @@ -250,10 +250,11 @@ abstract class CompletionSessionBase(protected val configuration: CompletionSess } protected fun addAllClasses(kindFilter: (ClassKind) -> Boolean) { - AllClassesCompletion( - parameters, lookupElementFactory, resolutionFacade, bindingContext, moduleDescriptor, - searchScope, prefixMatcher, kindFilter, { isVisibleDescriptor(it) } - ).collect(collector) + AllClassesCompletion(parameters, indicesHelper, prefixMatcher, kindFilter) + .collect( + { descriptor -> collector.addDescriptorElements(descriptor, suppressAutoInsertion = true) }, + { javaClass -> collector.addElementWithAutoInsertionSuppressed(lookupElementFactory.createLookupElementForJavaClass(javaClass)) } + ) } } @@ -287,6 +288,11 @@ class BasicCompletionSession(configuration: CompletionSessionConfiguration, null } + private val parameterNameAndTypeCompletion = if (completionKind == CompletionKind.ANNOTATION_TYPES_OR_PARAMETER_NAME) + ParameterNameAndTypeCompletion(collector, lookupElementFactory, prefixMatcher) + else + null + private fun calcCompletionKind(): CompletionKind { if (NamedArgumentCompletion.isOnlyNamedArgumentExpected(position)) { return CompletionKind.NAMED_ARGUMENTS_ONLY @@ -327,6 +333,8 @@ class BasicCompletionSession(configuration: CompletionSessionConfiguration, if (completionKind != CompletionKind.NAMED_ARGUMENTS_ONLY) { collector.addDescriptorElements(referenceVariants, suppressAutoInsertion = false) + parameterNameAndTypeCompletion?.addFromImports(reference!!.expression, 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 -> val keyword = lookupElement.getLookupString() @@ -405,6 +413,8 @@ class BasicCompletionSession(configuration: CompletionSessionConfiguration, collector.addDescriptorElements(getTopLevelCallables(), suppressAutoInsertion = true) } } + + parameterNameAndTypeCompletion?.addAll(parameters, indicesHelper) } } diff --git a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/KotlinCompletionContributor.kt b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/KotlinCompletionContributor.kt index 110e1b57854..deef7e1f7c9 100644 --- a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/KotlinCompletionContributor.kt +++ b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/KotlinCompletionContributor.kt @@ -225,11 +225,6 @@ public class KotlinCompletionContributor : CompletionContributor() { if (parameters.getCompletionType() == CompletionType.BASIC) { val session = BasicCompletionSession(configuration, parameters, result) - if (session.completionKind == BasicCompletionSession.CompletionKind.ANNOTATION_TYPES_OR_PARAMETER_NAME && parameters.isAutoPopup()) { - result.stopHere() - return - } - val somethingAdded = session.complete() if (!somethingAdded && parameters.getInvocationCount() < 2) { // Rerun completion if nothing was found diff --git a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/LookupElementsCollector.kt b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/LookupElementsCollector.kt index 3a49024f089..1ed9f088b3f 100644 --- a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/LookupElementsCollector.kt +++ b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/LookupElementsCollector.kt @@ -69,7 +69,7 @@ class LookupElementsCollector( } } - private fun addDescriptorElements(descriptor: DeclarationDescriptor, suppressAutoInsertion: Boolean, withReceiverCast: Boolean) { + public fun addDescriptorElements(descriptor: DeclarationDescriptor, suppressAutoInsertion: Boolean, withReceiverCast: Boolean = false) { run { var lookupElement = lookupElementFactory.createLookupElement(descriptor, true) diff --git a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/ParameterNameAndTypeCompletion.kt b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/ParameterNameAndTypeCompletion.kt new file mode 100644 index 00000000000..269ebb6bc9e --- /dev/null +++ b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/ParameterNameAndTypeCompletion.kt @@ -0,0 +1,127 @@ +/* + * Copyright 2010-2015 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.idea.completion + +import com.intellij.codeInsight.completion.CompletionParameters +import com.intellij.codeInsight.completion.InsertionContext +import com.intellij.codeInsight.completion.PrefixMatcher +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.codeStyle.CodeStyleSettingsManager +import org.jetbrains.kotlin.descriptors.ClassifierDescriptor +import org.jetbrains.kotlin.descriptors.DeclarationDescriptor +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.resolve.BindingContext +import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter +import org.jetbrains.kotlin.resolve.scopes.getDescriptorsFiltered + +class ParameterNameAndTypeCompletion( + private val collector: LookupElementsCollector, + private val lookupElementFactory: LookupElementFactory, + private val prefixMatcher: PrefixMatcher +) { + private val modifiedPrefixMatcher = prefixMatcher.cloneWithPrefix(prefixMatcher.getPrefix().capitalize()) + + public fun addFromImports(nameExpression: JetSimpleNameExpression, bindingContext: BindingContext, visibilityFilter: (DeclarationDescriptor) -> Boolean) { + if (prefixMatcher.getPrefix().isEmpty()) return + + val resolutionScope = bindingContext[BindingContext.RESOLUTION_SCOPE, nameExpression] ?: return + val classifiers = resolutionScope.getDescriptorsFiltered(DescriptorKindFilter.NON_SINGLETON_CLASSIFIERS, modifiedPrefixMatcher.asNameFilter()) + + for (classifier in classifiers) { + if (visibilityFilter(classifier)) { + addSuggestionsForClassifier(classifier) + } + } + } + + public fun addAll(parameters: CompletionParameters, indicesHelper: KotlinIndicesHelper) { + if (prefixMatcher.getPrefix().isEmpty()) return + + AllClassesCompletion(parameters, indicesHelper, modifiedPrefixMatcher, { !it.isSingleton() }) + .collect({ addSuggestionsForClassifier(it) }, { addSuggestionsForJavaClass(it) }) + } + + private fun addSuggestionsForClassifier(classifier: DeclarationDescriptor) { + addSuggestions(classifier.getName().asString()) { name -> NameAndDescriptorType(name, classifier as ClassifierDescriptor) } + } + + private fun addSuggestionsForJavaClass(psiClass: PsiClass) { + addSuggestions(psiClass.getName()) { name -> NameAndJavaType(name, psiClass) } + } + + private inline fun addSuggestions(className: String, nameAndTypeFactory: (String) -> NameAndType) { + val parameterNames = JetNameSuggester.getCamelNames(className, EmptyValidator) + for (parameterName in parameterNames) { + if (prefixMatcher.prefixMatches(parameterName)) { + val nameAndType = nameAndTypeFactory(parameterName) + collector.addElement(MyLookupElement(nameAndType, lookupElementFactory)) + } + } + } + + private interface NameAndType { + val parameterName: String + + fun createTypeLookupElement(lookupElementFactory: LookupElementFactory): LookupElement + } + + private data class NameAndDescriptorType(override val parameterName: String, val type: ClassifierDescriptor) : NameAndType { + override fun createTypeLookupElement(lookupElementFactory: LookupElementFactory) + = lookupElementFactory.createLookupElement(type, false) + } + + private data class NameAndJavaType(override val parameterName: String, val type: PsiClass) : NameAndType { + override fun createTypeLookupElement(lookupElementFactory: LookupElementFactory) + = lookupElementFactory.createLookupElementForJavaClass(type) + } + + private class MyLookupElement( + val nameAndType: NameAndType, + factory: LookupElementFactory + ) : LookupElementDecorator(nameAndType.createTypeLookupElement(factory)) { + override fun getObject() = nameAndType + + override fun equals(other: Any?) + = other is MyLookupElement && nameAndType.parameterName == other.getObject().parameterName && getDelegate() == other.getDelegate() + override fun hashCode() = nameAndType.parameterName.hashCode() + + override fun getLookupString() = nameAndType.parameterName + override fun getAllLookupStrings() = setOf(nameAndType.parameterName) + + override fun renderElement(presentation: LookupElementPresentation) { + super.renderElement(presentation) + presentation.setItemText(nameAndType.parameterName + ": " + presentation.getItemText()) + } + + override fun handleInsert(context: InsertionContext) { + super.handleInsert(context) + + val settings = CodeStyleSettingsManager.getInstance(context.getProject()).getCurrentSettings().getCustomSettings(javaClass()) + val spaceBefore = if (settings.SPACE_BEFORE_TYPE_COLON) " " else "" + val spaceAfter = if (settings.SPACE_AFTER_TYPE_COLON) " " else "" + val text = nameAndType.parameterName + spaceBefore + ":" + spaceAfter + context.getDocument().insertString(context.getStartOffset(), text) + } + } +} \ No newline at end of file diff --git a/idea/idea-completion/testData/basic/common/annotations/NoParameterAnnotationAutoPopup1.kt b/idea/idea-completion/testData/basic/common/annotations/NoParameterAnnotationAutoPopup1.kt deleted file mode 100644 index 30d1f85466c..00000000000 --- a/idea/idea-completion/testData/basic/common/annotations/NoParameterAnnotationAutoPopup1.kt +++ /dev/null @@ -1,4 +0,0 @@ -fun foo(i) { } - -// INVOCATION_COUNT: 0 -// NUMBER: 0 diff --git a/idea/idea-completion/testData/basic/common/annotations/NoParameterAnnotationAutoPopup2.kt b/idea/idea-completion/testData/basic/common/annotations/NoParameterAnnotationAutoPopup2.kt deleted file mode 100644 index 7453355e09a..00000000000 --- a/idea/idea-completion/testData/basic/common/annotations/NoParameterAnnotationAutoPopup2.kt +++ /dev/null @@ -1,4 +0,0 @@ -fun foo(@inlineOptions i) { } - -// INVOCATION_COUNT: 0 -// NUMBER: 0 diff --git a/idea/idea-completion/testData/basic/common/parameterNameAndType/NoDuplication.kt b/idea/idea-completion/testData/basic/common/parameterNameAndType/NoDuplication.kt new file mode 100644 index 00000000000..3162454ff16 --- /dev/null +++ b/idea/idea-completion/testData/basic/common/parameterNameAndType/NoDuplication.kt @@ -0,0 +1,6 @@ +import kotlin.properties.* + +fun f(readOnlyProp) + +// EXIST: { lookupString: "readOnlyProperty", itemText: "readOnlyProperty: ReadOnlyProperty", tailText: " (kotlin.properties)" } +// NUMBER: 1 diff --git a/idea/idea-completion/testData/basic/common/parameterNameAndType/NoDuplicationJava.kt b/idea/idea-completion/testData/basic/common/parameterNameAndType/NoDuplicationJava.kt new file mode 100644 index 00000000000..5f6b9fe24f1 --- /dev/null +++ b/idea/idea-completion/testData/basic/common/parameterNameAndType/NoDuplicationJava.kt @@ -0,0 +1,6 @@ +import java.io.* + +fun f(printSt) + +// EXIST_JAVA_ONLY: { lookupString: "printStream", itemText: "printStream: PrintStream", tailText: " (java.io)" } +// NUMBER_JAVA: 1 diff --git a/idea/idea-completion/testData/basic/common/parameterNameAndType/NotImported.kt b/idea/idea-completion/testData/basic/common/parameterNameAndType/NotImported.kt new file mode 100644 index 00000000000..181fb9881d1 --- /dev/null +++ b/idea/idea-completion/testData/basic/common/parameterNameAndType/NotImported.kt @@ -0,0 +1,3 @@ +fun f(read) + +// EXIST: { lookupString: "readOnlyProperty", itemText: "readOnlyProperty: ReadOnlyProperty", tailText: " (kotlin.properties)" } diff --git a/idea/idea-completion/testData/basic/common/parameterNameAndType/NotImportedJava.kt b/idea/idea-completion/testData/basic/common/parameterNameAndType/NotImportedJava.kt new file mode 100644 index 00000000000..3f30d7f8940 --- /dev/null +++ b/idea/idea-completion/testData/basic/common/parameterNameAndType/NotImportedJava.kt @@ -0,0 +1,3 @@ +fun f(file) + +// EXIST_JAVA_ONLY: { lookupString: "file", itemText: "file: File", tailText: " (java.io)" } diff --git a/idea/idea-completion/testData/basic/common/parameterNameAndType/Simple.kt b/idea/idea-completion/testData/basic/common/parameterNameAndType/Simple.kt new file mode 100644 index 00000000000..ee9e2ceaf5f --- /dev/null +++ b/idea/idea-completion/testData/basic/common/parameterNameAndType/Simple.kt @@ -0,0 +1,11 @@ +package pack + +class FooBar + +class Boo + +fun f(b) + +// EXIST: { lookupString: "bar", itemText: "bar: FooBar", tailText: " (pack)" } +// EXIST: { lookupString: "fooBar", itemText: "fooBar: FooBar", tailText: " (pack)" } +// EXIST: { lookupString: "boo", itemText: "boo: Boo", tailText: " (pack)" } diff --git a/idea/idea-completion/testData/basic/java/NoSyntheticClasses.kt b/idea/idea-completion/testData/basic/java/NoSyntheticClasses.kt new file mode 100644 index 00000000000..2db57b52784 --- /dev/null +++ b/idea/idea-completion/testData/basic/java/NoSyntheticClasses.kt @@ -0,0 +1,8 @@ +import kotlin.properties.* + +val x: ReadOnlyPr + +// INVOCATION_COUNT: 2 +// EXIST: "ReadOnlyProperty" +// ABSENT: "ReadOnlyProperty$$TImpl" +// NOTHING_ELSE diff --git a/idea/idea-completion/testData/handlers/basic/highOrderFunctions/FunctionLiteralInsertWhenNoSpacesForBraces.kt b/idea/idea-completion/testData/handlers/basic/highOrderFunctions/FunctionLiteralInsertWhenNoSpacesForBraces.kt index 701f67f739a..7b6ee42f6f4 100644 --- a/idea/idea-completion/testData/handlers/basic/highOrderFunctions/FunctionLiteralInsertWhenNoSpacesForBraces.kt +++ b/idea/idea-completion/testData/handlers/basic/highOrderFunctions/FunctionLiteralInsertWhenNoSpacesForBraces.kt @@ -1,4 +1,4 @@ -// INSERT_WHITESPACES_IN_SIMPLE_ONE_LINE_METHOD: false +// CODE_STYLE_SETTING: INSERT_WHITESPACES_IN_SIMPLE_ONE_LINE_METHOD = false fun main(args: Array) { args.fil diff --git a/idea/idea-completion/testData/handlers/basic/highOrderFunctions/FunctionLiteralInsertWhenNoSpacesForBraces.kt.after b/idea/idea-completion/testData/handlers/basic/highOrderFunctions/FunctionLiteralInsertWhenNoSpacesForBraces.kt.after index 660ad3bff57..c2441ce4a61 100644 --- a/idea/idea-completion/testData/handlers/basic/highOrderFunctions/FunctionLiteralInsertWhenNoSpacesForBraces.kt.after +++ b/idea/idea-completion/testData/handlers/basic/highOrderFunctions/FunctionLiteralInsertWhenNoSpacesForBraces.kt.after @@ -1,4 +1,4 @@ -// INSERT_WHITESPACES_IN_SIMPLE_ONE_LINE_METHOD: false +// CODE_STYLE_SETTING: INSERT_WHITESPACES_IN_SIMPLE_ONE_LINE_METHOD = false fun main(args: Array) { args.filter {} diff --git a/idea/idea-completion/testData/handlers/basic/parameterNameAndType/CodeStyleSettings.kt b/idea/idea-completion/testData/handlers/basic/parameterNameAndType/CodeStyleSettings.kt new file mode 100644 index 00000000000..0220ca6e717 --- /dev/null +++ b/idea/idea-completion/testData/handlers/basic/parameterNameAndType/CodeStyleSettings.kt @@ -0,0 +1,8 @@ +// CODE_STYLE_SETTING: SPACE_BEFORE_TYPE_COLON = true +// CODE_STYLE_SETTING: SPACE_AFTER_TYPE_COLON = false + +class FooBar + +fun f(b) + +// ELEMENT: bar diff --git a/idea/idea-completion/testData/handlers/basic/parameterNameAndType/CodeStyleSettings.kt.after b/idea/idea-completion/testData/handlers/basic/parameterNameAndType/CodeStyleSettings.kt.after new file mode 100644 index 00000000000..4a35270257d --- /dev/null +++ b/idea/idea-completion/testData/handlers/basic/parameterNameAndType/CodeStyleSettings.kt.after @@ -0,0 +1,8 @@ +// CODE_STYLE_SETTING: SPACE_BEFORE_TYPE_COLON = true +// CODE_STYLE_SETTING: SPACE_AFTER_TYPE_COLON = false + +class FooBar + +fun f(bar :FooBar) + +// ELEMENT: bar diff --git a/idea/idea-completion/testData/handlers/basic/parameterNameAndType/Comma.kt b/idea/idea-completion/testData/handlers/basic/parameterNameAndType/Comma.kt new file mode 100644 index 00000000000..21825a18939 --- /dev/null +++ b/idea/idea-completion/testData/handlers/basic/parameterNameAndType/Comma.kt @@ -0,0 +1,6 @@ +class FooBar + +fun f(b) + +// ELEMENT: bar +// CHAR: ',' diff --git a/idea/idea-completion/testData/handlers/basic/parameterNameAndType/Comma.kt.after b/idea/idea-completion/testData/handlers/basic/parameterNameAndType/Comma.kt.after new file mode 100644 index 00000000000..e2fc7d0a67e --- /dev/null +++ b/idea/idea-completion/testData/handlers/basic/parameterNameAndType/Comma.kt.after @@ -0,0 +1,6 @@ +class FooBar + +fun f(bar: FooBar, ) + +// ELEMENT: bar +// CHAR: ',' diff --git a/idea/idea-completion/testData/handlers/basic/parameterNameAndType/InsertImport.kt b/idea/idea-completion/testData/handlers/basic/parameterNameAndType/InsertImport.kt new file mode 100644 index 00000000000..c44f6430b18 --- /dev/null +++ b/idea/idea-completion/testData/handlers/basic/parameterNameAndType/InsertImport.kt @@ -0,0 +1,3 @@ +fun f(file) + +// ELEMENT_TEXT: "file: File" diff --git a/idea/idea-completion/testData/handlers/basic/parameterNameAndType/InsertImport.kt.after b/idea/idea-completion/testData/handlers/basic/parameterNameAndType/InsertImport.kt.after new file mode 100644 index 00000000000..cf38dafd037 --- /dev/null +++ b/idea/idea-completion/testData/handlers/basic/parameterNameAndType/InsertImport.kt.after @@ -0,0 +1,5 @@ +import java.io.File + +fun f(file: File) + +// ELEMENT_TEXT: "file: File" diff --git a/idea/idea-completion/testData/handlers/basic/parameterNameAndType/Simple.kt b/idea/idea-completion/testData/handlers/basic/parameterNameAndType/Simple.kt new file mode 100644 index 00000000000..77b3bbb4082 --- /dev/null +++ b/idea/idea-completion/testData/handlers/basic/parameterNameAndType/Simple.kt @@ -0,0 +1,5 @@ +class FooBar + +fun f(b) + +// ELEMENT: bar diff --git a/idea/idea-completion/testData/handlers/basic/parameterNameAndType/Simple.kt.after b/idea/idea-completion/testData/handlers/basic/parameterNameAndType/Simple.kt.after new file mode 100644 index 00000000000..5f3ad6bd6c5 --- /dev/null +++ b/idea/idea-completion/testData/handlers/basic/parameterNameAndType/Simple.kt.after @@ -0,0 +1,5 @@ +class FooBar + +fun f(bar: FooBar) + +// ELEMENT: bar diff --git a/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/JSBasicCompletionTestGenerated.java b/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/JSBasicCompletionTestGenerated.java index 479349908c5..7337e37100d 100644 --- a/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/JSBasicCompletionTestGenerated.java +++ b/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/JSBasicCompletionTestGenerated.java @@ -1053,18 +1053,6 @@ public class JSBasicCompletionTestGenerated extends AbstractJSBasicCompletionTes doTest(fileName); } - @TestMetadata("NoParameterAnnotationAutoPopup1.kt") - public void testNoParameterAnnotationAutoPopup1() throws Exception { - String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/annotations/NoParameterAnnotationAutoPopup1.kt"); - doTest(fileName); - } - - @TestMetadata("NoParameterAnnotationAutoPopup2.kt") - public void testNoParameterAnnotationAutoPopup2() throws Exception { - String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/annotations/NoParameterAnnotationAutoPopup2.kt"); - doTest(fileName); - } - @TestMetadata("ParameterAnnotation1.kt") public void testParameterAnnotation1() throws Exception { String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/annotations/ParameterAnnotation1.kt"); @@ -1402,6 +1390,45 @@ public class JSBasicCompletionTestGenerated extends AbstractJSBasicCompletionTes } } + @TestMetadata("idea/idea-completion/testData/basic/common/parameterNameAndType") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class ParameterNameAndType extends AbstractJSBasicCompletionTest { + public void testAllFilesPresentInParameterNameAndType() throws Exception { + JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/idea-completion/testData/basic/common/parameterNameAndType"), Pattern.compile("^(.+)\\.kt$"), true); + } + + @TestMetadata("NoDuplication.kt") + public void testNoDuplication() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/parameterNameAndType/NoDuplication.kt"); + doTest(fileName); + } + + @TestMetadata("NoDuplicationJava.kt") + public void testNoDuplicationJava() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/parameterNameAndType/NoDuplicationJava.kt"); + doTest(fileName); + } + + @TestMetadata("NotImported.kt") + public void testNotImported() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/parameterNameAndType/NotImported.kt"); + doTest(fileName); + } + + @TestMetadata("NotImportedJava.kt") + public void testNotImportedJava() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/parameterNameAndType/NotImportedJava.kt"); + doTest(fileName); + } + + @TestMetadata("Simple.kt") + public void testSimple() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/parameterNameAndType/Simple.kt"); + doTest(fileName); + } + } + @TestMetadata("idea/idea-completion/testData/basic/common/shadowing") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) diff --git a/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/JvmBasicCompletionTestGenerated.java b/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/JvmBasicCompletionTestGenerated.java index 3b103f0f601..33b3cd9b387 100644 --- a/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/JvmBasicCompletionTestGenerated.java +++ b/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/JvmBasicCompletionTestGenerated.java @@ -1053,18 +1053,6 @@ public class JvmBasicCompletionTestGenerated extends AbstractJvmBasicCompletionT doTest(fileName); } - @TestMetadata("NoParameterAnnotationAutoPopup1.kt") - public void testNoParameterAnnotationAutoPopup1() throws Exception { - String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/annotations/NoParameterAnnotationAutoPopup1.kt"); - doTest(fileName); - } - - @TestMetadata("NoParameterAnnotationAutoPopup2.kt") - public void testNoParameterAnnotationAutoPopup2() throws Exception { - String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/annotations/NoParameterAnnotationAutoPopup2.kt"); - doTest(fileName); - } - @TestMetadata("ParameterAnnotation1.kt") public void testParameterAnnotation1() throws Exception { String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/annotations/ParameterAnnotation1.kt"); @@ -1402,6 +1390,45 @@ public class JvmBasicCompletionTestGenerated extends AbstractJvmBasicCompletionT } } + @TestMetadata("idea/idea-completion/testData/basic/common/parameterNameAndType") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class ParameterNameAndType extends AbstractJvmBasicCompletionTest { + public void testAllFilesPresentInParameterNameAndType() throws Exception { + JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/idea-completion/testData/basic/common/parameterNameAndType"), Pattern.compile("^(.+)\\.kt$"), true); + } + + @TestMetadata("NoDuplication.kt") + public void testNoDuplication() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/parameterNameAndType/NoDuplication.kt"); + doTest(fileName); + } + + @TestMetadata("NoDuplicationJava.kt") + public void testNoDuplicationJava() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/parameterNameAndType/NoDuplicationJava.kt"); + doTest(fileName); + } + + @TestMetadata("NotImported.kt") + public void testNotImported() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/parameterNameAndType/NotImported.kt"); + doTest(fileName); + } + + @TestMetadata("NotImportedJava.kt") + public void testNotImportedJava() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/parameterNameAndType/NotImportedJava.kt"); + doTest(fileName); + } + + @TestMetadata("Simple.kt") + public void testSimple() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/parameterNameAndType/Simple.kt"); + doTest(fileName); + } + } + @TestMetadata("idea/idea-completion/testData/basic/common/shadowing") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) @@ -1696,6 +1723,12 @@ public class JvmBasicCompletionTestGenerated extends AbstractJvmBasicCompletionT doTest(fileName); } + @TestMetadata("NoSyntheticClasses.kt") + public void testNoSyntheticClasses() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/java/NoSyntheticClasses.kt"); + doTest(fileName); + } + @TestMetadata("PackageDirective.kt") public void testPackageDirective() throws Exception { String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/java/PackageDirective.kt"); diff --git a/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/handlers/AbstractCompletionHandlerTests.kt b/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/handlers/AbstractCompletionHandlerTests.kt index 9f6265c08b0..56531b30b42 100644 --- a/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/handlers/AbstractCompletionHandlerTests.kt +++ b/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/handlers/AbstractCompletionHandlerTests.kt @@ -22,6 +22,7 @@ import com.intellij.psi.codeStyle.CodeStyleSettingsManager import org.jetbrains.kotlin.idea.core.formatter.JetCodeStyleSettings import org.jetbrains.kotlin.idea.test.JetWithJdkAndRuntimeLightProjectDescriptor import org.jetbrains.kotlin.test.InTextDirectivesUtils +import org.jetbrains.kotlin.utils.addToStdlib.indexOfOrNull import java.io.File public abstract class AbstractCompletionHandlerTest(private val defaultCompletionType: CompletionType) : CompletionHandlerTestBase() { @@ -31,7 +32,7 @@ public abstract class AbstractCompletionHandlerTest(private val defaultCompletio private val TAIL_TEXT_PREFIX = "TAIL_TEXT:" private val COMPLETION_CHAR_PREFIX = "CHAR:" private val COMPLETION_TYPE_PREFIX = "COMPLETION_TYPE:" - private val INSERT_WHITESPACES_IN_SIMPLE_ONE_LINE_METHOD = "INSERT_WHITESPACES_IN_SIMPLE_ONE_LINE_METHOD:" + private val CODE_STYLE_SETTING_PREFIX = "CODE_STYLE_SETTING:" protected open fun doTest(testPath: String) { setUpFixture(testPath) @@ -61,8 +62,17 @@ public abstract class AbstractCompletionHandlerTest(private val defaultCompletio else -> error("Unknown completion type: $completionTypeString") } - InTextDirectivesUtils.getPrefixedBoolean(fileText, INSERT_WHITESPACES_IN_SIMPLE_ONE_LINE_METHOD)?.let { - JetCodeStyleSettings.getInstance(getProject()).INSERT_WHITESPACES_IN_SIMPLE_ONE_LINE_METHOD = it + val codeStyleSettings = JetCodeStyleSettings.getInstance(getProject()) + for (line in InTextDirectivesUtils.findLinesWithPrefixesRemoved(fileText, CODE_STYLE_SETTING_PREFIX)) { + val index = line.indexOfOrNull('=') ?: error("Invalid code style setting '$line': '=' expected") + val settingName = line.substring(0, index).trim() + val settingValue = line.substring(index + 1).trim() + val field = codeStyleSettings.javaClass.getDeclaredField(settingName) + when (field.getType().getName()) { + "boolean" -> field.setBoolean(codeStyleSettings, settingValue.toBoolean()) + "int" -> field.setInt(codeStyleSettings, settingValue.toInt()) + else -> error("Unsupported setting type: ${field.getType()}") + } } doTestWithTextLoaded(completionType, invocationCount, lookupString, itemText, tailText, completionChar, testPath + ".after") diff --git a/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/handlers/BasicCompletionHandlerTestGenerated.java b/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/handlers/BasicCompletionHandlerTestGenerated.java index 9fdb38f9459..5740ee686ab 100644 --- a/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/handlers/BasicCompletionHandlerTestGenerated.java +++ b/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/handlers/BasicCompletionHandlerTestGenerated.java @@ -239,6 +239,39 @@ public class BasicCompletionHandlerTestGenerated extends AbstractBasicCompletion } } + @TestMetadata("idea/idea-completion/testData/handlers/basic/parameterNameAndType") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class ParameterNameAndType extends AbstractBasicCompletionHandlerTest { + public void testAllFilesPresentInParameterNameAndType() throws Exception { + JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/idea-completion/testData/handlers/basic/parameterNameAndType"), Pattern.compile("^(.+)\\.kt$"), true); + } + + @TestMetadata("CodeStyleSettings.kt") + public void testCodeStyleSettings() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/handlers/basic/parameterNameAndType/CodeStyleSettings.kt"); + doTest(fileName); + } + + @TestMetadata("Comma.kt") + public void testComma() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/handlers/basic/parameterNameAndType/Comma.kt"); + doTest(fileName); + } + + @TestMetadata("InsertImport.kt") + public void testInsertImport() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/handlers/basic/parameterNameAndType/InsertImport.kt"); + doTest(fileName); + } + + @TestMetadata("Simple.kt") + public void testSimple() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/handlers/basic/parameterNameAndType/Simple.kt"); + doTest(fileName); + } + } + @TestMetadata("idea/idea-completion/testData/handlers/basic/stringTemplate") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) diff --git a/idea/idea-core/src/org/jetbrains/kotlin/idea/core/KotlinIndicesHelper.kt b/idea/idea-core/src/org/jetbrains/kotlin/idea/core/KotlinIndicesHelper.kt index 52f238ca2ef..f66331389cd 100644 --- a/idea/idea-core/src/org/jetbrains/kotlin/idea/core/KotlinIndicesHelper.kt +++ b/idea/idea-core/src/org/jetbrains/kotlin/idea/core/KotlinIndicesHelper.kt @@ -46,7 +46,6 @@ import java.util.LinkedHashSet public class KotlinIndicesHelper( private val project: Project, private val resolutionFacade: ResolutionFacade, - private val bindingContext: BindingContext, private val scope: GlobalSearchScope, private val moduleDescriptor: ModuleDescriptor, private val visibilityFilter: (DeclarationDescriptor) -> Boolean @@ -73,36 +72,36 @@ public class KotlinIndicesHelper( } public fun getTopLevelCallables(nameFilter: (String) -> Boolean): Collection { - return (JetTopLevelFunctionFqnNameIndex.getInstance().getAllKeys(project).sequence() + - JetTopLevelPropertyFqnNameIndex.getInstance().getAllKeys(project).sequence()) + return (JetTopLevelFunctionFqnNameIndex.getInstance().getAllKeys(project).asSequence() + + JetTopLevelPropertyFqnNameIndex.getInstance().getAllKeys(project).asSequence()) .map { FqName(it) } .filter { nameFilter(it.shortName().asString()) } .toSet() .flatMap { findTopLevelCallables(it).filter(visibilityFilter) } } - public fun getCallableTopLevelExtensions(nameFilter: (String) -> Boolean, expression: JetSimpleNameExpression): Collection { - val receiverValues = receiverValues(expression) + public fun getCallableTopLevelExtensions(nameFilter: (String) -> Boolean, expression: JetSimpleNameExpression, bindingContext: BindingContext): Collection { + val receiverValues = receiverValues(expression, bindingContext) if (receiverValues.isEmpty()) return emptyList() val dataFlowInfo = bindingContext.getDataFlowInfo(expression) - val receiverTypeNames = possibleReceiverTypeNames(receiverValues.map { it.first }, dataFlowInfo) + val receiverTypeNames = possibleReceiverTypeNames(receiverValues.map { it.first }, dataFlowInfo, bindingContext) val index = JetTopLevelExtensionsByReceiverTypeIndex.INSTANCE val declarations = index.getAllKeys(project) - .sequence() + .asSequence() .filter { JetTopLevelExtensionsByReceiverTypeIndex.receiverTypeNameFromKey(it) in receiverTypeNames && nameFilter(JetTopLevelExtensionsByReceiverTypeIndex.callableNameFromKey(it)) } - .flatMap { index.get(it, project, scope).sequence() } + .flatMap { index.get(it, project, scope).asSequence() } return findSuitableExtensions(declarations, receiverValues, dataFlowInfo, bindingContext) } - private fun possibleReceiverTypeNames(receiverValues: Collection, dataFlowInfo: DataFlowInfo): Set { + private fun possibleReceiverTypeNames(receiverValues: Collection, dataFlowInfo: DataFlowInfo, bindingContext: BindingContext): Set { val result = HashSet() for (receiverValue in receiverValues) { for (type in SmartCastUtils.getSmartCastVariants(receiverValue, bindingContext, moduleDescriptor, dataFlowInfo)) { @@ -118,7 +117,7 @@ public class KotlinIndicesHelper( constructor.getSupertypes().forEach { addTypeNames(it) } } - private fun receiverValues(expression: JetSimpleNameExpression): Collection> { + private fun receiverValues(expression: JetSimpleNameExpression, bindingContext: BindingContext): Collection> { val receiverPair = ReferenceVariantsHelper.getExplicitReceiverData(expression) if (receiverPair != null) { val (receiverExpression, callType) = receiverPair @@ -173,7 +172,7 @@ public class KotlinIndicesHelper( } public fun getClassDescriptors(nameFilter: (String) -> Boolean, kindFilter: (ClassKind) -> Boolean): Collection { - return JetFullClassNameIndex.getInstance().getAllKeys(project).sequence() + return JetFullClassNameIndex.getInstance().getAllKeys(project).asSequence() .map { FqName(it) } .filter { nameFilter(it.shortName().asString()) } .toList() diff --git a/idea/idea-core/src/org/jetbrains/kotlin/idea/core/refactoring/JetNameSuggester.java b/idea/idea-core/src/org/jetbrains/kotlin/idea/core/refactoring/JetNameSuggester.java index cbdc3957abc..66acdc5e5ec 100644 --- a/idea/idea-core/src/org/jetbrains/kotlin/idea/core/refactoring/JetNameSuggester.java +++ b/idea/idea-core/src/org/jetbrains/kotlin/idea/core/refactoring/JetNameSuggester.java @@ -37,6 +37,7 @@ import org.jetbrains.kotlin.types.TypeUtils; import org.jetbrains.kotlin.types.checker.JetTypeChecker; import java.util.ArrayList; +import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -198,6 +199,12 @@ public class JetNameSuggester { private static final String[] ACCESSOR_PREFIXES = { "get", "is", "set" }; + public static List getCamelNames(String name, JetNameValidator validator) { + ArrayList result = new ArrayList(); + addCamelNames(result, name, validator); + return result; + } + private static void addCamelNames(ArrayList result, String name, JetNameValidator validator) { if (name == "") return; String s = deleteNonLetterFromString(name); diff --git a/idea/src/org/jetbrains/kotlin/idea/quickfix/AutoImportFix.kt b/idea/src/org/jetbrains/kotlin/idea/quickfix/AutoImportFix.kt index c528b5863ca..d9ae0e1215a 100644 --- a/idea/src/org/jetbrains/kotlin/idea/quickfix/AutoImportFix.kt +++ b/idea/src/org/jetbrains/kotlin/idea/quickfix/AutoImportFix.kt @@ -138,7 +138,7 @@ public class AutoImportFix(element: JetSimpleNameExpression) : JetHintAction() val moduleDescriptor = resolutionFacade.findModuleDescriptor(element) - val indicesHelper = KotlinIndicesHelper(file.getProject(), resolutionFacade, bindingContext, searchScope, moduleDescriptor, ::isVisible) + val indicesHelper = KotlinIndicesHelper(file.getProject(), resolutionFacade, searchScope, moduleDescriptor, ::isVisible) if (!element.isImportDirectiveExpression() && !JetPsiUtil.isSelectorInQualified(element)) { if (ProjectStructureUtil.isJsKotlinModule(file)) { @@ -150,7 +150,7 @@ public class AutoImportFix(element: JetSimpleNameExpression) : JetHintAction