drop method signature cache on any change inside if it's non-physical (IDEA-132447)

This commit is contained in:
peter
2014-11-17 13:09:33 +01:00
parent bc4d37ea48
commit ac22a507da
3 changed files with 51 additions and 3 deletions
@@ -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);
}
@@ -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) {}
<caret>
}
""").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) {
<caret>
}
}
"""
}
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");
}
}
@@ -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> T getCachedValue(@NotNull PsiElement psi, @NotNull CachedValueProvider<T> provider) {
public static <T> T getCachedValue(@NotNull final PsiElement psi, @NotNull final CachedValueProvider<T> provider) {
CachedValuesManager manager = getManager(psi.getProject());
return manager.getCachedValue(psi, manager.<T>getKeyForClass(provider.getClass()), provider, false);
return manager.getCachedValue(psi, manager.<T>getKeyForClass(provider.getClass()), new CachedValueProvider<T>() {
@Nullable
@Override
public Result<T> compute() {
Result<T> result = provider.compute();
if (result != null && !psi.isPhysical()) {
return Result.create(result.getValue(), ArrayUtil.append(result.getDependencyItems(), psi));
}
return result;
}
}, false);
}
private final ConcurrentMap<String, Key<CachedValue>> keyForProvider = ContainerUtil.newConcurrentMap();