diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/CodeFragmentAnalyzer.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/CodeFragmentAnalyzer.kt index 6a3e7850517..172dc420c7f 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/CodeFragmentAnalyzer.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/CodeFragmentAnalyzer.kt @@ -18,6 +18,8 @@ package org.jetbrains.kotlin.idea.caches.resolve import com.intellij.psi.PsiElement import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.idea.analysis.analyzeInContext +import org.jetbrains.kotlin.idea.caches.resolve.util.analyzeControlFlow import org.jetbrains.kotlin.idea.project.ResolveElementCache import org.jetbrains.kotlin.idea.util.getResolutionScope import org.jetbrains.kotlin.incremental.components.NoLookupLocation @@ -27,21 +29,16 @@ import org.jetbrains.kotlin.psi.psiUtil.getParentOfType import org.jetbrains.kotlin.psi.psiUtil.getParentOfTypes3 import org.jetbrains.kotlin.resolve.* import org.jetbrains.kotlin.resolve.bindingContextUtil.getDataFlowInfoAfter -import org.jetbrains.kotlin.resolve.calls.components.InferenceSession import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode import org.jetbrains.kotlin.resolve.lazy.ResolveSession import org.jetbrains.kotlin.resolve.scopes.* import org.jetbrains.kotlin.resolve.scopes.utils.addImportingScopes -import org.jetbrains.kotlin.types.TypeUtils -import org.jetbrains.kotlin.types.expressions.ExpressionTypingServices -import org.jetbrains.kotlin.types.expressions.PreliminaryDeclarationVisitor import javax.inject.Inject class CodeFragmentAnalyzer( private val resolveSession: ResolveSession, private val qualifierResolver: QualifiedExpressionResolver, - private val expressionTypingServices: ExpressionTypingServices, private val typeResolver: TypeResolver ) { @set:Inject // component dependency cycle @@ -58,15 +55,8 @@ class CodeFragmentAnalyzer( when (val contentElement = codeFragment.getContentElement()) { is KtExpression -> { - PreliminaryDeclarationVisitor.createForExpression( - contentElement, bindingTrace, - expressionTypingServices.languageVersionSettings - ) - - expressionTypingServices.getTypeInfo( - scope, contentElement, TypeUtils.NO_EXPECTED_TYPE, - dataFlowInfo, InferenceSession.default, bindingTrace, false - ) + contentElement.analyzeInContext(scope, trace = bindingTrace, dataFlowInfo = dataFlowInfo) + analyzeControlFlow(resolveSession, contentElement, bindingTrace) } is KtTypeReference -> { diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/util/ControlFlowUtils.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/util/ControlFlowUtils.kt new file mode 100644 index 00000000000..8ab2efd620a --- /dev/null +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/util/ControlFlowUtils.kt @@ -0,0 +1,23 @@ +/* + * Copyright 2010-2019 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. + */ + +package org.jetbrains.kotlin.idea.caches.resolve.util + +import org.jetbrains.kotlin.cfg.ControlFlowInformationProvider +import org.jetbrains.kotlin.idea.project.languageVersionSettings +import org.jetbrains.kotlin.psi.KtElement +import org.jetbrains.kotlin.resolve.BindingTrace +import org.jetbrains.kotlin.resolve.DelegatingBindingTrace +import org.jetbrains.kotlin.resolve.lazy.ResolveSession + +fun analyzeControlFlow(resolveSession: ResolveSession, resolveElement: KtElement, trace: BindingTrace) { + val controlFlowTrace = DelegatingBindingTrace( + trace.bindingContext, "Element control flow resolve", resolveElement, allowSliceRewrite = true + ) + ControlFlowInformationProvider( + resolveElement, controlFlowTrace, resolveElement.languageVersionSettings, resolveSession.platformDiagnosticSuppressor + ).checkDeclaration() + controlFlowTrace.addOwnDataTo(trace, null, false) +} \ No newline at end of file diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/project/ResolveElementCache.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/project/ResolveElementCache.kt index db708e2f2f1..5b8467abf99 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/project/ResolveElementCache.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/project/ResolveElementCache.kt @@ -32,6 +32,7 @@ import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.annotations.Annotations import org.jetbrains.kotlin.frontend.di.createContainerForBodyResolve import org.jetbrains.kotlin.idea.caches.resolve.CodeFragmentAnalyzer +import org.jetbrains.kotlin.idea.caches.resolve.util.analyzeControlFlow import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.psiUtil.forEachDescendantOfType @@ -413,13 +414,7 @@ class ResolveElementCache( } if (bodyResolveMode.doControlFlowAnalysis) { - val controlFlowTrace = DelegatingBindingTrace( - trace.bindingContext, "Element control flow resolve", resolveElement, allowSliceRewrite = true - ) - ControlFlowInformationProvider( - resolveElement, controlFlowTrace, resolveElement.languageVersionSettings, resolveSession.platformDiagnosticSuppressor - ).checkDeclaration() - controlFlowTrace.addOwnDataTo(trace, null, false) + analyzeControlFlow(resolveSession, resolveElement, trace) } return Pair(trace.bindingContext, statementFilterUsed) diff --git a/idea/testData/checker/codeFragments/unusedEquals.kt b/idea/testData/checker/codeFragments/unusedEquals.kt new file mode 100644 index 00000000000..c4e84d4ce4a --- /dev/null +++ b/idea/testData/checker/codeFragments/unusedEquals.kt @@ -0,0 +1,16 @@ +// INSPECTION_CLASS: org.jetbrains.kotlin.idea.inspections.UnusedEqualsInspection + +fun main() { + val list = java.util.ArrayList() + val x = 0 +} + +fun Collection.isAny(predicate: (T) -> Boolean): Boolean { + for (item in this) { + if (predicate(item)) { + return true + } + } + + return false +} \ No newline at end of file diff --git a/idea/testData/checker/codeFragments/unusedEquals.kt.fragment b/idea/testData/checker/codeFragments/unusedEquals.kt.fragment new file mode 100644 index 00000000000..5c2292052fd --- /dev/null +++ b/idea/testData/checker/codeFragments/unusedEquals.kt.fragment @@ -0,0 +1 @@ +list.isAny { it == 2 } \ No newline at end of file diff --git a/idea/tests/org/jetbrains/kotlin/idea/debugger/evaluate/AbstractEditorForEvaluateExpressionTest.kt b/idea/tests/org/jetbrains/kotlin/idea/debugger/evaluate/AbstractEditorForEvaluateExpressionTest.kt index 923f5712160..c2e46dea068 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/debugger/evaluate/AbstractEditorForEvaluateExpressionTest.kt +++ b/idea/tests/org/jetbrains/kotlin/idea/debugger/evaluate/AbstractEditorForEvaluateExpressionTest.kt @@ -6,6 +6,7 @@ package org.jetbrains.kotlin.idea.debugger.evaluate import com.intellij.codeInsight.completion.CompletionType +import com.intellij.codeInspection.InspectionProfileEntry import com.intellij.openapi.util.io.FileUtil import com.intellij.openapi.util.text.StringUtil import com.intellij.psi.PsiElement @@ -33,7 +34,7 @@ import kotlin.test.assertTrue abstract class AbstractCodeFragmentHighlightingTest : AbstractPsiCheckerTest() { override fun doTest(filePath: String) { myFixture.configureByCodeFragment(filePath) - myFixture.checkHighlighting(true, false, false) + checkHighlighting(filePath) } fun doTestWithImport(filePath: String) { @@ -49,6 +50,22 @@ abstract class AbstractCodeFragmentHighlightingTest : AbstractPsiCheckerTest() { } } + checkHighlighting(filePath) + } + + private fun checkHighlighting(filePath: String) { + val inspectionName = InTextDirectivesUtils.findStringWithPrefixes(File(filePath).readText(), "// INSPECTION_CLASS: ") + if (inspectionName != null) { + val inspection = Class.forName(inspectionName).newInstance() as InspectionProfileEntry + myFixture.enableInspections(inspection) + try { + myFixture.checkHighlighting(true, false, false) + } finally { + myFixture.disableInspections(inspection) + } + return + } + myFixture.checkHighlighting(true, false, false) } } diff --git a/idea/tests/org/jetbrains/kotlin/idea/debugger/evaluate/CodeFragmentHighlightingTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/debugger/evaluate/CodeFragmentHighlightingTestGenerated.java index 14822caa8e0..7dcd912a05c 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/debugger/evaluate/CodeFragmentHighlightingTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/debugger/evaluate/CodeFragmentHighlightingTestGenerated.java @@ -141,6 +141,11 @@ public class CodeFragmentHighlightingTestGenerated extends AbstractCodeFragmentH runTest("idea/testData/checker/codeFragments/startingFromReturn.kt"); } + @TestMetadata("unusedEquals.kt") + public void testUnusedEquals() throws Exception { + runTest("idea/testData/checker/codeFragments/unusedEquals.kt"); + } + @TestMetadata("withoutBodyFunction.kt") public void testWithoutBodyFunction() throws Exception { runTest("idea/testData/checker/codeFragments/withoutBodyFunction.kt");