Fix accessibility check for experimental declarations from default scope

#KT-40919 Fixed
This commit is contained in:
Mikhail Zarechenskiy
2020-08-07 14:04:10 +03:00
parent b403b63f48
commit 0c13a7f89a
12 changed files with 73 additions and 7 deletions
@@ -80,6 +80,7 @@ class KotlinResolutionStatelessCallbacksImpl(
kotlinCallArgument.psiCallArgument.psiExpression,
(resolutionCallbacks as? KotlinResolutionCallbacksImpl)?.trace?.bindingContext,
isSuperCall = false,
fromImportingScope = false
)
override fun isSuperExpression(receiver: SimpleKotlinCallArgument?): Boolean =
@@ -64,15 +64,17 @@ class DeprecationResolver(
descriptor: DeclarationDescriptor,
call: Call? = null,
bindingContext: BindingContext? = null,
isSuperCall: Boolean = false
isSuperCall: Boolean = false,
fromImportingScope: Boolean = false
): Boolean =
isHiddenInResolution(descriptor, call?.callElement, bindingContext, isSuperCall)
isHiddenInResolution(descriptor, call?.callElement, bindingContext, isSuperCall, fromImportingScope)
fun isHiddenInResolution(
descriptor: DeclarationDescriptor,
callElement: KtElement?,
bindingContext: BindingContext?,
isSuperCall: Boolean
isSuperCall: Boolean,
fromImportingScope: Boolean
): Boolean {
if (descriptor is FunctionDescriptor) {
if (descriptor.isHiddenToOvercomeSignatureClash) return true
@@ -83,14 +85,17 @@ class DeprecationResolver(
if (sinceKotlinAccessibility is SinceKotlinAccessibility.NotAccessible) return true
if (sinceKotlinAccessibility is SinceKotlinAccessibility.NotAccessibleButWasExperimental) {
if (callElement != null && bindingContext != null) {
return with(ExperimentalUsageChecker) {
return if (callElement != null && bindingContext != null) {
with(ExperimentalUsageChecker) {
sinceKotlinAccessibility.markerClasses.any { classDescriptor ->
!callElement.isExperimentalityAccepted(classDescriptor.fqNameSafe, languageVersionSettings, bindingContext)
}
}
} else {
// We need a softer check for descriptors from importing scope as there is no access to PSI elements
// It's fine to return false here as there will be additional checks for accessibility later
!fromImportingScope
}
return true
}
return isDeprecatedHidden(descriptor)
@@ -235,7 +235,8 @@ class LazyImportScope(
private fun LazyImportResolver<*>.isClassifierVisible(descriptor: ClassifierDescriptor): Boolean {
if (filteringKind == FilteringKind.ALL) return true
if (components.deprecationResolver.isHiddenInResolution(descriptor)) return false
// TODO: do not perform this check here because for correct work it requires corresponding PSI element
if (components.deprecationResolver.isHiddenInResolution(descriptor, fromImportingScope = true)) return false
val visibility = (descriptor as DeclarationDescriptorWithVisibility).visibility
val includeVisible = filteringKind == FilteringKind.VISIBLE_CLASSES
@@ -0,0 +1,5 @@
$TESTDATA_DIR$/useDeclarationThatWasExperimentalWithoutExplicitImport.kt
-d
$TEMP_DIR$
-language-version
1.3
@@ -0,0 +1,7 @@
@ExperimentalStdlibApi
fun test(s: ArrayDeque<Int>): ArrayDeque<Int>? {
ArrayDeque<Int>(42)
val x: ArrayDeque<Int>? = null
return x ?: s
}
@@ -0,0 +1,6 @@
$TESTDATA_DIR$/useDeclarationThatWasExperimentalWithoutMarker.kt
-d
$TEMP_DIR$
-language-version
1.3
-Xopt-in=kotlin.ExperimentalStdlibApi
@@ -0,0 +1,5 @@
$TESTDATA_DIR$/useDeclarationThatWasExperimentalWithoutMarker.kt
-d
$TEMP_DIR$
-language-version
1.3
@@ -0,0 +1,6 @@
fun test(s: ArrayDeque<Int>): ArrayDeque<Int>? {
ArrayDeque<Int>(42)
val x: ArrayDeque<Int>? = null
return x ?: s
}
@@ -0,0 +1,13 @@
compiler/testData/cli/jvm/useDeclarationThatWasExperimentalWithoutMarker.kt:1:13: error: this declaration is experimental and its usage must be marked with '@kotlin.ExperimentalStdlibApi' or '@OptIn(kotlin.ExperimentalStdlibApi::class)'
fun test(s: ArrayDeque<Int>): ArrayDeque<Int>? {
^
compiler/testData/cli/jvm/useDeclarationThatWasExperimentalWithoutMarker.kt:1:31: error: this declaration is experimental and its usage must be marked with '@kotlin.ExperimentalStdlibApi' or '@OptIn(kotlin.ExperimentalStdlibApi::class)'
fun test(s: ArrayDeque<Int>): ArrayDeque<Int>? {
^
compiler/testData/cli/jvm/useDeclarationThatWasExperimentalWithoutMarker.kt:2:5: error: unresolved reference: ArrayDeque
ArrayDeque<Int>(42)
^
compiler/testData/cli/jvm/useDeclarationThatWasExperimentalWithoutMarker.kt:4:12: error: this declaration is experimental and its usage must be marked with '@kotlin.ExperimentalStdlibApi' or '@OptIn(kotlin.ExperimentalStdlibApi::class)'
val x: ArrayDeque<Int>? = null
^
COMPILATION_ERROR
@@ -720,6 +720,21 @@ public class CliTestGenerated extends AbstractCliTest {
runTest("compiler/testData/cli/jvm/unknownExtraFlags.args");
}
@TestMetadata("useDeclarationThatWasExperimentalWithoutExplicitImport.args")
public void testUseDeclarationThatWasExperimentalWithoutExplicitImport() throws Exception {
runTest("compiler/testData/cli/jvm/useDeclarationThatWasExperimentalWithoutExplicitImport.args");
}
@TestMetadata("useDeclarationThatWasExperimentalWithoutExplicitImportCommandLine.args")
public void testUseDeclarationThatWasExperimentalWithoutExplicitImportCommandLine() throws Exception {
runTest("compiler/testData/cli/jvm/useDeclarationThatWasExperimentalWithoutExplicitImportCommandLine.args");
}
@TestMetadata("useDeclarationThatWasExperimentalWithoutMarker.args")
public void testUseDeclarationThatWasExperimentalWithoutMarker() throws Exception {
runTest("compiler/testData/cli/jvm/useDeclarationThatWasExperimentalWithoutMarker.args");
}
@TestMetadata("useMixedNamedArgumentsFlag.args")
public void testUseMixedNamedArgumentsFlag() throws Exception {
runTest("compiler/testData/cli/jvm/useMixedNamedArgumentsFlag.args");