19
19
import java.util.Collections;
20
20
import java.util.HashMap;
21
21
import java.util.HashSet;
22
import java.util.Iterator;
23
22
import java.util.LinkedList;
24
23
import java.util.List;
25
24
import java.util.Map;
28
26
import org.eclipse.cdt.core.dom.ast.ASTTypeUtil;
29
27
import org.eclipse.cdt.core.dom.ast.IASTDeclSpecifier;
85
83
* @see CPPClassTemplate
87
85
public class ClassTypeHelper {
88
private static final String DESTRUCTOR_OVERRIDE_KEY = "~"; //$NON-NLS-1$
90
86
public static IBinding[] getFriends(ICPPInternalClassTypeMixinHost host) {
91
87
if (host.getDefinition() == null) {
92
88
host.checkForDefinition();
283
279
* Returns all direct and indirect base classes.
284
280
* @param classType a class
285
* @return An array of visible base classes in arbitrary order.
281
* @return An array of base classes in arbitrary order.
287
283
public static ICPPClassType[] getAllBases(ICPPClassType classType, IASTNode point) {
288
284
HashSet<ICPPClassType> result= new HashSet<ICPPClassType>();
309
305
* Checks inheritance relationship between two classes.
310
306
* @return <code>true</code> if {@code subclass} is a subclass of {@code superclass}.
312
public static boolean isSubclass(ICPPClassType subclass, ICPPClassType superclass) {
313
ICPPBase[] bases= subclass.getBases();
308
public static boolean isSubclass(ICPPClassType subclass, ICPPClassType superclass, IASTNode point) {
309
ICPPBase[] bases= getBases(subclass, point);
314
310
for (ICPPBase base : bases) {
315
311
IBinding b= base.getBaseClass();
316
312
if (b instanceof ICPPClassType) {
350
346
* Returns methods either declared by the given class or generated by the compiler. Does not
351
347
* include methods declared in base classes.
353
private static ObjectSet<ICPPMethod> getOwnMethods(ICPPClassType classType, IASTNode point) {
349
public static ObjectSet<ICPPMethod> getOwnMethods(ICPPClassType classType, IASTNode point) {
354
350
ObjectSet<ICPPMethod> set= new ObjectSet<ICPPMethod>(4);
355
351
set.addAll(ClassTypeHelper.getDeclaredMethods(classType, point));
356
352
set.addAll(getImplicitMethods(classType, point));
617
613
if (visitedBefore != null)
618
614
return visitedBefore;
620
ICPPMethod[] methods= classType.getDeclaredMethods();
616
ICPPMethod[] methods= ClassTypeHelper.getDeclaredMethods(classType, point);
621
617
ICPPMethod candidate= null;
622
618
boolean hasOverridden= false;
623
619
for (ICPPMethod method : methods) {
624
if (CharArrayUtils.equals(methodName, method.getNameCharArray()) &&
625
functionTypesAllowOverride(methodType, method.getType())) {
620
if (methodName[0] == '~' && method.isDestructor()
621
|| (CharArrayUtils.equals(methodName, method.getNameCharArray())
622
&& functionTypesAllowOverride(methodType, method.getType()))) {
626
623
candidate= method;
627
624
hasOverridden= method.isVirtual();
868
* Checks whether class is abstract, i.e. has pure virtual functions that were
869
* not implemented in base after declaration.
871
* NOTE: The method produces complete results for template instantiations
872
* but doesn't take into account base classes and methods dependent on unspecified
873
* template parameters.
875
public static ICPPMethod[] getPureVirtualMethods(ICPPClassType classType, IASTNode point) {
876
Map<String, List<ICPPMethod>> result= collectPureVirtualMethods(classType,
877
new HashMap<ICPPClassType, Map<String, List<ICPPMethod>>>(), point);
879
int resultArraySize = 0;
880
for (List<ICPPMethod> methods : result.values()) {
881
resultArraySize += methods.size();
883
ICPPMethod[] resultArray = new ICPPMethod[resultArraySize];
884
int resultArrayIdx = 0;
885
for (List<ICPPMethod> methods : result.values()) {
886
for (ICPPMethod method : methods) {
887
resultArray[resultArrayIdx++] = method;
894
865
* Returns the visibility for a given <code>member</code> in the <code>host</code>.
895
866
* Throws an IllegalArgumentException if <code>member</code> is not a member of <code>host</code>
1035
1006
name = "<anonymous>"; //$NON-NLS-1$
1036
1007
return new IllegalArgumentException(name + " is not a member of " + classType.getName()); //$NON-NLS-1$
1039
private static Map<String, List<ICPPMethod>> collectPureVirtualMethods(ICPPClassType classType,
1040
Map<ICPPClassType, Map<String, List<ICPPMethod>>> cache, IASTNode point) {
1041
Map<String, List<ICPPMethod>> result = cache.get(classType);
1045
result= new HashMap<String, List<ICPPMethod>>();
1046
cache.put(classType, result);
1048
// Look at the pure virtual methods of the base classes
1049
Set<IBinding> handledBaseClasses= new HashSet<IBinding>();
1050
for (ICPPBase base : ClassTypeHelper.getBases(classType, point)) {
1051
final IBinding baseClass = base.getBaseClass();
1052
if (baseClass instanceof ICPPClassType && handledBaseClasses.add(baseClass)) {
1053
Map<String, List<ICPPMethod>> pureVirtuals = collectPureVirtualMethods((ICPPClassType) baseClass, cache, point);
1054
// Merge derived pure virtual methods
1055
for (String key : pureVirtuals.keySet()) {
1056
List<ICPPMethod> list = result.get(key);
1058
list= new ArrayList<ICPPMethod>();
1059
result.put(key, list);
1061
list.addAll(pureVirtuals.get(key));
1066
// Remove overridden pure-virtual methods and add in new pure virtuals.
1067
final ObjectSet<ICPPMethod> methods = getOwnMethods(classType, point);
1068
for (ICPPMethod method : methods) {
1069
String key= getMethodNameForOverrideKey(method);
1070
List<ICPPMethod> list = result.get(key);
1072
final ICPPFunctionType methodType = method.getType();
1073
for (Iterator<ICPPMethod> it= list.iterator(); it.hasNext(); ) {
1074
ICPPMethod pureVirtual = it.next();
1075
if (functionTypesAllowOverride(methodType, pureVirtual.getType())) {
1080
if (method.isPureVirtual()) {
1082
list= new ArrayList<ICPPMethod>();
1083
result.put(key, list);
1086
} else if (list != null && list.isEmpty()) {
1093
private static String getMethodNameForOverrideKey(ICPPMethod method) {
1094
if (method.isDestructor()) {
1095
// Destructor's names may differ but they will override each other.
1096
return DESTRUCTOR_OVERRIDE_KEY;
1098
return method.getName();