mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-18 09:34:34 +07:00
IDEA-125900 (resolve of synthetic enum methods in class files fixed)
This commit is contained in:
@@ -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<ParameterizedCachedValue<MembersMap, PsiClass>> 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;
|
||||
}
|
||||
|
||||
|
||||
@@ -448,6 +448,10 @@ public class ClsClassImpl extends ClsMemberImpl<PsiClassStub<?>> 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);
|
||||
}
|
||||
|
||||
@@ -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<PsiMethod>() {
|
||||
@Nullable
|
||||
@Override
|
||||
public Result<PsiMethod> 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<PsiMethod>(method, OUT_OF_CODE_BLOCK_MODIFICATION_COUNT, myTracker);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public PsiMethod getValueOfMethod() {
|
||||
return !myClass.isEnum() || myClass.getName() == null ? null : CachedValuesManager.getCachedValue(myClass, new CachedValueProvider<PsiMethod>() {
|
||||
@Nullable
|
||||
@Override
|
||||
public Result<PsiMethod> 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<PsiMethod>(method, OUT_OF_CODE_BLOCK_MODIFICATION_COUNT, myTracker);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private PsiField[] getAllFields() {
|
||||
List<PsiField> own = myClass.getOwnFields();
|
||||
List<PsiField> ext = PsiAugmentProvider.collectAugments(myClass, PsiField.class);
|
||||
|
||||
@@ -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<PsiClassStub<?>> 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<PsiClassStub<?>> implements
|
||||
private void dropCaches() {
|
||||
myInnersCache.dropCaches();
|
||||
myCachedName = null;
|
||||
myValueOfMethod = null;
|
||||
myValuesMethod = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -494,30 +484,11 @@ public class PsiClassImpl extends JavaStubPsiElement<PsiClassStub<?>> 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<PsiClassStub<?>> 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();
|
||||
}
|
||||
}
|
||||
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
import java.lang.annotation.ElementType;
|
||||
|
||||
class EnumSynthetics {
|
||||
void m() {
|
||||
//ElementType[] values = ElementType.values();
|
||||
ElementType type = ElementType.valueOf("TYPE");
|
||||
}
|
||||
}
|
||||
+1
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user