diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/PsiClassImplUtil.java b/java/java-psi-impl/src/com/intellij/psi/impl/PsiClassImplUtil.java index 748d907aec47..107bff5e60f2 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/PsiClassImplUtil.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/PsiClassImplUtil.java @@ -25,6 +25,7 @@ import com.intellij.pom.java.LanguageLevel; import com.intellij.psi.*; import com.intellij.psi.filters.OrFilter; import com.intellij.psi.impl.compiled.ClsElementImpl; +import com.intellij.psi.impl.source.ClassInnerStuffCache; import com.intellij.psi.impl.source.PsiImmediateClassType; import com.intellij.psi.infos.MethodCandidateInfo; import com.intellij.psi.scope.ElementClassFilter; @@ -56,18 +57,15 @@ import java.util.*; /** * @author ik - * Date: 24.10.2003 + * @since 24.10.2003 */ public class PsiClassImplUtil { private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.PsiClassImplUtil"); private static final Key> MAP_IN_CLASS_KEY = Key.create("MAP_KEY"); + private static final String VALUES_METHOD = "values"; + private static final String VALUE_OF_METHOD = "valueOf"; - private PsiClassImplUtil() { - } - - public static void cacheEverything(PsiClass aClass) { - getValues(aClass).getValue(aClass); - } + private PsiClassImplUtil() { } @NotNull public static PsiField[] getAllFields(@NotNull PsiClass aClass) { @@ -126,7 +124,7 @@ public class PsiClassImplUtil { for (final PsiMethod method : methodsByName) { final PsiClass superClass = method.getContainingClass(); final PsiSubstitutor substitutor; - if (checkBases && !aClass.equals(superClass)) { + if (checkBases && !aClass.equals(superClass) && superClass != null) { substitutor = TypeConversionUtil.getSuperClassSubstitutor(superClass, aClass, PsiSubstitutor.EMPTY); } else { @@ -425,6 +423,25 @@ public class PsiClassImplUtil { } } + public static boolean processDeclarationsInEnum(@NotNull PsiScopeProcessor processor, + @NotNull ResolveState state, + @NotNull ClassInnerStuffCache innerStuffCache) { + ElementClassHint classHint = processor.getHint(ElementClassHint.KEY); + if (classHint == null || classHint.shouldProcess(ElementClassHint.DeclarationKind.METHOD)) { + NameHint nameHint = processor.getHint(NameHint.KEY); + if ((nameHint == null || VALUES_METHOD.equals(nameHint.getName(state)))) { + PsiMethod method = innerStuffCache.getValuesMethod(); + if (method != null && !processor.execute(method, ResolveState.initial())) return false; + } + if ((nameHint == null || VALUE_OF_METHOD.equals(nameHint.getName(state)))) { + PsiMethod method = innerStuffCache.getValueOfMethod(); + if (method != null && !processor.execute(method, ResolveState.initial())) return false; + } + } + + return true; + } + public static boolean processDeclarationsInClass(@NotNull PsiClass aClass, @NotNull final PsiScopeProcessor processor, @NotNull ResolveState state, @@ -560,7 +577,7 @@ public class PsiClassImplUtil { if (candidateMethod.isConstructor() != ((MethodResolverProcessor)processor).isConstructor()) continue; } final PsiClass containingClass = candidateMethod.getContainingClass(); - if (visited != null && visited.contains(candidateMethod.getContainingClass())) { + if (containingClass == null || visited != null && visited.contains(containingClass)) { continue; } diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClsClassImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClsClassImpl.java index 26a2e7fa0672..c6d9962392c6 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClsClassImpl.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClsClassImpl.java @@ -448,6 +448,10 @@ public class ClsClassImpl extends ClsMemberImpl> implements PsiE @NotNull ResolveState state, PsiElement lastParent, @NotNull PsiElement place) { + if (isEnum()) { + if (!PsiClassImplUtil.processDeclarationsInEnum(processor, state, myInnersCache)) return false; + } + LanguageLevel level = processor instanceof MethodsProcessor ? ((MethodsProcessor)processor).getLanguageLevel() : PsiUtil.getLanguageLevel(place); return PsiClassImplUtil.processDeclarationsInClass(this, processor, state, null, lastParent, place, level, false); } diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/ClassInnerStuffCache.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/ClassInnerStuffCache.java index 33fe5b6658f4..429c276303c9 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/ClassInnerStuffCache.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/ClassInnerStuffCache.java @@ -16,13 +16,11 @@ package com.intellij.psi.impl.source; import com.intellij.openapi.util.SimpleModificationTracker; -import com.intellij.psi.ExternallyDefinedPsiElement; -import com.intellij.psi.PsiClass; -import com.intellij.psi.PsiField; -import com.intellij.psi.PsiMethod; +import com.intellij.psi.*; import com.intellij.psi.augment.PsiAugmentProvider; import com.intellij.psi.impl.PsiClassImplUtil; import com.intellij.psi.impl.PsiImplUtil; +import com.intellij.psi.impl.light.LightMethod; import com.intellij.psi.util.CachedValueProvider; import com.intellij.psi.util.CachedValuesManager; import com.intellij.util.ArrayUtil; @@ -139,6 +137,36 @@ public class ClassInnerStuffCache { } } + @Nullable + public PsiMethod getValuesMethod() { + return !myClass.isEnum() || myClass.getName() == null ? null : CachedValuesManager.getCachedValue(myClass, new CachedValueProvider() { + @Nullable + @Override + public Result compute() { + PsiElementFactory factory = JavaPsiFacade.getInstance(myClass.getProject()).getElementFactory(); + String text = "public static " + myClass.getName() + "[] values() { }"; + PsiMethod physicalMethod = factory.createMethodFromText(text, myClass); + PsiMethod method = new LightMethod(myClass.getManager(), physicalMethod, myClass); + return new Result(method, OUT_OF_CODE_BLOCK_MODIFICATION_COUNT, myTracker); + } + }); + } + + @Nullable + public PsiMethod getValueOfMethod() { + return !myClass.isEnum() || myClass.getName() == null ? null : CachedValuesManager.getCachedValue(myClass, new CachedValueProvider() { + @Nullable + @Override + public Result compute() { + PsiElementFactory factory = JavaPsiFacade.getInstance(myClass.getProject()).getElementFactory(); + String text = "public static " + myClass.getName() + " valueOf(java.lang.String name) throws java.lang.IllegalArgumentException { }"; + PsiMethod physicalMethod = factory.createMethodFromText(text, myClass); + PsiMethod method = new LightMethod(myClass.getManager(), physicalMethod, myClass); + return new Result(method, OUT_OF_CODE_BLOCK_MODIFICATION_COUNT, myTracker); + } + }); + } + private PsiField[] getAllFields() { List own = myClass.getOwnFields(); List ext = PsiAugmentProvider.collectAugments(myClass, PsiField.class); diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiClassImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiClassImpl.java index f66f41932145..0ede3a39b19a 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiClassImpl.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiClassImpl.java @@ -23,17 +23,15 @@ import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.ui.Queryable; import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.UserDataHolder; +import com.intellij.pom.java.LanguageLevel; import com.intellij.psi.*; import com.intellij.psi.impl.*; import com.intellij.psi.impl.java.stubs.JavaStubElementTypes; import com.intellij.psi.impl.java.stubs.PsiClassStub; -import com.intellij.psi.impl.light.LightMethod; import com.intellij.psi.impl.source.tree.ChildRole; import com.intellij.psi.impl.source.tree.CompositeElement; import com.intellij.psi.impl.source.tree.SharedImplUtil; import com.intellij.psi.javadoc.PsiDocComment; -import com.intellij.psi.scope.ElementClassHint; -import com.intellij.psi.scope.NameHint; import com.intellij.psi.scope.PsiScopeProcessor; import com.intellij.psi.search.SearchScope; import com.intellij.psi.stubs.IStubElementType; @@ -42,7 +40,6 @@ import com.intellij.psi.stubs.StubElement; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.PsiUtil; import com.intellij.util.IncorrectOperationException; -import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -56,12 +53,7 @@ public class PsiClassImpl extends JavaStubPsiElement> implements private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.source.PsiClassImpl"); private final ClassInnerStuffCache myInnersCache = new ClassInnerStuffCache(this); - - private volatile PsiMethod myValuesMethod; - private volatile PsiMethod myValueOfMethod; private volatile String myCachedName; - @NonNls private static final String VALUES_METHOD = "values"; - @NonNls private static final String VALUE_OF_METHOD = "valueOf"; public PsiClassImpl(final PsiClassStub stub) { this(stub, JavaStubElementTypes.CLASS); @@ -102,8 +94,6 @@ public class PsiClassImpl extends JavaStubPsiElement> implements private void dropCaches() { myInnersCache.dropCaches(); myCachedName = null; - myValueOfMethod = null; - myValuesMethod = null; } @Override @@ -494,30 +484,11 @@ public class PsiClassImpl extends JavaStubPsiElement> implements @Override public boolean processDeclarations(@NotNull PsiScopeProcessor processor, @NotNull ResolveState state, PsiElement lastParent, @NotNull PsiElement place) { if (isEnum()) { - String myName = getName(); - if (myName != null) { - try { - final NameHint nameHint = processor.getHint(NameHint.KEY); - final ElementClassHint classHint = processor.getHint(ElementClassHint.KEY); - String nameToSearch = nameHint == null ? null : nameHint.getName(state); - if ((nameToSearch == null || VALUES_METHOD.equals(nameToSearch)) && - (classHint == null || classHint.shouldProcess(ElementClassHint.DeclarationKind.METHOD))) { - PsiMethod method = getValuesMethod(); - if (method != null && !processor.execute(method, ResolveState.initial())) return false; - } - if ((nameToSearch == null || VALUE_OF_METHOD.equals(nameToSearch)) && - (classHint == null || classHint.shouldProcess(ElementClassHint.DeclarationKind.METHOD))) { - PsiMethod method = getValueOfMethod(); - if (method != null && !processor.execute(method, ResolveState.initial())) return false; - } - } - catch (IncorrectOperationException e) { - LOG.error(e); - } - } + if (!PsiClassImplUtil.processDeclarationsInEnum(processor, state, myInnersCache)) return false; } - return PsiClassImplUtil.processDeclarationsInClass(this, processor, state, null, lastParent, place, PsiUtil.getLanguageLevel(place), false); + LanguageLevel level = PsiUtil.getLanguageLevel(place); + return PsiClassImplUtil.processDeclarationsInClass(this, processor, state, null, lastParent, place, level, false); } @Override @@ -706,23 +677,6 @@ public class PsiClassImpl extends JavaStubPsiElement> implements @Nullable public PsiMethod getValuesMethod() { - PsiMethod method = myValuesMethod; - if (method == null && isEnum() && getName() != null) { - PsiElementFactory elementFactory = JavaPsiFacade.getInstance(getProject()).getElementFactory(); - final PsiMethod valuesMethod = elementFactory.createMethodFromText("public static " + getName() + "[] values() {}", this); - myValuesMethod = method = new LightMethod(getManager(), valuesMethod, this); - } - return method; - } - - @Nullable - public PsiMethod getValueOfMethod() { - PsiMethod method = myValueOfMethod; - if (method == null && isEnum() && getName() != null) { - PsiElementFactory elementFactory = JavaPsiFacade.getInstance(getProject()).getElementFactory(); - final PsiMethod valuesMethod = elementFactory.createMethodFromText("public static " + getName() + " valueOf(String name) throws java.lang.IllegalArgumentException {}", this); - myValueOfMethod = method = new LightMethod(getManager(), valuesMethod, this); - } - return method; + return myInnersCache.getValuesMethod(); } } diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting6/EnumSynthetics.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting6/EnumSynthetics.java new file mode 100644 index 000000000000..fa25bbff5ab4 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting6/EnumSynthetics.java @@ -0,0 +1,8 @@ +import java.lang.annotation.ElementType; + +class EnumSynthetics { + void m() { + //ElementType[] values = ElementType.values(); + ElementType type = ElementType.valueOf("TYPE"); + } +} diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/LightAdvHighlightingJdk6Test.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/LightAdvHighlightingJdk6Test.java index 8d2c8156dc18..671d151179fe 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/LightAdvHighlightingJdk6Test.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/LightAdvHighlightingJdk6Test.java @@ -62,6 +62,7 @@ public class LightAdvHighlightingJdk6Test extends LightDaemonAnalyzerTestCase { public void testUnhandledExceptionsValueOf() { doTest(true, false); } public void testUnsupportedFeatures7() { doTest(false, false); } public void testEnumInitializers() { doTest(false, false); } + public void testEnumSynthetics() { doTest(false, false); } public void testIDEA79251() { doTest(false, false); } public void testAgentPremain() { doTest(false, false);