diff --git a/idea/src/org/jetbrains/kotlin/idea/inspections/ProtectedInFinalInspection.kt b/idea/src/org/jetbrains/kotlin/idea/inspections/ProtectedInFinalInspection.kt
index 4962e5b8182..97eac9a4538 100644
--- a/idea/src/org/jetbrains/kotlin/idea/inspections/ProtectedInFinalInspection.kt
+++ b/idea/src/org/jetbrains/kotlin/idea/inspections/ProtectedInFinalInspection.kt
@@ -9,16 +9,16 @@ import com.intellij.codeInsight.FileModificationService
import com.intellij.codeInspection.*
import com.intellij.openapi.project.Project
import com.intellij.psi.PsiElementVisitor
-import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.idea.core.implicitVisibility
import org.jetbrains.kotlin.idea.core.isInheritable
-import org.jetbrains.kotlin.idea.search.usagesSearch.descriptor
+import org.jetbrains.kotlin.idea.intentions.isFinalizeMethod
import org.jetbrains.kotlin.lexer.KtTokens
-import org.jetbrains.kotlin.psi.*
+import org.jetbrains.kotlin.psi.KtClass
+import org.jetbrains.kotlin.psi.KtModifierListOwner
import org.jetbrains.kotlin.psi.addRemoveModifier.addModifier
+import org.jetbrains.kotlin.psi.declarationVisitor
import org.jetbrains.kotlin.psi.psiUtil.getParentOfType
import org.jetbrains.kotlin.psi.psiUtil.visibilityModifier
-import org.jetbrains.kotlin.types.typeUtil.isUnit
class ProtectedInFinalInspection : AbstractKotlinInspection() {
override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean, session: LocalInspectionToolSession): PsiElementVisitor {
@@ -43,13 +43,6 @@ class ProtectedInFinalInspection : AbstractKotlinInspection() {
})
}
- private fun KtDeclaration.isFinalizeMethod(): Boolean {
- val function = this as? KtNamedFunction ?: return false
- return function.name == "finalize"
- && function.valueParameters.isEmpty()
- && (function.descriptor as? FunctionDescriptor)?.returnType?.isUnit() == true
- }
-
class MakePrivateFix : LocalQuickFix {
override fun getName(): String = "Make private"
diff --git a/idea/src/org/jetbrains/kotlin/idea/inspections/UnusedSymbolInspection.kt b/idea/src/org/jetbrains/kotlin/idea/inspections/UnusedSymbolInspection.kt
index c85fe29ff7c..7d6221fe385 100644
--- a/idea/src/org/jetbrains/kotlin/idea/inspections/UnusedSymbolInspection.kt
+++ b/idea/src/org/jetbrains/kotlin/idea/inspections/UnusedSymbolInspection.kt
@@ -46,6 +46,7 @@ import org.jetbrains.kotlin.idea.core.toDescriptor
import org.jetbrains.kotlin.idea.findUsages.KotlinFindUsagesHandlerFactory
import org.jetbrains.kotlin.idea.findUsages.handlers.KotlinFindClassUsagesHandler
import org.jetbrains.kotlin.idea.imports.importableFqName
+import org.jetbrains.kotlin.idea.intentions.isFinalizeMethod
import org.jetbrains.kotlin.idea.isMainFunction
import org.jetbrains.kotlin.idea.project.languageVersionSettings
import org.jetbrains.kotlin.idea.quickfix.RemoveUnusedFunctionParameterFix
@@ -168,6 +169,7 @@ class UnusedSymbolInspection : AbstractKotlinInspection() {
val descriptor = declaration.resolveToDescriptorIfAny() ?: return
if (descriptor is FunctionDescriptor && descriptor.isOperator) return
if (isEntryPoint(declaration)) return
+ if (declaration.isFinalizeMethod(descriptor)) return
if (declaration is KtProperty && declaration.isSerializationImplicitlyUsedField()) return
if (declaration is KtNamedFunction && declaration.isSerializationImplicitlyUsedMethod()) return
// properties can be referred by component1/component2, which is too expensive to search, don't mark them as unused
@@ -283,7 +285,7 @@ class UnusedSymbolInspection : AbstractKotlinInspection() {
if (import.importedFqName != declaration.fqName) {
val importedDeclaration =
import.importedReference?.getQualifiedElementSelector()?.mainReference?.resolve() as? KtNamedDeclaration
- ?: return true
+ ?: return true
if (declaration is KtObjectDeclaration ||
(declaration is KtClass && declaration.isEnum()) ||
importedDeclaration.containingClassOrObject is KtObjectDeclaration
diff --git a/idea/src/org/jetbrains/kotlin/idea/intentions/Utils.kt b/idea/src/org/jetbrains/kotlin/idea/intentions/Utils.kt
index 71a94de671a..6cbdd770205 100644
--- a/idea/src/org/jetbrains/kotlin/idea/intentions/Utils.kt
+++ b/idea/src/org/jetbrains/kotlin/idea/intentions/Utils.kt
@@ -19,17 +19,17 @@ package org.jetbrains.kotlin.idea.intentions
import com.intellij.psi.tree.IElementType
import org.jetbrains.kotlin.KtNodeTypes
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
-import org.jetbrains.kotlin.descriptors.CallableDescriptor
-import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor
-import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
+import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.idea.caches.resolve.analyze
import org.jetbrains.kotlin.idea.caches.resolve.resolveToCall
import org.jetbrains.kotlin.idea.core.replaced
import org.jetbrains.kotlin.idea.core.setType
import org.jetbrains.kotlin.idea.references.mainReference
+import org.jetbrains.kotlin.idea.search.usagesSearch.descriptor
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.*
+import org.jetbrains.kotlin.psi.psiUtil.containingClass
import org.jetbrains.kotlin.psi.psiUtil.getCallNameExpression
import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType
import org.jetbrains.kotlin.resolve.BindingContext
@@ -40,6 +40,7 @@ import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
import org.jetbrains.kotlin.resolve.source.getPsi
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.isFlexible
+import org.jetbrains.kotlin.types.typeUtil.isUnit
import java.lang.IllegalArgumentException
fun KtContainerNode.description(): String? {
@@ -311,4 +312,12 @@ fun KtBlockExpression.getParentLambdaLabelName(): String? {
return lambdaLabelName ?: callExpression.getCallNameExpression()?.text
}
-internal fun KtExpression.getCallableDescriptor() = resolveToCall()?.resultingDescriptor
\ No newline at end of file
+internal fun KtExpression.getCallableDescriptor() = resolveToCall()?.resultingDescriptor
+
+fun KtDeclaration.isFinalizeMethod(descriptor: DeclarationDescriptor? = null): Boolean {
+ if (containingClass() == null) return false
+ val function = this as? KtNamedFunction ?: return false
+ return function.name == "finalize"
+ && function.valueParameters.isEmpty()
+ && ((descriptor ?: function.descriptor) as? FunctionDescriptor)?.returnType?.isUnit() == true
+}
\ No newline at end of file
diff --git a/idea/testData/inspections/unusedSymbol/function/finalize.kt b/idea/testData/inspections/unusedSymbol/function/finalize.kt
new file mode 100644
index 00000000000..005fa6beb27
--- /dev/null
+++ b/idea/testData/inspections/unusedSymbol/function/finalize.kt
@@ -0,0 +1,4 @@
+class C {
+ protected fun finalize() {
+ }
+}
\ No newline at end of file
diff --git a/idea/testData/inspections/unusedSymbol/function/inspectionData/expected.xml b/idea/testData/inspections/unusedSymbol/function/inspectionData/expected.xml
index c8de5ceba0b..81cbcf2e8cc 100644
--- a/idea/testData/inspections/unusedSymbol/function/inspectionData/expected.xml
+++ b/idea/testData/inspections/unusedSymbol/function/inspectionData/expected.xml
@@ -87,4 +87,13 @@
Unused symbol
Function "foo" is never used
+
+
+ finalize.kt
+ 1
+ light_idea_test_case
+
+ Unused symbol
+ Class "C" is never used
+