diff --git a/plugins/kotlin/code-insight/inspections-k2/tests/test/org/jetbrains/kotlin/idea/k2/inspections/tests/K2UnusedSymbolHighlightingTestGenerated.java b/plugins/kotlin/code-insight/inspections-k2/tests/test/org/jetbrains/kotlin/idea/k2/inspections/tests/K2UnusedSymbolHighlightingTestGenerated.java index 73eb8b11ca11..0bccbcb9b78d 100644 --- a/plugins/kotlin/code-insight/inspections-k2/tests/test/org/jetbrains/kotlin/idea/k2/inspections/tests/K2UnusedSymbolHighlightingTestGenerated.java +++ b/plugins/kotlin/code-insight/inspections-k2/tests/test/org/jetbrains/kotlin/idea/k2/inspections/tests/K2UnusedSymbolHighlightingTestGenerated.java @@ -307,6 +307,11 @@ public abstract class K2UnusedSymbolHighlightingTestGenerated extends AbstractK2 runTest("../../../idea/tests/testData/inspectionsLocal/unusedSymbol/expectFunctionParameter.kt"); } + @TestMetadata("externalFunWithUnusedParameter.kt") + public void testExternalFunWithUnusedParameter() throws Exception { + runTest("../../../idea/tests/testData/inspectionsLocal/unusedSymbol/externalFunWithUnusedParameter.kt"); + } + @TestMetadata("functionCall.kt") public void testFunctionCall() throws Exception { runTest("../../../idea/tests/testData/inspectionsLocal/unusedSymbol/functionCall.kt"); diff --git a/plugins/kotlin/highlighting/highlighting-k2/src/org/jetbrains/kotlin/idea/highlighting/K2UnusedSymbolUtil.kt b/plugins/kotlin/highlighting/highlighting-k2/src/org/jetbrains/kotlin/idea/highlighting/K2UnusedSymbolUtil.kt index 1904d4315280..9e618a2d32ed 100644 --- a/plugins/kotlin/highlighting/highlighting-k2/src/org/jetbrains/kotlin/idea/highlighting/K2UnusedSymbolUtil.kt +++ b/plugins/kotlin/highlighting/highlighting-k2/src/org/jetbrains/kotlin/idea/highlighting/K2UnusedSymbolUtil.kt @@ -130,6 +130,9 @@ object K2UnusedSymbolUtil { context(KaSession) @OptIn(KaExperimentalApi::class) fun getPsiToReportProblem(declaration: KtNamedDeclaration, isJavaEntryPointInspection: UnusedDeclarationInspectionBase): PsiElement? { + if (((declaration as? KtParameter)?.parent?.parent as? KtModifierListOwner)?.hasModifier(KtTokens.EXTERNAL_KEYWORD) == true) { + return null + } val symbol = declaration.symbol if (declaration.languageVersionSettings.getFlag( AnalysisFlags.explicitApiMode) != ExplicitApiMode.DISABLED && symbol.compilerVisibility.isPublicAPI) { @@ -647,7 +650,7 @@ object K2UnusedSymbolUtil { return when { symbol is KaConstructorSymbol -> { val classSymbol = symbol.containingDeclaration as? KaNamedClassSymbol ?: return false - !classSymbol.isInline && !(classSymbol.visibility == KaSymbolVisibility.PRIVATE) + !classSymbol.isInline && classSymbol.visibility != KaSymbolVisibility.PRIVATE } hasModifier(KtTokens.INTERNAL_KEYWORD) -> false symbol !is KaNamedFunctionSymbol -> true diff --git a/plugins/kotlin/highlighting/highlighting-k2/src/org/jetbrains/kotlin/idea/highlighting/KotlinUnusedHighlightingVisitor.kt b/plugins/kotlin/highlighting/highlighting-k2/src/org/jetbrains/kotlin/idea/highlighting/KotlinUnusedHighlightingVisitor.kt index cbd2a089232a..7c6b61a27cd5 100644 --- a/plugins/kotlin/highlighting/highlighting-k2/src/org/jetbrains/kotlin/idea/highlighting/KotlinUnusedHighlightingVisitor.kt +++ b/plugins/kotlin/highlighting/highlighting-k2/src/org/jetbrains/kotlin/idea/highlighting/KotlinUnusedHighlightingVisitor.kt @@ -161,9 +161,10 @@ class KotlinUnusedHighlightingVisitor(private val ktFile: KtFile) { holder: HighlightInfoHolder) { if (!K2UnusedSymbolUtil.isApplicableByPsi(declaration)) return if (refHolder.isUsedLocally(declaration)) return // even for non-private declarations our refHolder might have usage info - val mustBeLocallyReferenced = declaration is KtParameter && !(declaration.hasValOrVar()) || - declaration.hasModifier(KtTokens.PRIVATE_KEYWORD) || - ((declaration.parent as? KtClassBody)?.parent as? KtClassOrObject)?.isLocal == true + val mustBeLocallyReferenced = declaration is KtParameter && !declaration.hasValOrVar() + && (declaration.parent?.parent as? KtModifierListOwner)?.hasModifier(KtTokens.EXTERNAL_KEYWORD) != true // parameters of external functions might be referenced elsewhere + || declaration.hasModifier(KtTokens.PRIVATE_KEYWORD) + || ((declaration.parent as? KtClassBody)?.parent as? KtClassOrObject)?.isLocal == true if (SuppressionUtil.inspectionResultSuppressed(declaration, deadCodeInspection)) { return } diff --git a/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/inspections/LocalInspectionTestGenerated.java b/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/inspections/LocalInspectionTestGenerated.java index a4b7eac36bb8..d395879228bd 100644 --- a/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/inspections/LocalInspectionTestGenerated.java +++ b/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/inspections/LocalInspectionTestGenerated.java @@ -18173,6 +18173,11 @@ public abstract class LocalInspectionTestGenerated extends AbstractLocalInspecti runTest("testData/inspectionsLocal/unusedSymbol/expectFunctionParameter.kt"); } + @TestMetadata("externalFunWithUnusedParameter.kt") + public void testExternalFunWithUnusedParameter() throws Exception { + runTest("testData/inspectionsLocal/unusedSymbol/externalFunWithUnusedParameter.kt"); + } + @TestMetadata("functionCall.kt") public void testFunctionCall() throws Exception { runTest("testData/inspectionsLocal/unusedSymbol/functionCall.kt"); diff --git a/plugins/kotlin/idea/tests/testData/inspectionsLocal/unusedSymbol/externalFunWithUnusedParameter.kt b/plugins/kotlin/idea/tests/testData/inspectionsLocal/unusedSymbol/externalFunWithUnusedParameter.kt new file mode 100644 index 000000000000..a53f5485401d --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/inspectionsLocal/unusedSymbol/externalFunWithUnusedParameter.kt @@ -0,0 +1,5 @@ +// PROBLEM: none +class M { + private external fun sdkfjlsdkjf(sdfsd: Int):Int + override fun hashCode() = sdkfjlsdkjf(0) +} \ No newline at end of file