blob: c99f9fd1c8e8962c05d042af3470cbf8d938f836 [file] [log] [blame]
/*
* Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.plugins.groovy.lang.psi.util;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.Computable;
import com.intellij.openapi.util.Condition;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.RecursionManager;
import com.intellij.pom.java.LanguageLevel;
import com.intellij.psi.*;
import com.intellij.psi.impl.PsiClassImplUtil;
import com.intellij.psi.infos.CandidateInfo;
import com.intellij.psi.scope.NameHint;
import com.intellij.psi.scope.PsiScopeProcessor;
import com.intellij.psi.util.*;
import com.intellij.psi.util.PsiUtil;
import com.intellij.util.ArrayUtil;
import com.intellij.util.Function;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.hash.HashSet;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.groovy.GroovyLanguage;
import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.GrModifierList;
import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.annotation.GrAnnotation;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrField;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrClosableBlock;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrEnumConstantInitializer;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrReferenceList;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinition;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinitionBody;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrAccessorMethod;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrGdkMethod;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrReflectedMethod;
import org.jetbrains.plugins.groovy.lang.psi.api.types.GrCodeReferenceElement;
import org.jetbrains.plugins.groovy.lang.psi.impl.GrAnnotationUtil;
import org.jetbrains.plugins.groovy.lang.psi.impl.GroovyPsiManager;
import org.jetbrains.plugins.groovy.lang.psi.impl.PsiImplUtil;
import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil;
import org.jetbrains.plugins.groovy.lang.psi.impl.statements.typedef.GrTypeDefinitionImpl;
import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.GrScriptField;
import org.jetbrains.plugins.groovy.lang.resolve.CollectClassMembersUtil;
import org.jetbrains.plugins.groovy.lang.resolve.ResolveUtil;
import org.jetbrains.plugins.groovy.lang.resolve.processors.ClassHint;
import java.util.*;
/**
* @author Maxim.Medvedev
*/
public class GrClassImplUtil {
private static final Logger LOG = Logger.getInstance(GrClassImplUtil.class);
private static final Condition<PsiClassType> IS_GROOVY_OBJECT = new Condition<PsiClassType>() {
@Override
public boolean value(PsiClassType psiClassType) {
return TypesUtil.isClassType(psiClassType, GroovyCommonClassNames.DEFAULT_BASE_CLASS_NAME);
}
};
private GrClassImplUtil() {
}
@Nullable
public static PsiClass findInnerClassByName(GrTypeDefinition grType, String name, boolean checkBases) {
if (!checkBases) {
for (PsiClass inner : grType.getInnerClasses()) {
if (name.equals(inner.getName())) return inner;
}
return null;
}
else {
Map<String, CandidateInfo> innerClasses = CollectClassMembersUtil.getAllInnerClasses(grType, true);
final CandidateInfo info = innerClasses.get(name);
return info == null ? null : (PsiClass)info.getElement();
}
}
@Nullable
public static PsiClass getSuperClass(GrTypeDefinition grType) {
final PsiClassType[] extendsList = grType.getExtendsListTypes();
if (extendsList.length == 0) return getBaseClass(grType);
final PsiClass superClass = extendsList[0].resolve();
return superClass != null ? superClass : getBaseClass(grType);
}
@Nullable
public static PsiClass getBaseClass(GrTypeDefinition grType) {
if (grType.isEnum()) {
return JavaPsiFacade.getInstance(grType.getProject()).findClass(CommonClassNames.JAVA_LANG_ENUM, grType.getResolveScope());
}
else {
return JavaPsiFacade.getInstance(grType.getProject()).findClass(CommonClassNames.JAVA_LANG_OBJECT, grType.getResolveScope());
}
}
@NotNull
public static PsiClassType[] getExtendsListTypes(GrTypeDefinition grType) {
final PsiClassType[] extendsTypes = getReferenceListTypes(grType.getExtendsClause());
if (grType.isInterface()) {
return extendsTypes;
}
for (PsiClassType type : extendsTypes) {
final PsiClass superClass = type.resolve();
if (superClass instanceof GrTypeDefinition && !superClass.isInterface() ||
superClass != null && GroovyCommonClassNames.GROOVY_OBJECT_SUPPORT.equals(superClass.getQualifiedName())) {
return extendsTypes;
}
}
PsiClass grObSupport = GroovyPsiManager.getInstance(grType.getProject()).findClassWithCache(GroovyCommonClassNames.GROOVY_OBJECT_SUPPORT, grType.getResolveScope());
if (grObSupport != null) {
final PsiClassType type = JavaPsiFacade.getInstance(grType.getProject()).getElementFactory().createType(grObSupport);
return ArrayUtil.append(extendsTypes, type, PsiClassType.ARRAY_FACTORY);
}
return extendsTypes;
}
@NotNull
public static PsiClassType[] getImplementsListTypes(GrTypeDefinition grType) {
Set<PsiClass> visited = new HashSet<PsiClass>();
List<PsiClassType> result = new ArrayList<PsiClassType>();
getImplementListsInner(grType, result, visited);
return result.toArray(new PsiClassType[result.size()]);
}
private static void getImplementListsInner(GrTypeDefinition grType, List<PsiClassType> result, Set<PsiClass> visited) {
if (!visited.add(grType)) return;
final PsiClassType[] implementsTypes = getReferenceListTypes(grType.getImplementsClause());
List<PsiClassType> fromDelegates = getImplementsFromDelegate(grType, visited);
if (fromDelegates != null) {
result.addAll(fromDelegates);
}
result.addAll(Arrays.asList(implementsTypes));
if (!grType.isInterface() &&
!ContainerUtil.or(implementsTypes, IS_GROOVY_OBJECT) &&
!ContainerUtil.or(getReferenceListTypes(grType.getExtendsClause()), IS_GROOVY_OBJECT)) {
result.add(getGroovyObjectType(grType));
}
}
@Nullable
private static List<PsiClassType> getImplementsFromDelegate(@NotNull final GrTypeDefinition grType, final Set<PsiClass> visited) {
return RecursionManager.doPreventingRecursion(grType, true, new Computable<List<PsiClassType>>() {
@Override
public List<PsiClassType> compute() {
List<PsiClassType> result = new ArrayList<PsiClassType>();
final GrField[] fields = grType.getCodeFields();
for (GrField field : fields) {
final PsiAnnotation delegate = PsiImplUtil.getAnnotation(field, GroovyCommonClassNames.GROOVY_LANG_DELEGATE);
if (delegate == null) continue;
final boolean shouldImplement = shouldImplementDelegatedInterfaces(delegate);
if (!shouldImplement) continue;
final PsiType type = field.getDeclaredType();
if (!(type instanceof PsiClassType)) continue;
final PsiClass psiClass = ((PsiClassType)type).resolve();
if (psiClass == null) continue;
if (psiClass instanceof GrTypeDefinition) {
getImplementListsInner((GrTypeDefinition)psiClass, result, visited);
}
else {
result.addAll(Arrays.asList(psiClass.getImplementsListTypes()));
}
if (psiClass.isInterface()) {
result.add((PsiClassType)type);
}
}
return result;
}
});
}
public static PsiClassType getGroovyObjectType(@NotNull PsiElement context) {
return TypesUtil.createTypeByFQClassName(GroovyCommonClassNames.DEFAULT_BASE_CLASS_NAME, context);
}
@NotNull
public static PsiClassType[] getSuperTypes(GrTypeDefinition grType) {
PsiClassType[] extendsList = grType.getExtendsListTypes();
if (extendsList.length == 0) {
extendsList = new PsiClassType[]{createBaseClassType(grType)};
}
return ArrayUtil.mergeArrays(extendsList, grType.getImplementsListTypes(), PsiClassType.ARRAY_FACTORY);
}
public static PsiClassType createBaseClassType(GrTypeDefinition grType) {
if (grType.isEnum()) {
return TypesUtil.createTypeByFQClassName(CommonClassNames.JAVA_LANG_ENUM, grType);
}
return TypesUtil.getJavaLangObject(grType);
}
@NotNull
public static PsiMethod[] getAllMethods(final GrTypeDefinition grType) {
return CachedValuesManager.getCachedValue(grType, new CachedValueProvider<PsiMethod[]>() {
@Nullable
@Override
public Result<PsiMethod[]> compute() {
List<PsiMethod> list = ContainerUtil.newArrayList();
getAllMethodsInner(grType, list, new HashSet<PsiClass>());
return Result.create(list.toArray(new PsiMethod[list.size()]), PsiModificationTracker.JAVA_STRUCTURE_MODIFICATION_COUNT, grType);
}
});
}
@NotNull
public static List<PsiMethod> getAllMethods(Collection<? extends PsiClass> classes) {
List<PsiMethod> allMethods = new ArrayList<PsiMethod>();
HashSet<PsiClass> visited = new HashSet<PsiClass>();
for (PsiClass psiClass : classes) {
getAllMethodsInner(psiClass, allMethods, visited);
}
return allMethods;
}
private static void getAllMethodsInner(PsiClass clazz, List<PsiMethod> allMethods, HashSet<PsiClass> visited) {
if (visited.contains(clazz)) return;
visited.add(clazz);
ContainerUtil.addAll(allMethods, clazz.getMethods());
final PsiClass[] supers = clazz.getSupers();
for (PsiClass aSuper : supers) {
getAllMethodsInner(aSuper, allMethods, visited);
}
}
private static PsiClassType[] getReferenceListTypes(@Nullable GrReferenceList list) {
if (list == null) return PsiClassType.EMPTY_ARRAY;
return list.getReferencedTypes();
}
public static PsiClass[] getInterfaces(GrTypeDefinition grType) {
final PsiClassType[] implementsListTypes = grType.getImplementsListTypes();
List<PsiClass> result = new ArrayList<PsiClass>(implementsListTypes.length);
for (PsiClassType type : implementsListTypes) {
final PsiClass psiClass = type.resolve();
if (psiClass != null) result.add(psiClass);
}
return result.toArray(new PsiClass[result.size()]);
}
@NotNull
public static PsiClass[] getSupers(GrTypeDefinition grType) {
PsiClassType[] superTypes = grType.getSuperTypes();
List<PsiClass> result = new ArrayList<PsiClass>();
for (PsiClassType superType : superTypes) {
PsiClass superClass = superType.resolve();
if (superClass != null) {
result.add(superClass);
}
}
return result.toArray(new PsiClass[result.size()]);
}
public static boolean processDeclarations(@NotNull GrTypeDefinition grType,
@NotNull PsiScopeProcessor processor,
@NotNull ResolveState state,
@Nullable PsiElement lastParent,
@NotNull PsiElement place) {
if (place instanceof GrCodeReferenceElement && lastParent instanceof GrModifierList) {
final PsiElement possibleAnnotation = PsiTreeUtil.skipParentsOfType(place, GrCodeReferenceElement.class);
if (possibleAnnotation instanceof GrAnnotation && possibleAnnotation.getParent() == lastParent) {
return true; //don't process class members while resolving annotation which annotates current class
}
}
for (final PsiTypeParameter typeParameter : grType.getTypeParameters()) {
if (!ResolveUtil.processElement(processor, typeParameter, state)) return false;
}
NameHint nameHint = processor.getHint(NameHint.KEY);
String name = nameHint == null ? null : nameHint.getName(state);
ClassHint classHint = processor.getHint(ClassHint.KEY);
final PsiSubstitutor substitutor = state.get(PsiSubstitutor.KEY);
final PsiElementFactory factory = JavaPsiFacade.getElementFactory(place.getProject());
boolean processInstanceMethods = (ResolveUtil.shouldProcessMethods(classHint) || ResolveUtil.shouldProcessProperties(classHint)) && shouldProcessInstanceMembers(grType, lastParent);
LanguageLevel level = PsiUtil.getLanguageLevel(place);
if (ResolveUtil.shouldProcessProperties(classHint)) {
Map<String, CandidateInfo> fieldsMap = CollectClassMembersUtil.getAllFields(grType);
if (name != null) {
CandidateInfo fieldInfo = fieldsMap.get(name);
if (fieldInfo != null) {
if (!processField(grType, processor, state, place, processInstanceMethods, substitutor, factory, level, fieldInfo)) {
return false;
}
}
else if (grType.isTrait() && lastParent != null) {
PsiField field = findFieldByName(grType, name, false, true);
if (field != null && field.hasModifierProperty(PsiModifier.PUBLIC)) {
if (!processField(grType, processor, state, place, processInstanceMethods, substitutor, factory, level, new CandidateInfo(field, PsiSubstitutor.EMPTY))) {
return false;
}
}
}
}
else {
for (CandidateInfo info : fieldsMap.values()) {
if (!processField(grType, processor, state, place, processInstanceMethods, substitutor, factory, level, info)) {
return false;
}
}
if (grType.isTrait() && lastParent != null) {
for (PsiField field : CollectClassMembersUtil.getFields(grType, true)) {
if (field.hasModifierProperty(PsiModifier.PUBLIC)) {
if (!processField(grType, processor, state, place, processInstanceMethods, substitutor, factory, level, new CandidateInfo(field, PsiSubstitutor.EMPTY))) {
return false;
}
}
}
}
}
}
if (ResolveUtil.shouldProcessMethods(classHint)) {
Map<String, List<CandidateInfo>> methodsMap = CollectClassMembersUtil.getAllMethods(grType, true);
boolean isPlaceGroovy = place.getLanguage() == GroovyLanguage.INSTANCE;
if (name == null) {
for (List<CandidateInfo> list : methodsMap.values()) {
for (CandidateInfo info : list) {
if (!processMethod(grType, processor, state, place, processInstanceMethods, substitutor, factory, level, isPlaceGroovy, info)) {
return false;
}
}
}
}
else {
List<CandidateInfo> byName = methodsMap.get(name);
if (byName != null) {
for (CandidateInfo info : byName) {
if (!processMethod(grType, processor, state, place, processInstanceMethods, substitutor, factory, level, isPlaceGroovy, info)) {
return false;
}
}
}
}
}
final GrTypeDefinitionBody body = grType.getBody();
if (body != null) {
if (ResolveUtil.shouldProcessClasses(classHint)) {
for (PsiClass innerClass : getInnerClassesForResolve(grType, lastParent, place)) {
final String innerClassName = innerClass.getName();
if (nameHint != null && !innerClassName.equals(nameHint.getName(state))) {
continue;
}
if (!processor.execute(innerClass, state)) {
return false;
}
}
}
}
return true;
}
private static boolean processField(@NotNull GrTypeDefinition grType,
@NotNull PsiScopeProcessor processor,
@NotNull ResolveState state,
@NotNull PsiElement place,
boolean processInstanceMethods,
@NotNull PsiSubstitutor substitutor,
@NotNull PsiElementFactory factory,
@NotNull LanguageLevel level, CandidateInfo fieldInfo) {
final PsiField field = (PsiField)fieldInfo.getElement();
if (!processInstanceMember(processInstanceMethods, field) || isSameDeclaration(place, field)) {
return true;
}
LOG.assertTrue(field.getContainingClass() != null);
final PsiSubstitutor finalSubstitutor = PsiClassImplUtil.obtainFinalSubstitutor(field.getContainingClass(), fieldInfo.getSubstitutor(), grType, substitutor, factory, level);
return processor.execute(field, state.put(PsiSubstitutor.KEY, finalSubstitutor));
}
private static boolean processMethod(@NotNull GrTypeDefinition grType,
@NotNull PsiScopeProcessor processor,
@NotNull ResolveState state,
@NotNull PsiElement place,
boolean processInstanceMethods,
@NotNull PsiSubstitutor substitutor,
@NotNull PsiElementFactory factory,
@NotNull LanguageLevel level,
boolean placeGroovy,
@NotNull CandidateInfo info) {
PsiMethod method = (PsiMethod)info.getElement();
if (!processInstanceMember(processInstanceMethods, method) || isSameDeclaration(place, method) || !isMethodVisible(placeGroovy, method)) {
return true;
}
LOG.assertTrue(method.getContainingClass() != null);
final PsiSubstitutor finalSubstitutor = PsiClassImplUtil.obtainFinalSubstitutor(method.getContainingClass(), info.getSubstitutor(), grType, substitutor, factory, level);
return processor.execute(method, state.put(PsiSubstitutor.KEY, finalSubstitutor));
}
private static boolean shouldProcessInstanceMembers(@NotNull GrTypeDefinition grType, @Nullable PsiElement lastParent) {
if (lastParent != null) {
final GrModifierList modifierList = grType.getModifierList();
if (modifierList != null && modifierList.findAnnotation(GroovyCommonClassNames.GROOVY_LANG_CATEGORY) != null) {
return false;
}
}
return true;
}
private static boolean processInstanceMember(boolean shouldProcessInstance, @NotNull PsiMember member) {
if (shouldProcessInstance) return true;
if (member instanceof GrReflectedMethod) {
return ((GrReflectedMethod)member).getBaseMethod().hasModifierProperty(PsiModifier.STATIC);
}
else {
return member.hasModifierProperty(PsiModifier.STATIC);
}
}
@NotNull
private static List<PsiClass> getInnerClassesForResolve(@NotNull final GrTypeDefinition grType,
@Nullable final PsiElement lastParent,
@NotNull final PsiElement place) {
if (lastParent instanceof GrReferenceList || PsiTreeUtil.getParentOfType(place, GrReferenceList.class) != null) {
return Arrays.asList(grType.getInnerClasses());
}
List<PsiClass> classes = RecursionManager.doPreventingRecursion(grType, true, new Computable<List<PsiClass>>() {
@Override
public List<PsiClass> compute() {
List<PsiClass> result = new ArrayList<PsiClass>();
for (CandidateInfo info : CollectClassMembersUtil.getAllInnerClasses(grType, false).values()) {
final PsiClass inner = (PsiClass)info.getElement();
final PsiClass containingClass = inner.getContainingClass();
assert containingClass != null;
if (lastParent == null || !containingClass.isInterface() || PsiTreeUtil.isAncestor(containingClass, place, false)) {
ContainerUtil.addIfNotNull(result, inner);
}
}
return result;
}
});
if (classes == null) {
return Arrays.asList(grType.getInnerClasses());
}
return classes;
}
public static boolean isSameDeclaration(PsiElement place, PsiElement element) {
if (element instanceof GrAccessorMethod) element = ((GrAccessorMethod)element).getProperty();
if (!(element instanceof GrField)) return false;
if (element instanceof GrScriptField) element = ((GrScriptField)element).getOriginalVariable();
while (place != null) {
if (place == element) return true;
place = place.getParent();
if (place instanceof GrClosableBlock) return false;
if (place instanceof GrEnumConstantInitializer) return false;
}
return false;
}
private static boolean isMethodVisible(boolean isPlaceGroovy, PsiMethod method) {
return isPlaceGroovy || !(method instanceof GrGdkMethod);
}
@Nullable
public static PsiMethod findMethodBySignature(GrTypeDefinition grType, PsiMethod patternMethod, boolean checkBases) {
final MethodSignature patternSignature = patternMethod.getSignature(PsiSubstitutor.EMPTY);
for (PsiMethod method : findMethodsByName(grType, patternMethod.getName(), checkBases, false)) {
MethodSignature signature = getSignatureForInheritor(method, grType);
if (patternSignature.equals(signature)) return method;
}
return null;
}
private static PsiMethod[] findMethodsByName(GrTypeDefinition grType,
String name,
boolean checkBases,
boolean includeSyntheticAccessors) {
if (!checkBases) {
List<PsiMethod> result = new ArrayList<PsiMethod>();
for (PsiMethod method : CollectClassMembersUtil.getMethods(grType, includeSyntheticAccessors)) {
if (name.equals(method.getName())) result.add(method);
}
return result.toArray(new PsiMethod[result.size()]);
}
Map<String, List<CandidateInfo>> methodsMap = CollectClassMembersUtil.getAllMethods(grType, includeSyntheticAccessors);
return PsiImplUtil.mapToMethods(methodsMap.get(name));
}
@NotNull
public static PsiMethod[] findMethodsBySignature(GrTypeDefinition grType, PsiMethod patternMethod, boolean checkBases) {
return findMethodsBySignature(grType, patternMethod, checkBases, true);
}
@NotNull
public static PsiMethod[] findCodeMethodsBySignature(GrTypeDefinition grType, PsiMethod patternMethod, boolean checkBases) {
return findMethodsBySignature(grType, patternMethod, checkBases, false);
}
@NotNull
public static PsiMethod[] findMethodsByName(GrTypeDefinition grType, @NonNls String name, boolean checkBases) {
return findMethodsByName(grType, name, checkBases, true);
}
private static PsiMethod[] findMethodsBySignature(GrTypeDefinition grType,
PsiMethod patternMethod,
boolean checkBases,
boolean includeSynthetic) {
ArrayList<PsiMethod> result = new ArrayList<PsiMethod>();
final MethodSignature patternSignature = patternMethod.getSignature(PsiSubstitutor.EMPTY);
for (PsiMethod method : findMethodsByName(grType, patternMethod.getName(), checkBases, includeSynthetic)) {
MethodSignature signature = getSignatureForInheritor(method, grType);
if (patternSignature.equals(signature)) {
result.add(method);
}
}
return result.toArray(new PsiMethod[result.size()]);
}
@Nullable
private static MethodSignature getSignatureForInheritor(@NotNull PsiMethod methodFromSuperClass, @NotNull GrTypeDefinition inheritor) {
final PsiClass clazz = methodFromSuperClass.getContainingClass();
if (clazz == null) return null;
PsiSubstitutor superSubstitutor = TypeConversionUtil.getClassSubstitutor(clazz, inheritor, PsiSubstitutor.EMPTY);
if (superSubstitutor == null) return null;
return methodFromSuperClass.getSignature(superSubstitutor);
}
@NotNull
public static PsiMethod[] findCodeMethodsByName(GrTypeDefinition grType, @NonNls String name, boolean checkBases) {
return findMethodsByName(grType, name, checkBases, false);
}
@NotNull
public static List<Pair<PsiMethod, PsiSubstitutor>> findMethodsAndTheirSubstitutorsByName(GrTypeDefinition grType,
String name,
boolean checkBases) {
final ArrayList<Pair<PsiMethod, PsiSubstitutor>> result = new ArrayList<Pair<PsiMethod, PsiSubstitutor>>();
if (!checkBases) {
final PsiMethod[] methods = grType.findMethodsByName( name, false);
for (PsiMethod method : methods) {
result.add(Pair.create(method, PsiSubstitutor.EMPTY));
}
}
else {
final Map<String, List<CandidateInfo>> map = CollectClassMembersUtil.getAllMethods(grType, true);
final List<CandidateInfo> candidateInfos = map.get(name);
if (candidateInfos != null) {
for (CandidateInfo info : candidateInfos) {
final PsiElement element = info.getElement();
result.add(Pair.create((PsiMethod)element, info.getSubstitutor()));
}
}
}
return result;
}
@NotNull
public static List<Pair<PsiMethod, PsiSubstitutor>> getAllMethodsAndTheirSubstitutors(GrTypeDefinition grType) {
final Map<String, List<CandidateInfo>> allMethodsMap = CollectClassMembersUtil.getAllMethods(grType, true);
List<Pair<PsiMethod, PsiSubstitutor>> result = new ArrayList<Pair<PsiMethod, PsiSubstitutor>>();
for (List<CandidateInfo> infos : allMethodsMap.values()) {
for (CandidateInfo info : infos) {
result.add(Pair.create((PsiMethod)info.getElement(), info.getSubstitutor()));
}
}
return result;
}
@Nullable
public static PsiField findFieldByName(GrTypeDefinition grType, String name, boolean checkBases, boolean includeSynthetic) {
if (!checkBases) {
for (PsiField field : CollectClassMembersUtil.getFields(grType, includeSynthetic)) {
if (name.equals(field.getName())) return field;
}
return null;
}
Map<String, CandidateInfo> fieldsMap = CollectClassMembersUtil.getAllFields(grType, includeSynthetic);
final CandidateInfo info = fieldsMap.get(name);
return info == null ? null : (PsiField)info.getElement();
}
public static PsiField[] getAllFields(GrTypeDefinition grType) {
Map<String, CandidateInfo> fieldsMap = CollectClassMembersUtil.getAllFields(grType);
return ContainerUtil.map2Array(fieldsMap.values(), PsiField.class, new Function<CandidateInfo, PsiField>() {
@Override
public PsiField fun(CandidateInfo entry) {
return (PsiField)entry.getElement();
}
});
}
public static boolean isClassEquivalentTo(GrTypeDefinitionImpl definition, PsiElement another) {
return PsiClassImplUtil.isClassEquivalentTo(definition, another);
}
private static boolean shouldImplementDelegatedInterfaces(PsiAnnotation delegate) {
final Boolean result = GrAnnotationUtil.inferBooleanAttribute(delegate, "interfaces");
return result == null || result.booleanValue();
}
public static void addExpandingReflectedMethods(List<PsiMethod> result, PsiMethod method) {
if (method instanceof GrMethod) {
final GrReflectedMethod[] reflectedMethods = ((GrMethod)method).getReflectedMethods();
if (reflectedMethods.length > 0) {
result.addAll(Arrays.asList(reflectedMethods));
return;
}
}
result.add(method);
}
public static void collectMethodsFromBody(@NotNull GrTypeDefinition definition, List<PsiMethod> result) {
for (GrMethod method : definition.getCodeMethods()) {
addExpandingReflectedMethods(result, method);
}
for (GrField field : definition.getFields()) {
if (!field.isProperty()) continue;
ContainerUtil.addAll(result, field.getGetters());
ContainerUtil.addIfNotNull(result, field.getSetter());
}
}
}