From e8e0f2d7e1a99f938a54a623552a948005d3e85d Mon Sep 17 00:00:00 2001 From: Alexey Sedunov Date: Wed, 7 Oct 2015 15:06:32 +0300 Subject: [PATCH] Unused Symbol: Check descriptor before creating light class to prevent InvalidMirrorException on red code --- .../kotlin/idea/caches/resolve/resolutionApi.kt | 9 ++++++++- .../highlighter/KotlinTestRunLineMarkerContributor.kt | 7 ++----- .../idea/highlighter/markers/SuperDeclarationMarker.kt | 4 ++-- .../kotlin/idea/inspections/UnusedSymbolInspection.kt | 5 +++++ .../unusedSymbol/class/BadCodeNoExceptions.kt | 6 ++++++ .../unusedSymbol/class/inspectionData/expected.xml | 8 ++++++++ 6 files changed, 31 insertions(+), 8 deletions(-) create mode 100644 idea/testData/inspections/unusedSymbol/class/BadCodeNoExceptions.kt diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/resolutionApi.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/resolutionApi.kt index 83b101d6894..cbe3c25a7a9 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/resolutionApi.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/resolutionApi.kt @@ -29,7 +29,10 @@ import org.jetbrains.kotlin.psi.JetDeclaration import org.jetbrains.kotlin.psi.JetElement import org.jetbrains.kotlin.psi.JetFile import org.jetbrains.kotlin.psi.JetPsiFactory -import org.jetbrains.kotlin.resolve.* +import org.jetbrains.kotlin.resolve.BindingContext +import org.jetbrains.kotlin.resolve.BindingTraceContext +import org.jetbrains.kotlin.resolve.ImportPath +import org.jetbrains.kotlin.resolve.QualifiedExpressionResolver import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode import org.jetbrains.kotlin.resolve.lazy.FileScopeProvider import org.jetbrains.kotlin.resolve.lazy.LazyFileScope @@ -42,6 +45,10 @@ public fun JetDeclaration.resolveToDescriptor(): DeclarationDescriptor { return getResolutionFacade().resolveToDescriptor(this) } +public fun JetDeclaration.resolveToDescriptorIfAny(): DeclarationDescriptor? { + return analyze(BodyResolveMode.PARTIAL).get(BindingContext.DECLARATION_TO_DESCRIPTOR, this) +} + public fun JetFile.resolveImportReference(fqName: FqName): Collection { val facade = getResolutionFacade() return facade.resolveImportReference(facade.moduleDescriptor, fqName) diff --git a/idea/src/org/jetbrains/kotlin/idea/highlighter/KotlinTestRunLineMarkerContributor.kt b/idea/src/org/jetbrains/kotlin/idea/highlighter/KotlinTestRunLineMarkerContributor.kt index a140c30c7cf..a539d011ef3 100644 --- a/idea/src/org/jetbrains/kotlin/idea/highlighter/KotlinTestRunLineMarkerContributor.kt +++ b/idea/src/org/jetbrains/kotlin/idea/highlighter/KotlinTestRunLineMarkerContributor.kt @@ -26,13 +26,11 @@ import com.intellij.psi.PsiElement import org.jetbrains.kotlin.asJava.KotlinLightClass import org.jetbrains.kotlin.asJava.toLightClass import org.jetbrains.kotlin.asJava.toLightMethods -import org.jetbrains.kotlin.idea.caches.resolve.analyze +import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptorIfAny import org.jetbrains.kotlin.psi.JetClassOrObject import org.jetbrains.kotlin.psi.JetNamedDeclaration import org.jetbrains.kotlin.psi.JetNamedFunction import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType -import org.jetbrains.kotlin.resolve.BindingContext -import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode import javax.swing.Icon class KotlinTestRunLineMarkerContributor : RunLineMarkerContributor() { @@ -47,8 +45,7 @@ class KotlinTestRunLineMarkerContributor : RunLineMarkerContributor() { if (declaration.nameIdentifier != element) return null // To prevent IDEA failing on red code - if (declaration.analyze(BodyResolveMode.PARTIAL) - .get(BindingContext.DECLARATION_TO_DESCRIPTOR, declaration) == null) return null + if (declaration.resolveToDescriptorIfAny() == null) return null val project = element.project diff --git a/idea/src/org/jetbrains/kotlin/idea/highlighter/markers/SuperDeclarationMarker.kt b/idea/src/org/jetbrains/kotlin/idea/highlighter/markers/SuperDeclarationMarker.kt index 4f8be7530cc..bef35e75d01 100644 --- a/idea/src/org/jetbrains/kotlin/idea/highlighter/markers/SuperDeclarationMarker.kt +++ b/idea/src/org/jetbrains/kotlin/idea/highlighter/markers/SuperDeclarationMarker.kt @@ -28,6 +28,7 @@ import org.jetbrains.kotlin.descriptors.PropertyAccessorDescriptor import org.jetbrains.kotlin.descriptors.PropertyDescriptor import org.jetbrains.kotlin.idea.JetBundle import org.jetbrains.kotlin.idea.caches.resolve.analyze +import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptorIfAny import org.jetbrains.kotlin.idea.codeInsight.DescriptorToSourceUtilsIde import org.jetbrains.kotlin.idea.codeInsight.JetFunctionPsiElementCellRenderer import org.jetbrains.kotlin.psi.JetDeclaration @@ -112,8 +113,7 @@ public data class ResolveWithParentsResult( val overriddenDescriptors: Collection) public fun resolveDeclarationWithParents(element: JetDeclaration): ResolveWithParentsResult { - val bindingContext = element.analyze() - val descriptor = bindingContext.get(BindingContext.DECLARATION_TO_DESCRIPTOR, element) + val descriptor = element.resolveToDescriptorIfAny() if (descriptor !is CallableMemberDescriptor) return ResolveWithParentsResult(null, listOf()) diff --git a/idea/src/org/jetbrains/kotlin/idea/inspections/UnusedSymbolInspection.kt b/idea/src/org/jetbrains/kotlin/idea/inspections/UnusedSymbolInspection.kt index 313feaa655f..3fb5fac159c 100644 --- a/idea/src/org/jetbrains/kotlin/idea/inspections/UnusedSymbolInspection.kt +++ b/idea/src/org/jetbrains/kotlin/idea/inspections/UnusedSymbolInspection.kt @@ -42,6 +42,8 @@ import org.jetbrains.kotlin.asJava.LightClassUtil import org.jetbrains.kotlin.asJava.toLightClass import org.jetbrains.kotlin.descriptors.annotations.Annotated import org.jetbrains.kotlin.idea.JetBundle +import org.jetbrains.kotlin.idea.caches.resolve.analyze +import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptorIfAny import org.jetbrains.kotlin.idea.findUsages.KotlinFindUsagesHandlerFactory import org.jetbrains.kotlin.idea.findUsages.handlers.KotlinFindClassUsagesHandler import org.jetbrains.kotlin.idea.search.usagesSearch.* @@ -52,7 +54,9 @@ import org.jetbrains.kotlin.psi.psiUtil.getElementTextWithContext import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType import org.jetbrains.kotlin.psi.psiUtil.getParentOfType import org.jetbrains.kotlin.psi.psiUtil.isAncestor +import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.DescriptorUtils +import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode import org.jetbrains.kotlin.types.expressions.OperatorConventions import org.jetbrains.kotlin.utils.singletonOrEmptyList import java.awt.GridBagConstraints @@ -159,6 +163,7 @@ public class UnusedSymbolInspection : AbstractKotlinInspection() { if (declaration is JetNamedFunction && isConventionalName(declaration)) return // More expensive, resolve-based checks + if (declaration.resolveToDescriptorIfAny() == null) return if (isEntryPoint(declaration)) return if (declaration is JetProperty && declaration.isSerializationImplicitlyUsedField()) return if (isCompanionObject && (declaration as JetObjectDeclaration).hasSerializationImplicitlyUsedField()) return diff --git a/idea/testData/inspections/unusedSymbol/class/BadCodeNoExceptions.kt b/idea/testData/inspections/unusedSymbol/class/BadCodeNoExceptions.kt new file mode 100644 index 00000000000..39776538b02 --- /dev/null +++ b/idea/testData/inspections/unusedSymbol/class/BadCodeNoExceptions.kt @@ -0,0 +1,6 @@ +// Closing brace is intentionally missed +val id = array("kotlin.FlexibleType" + +private class Some() { + override fun foo() = 1 +} \ No newline at end of file diff --git a/idea/testData/inspections/unusedSymbol/class/inspectionData/expected.xml b/idea/testData/inspections/unusedSymbol/class/inspectionData/expected.xml index 0414b1df77d..0e6006042b0 100644 --- a/idea/testData/inspections/unusedSymbol/class/inspectionData/expected.xml +++ b/idea/testData/inspections/unusedSymbol/class/inspectionData/expected.xml @@ -47,4 +47,12 @@ Unused Symbol Class 'B' is never used + + BadCodeNoExceptions.kt + 2 + light_idea_test_case + + Unused Symbol + Property 'id' is never used +