001: /*******************************************************************************
002: * Copyright (c) 2000, 2006 IBM Corporation and others.
003: * All rights reserved. This program and the accompanying materials
004: * are made available under the terms of the Eclipse Public License v1.0
005: * which accompanies this distribution, and is available at
006: * http://www.eclipse.org/legal/epl-v10.html
007: *
008: * Contributors:
009: * IBM Corporation - initial API and implementation
010: *******************************************************************************/package org.eclipse.jdt.internal.core;
011:
012: import java.util.ArrayList;
013: import java.util.HashMap;
014:
015: import org.eclipse.jdt.core.*;
016: import org.eclipse.jdt.core.IClassFile;
017: import org.eclipse.jdt.core.IField;
018: import org.eclipse.jdt.core.IJavaElement;
019: import org.eclipse.jdt.core.IPackageFragment;
020: import org.eclipse.jdt.core.IType;
021: import org.eclipse.jdt.core.JavaModelException;
022: import org.eclipse.jdt.core.Signature;
023: import org.eclipse.jdt.core.compiler.CharOperation;
024: import org.eclipse.jdt.internal.compiler.env.IBinaryField;
025: import org.eclipse.jdt.internal.compiler.env.IBinaryMethod;
026: import org.eclipse.jdt.internal.compiler.env.IBinaryNestedType;
027: import org.eclipse.jdt.internal.compiler.env.IBinaryType;
028: import org.eclipse.jdt.internal.compiler.util.SuffixConstants;
029:
030: /**
031: * Element info for <code>ClassFile</code> handles.
032: */
033:
034: /* package */class ClassFileInfo extends OpenableElementInfo implements
035: SuffixConstants {
036: /**
037: * The children of the <code>BinaryType</code> corresponding to our
038: * <code>ClassFile</code>. These are kept here because we don't have
039: * access to the <code>BinaryType</code> info (<code>ClassFileReader</code>).
040: */
041: protected JavaElement[] binaryChildren = null;
042: /*
043: * The type parameters in this class file.
044: */
045: protected ITypeParameter[] typeParameters;
046:
047: /**
048: * Creates the handles and infos for the fields of the given binary type.
049: * Adds new handles to the given vector.
050: */
051: private void generateFieldInfos(IType type, IBinaryType typeInfo,
052: HashMap newElements, ArrayList childrenHandles) {
053: // Make the fields
054: IBinaryField[] fields = typeInfo.getFields();
055: if (fields == null) {
056: return;
057: }
058: JavaModelManager manager = JavaModelManager
059: .getJavaModelManager();
060: for (int i = 0, fieldCount = fields.length; i < fieldCount; i++) {
061: IBinaryField fieldInfo = fields[i];
062: IField field = new BinaryField((JavaElement) type, manager
063: .intern(new String(fieldInfo.getName())));
064: newElements.put(field, fieldInfo);
065: childrenHandles.add(field);
066: }
067: }
068:
069: /**
070: * Creates the handles for the inner types of the given binary type.
071: * Adds new handles to the given vector.
072: */
073: private void generateInnerClassHandles(IType type,
074: IBinaryType typeInfo, ArrayList childrenHandles) {
075: // Add inner types
076: // If the current type is an inner type, innerClasses returns
077: // an extra entry for the current type. This entry must be removed.
078: // Can also return an entry for the enclosing type of an inner type.
079: IBinaryNestedType[] innerTypes = typeInfo.getMemberTypes();
080: if (innerTypes != null) {
081: IPackageFragment pkg = (IPackageFragment) type
082: .getAncestor(IJavaElement.PACKAGE_FRAGMENT);
083: for (int i = 0, typeCount = innerTypes.length; i < typeCount; i++) {
084: IBinaryNestedType binaryType = innerTypes[i];
085: IClassFile parentClassFile = pkg
086: .getClassFile(new String(ClassFile
087: .unqualifiedName(binaryType.getName()))
088: + SUFFIX_STRING_class);
089: IType innerType = new BinaryType(
090: (JavaElement) parentClassFile, ClassFile
091: .simpleName(binaryType.getName()));
092: childrenHandles.add(innerType);
093: }
094: }
095: }
096:
097: /**
098: * Creates the handles and infos for the methods of the given binary type.
099: * Adds new handles to the given vector.
100: */
101: private void generateMethodInfos(IType type, IBinaryType typeInfo,
102: HashMap newElements, ArrayList childrenHandles,
103: ArrayList typeParameterHandles) {
104: IBinaryMethod[] methods = typeInfo.getMethods();
105: if (methods == null) {
106: return;
107: }
108: for (int i = 0, methodCount = methods.length; i < methodCount; i++) {
109: IBinaryMethod methodInfo = methods[i];
110: // TODO (jerome) filter out synthetic members
111: // indexer should not index them as well
112: // if ((methodInfo.getModifiers() & IConstants.AccSynthetic) != 0) continue; // skip synthetic
113: char[] signature = methodInfo.getGenericSignature();
114: if (signature == null)
115: signature = methodInfo.getMethodDescriptor();
116: String[] pNames = null;
117: try {
118: pNames = Signature.getParameterTypes(new String(
119: signature));
120: } catch (IllegalArgumentException e) {
121: // protect against malformed .class file (e.g. com/sun/crypto/provider/SunJCE_b.class has a 'a' generic signature)
122: signature = methodInfo.getMethodDescriptor();
123: pNames = Signature.getParameterTypes(new String(
124: signature));
125: }
126: char[][] paramNames = new char[pNames.length][];
127: for (int j = 0; j < pNames.length; j++) {
128: paramNames[j] = pNames[j].toCharArray();
129: }
130: char[][] parameterTypes = ClassFile
131: .translatedNames(paramNames);
132: JavaModelManager manager = JavaModelManager
133: .getJavaModelManager();
134: String selector = new String(methodInfo.getSelector());
135: if (methodInfo.isConstructor()) {
136: selector = type.getElementName();
137: }
138: selector = manager.intern(selector);
139: for (int j = 0; j < pNames.length; j++) {
140: pNames[j] = manager
141: .intern(new String(parameterTypes[j]));
142: }
143: BinaryMethod method = new BinaryMethod((JavaElement) type,
144: selector, pNames);
145: childrenHandles.add(method);
146:
147: // ensure that 2 binary methods with the same signature but with different return types have different occurence counts.
148: // (case of bridge methods in 1.5)
149: while (newElements.containsKey(method))
150: method.occurrenceCount++;
151:
152: newElements.put(method, methodInfo);
153:
154: generateTypeParameterInfos(method, signature, newElements,
155: typeParameterHandles);
156: }
157: }
158:
159: /**
160: * Creates the handles and infos for the type parameter of the given binary member.
161: * Adds new handles to the given vector.
162: */
163: private void generateTypeParameterInfos(BinaryMember parent,
164: char[] signature, HashMap newElements,
165: ArrayList typeParameterHandles) {
166: if (signature == null)
167: return;
168: char[][] typeParameterSignatures = Signature
169: .getTypeParameters(signature);
170: for (int i = 0, typeParameterCount = typeParameterSignatures.length; i < typeParameterCount; i++) {
171: char[] typeParameterSignature = typeParameterSignatures[i];
172: char[] typeParameterName = Signature
173: .getTypeVariable(typeParameterSignature);
174: char[][] typeParameterBoundSignatures = Signature
175: .getTypeParameterBounds(typeParameterSignature);
176: int boundLength = typeParameterBoundSignatures.length;
177: char[][] typeParameterBounds = new char[boundLength][];
178: for (int j = 0; j < boundLength; j++) {
179: typeParameterBounds[j] = Signature
180: .toCharArray(typeParameterBoundSignatures[j]);
181: CharOperation.replace(typeParameterBounds[j], '/', '.');
182: }
183: TypeParameter typeParameter = new TypeParameter(parent,
184: new String(typeParameterName));
185: TypeParameterElementInfo info = new TypeParameterElementInfo();
186: info.bounds = typeParameterBounds;
187: typeParameterHandles.add(typeParameter);
188:
189: // ensure that 2 binary methods with the same signature but with different return types have different occurence counts.
190: // (case of bridge methods in 1.5)
191: while (newElements.containsKey(typeParameter))
192: typeParameter.occurrenceCount++;
193:
194: newElements.put(typeParameter, info);
195: }
196: }
197:
198: /**
199: * Returns true iff the <code>readBinaryChildren</code> has already
200: * been called.
201: */
202: boolean hasReadBinaryChildren() {
203: return this .binaryChildren != null;
204: }
205:
206: /**
207: * Creates the handles for <code>BinaryMember</code>s defined in this
208: * <code>ClassFile</code> and adds them to the
209: * <code>JavaModelManager</code>'s cache.
210: */
211: protected void readBinaryChildren(ClassFile classFile,
212: HashMap newElements, IBinaryType typeInfo) {
213: ArrayList childrenHandles = new ArrayList();
214: BinaryType type = (BinaryType) classFile.getType();
215: ArrayList typeParameterHandles = new ArrayList();
216: if (typeInfo != null) { //may not be a valid class file
217: generateTypeParameterInfos(type, typeInfo
218: .getGenericSignature(), newElements,
219: typeParameterHandles);
220: generateFieldInfos(type, typeInfo, newElements,
221: childrenHandles);
222: generateMethodInfos(type, typeInfo, newElements,
223: childrenHandles, typeParameterHandles);
224: generateInnerClassHandles(type, typeInfo, childrenHandles); // Note inner class are separate openables that are not opened here: no need to pass in newElements
225: }
226:
227: this .binaryChildren = new JavaElement[childrenHandles.size()];
228: childrenHandles.toArray(this .binaryChildren);
229: int typeParameterHandleSize = typeParameterHandles.size();
230: if (typeParameterHandleSize == 0) {
231: this .typeParameters = TypeParameter.NO_TYPE_PARAMETERS;
232: } else {
233: this .typeParameters = new ITypeParameter[typeParameterHandleSize];
234: typeParameterHandles.toArray(this .typeParameters);
235: }
236: }
237:
238: /**
239: * Removes the binary children handles and remove their infos from
240: * the <code>JavaModelManager</code>'s cache.
241: */
242: void removeBinaryChildren() throws JavaModelException {
243: if (this .binaryChildren != null) {
244: JavaModelManager manager = JavaModelManager
245: .getJavaModelManager();
246: for (int i = 0; i < this .binaryChildren.length; i++) {
247: JavaElement child = this .binaryChildren[i];
248: if (child instanceof BinaryType) {
249: manager.removeInfoAndChildren((JavaElement) child
250: .getParent());
251: } else {
252: manager.removeInfoAndChildren(child);
253: }
254: }
255: this .binaryChildren = JavaElement.NO_ELEMENTS;
256: }
257: if (this .typeParameters != null) {
258: JavaModelManager manager = JavaModelManager
259: .getJavaModelManager();
260: for (int i = 0; i < this .typeParameters.length; i++) {
261: TypeParameter typeParameter = (TypeParameter) this.typeParameters[i];
262: manager.removeInfoAndChildren(typeParameter);
263: }
264: this.typeParameters = TypeParameter.NO_TYPE_PARAMETERS;
265: }
266: }
267: }
|