1
/*******************************************************************************
2
* Copyright (c) 2004, 2009 QNX Software Systems and others.
3
* All rights reserved. This program and the accompanying materials
4
* are made available under the terms of the Eclipse Public License v1.0
5
* which accompanies this distribution, and is available at
6
* http://www.eclipse.org/legal/epl-v10.html
9
* QNX Software Systems - initial API and implementation
10
*******************************************************************************/
11
package org.eclipse.cdt.core.browser;
13
import java.util.ArrayList;
14
import java.util.List;
16
import org.eclipse.cdt.core.model.CModelException;
17
import org.eclipse.cdt.core.model.ICElement;
18
import org.eclipse.cdt.core.model.IMember;
19
import org.eclipse.cdt.core.model.IMethodDeclaration;
20
import org.eclipse.cdt.core.model.IParent;
21
import org.eclipse.cdt.core.model.IStructure;
22
import org.eclipse.cdt.core.model.ITranslationUnit;
25
* @noextend This class is not intended to be subclassed by clients.
26
* @noinstantiate This class is not intended to be instantiated by clients.
28
public class TypeUtil {
30
public static boolean isDeclaringType(ICElement elem) {
31
int type = elem.getElementType();
32
return (type == ICElement.C_CLASS
33
|| type == ICElement.C_STRUCT
34
|| type == ICElement.C_ENUMERATION
35
|| type == ICElement.C_UNION
36
|| type == ICElement.C_TYPEDEF
37
|| type == ICElement.C_NAMESPACE);
40
public static boolean isMemberType(ICElement elem) {
41
int type = elem.getElementType();
42
if (type == ICElement.C_CLASS
43
|| type == ICElement.C_STRUCT
44
|| type == ICElement.C_ENUMERATION
45
|| type == ICElement.C_UNION
46
|| type == ICElement.C_TYPEDEF
47
|| type == ICElement.C_NAMESPACE)
49
return elem instanceof IMember;
53
* Returns the type in which this member is declared, or <code>null</code>
54
* if this member is not declared in a type (for example, a top-level type).
55
* This is a handle-only method.
57
* @return the type in which this member is declared, or <code>null</code>
58
* if this member is not declared in a type (for example, a top-level type)
60
public static ICElement getDeclaringType(ICElement elem) {
61
if (!isMemberType(elem))
63
ICElement parent = elem.getParent();
64
while (parent != null && !(parent instanceof ITranslationUnit)) {
65
if (isDeclaringType(parent))
67
parent = parent.getParent();
72
public static ICElement getDeclaringClass(ICElement type) {
73
ICElement parentElement = type.getParent();
74
if (parentElement != null && isClassOrStruct(parentElement)) {
78
if (isClassOrStruct(type)) {
79
while (parentElement != null) {
80
if (isClassOrStruct(parentElement)) {
82
} else if (parentElement instanceof IMember) {
83
parentElement = parentElement.getParent();
93
public static boolean isClassOrStruct(ICElement type) {
94
int kind = type.getElementType();
95
// case ICElement.C_TEMPLATE_CLASS:
96
// case ICElement.C_TEMPLATE_STRUCT:
97
return (kind == ICElement.C_CLASS || kind == ICElement.C_STRUCT);
100
public static boolean isClass(ICElement type) {
101
return (type.getElementType() == ICElement.C_CLASS);
104
public static boolean isNamespace(ICElement type) {
105
return (type.getElementType() == ICElement.C_NAMESPACE);
109
* Returns the top-level types declared in the given translation unit
110
* in the order in which they appear in the source.
112
* @param tu the translation unit
113
* @return the top-level types declared in the given translation unit
114
* @throws CModelException if this element does not exist or if an
115
* exception occurs while accessing its corresponding resource
117
public static ICElement[] getTypes(ITranslationUnit tu) throws CModelException {
118
List<ICElement> typeList = new ArrayList<ICElement>();
119
ICElement[] children = tu.getChildren();
120
for (int i = 0; i < children.length; ++i) {
121
if (isDeclaringType(children[i]))
122
typeList.add(children[i]);
124
return typeList.toArray(new ICElement[typeList.size()]);
128
* Returns all types declared in the given translation unit in the order
129
* in which they appear in the source.
130
* This includes all top-level types and nested member types.
131
* It does NOT include local types (types defined in methods).
133
* @return the array of top-level and member types defined in the given translation unit, in declaration order.
134
* @throws CModelException if this element does not exist or if an
135
* exception occurs while accessing its corresponding resource
137
public static ICElement[] getAllTypes(ITranslationUnit tu) throws CModelException {
138
ICElement[] types = getTypes(tu);
139
ArrayList<ICElement> allTypes = new ArrayList<ICElement>(types.length);
140
ArrayList<ICElement> typesToTraverse = new ArrayList<ICElement>(types.length);
141
for (ICElement type : types) {
142
typesToTraverse.add(type);
144
while (!typesToTraverse.isEmpty()) {
145
ICElement type = typesToTraverse.get(0);
146
typesToTraverse.remove(type);
148
types = getTypes(type);
149
for (ICElement type2 : types) {
150
typesToTraverse.add(type2);
153
return allTypes.toArray(new ICElement[allTypes.size()]);
158
* Returns the immediate member types declared by the given element.
159
* The results are listed in the order in which they appear in the source file.
161
* @param elem the element
162
* @exception CModelException if this element does not exist or if an
163
* exception occurs while accessing its corresponding resource.
164
* @return the immediate member types declared by this type
166
public static ICElement[] getTypes(ICElement elem) throws CModelException {
167
List<ICElement> typeList = new ArrayList<ICElement>();
168
if (isDeclaringType(elem) && elem instanceof IParent) {
169
ICElement[] children = ((IParent)elem).getChildren();
170
for (int i = 0; i < children.length; ++i) {
171
if (isDeclaringType(children[i]))
172
typeList.add(children[i]);
175
return typeList.toArray(new ICElement[typeList.size()]);
178
public static ITranslationUnit getTranslationUnit(ICElement elem) {
179
while (elem != null) {
180
if (elem instanceof ITranslationUnit)
181
return (ITranslationUnit)elem;
182
elem = elem.getParent();
187
// TODO move method to CModelUtil
188
public static IQualifiedTypeName getFullyQualifiedName(ICElement type) {
189
String name = type.getElementName();
190
IQualifiedTypeName qualifiedName = new QualifiedTypeName(name);
191
ICElement parent = type.getParent();
192
while (parent != null && (isNamespace(parent) || isClass(parent))) {
193
qualifiedName = new QualifiedTypeName(parent.getElementName()).append(qualifiedName);
194
parent = parent.getParent();
196
return qualifiedName;
199
public static IMethodDeclaration[] getMethods(ICElement elem) {
200
if (elem instanceof IStructure) {
202
List<?> list = ((IParent)elem).getChildrenOfType(ICElement.C_METHOD_DECLARATION);
203
if (list != null && !list.isEmpty()) {
204
return list.toArray(new IMethodDeclaration[list.size()]);
206
} catch (CModelException e) {
212
public static ICElement[] getFields(ICElement elem) {
213
if (elem instanceof IStructure) {
215
List<?> list = ((IParent)elem).getChildrenOfType(ICElement.C_FIELD);
216
if (list != null && !list.isEmpty()) {
217
return list.toArray(new ICElement[list.size()]);
219
} catch (CModelException e) {
227
* Finds a method by name.
228
* This searches for a method with a name and signature. Parameter types are only
229
* compared by the simple name, no resolving for the fully qualified type name is done.
230
* Constructors are only compared by parameters, not the name.
231
* @param name The name of the method to find
232
* @param paramTypes The type signatures of the parameters e.g. <code>{"QString;","I"}</code>
233
* @param isConstructor If the method is a constructor
234
* @param methods The methods to search in
235
* @return The found method or <code>null</code>, if nothing found
237
// TODO move methods to CModelUtil
238
public static IMethodDeclaration findMethod(String name, String[] paramTypes, boolean isConstructor, boolean isDestructor, IMethodDeclaration[] methods) throws CModelException {
239
for (int i= methods.length - 1; i >= 0; i--) {
240
if (isSameMethodSignature(name, paramTypes, isConstructor, isDestructor, methods[i])) {
248
* Tests if a method equals to the given signature.
249
* Parameter types are only compared by the simple name, no resolving for
250
* the fully qualified type name is done. Constructors are only compared by
251
* parameters, not the name.
252
* @param name Name of the method
253
* @param paramTypes The type signatures of the parameters e.g. <code>{"QString;","I"}</code>
254
* @param isConstructor Specifies if the method is a constructor
255
* @return Returns <code>true</code> if the method has the given name and parameter types and constructor state.
257
//TODO move methods to CModelUtil
258
public static boolean isSameMethodSignature(String name, String[] paramTypes, boolean isConstructor, boolean isDestructor, IMethodDeclaration curr) throws CModelException {
259
if (isConstructor || isDestructor || name.equals(curr.getElementName())) {
260
if ((isConstructor == curr.isConstructor()) && (isDestructor == curr.isDestructor())) {
261
String[] currParamTypes= curr.getParameterTypes();
262
if (paramTypes.length == currParamTypes.length) {
263
for (int i= 0; i < paramTypes.length; i++) {
264
// TODO should compare signatures
265
String t1= paramTypes[i];
266
String t2= currParamTypes[i];
267
if (!t1.equals(t2)) {
279
* Finds a method in a type.
280
* This searches for a method with the same name and signature. Parameter types are only
281
* compared by the simple name, no resolving for the fully qualified type name is done.
282
* Constructors are only compared by parameters, not the name.
283
* @param name The name of the method to find
284
* @param paramTypes The type signatures of the parameters e.g. <code>{"QString;","I"}</code>
285
* @param isConstructor If the method is a constructor
286
* @return The first found method or <code>null</code>, if nothing found
288
// TODO move methods to CModelUtil
289
public static IMethodDeclaration findMethod(String name, String[] paramTypes, boolean isConstructor, boolean isDestructor, ICElement type) throws CModelException {
290
return findMethod(name, paramTypes, isConstructor, isDestructor, getMethods(type));