From 152327d69d5088c2c9ef75bc6e0e5b38c35e3f0d Mon Sep 17 00:00:00 2001 From: Mikhail Glukhikh Date: Tue, 19 Jun 2018 16:37:47 +0300 Subject: [PATCH] Fix erroneous full resolve cache filling Before this commit, we could store partial resolve results in full resolve cache (for some declarations, e.g. primary constructors). This may be done iff current partial resolve mode provides all results from full resolve mode (CFA results & diagnostics). Otherwise we should not do it. This fixes four quick-fix tests on CreateTypeParameter So #KT-23860 Fixed So #KT-22758 Fixed --- .../kotlin/idea/project/ResolveElementCache.kt | 16 +++++++++++----- .../quickfix/autoImports/inPrimaryConstructor.kt | 4 ++++ .../autoImports/inPrimaryConstructor.kt.after | 6 ++++++ .../classInPrimaryConstructor.kt | 3 +++ .../classInPrimaryConstructor.kt.after | 7 +++++++ .../kotlin/idea/ResolveElementCacheTest.kt | 6 +++--- .../idea/quickfix/QuickFixTestGenerated.java | 10 ++++++++++ 7 files changed, 44 insertions(+), 8 deletions(-) create mode 100644 idea/testData/quickfix/autoImports/inPrimaryConstructor.kt create mode 100644 idea/testData/quickfix/autoImports/inPrimaryConstructor.kt.after create mode 100644 idea/testData/quickfix/createFromUsage/createClass/referenceExpression/classInPrimaryConstructor.kt create mode 100644 idea/testData/quickfix/createFromUsage/createClass/referenceExpression/classInPrimaryConstructor.kt.after 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 aa57e787243..6f134a15053 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 @@ -177,17 +177,23 @@ class ResolveElementCache( val (bindingContext, statementFilter) = performElementAdditionalResolve(resolveElement, contextElements, bodyResolveMode) - if (statementFilter == StatementFilter.NONE) { - // partial resolve is not supported for the given declaration - full resolve performed instead + if (statementFilter == StatementFilter.NONE && + bodyResolveMode.doControlFlowAnalysis && !bodyResolveMode.bindingTraceFilter.ignoreDiagnostics + ) { + // Without statement filter, we analyze everything, so we can count partial resolve result as full resolve + // But we can do this only if our resolve mode also provides *both* CFA and diagnostics + // This is true only for PARTIAL_WITH_DIAGNOSTICS resolve mode fullResolveMap[resolveElement] = CachedFullResolve(bindingContext, resolveElement) return bindingContext } val resolveToCache = CachedPartialResolve(bindingContext, file, bodyResolveMode) - for (statement in (statementFilter as PartialBodyResolveFilter).allStatementsToResolve) { - if (bindingContext[BindingContext.PROCESSED, statement] == true) { - partialResolveMap.putIfAbsent(statement, resolveToCache) + if (statementFilter is PartialBodyResolveFilter) { + for (statement in statementFilter.allStatementsToResolve) { + if (bindingContext[BindingContext.PROCESSED, statement] == true) { + partialResolveMap.putIfAbsent(statement, resolveToCache) + } } } diff --git a/idea/testData/quickfix/autoImports/inPrimaryConstructor.kt b/idea/testData/quickfix/autoImports/inPrimaryConstructor.kt new file mode 100644 index 00000000000..65c78f10175 --- /dev/null +++ b/idea/testData/quickfix/autoImports/inPrimaryConstructor.kt @@ -0,0 +1,4 @@ +// "Import" "true" +// RUNTIME_WITH_FULL_JDK + +class LL(val list: LinkedList) \ No newline at end of file diff --git a/idea/testData/quickfix/autoImports/inPrimaryConstructor.kt.after b/idea/testData/quickfix/autoImports/inPrimaryConstructor.kt.after new file mode 100644 index 00000000000..ec777017df4 --- /dev/null +++ b/idea/testData/quickfix/autoImports/inPrimaryConstructor.kt.after @@ -0,0 +1,6 @@ +import java.util.LinkedList + +// "Import" "true" +// RUNTIME_WITH_FULL_JDK + +class LL(val list: LinkedList) \ No newline at end of file diff --git a/idea/testData/quickfix/createFromUsage/createClass/referenceExpression/classInPrimaryConstructor.kt b/idea/testData/quickfix/createFromUsage/createClass/referenceExpression/classInPrimaryConstructor.kt new file mode 100644 index 00000000000..1b613834de4 --- /dev/null +++ b/idea/testData/quickfix/createFromUsage/createClass/referenceExpression/classInPrimaryConstructor.kt @@ -0,0 +1,3 @@ +// "Create class 'X'" "true" + +class Foo(x: X) \ No newline at end of file diff --git a/idea/testData/quickfix/createFromUsage/createClass/referenceExpression/classInPrimaryConstructor.kt.after b/idea/testData/quickfix/createFromUsage/createClass/referenceExpression/classInPrimaryConstructor.kt.after new file mode 100644 index 00000000000..12ec77d94c2 --- /dev/null +++ b/idea/testData/quickfix/createFromUsage/createClass/referenceExpression/classInPrimaryConstructor.kt.after @@ -0,0 +1,7 @@ +// "Create class 'X'" "true" + +class Foo(x: X) + +class X { + +} diff --git a/idea/tests/org/jetbrains/kotlin/idea/ResolveElementCacheTest.kt b/idea/tests/org/jetbrains/kotlin/idea/ResolveElementCacheTest.kt index 198d073a132..60670569d08 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/ResolveElementCacheTest.kt +++ b/idea/tests/org/jetbrains/kotlin/idea/ResolveElementCacheTest.kt @@ -302,9 +302,9 @@ class C(param1: String = "", param2: Int = 0) { fun testFullResolvedCachedWhenPartialForConstructorInvoked() { doTest { - val defaultValue1 = klass.getPrimaryConstructorParameters()[0].defaultValue!! - val defaultValue2 = klass.getPrimaryConstructorParameters()[1].defaultValue!! - val bindingContext1 = defaultValue1.analyze(BodyResolveMode.PARTIAL) + val defaultValue1 = klass.primaryConstructorParameters[0].defaultValue!! + val defaultValue2 = klass.primaryConstructorParameters[1].defaultValue!! + val bindingContext1 = defaultValue1.analyze(BodyResolveMode.PARTIAL_WITH_DIAGNOSTICS) val bindingContext2 = defaultValue2.analyze(BodyResolveMode.FULL) assert(bindingContext1 === bindingContext2) } diff --git a/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java index 0900149947d..6afd848efa0 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java @@ -1301,6 +1301,11 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest { runTest("idea/testData/quickfix/autoImports/excludedFromImport.kt"); } + @TestMetadata("inPrimaryConstructor.kt") + public void testInPrimaryConstructor() throws Exception { + runTest("idea/testData/quickfix/autoImports/inPrimaryConstructor.kt"); + } + @TestMetadata("infixCallAndObject.kt") public void testInfixCallAndObject() throws Exception { runTest("idea/testData/quickfix/autoImports/infixCallAndObject.kt"); @@ -2503,6 +2508,11 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest { runTest("idea/testData/quickfix/createFromUsage/createClass/referenceExpression/classInPackage.kt"); } + @TestMetadata("classInPrimaryConstructor.kt") + public void testClassInPrimaryConstructor() throws Exception { + runTest("idea/testData/quickfix/createFromUsage/createClass/referenceExpression/classInPrimaryConstructor.kt"); + } + @TestMetadata("classNoReceiver.kt") public void testClassNoReceiver() throws Exception { runTest("idea/testData/quickfix/createFromUsage/createClass/referenceExpression/classNoReceiver.kt");