diff --git a/idea/src/org/jetbrains/kotlin/idea/inspections/UnusedSymbolInspection.kt b/idea/src/org/jetbrains/kotlin/idea/inspections/UnusedSymbolInspection.kt index edbad823697..0b9627d4f29 100644 --- a/idea/src/org/jetbrains/kotlin/idea/inspections/UnusedSymbolInspection.kt +++ b/idea/src/org/jetbrains/kotlin/idea/inspections/UnusedSymbolInspection.kt @@ -18,6 +18,7 @@ package org.jetbrains.kotlin.idea.inspections import com.intellij.codeInsight.FileModificationService import com.intellij.codeInsight.daemon.QuickFixBundle +import com.intellij.codeInsight.daemon.impl.analysis.HighlightUtil import com.intellij.codeInspection.* import com.intellij.codeInspection.deadCode.UnusedDeclarationInspection import com.intellij.codeInspection.ex.EntryPointsManager @@ -45,6 +46,7 @@ import org.jetbrains.kotlin.idea.util.ProjectRootsUtil import org.jetbrains.kotlin.lexer.JetTokens import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.psiUtil.getElementTextWithContext +import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType import org.jetbrains.kotlin.psi.psiUtil.isAncestor import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.types.expressions.OperatorConventions @@ -77,6 +79,19 @@ public class UnusedSymbolInspection : AbstractKotlinInspection() { return lightElement != null && javaInspection.isEntryPoint(lightElement) } + private fun JetProperty.isSerializationImplicitlyUsedField(): Boolean { + val ownerObject = getNonStrictParentOfType() + if (ownerObject is JetObjectDeclaration && ownerObject.isCompanion()) { + val lightClass = ownerObject.getNonStrictParentOfType()?.toLightClass() ?: return false + return lightClass.getFields().any { it.getName() == getName() && HighlightUtil.isSerializationImplicitlyUsedField(it) } + } + return false + } + + private fun JetObjectDeclaration.hasSerializationImplicitlyUsedField(): Boolean { + return getDeclarations().any { it is JetProperty && it.isSerializationImplicitlyUsedField() } + } + // variation of IDEA's AnnotationUtil.checkAnnotatedUsingPatterns() private fun checkAnnotatedUsingPatterns(annotated: Annotated, annotationPatterns: Collection): Boolean { val annotationsPresent = annotated.getAnnotations() @@ -141,6 +156,8 @@ public class UnusedSymbolInspection : AbstractKotlinInspection() { // More expensive, resolve-based checks if (isEntryPoint(declaration)) return + if (declaration is JetProperty && declaration.isSerializationImplicitlyUsedField()) return + if (isCompanionObject && (declaration as JetObjectDeclaration).hasSerializationImplicitlyUsedField()) return // properties can be referred by component1/component2, which is too expensive to search, don't mark them as unused if (declaration is JetParameter && declaration.dataClassComponentFunctionName() != null) return diff --git a/idea/testData/inspections/unusedSymbol/property/serialVersionUid.kt b/idea/testData/inspections/unusedSymbol/property/serialVersionUid.kt new file mode 100644 index 00000000000..92ed1eab1c1 --- /dev/null +++ b/idea/testData/inspections/unusedSymbol/property/serialVersionUid.kt @@ -0,0 +1,13 @@ +// FULL_JDK + +import kotlin.platform.platformStatic + +class Klass : java.io.Serializable { + companion object { + private platformStatic val serialVersionUID: Long = 239 + } +} + +fun main(args: Array) { + Klass() +}