Exclude public API symbols in explicit mode from unused symbol inspection
#KT-41659 Fixed
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2000-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -37,6 +37,7 @@ import org.jetbrains.kotlin.asJava.classes.KtLightClass
|
|||||||
import org.jetbrains.kotlin.asJava.toLightClass
|
import org.jetbrains.kotlin.asJava.toLightClass
|
||||||
import org.jetbrains.kotlin.asJava.toLightMethods
|
import org.jetbrains.kotlin.asJava.toLightMethods
|
||||||
import org.jetbrains.kotlin.config.AnalysisFlags
|
import org.jetbrains.kotlin.config.AnalysisFlags
|
||||||
|
import org.jetbrains.kotlin.config.ExplicitApiMode
|
||||||
import org.jetbrains.kotlin.descriptors.*
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
import org.jetbrains.kotlin.idea.KotlinBundle
|
import org.jetbrains.kotlin.idea.KotlinBundle
|
||||||
import org.jetbrains.kotlin.idea.caches.project.implementingDescriptors
|
import org.jetbrains.kotlin.idea.caches.project.implementingDescriptors
|
||||||
@@ -75,7 +76,9 @@ import org.jetbrains.kotlin.psi.psiUtil.*
|
|||||||
import org.jetbrains.kotlin.resolve.BindingContext
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||||
import org.jetbrains.kotlin.resolve.bindingContextUtil.isUsedAsExpression
|
import org.jetbrains.kotlin.resolve.bindingContextUtil.isUsedAsExpression
|
||||||
|
import org.jetbrains.kotlin.resolve.checkers.explicitApiEnabled
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
|
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
|
||||||
|
import org.jetbrains.kotlin.resolve.descriptorUtil.isEffectivelyPublicApi
|
||||||
import org.jetbrains.kotlin.resolve.isInlineClass
|
import org.jetbrains.kotlin.resolve.isInlineClass
|
||||||
import org.jetbrains.kotlin.resolve.isInlineClassType
|
import org.jetbrains.kotlin.resolve.isInlineClassType
|
||||||
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
|
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
|
||||||
@@ -266,6 +269,10 @@ class UnusedSymbolInspection : AbstractKotlinInspection() {
|
|||||||
|
|
||||||
// More expensive, resolve-based checks
|
// More expensive, resolve-based checks
|
||||||
val descriptor = declaration.resolveToDescriptorIfAny() ?: return
|
val descriptor = declaration.resolveToDescriptorIfAny() ?: return
|
||||||
|
if (declaration.languageVersionSettings.explicitApiEnabled
|
||||||
|
&& (descriptor as? DeclarationDescriptorWithVisibility)?.isEffectivelyPublicApi == true) {
|
||||||
|
return
|
||||||
|
}
|
||||||
if (descriptor is FunctionDescriptor && descriptor.isOperator) return
|
if (descriptor is FunctionDescriptor && descriptor.isOperator) return
|
||||||
val isCheapEnough = lazy(LazyThreadSafetyMode.NONE) {
|
val isCheapEnough = lazy(LazyThreadSafetyMode.NONE) {
|
||||||
isCheapEnoughToSearchUsages(declaration)
|
isCheapEnoughToSearchUsages(declaration)
|
||||||
|
|||||||
@@ -0,0 +1,5 @@
|
|||||||
|
// PROBLEM: none
|
||||||
|
// COMPILER_ARGUMENTS: -Xexplicit-api=strict
|
||||||
|
|
||||||
|
public class <caret>X {
|
||||||
|
}
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
// PROBLEM: none
|
||||||
|
// COMPILER_ARGUMENTS: -Xexplicit-api=strict
|
||||||
|
|
||||||
|
public fun String.<caret>baz() {}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
// PROBLEM: none
|
||||||
|
// COMPILER_ARGUMENTS: -Xexplicit-api=strict
|
||||||
|
|
||||||
|
public class X {
|
||||||
|
public fun <caret>foo() {}
|
||||||
|
}
|
||||||
+15
@@ -14529,11 +14529,26 @@ public class LocalInspectionTestGenerated extends AbstractLocalInspectionTest {
|
|||||||
runTest("idea/testData/inspectionsLocal/unusedSymbol/typeAlias.kt");
|
runTest("idea/testData/inspectionsLocal/unusedSymbol/typeAlias.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("unusedClassExplicitApi.kt")
|
||||||
|
public void testUnusedClassExplicitApi() throws Exception {
|
||||||
|
runTest("idea/testData/inspectionsLocal/unusedSymbol/unusedClassExplicitApi.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("unusedEnumEntry.kt")
|
@TestMetadata("unusedEnumEntry.kt")
|
||||||
public void testUnusedEnumEntry() throws Exception {
|
public void testUnusedEnumEntry() throws Exception {
|
||||||
runTest("idea/testData/inspectionsLocal/unusedSymbol/unusedEnumEntry.kt");
|
runTest("idea/testData/inspectionsLocal/unusedSymbol/unusedEnumEntry.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("unusedExtensionExplicitApi.kt")
|
||||||
|
public void testUnusedExtensionExplicitApi() throws Exception {
|
||||||
|
runTest("idea/testData/inspectionsLocal/unusedSymbol/unusedExtensionExplicitApi.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("unusedFunctionExplicitApi.kt")
|
||||||
|
public void testUnusedFunctionExplicitApi() throws Exception {
|
||||||
|
runTest("idea/testData/inspectionsLocal/unusedSymbol/unusedFunctionExplicitApi.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("usedEnumFunction.kt")
|
@TestMetadata("usedEnumFunction.kt")
|
||||||
public void testUsedEnumFunction() throws Exception {
|
public void testUsedEnumFunction() throws Exception {
|
||||||
runTest("idea/testData/inspectionsLocal/unusedSymbol/usedEnumFunction.kt");
|
runTest("idea/testData/inspectionsLocal/unusedSymbol/usedEnumFunction.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user