/******************************************************************************* * Copyright (c) 2004, 2012 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.jdt.internal.core; import org.eclipse.jdt.core.BindingKey; import org.eclipse.jdt.core.ICompilationUnit; import org.eclipse.jdt.core.IField; import org.eclipse.jdt.core.IJavaElement; import org.eclipse.jdt.core.IMember; import org.eclipse.jdt.core.IMethod; import org.eclipse.jdt.core.IPackageFragment; import org.eclipse.jdt.core.IType; import org.eclipse.jdt.core.ITypeParameter; import org.eclipse.jdt.core.JavaModelException; import org.eclipse.jdt.core.Signature; import org.eclipse.jdt.core.WorkingCopyOwner; import org.eclipse.jdt.core.compiler.CategorizedProblem; import org.eclipse.jdt.core.compiler.CharOperation; import org.eclipse.jdt.internal.codeassist.ISelectionRequestor; import org.eclipse.jdt.internal.codeassist.SelectionEngine; public abstract class NamedMember extends Member { /* * This element's name, or an empty <code>String</code> if this * element does not have a name. */ protected String name; public NamedMember(JavaElement parent, String name) { super(parent); this.name = name; } private void appendTypeParameters(StringBuffer buffer) throws JavaModelException { ITypeParameter[] typeParameters = getTypeParameters(); int length = typeParameters.length; if (length == 0) return; buffer.append('<'); for (int i = 0; i < length; i++) { ITypeParameter typeParameter = typeParameters[i]; buffer.append(typeParameter.getElementName()); String[] bounds = typeParameter.getBounds(); int boundsLength = bounds.length; if (boundsLength > 0) { buffer.append(" extends "); //$NON-NLS-1$ for (int j = 0; j < boundsLength; j++) { buffer.append(bounds[j]); if (j < boundsLength-1) buffer.append(" & "); //$NON-NLS-1$ } } if (i < length-1) buffer.append(", "); //$NON-NLS-1$ } buffer.append('>'); } public String getElementName() { return this.name; } protected String getKey(IField field, boolean forceOpen) throws JavaModelException { StringBuffer key = new StringBuffer(); // declaring class String declaringKey = getKey((IType) field.getParent(), forceOpen); key.append(declaringKey); // field name key.append('.'); key.append(field.getElementName()); return key.toString(); } protected String getKey(IMethod method, boolean forceOpen) throws JavaModelException { StringBuffer key = new StringBuffer(); // declaring class String declaringKey = getKey((IType) method.getParent(), forceOpen); key.append(declaringKey); // selector key.append('.'); String selector = method.getElementName(); key.append(selector); // type parameters if (forceOpen) { ITypeParameter[] typeParameters = method.getTypeParameters(); int length = typeParameters.length; if (length > 0) { key.append('<'); for (int i = 0; i < length; i++) { ITypeParameter typeParameter = typeParameters[i]; String[] bounds = typeParameter.getBounds(); int boundsLength = bounds.length; char[][] boundSignatures = new char[boundsLength][]; for (int j = 0; j < boundsLength; j++) { boundSignatures[j] = Signature.createCharArrayTypeSignature(bounds[j].toCharArray(), method.isBinary()); CharOperation.replace(boundSignatures[j], '.', '/'); } char[] sig = Signature.createTypeParameterSignature(typeParameter.getElementName().toCharArray(), boundSignatures); key.append(sig); } key.append('>'); } } // parameters key.append('('); String[] parameters = method.getParameterTypes(); for (int i = 0, length = parameters.length; i < length; i++) key.append(parameters[i].replace('.', '/')); key.append(')'); // return type if (forceOpen) key.append(method.getReturnType().replace('.', '/')); else key.append('V'); return key.toString(); } protected String getKey(IType type, boolean forceOpen) throws JavaModelException { StringBuffer key = new StringBuffer(); key.append('L'); String packageName = type.getPackageFragment().getElementName(); key.append(packageName.replace('.', '/')); if (packageName.length() > 0) key.append('/'); String typeQualifiedName = type.getTypeQualifiedName('$'); ICompilationUnit cu = (ICompilationUnit) type.getAncestor(IJavaElement.COMPILATION_UNIT); if (cu != null) { String cuName = cu.getElementName(); String mainTypeName = cuName.substring(0, cuName.lastIndexOf('.')); int end = typeQualifiedName.indexOf('$'); if (end == -1) end = typeQualifiedName.length(); String topLevelTypeName = typeQualifiedName.substring(0, end); if (!mainTypeName.equals(topLevelTypeName)) { key.append(mainTypeName); key.append('~'); } } key.append(typeQualifiedName); key.append(';'); return key.toString(); } protected String getFullyQualifiedParameterizedName(String fullyQualifiedName, String uniqueKey) throws JavaModelException { String[] typeArguments = new BindingKey(uniqueKey).getTypeArguments(); int length = typeArguments.length; if (length == 0) return fullyQualifiedName; StringBuffer buffer = new StringBuffer(); buffer.append(fullyQualifiedName); buffer.append('<'); for (int i = 0; i < length; i++) { String typeArgument = typeArguments[i]; buffer.append(Signature.toString(typeArgument)); if (i < length-1) buffer.append(','); } buffer.append('>'); return buffer.toString(); } protected IPackageFragment getPackageFragment() { return null; } public String getFullyQualifiedName(char enclosingTypeSeparator, boolean showParameters) throws JavaModelException { String packageName = getPackageFragment().getElementName(); if (packageName.equals(IPackageFragment.DEFAULT_PACKAGE_NAME)) { return getTypeQualifiedName(enclosingTypeSeparator, showParameters); } return packageName + '.' + getTypeQualifiedName(enclosingTypeSeparator, showParameters); } public String getTypeQualifiedName(char enclosingTypeSeparator, boolean showParameters) throws JavaModelException { NamedMember declaringType; switch (this.parent.getElementType()) { case IJavaElement.COMPILATION_UNIT: if (showParameters) { StringBuffer buffer = new StringBuffer(this.name); appendTypeParameters(buffer); return buffer.toString(); } return this.name; case IJavaElement.CLASS_FILE: String classFileName = this.parent.getElementName(); String typeName; if (classFileName.indexOf('$') == -1) { // top level class file: name of type is same as name of class file typeName = this.name; } else { // anonymous or local class file typeName = classFileName.substring(0, classFileName.lastIndexOf('.'))/*remove .class*/.replace('$', enclosingTypeSeparator); } if (showParameters) { StringBuffer buffer = new StringBuffer(typeName); appendTypeParameters(buffer); return buffer.toString(); } return typeName; case IJavaElement.TYPE: declaringType = (NamedMember) this.parent; break; case IJavaElement.FIELD: case IJavaElement.INITIALIZER: case IJavaElement.METHOD: declaringType = (NamedMember) ((IMember) this.parent).getDeclaringType(); break; default: return null; } StringBuffer buffer = new StringBuffer(declaringType.getTypeQualifiedName(enclosingTypeSeparator, showParameters)); buffer.append(enclosingTypeSeparator); String simpleName = this.name.length() == 0 ? getOccurrenceCountSignature() : this.name; buffer.append(simpleName); if (showParameters) { appendTypeParameters(buffer); } return buffer.toString(); } /* * Returns the String representation of the occurrence count for this element. * The occurrence count is a unique number representation to identify the particular element. * * @return the occurrence count for this element in the form of String */ protected String getOccurrenceCountSignature() { return Integer.toString(this.occurrenceCount); } protected ITypeParameter[] getTypeParameters() throws JavaModelException { return null; } /** * @see IType#resolveType(String) */ public String[][] resolveType(String typeName) throws JavaModelException { return resolveType(typeName, DefaultWorkingCopyOwner.PRIMARY); } /** * @see IType#resolveType(String, WorkingCopyOwner) */ public String[][] resolveType(String typeName, WorkingCopyOwner owner) throws JavaModelException { JavaProject project = (JavaProject) getJavaProject(); SearchableEnvironment environment = project.newSearchableNameEnvironment(owner); class TypeResolveRequestor implements ISelectionRequestor { String[][] answers = null; public void acceptType(char[] packageName, char[] tName, int modifiers, boolean isDeclaration, char[] uniqueKey, int start, int end) { String[] answer = new String[] {new String(packageName), new String(tName) }; if (this.answers == null) { this.answers = new String[][]{ answer }; } else { // grow int length = this.answers.length; System.arraycopy(this.answers, 0, this.answers = new String[length+1][], 0, length); this.answers[length] = answer; } } public void acceptError(CategorizedProblem error) { // ignore } public void acceptField(char[] declaringTypePackageName, char[] declaringTypeName, char[] fieldName, boolean isDeclaration, char[] uniqueKey, int start, int end) { // ignore } public void acceptMethod(char[] declaringTypePackageName, char[] declaringTypeName, String enclosingDeclaringTypeSignature, char[] selector, char[][] parameterPackageNames, char[][] parameterTypeNames, String[] parameterSignatures, char[][] typeParameterNames, char[][][] typeParameterBoundNames, boolean isConstructor, boolean isDeclaration, char[] uniqueKey, int start, int end) { // ignore } public void acceptPackage(char[] packageName){ // ignore } public void acceptTypeParameter(char[] declaringTypePackageName, char[] declaringTypeName, char[] typeParameterName, boolean isDeclaration, int start, int end) { // ignore } public void acceptMethodTypeParameter(char[] declaringTypePackageName, char[] declaringTypeName, char[] selector, int selectorStart, int selcetorEnd, char[] typeParameterName, boolean isDeclaration, int start, int end) { // ignore } } TypeResolveRequestor requestor = new TypeResolveRequestor(); SelectionEngine engine = new SelectionEngine(environment, requestor, project.getOptions(true), owner); engine.selectType(typeName.toCharArray(), (IType) this); if (NameLookup.VERBOSE) { System.out.println(Thread.currentThread() + " TIME SPENT in NameLoopkup#seekTypesInSourcePackage: " + environment.nameLookup.timeSpentInSeekTypesInSourcePackage + "ms"); //$NON-NLS-1$ //$NON-NLS-2$ System.out.println(Thread.currentThread() + " TIME SPENT in NameLoopkup#seekTypesInBinaryPackage: " + environment.nameLookup.timeSpentInSeekTypesInBinaryPackage + "ms"); //$NON-NLS-1$ //$NON-NLS-2$ } return requestor.answers; } }