Allow to force-require syntetic SAM-adapters even in NI

This is needed for some IDE clients, particularly, completion: even
though presenting only non-converted member (e.g., 'foo(Consumer<Int>')
is nominally OK, as resolution with NI is smart enough to accept 'foo { }'
for such a call, it is inconvenient for users (for example, hitting
enter would insert round brackets instead of a figure brackets)

This commit adds very-very narrow API (borderline hacky) in
JavaSyntheticScopes, to allow clients explicitly ask for a scopes with
force-enabled synthetic conversions. It fixes several tests, which had
started to fail after corresponding commit about NI and SAM-adapters
(fe5976d7f4), e.g.:
- Java8BasicCompletionTestGenerated.testCollectionMethods
- Java8BasicCompletionTestGenerated.testStreamMethods
- JvmBasicCompletionTestGenerated$Common$StaticMembers.testJavaStaticMethods
- JvmBasicCompletionTestGenerated$Java.testSAMAdaptersStatic
- JvmWithLibBasicCompletionTestGenerated.testSamAdapter
- JvmWithLibBasicCompletionTestGenerated.testSamAdapterAndGenerics

Note that changes are made in ReferenceVariantsHelper, which is used by
several other clients in IDE. Presumably, those changes are needed for
them too.
This commit is contained in:
Dmitry Savvinov
2019-05-29 14:32:39 +03:00
parent eda975d317
commit dca23f871c
8 changed files with 146 additions and 36 deletions
@@ -17,6 +17,7 @@
package org.jetbrains.kotlin.synthetic
import com.intellij.openapi.project.Project
import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.extensions.ProjectExtensionDescriptor
@@ -28,34 +29,61 @@ import org.jetbrains.kotlin.resolve.scopes.SyntheticScopes
import org.jetbrains.kotlin.storage.StorageManager
class JavaSyntheticScopes(
private val project: Project,
private val moduleDescriptor: ModuleDescriptor,
storageManager: StorageManager,
lookupTracker: LookupTracker,
languageVersionSettings: LanguageVersionSettings,
samConventionResolver: SamConversionResolver,
deprecationResolver: DeprecationResolver
): SyntheticScopes {
override val scopes = run {
val javaSyntheticPropertiesScope = JavaSyntheticPropertiesScope(storageManager, lookupTracker)
private val project: Project,
private val moduleDescriptor: ModuleDescriptor,
storageManager: StorageManager,
lookupTracker: LookupTracker,
languageVersionSettings: LanguageVersionSettings,
samConventionResolver: SamConversionResolver,
deprecationResolver: DeprecationResolver
) : SyntheticScopes {
override val scopes: Collection<SyntheticScope>
// New Inference disables SAM-adapters scope, because it knows how to perform SAM-conversion in resolution
// However, some outer clients (mostly in IDE) sometimes would like to look at synthetic SAM-produced descriptors
// (e.g., completion)
val scopesWithForceEnabledSamAdapters: Collection<SyntheticScope>
init {
val newInferenceEnabled = languageVersionSettings.supportsFeature(LanguageFeature.NewInference)
val javaSyntheticPropertiesScope = JavaSyntheticPropertiesScope(storageManager, lookupTracker)
val scopesFromExtensions = SyntheticScopeProviderExtension
.getInstances(project)
.flatMap { it.getScopes(moduleDescriptor, javaSyntheticPropertiesScope) }
listOf(
javaSyntheticPropertiesScope,
SamAdapterFunctionsScope(
storageManager, languageVersionSettings, samConventionResolver, deprecationResolver,
lookupTracker
val samAdapterFunctionsScope = SamAdapterFunctionsScope(
storageManager,
samConventionResolver,
deprecationResolver,
lookupTracker,
samViaSyntheticScopeDisabled = newInferenceEnabled
)
scopes = listOf(javaSyntheticPropertiesScope, samAdapterFunctionsScope) + scopesFromExtensions
if (newInferenceEnabled) {
val forceEnabledSamAdapterFunctionsScope = SamAdapterFunctionsScope(
storageManager,
samConventionResolver,
deprecationResolver,
lookupTracker,
samViaSyntheticScopeDisabled = false
)
) + scopesFromExtensions
scopesWithForceEnabledSamAdapters =
listOf(javaSyntheticPropertiesScope, forceEnabledSamAdapterFunctionsScope) + scopesFromExtensions
} else {
scopesWithForceEnabledSamAdapters = scopes
}
}
}
interface SyntheticScopeProviderExtension {
companion object : ProjectExtensionDescriptor<SyntheticScopeProviderExtension>(
"org.jetbrains.kotlin.syntheticScopeProviderExtension", SyntheticScopeProviderExtension::class.java)
"org.jetbrains.kotlin.syntheticScopeProviderExtension", SyntheticScopeProviderExtension::class.java
)
fun getScopes(moduleDescriptor: ModuleDescriptor, javaSyntheticPropertiesScope: JavaSyntheticPropertiesScope): List<SyntheticScope>
}
@@ -55,12 +55,11 @@ val SAM_LOOKUP_NAME = Name.special("<SAM-CONSTRUCTOR>")
class SamAdapterFunctionsScope(
storageManager: StorageManager,
private val languageVersionSettings: LanguageVersionSettings,
private val samResolver: SamConversionResolver,
private val deprecationResolver: DeprecationResolver,
private val lookupTracker: LookupTracker
private val lookupTracker: LookupTracker,
private val samViaSyntheticScopeDisabled: Boolean
) : SyntheticScope.Default() {
private val samViaSyntheticScopeDisabled = languageVersionSettings.supportsFeature(LanguageFeature.NewInference)
private val extensionForFunction =
storageManager.createMemoizedFunctionWithNullableValues<FunctionDescriptor, FunctionDescriptor> { function ->
@@ -17,8 +17,14 @@
package org.jetbrains.kotlin.synthetic
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.synthetic.SyntheticMemberDescriptor
import org.jetbrains.kotlin.load.java.descriptors.JavaCallableMemberDescriptor
import org.jetbrains.kotlin.load.java.descriptors.JavaClassDescriptor
import org.jetbrains.kotlin.load.java.sam.SamAdapterDescriptor
import org.jetbrains.kotlin.load.java.sam.SamConstructorDescriptor
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCallImpl
import org.jetbrains.kotlin.resolve.calls.tower.NewResolvedCallImpl
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
fun FunctionDescriptor.hasJavaOriginInHierarchy(): Boolean {
@@ -55,3 +61,15 @@ fun syntheticVisibility(originalDescriptor: DeclarationDescriptorWithVisibility,
}
}
fun <D : CallableDescriptor> ResolvedCall<D>.isResolvedWithSamConversions(): Boolean {
return if (this is NewResolvedCallImpl<D>) {
// New inference
this.resolvedCallAtom.argumentsWithConversion.isNotEmpty()
} else {
// Old Inference
this.resultingDescriptor is SamAdapterDescriptor<*> ||
this.resultingDescriptor is SamConstructorDescriptor ||
this.resultingDescriptor is SamAdapterExtensionFunctionDescriptor
}
}