From ac22a507da875d8ea0a29b4ff22af92186ae37a0 Mon Sep 17 00:00:00 2001 From: peter Date: Mon, 17 Nov 2014 13:05:59 +0100 Subject: [PATCH] drop method signature cache on any change inside if it's non-physical (IDEA-132447) --- .../psi/impl/PsiSuperMethodImplUtil.java | 1 + .../codeInsight/OverrideImplementTest.groovy | 37 ++++++++++++++++++- .../psi/util/CachedValuesManager.java | 16 +++++++- 3 files changed, 51 insertions(+), 3 deletions(-) diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/PsiSuperMethodImplUtil.java b/java/java-psi-impl/src/com/intellij/psi/impl/PsiSuperMethodImplUtil.java index e0db7701574d..87a45bf8cdeb 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/PsiSuperMethodImplUtil.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/PsiSuperMethodImplUtil.java @@ -375,6 +375,7 @@ public class PsiSuperMethodImplUtil { Project project = aClass == null ? method.getProject() : aClass.getProject(); // cache Cls method hierarchy until root changed Object dependency = method instanceof PsiCompiledElement ? ProjectRootModificationTracker.getInstance(project) : + !method.isPhysical() ? method : PsiModificationTracker.JAVA_STRUCTURE_MODIFICATION_COUNT; return CachedValueProvider.Result.create(result, dependency); } diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/OverrideImplementTest.groovy b/java/java-tests/testSrc/com/intellij/codeInsight/OverrideImplementTest.groovy index acec8be9ea0e..ad1e2c636690 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/OverrideImplementTest.groovy +++ b/java/java-tests/testSrc/com/intellij/codeInsight/OverrideImplementTest.groovy @@ -40,13 +40,48 @@ public class OverrideImplementTest extends LightCodeInsightFixtureTestCase { public void testOverrideInInterface() { doTest(false); } public void testMultipleInheritedThrows() {doTest(false);} + public void "test overriding overloaded method"() { + myFixture.addClass """package bar; +interface A { + void foo(Foo2 f); + void foo(Foo1 f); +} +""" + myFixture.addClass "package bar; class Foo1 {}" + myFixture.addClass "package bar; class Foo2 {}" + def file = myFixture.addClass("""package bar; +class Test implements A { + public void foo(Foo1 f) {} + +} +""").containingFile.virtualFile + myFixture.configureFromExistingVirtualFile(file) + + invokeAction(true) + + myFixture.checkResult """package bar; +class Test implements A { + public void foo(Foo1 f) {} + + @Override + public void foo(Foo2 f) { + + } +} +""" + } + private void doTest(boolean toImplement) { String name = getTestName(false); myFixture.configureByFile(BASE_DIR + "before" + name + ".java"); + invokeAction(toImplement) + myFixture.checkResultByFile(BASE_DIR + "after" + name + ".java"); + } + + private void invokeAction(boolean toImplement) { int offset = myFixture.getEditor().getCaretModel().getOffset(); PsiClass psiClass = PsiTreeUtil.findElementOfClassAtOffset(myFixture.getFile(), offset, PsiClass.class, false); assert psiClass != null; OverrideImplementUtil.chooseAndOverrideOrImplementMethods(getProject(), myFixture.getEditor(), psiClass, toImplement); - myFixture.checkResultByFile(BASE_DIR + "after" + name + ".java"); } } \ No newline at end of file diff --git a/platform/core-api/src/com/intellij/psi/util/CachedValuesManager.java b/platform/core-api/src/com/intellij/psi/util/CachedValuesManager.java index bb3812f5bb4d..726a07f0d0ca 100644 --- a/platform/core-api/src/com/intellij/psi/util/CachedValuesManager.java +++ b/platform/core-api/src/com/intellij/psi/util/CachedValuesManager.java @@ -22,9 +22,11 @@ import com.intellij.openapi.util.NotNullLazyKey; import com.intellij.openapi.util.UserDataHolder; import com.intellij.openapi.util.UserDataHolderEx; import com.intellij.psi.PsiElement; +import com.intellij.util.ArrayUtil; import com.intellij.util.ConcurrencyUtil; import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.util.concurrent.ConcurrentMap; @@ -120,9 +122,19 @@ public abstract class CachedValuesManager { * Create a cached value with the given provider and non-tracked return value, store it in PSI element's user data. If it's already stored, reuse it. * @return The cached value */ - public static T getCachedValue(@NotNull PsiElement psi, @NotNull CachedValueProvider provider) { + public static T getCachedValue(@NotNull final PsiElement psi, @NotNull final CachedValueProvider provider) { CachedValuesManager manager = getManager(psi.getProject()); - return manager.getCachedValue(psi, manager.getKeyForClass(provider.getClass()), provider, false); + return manager.getCachedValue(psi, manager.getKeyForClass(provider.getClass()), new CachedValueProvider() { + @Nullable + @Override + public Result compute() { + Result result = provider.compute(); + if (result != null && !psi.isPhysical()) { + return Result.create(result.getValue(), ArrayUtil.append(result.getDependencyItems(), psi)); + } + return result; + } + }, false); } private final ConcurrentMap> keyForProvider = ContainerUtil.newConcurrentMap();