/*******************************************************************************
* Copyright (c) 2000, 2009 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 java.util.HashMap;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.ITypeParameter;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.compiler.CharOperation;
import org.eclipse.jdt.internal.compiler.env.ISourceField;
import org.eclipse.jdt.internal.compiler.env.ISourceImport;
import org.eclipse.jdt.internal.compiler.env.ISourceMethod;
import org.eclipse.jdt.internal.compiler.env.ISourceType;
/**
* Element info for an IType element that originated from source.
*/
public class SourceTypeElementInfo extends AnnotatableInfo implements ISourceType {
protected static final ISourceImport[] NO_IMPORTS= new ISourceImport[0];
protected static final InitializerElementInfo[] NO_INITIALIZERS= new InitializerElementInfo[0];
protected static final SourceField[] NO_FIELDS= new SourceField[0];
protected static final SourceMethod[] NO_METHODS= new SourceMethod[0];
protected static final SourceType[] NO_TYPES= new SourceType[0];
protected IJavaElement[] children= JavaElement.NO_ELEMENTS;
/**
* The name of the superclass for this type. This name is fully qualified for binary types and
* is NOT fully qualified for source types.
*/
protected char[] superclassName;
/**
* The names of the interfaces this type implements or extends. These names are fully qualified
* in the case of a binary type, and are NOT fully qualified in the case of a source type
*/
protected char[][] superInterfaceNames;
/**
* Backpointer to my type handle - useful for translation from info to handle.
*/
protected IType handle= null;
/*
* The type parameters of this source type. Empty if none.
*/
protected ITypeParameter[] typeParameters= TypeParameter.NO_TYPE_PARAMETERS;
/*
* A map from an IJavaElement (this type or a child of this type) to a String[] (the categories of this element)
*/
protected HashMap categories;
protected void addCategories(IJavaElement element, char[][] elementCategories) {
if (elementCategories == null)
return;
if (this.categories == null)
this.categories= new HashMap();
this.categories.put(element, CharOperation.toStrings(elementCategories));
}
/*
* Return a map from an IJavaElement (this type or a child of this type) to a String[] (the categories of this element)
*/
public HashMap getCategories() {
return this.categories;
}
public IJavaElement[] getChildren() {
return this.children;
}
/**
* Returns the ISourceType that is the enclosing type for this type, or <code>null</code> if
* this type is a top level type.
*/
public ISourceType getEnclosingType() {
IJavaElement parent= this.handle.getParent();
if (parent != null && parent.getElementType() == IJavaElement.TYPE) {
try {
return (ISourceType)((JavaElement)parent).getElementInfo();
} catch (JavaModelException e) {
return null;
}
} else {
return null;
}
}
/**
* @see ISourceType
*/
public ISourceField[] getFields() {
SourceField[] fieldHandles= getFieldHandles();
int length= fieldHandles.length;
ISourceField[] fields= new ISourceField[length];
for (int i= 0; i < length; i++) {
try {
ISourceField field= (ISourceField)fieldHandles[i].getElementInfo();
fields[i]= field;
} catch (JavaModelException e) {
// ignore
}
}
return fields;
}
public SourceField[] getFieldHandles() {
int length= this.children.length;
if (length == 0)
return NO_FIELDS;
SourceField[] fields= new SourceField[length];
int fieldIndex= 0;
for (int i= 0; i < length; i++) {
IJavaElement child= this.children[i];
if (child instanceof SourceField)
fields[fieldIndex++]= (SourceField)child;
}
if (fieldIndex == 0)
return NO_FIELDS;
if (fieldIndex < length)
System.arraycopy(fields, 0, fields= new SourceField[fieldIndex], 0, fieldIndex);
return fields;
}
/**
* @see org.eclipse.jdt.internal.compiler.env.IDependent#getFileName()
*/
public char[] getFileName() {
return this.handle.getPath().toString().toCharArray();
}
/**
* Returns the handle for this type info
*/
public IType getHandle() {
return this.handle;
}
/*
* Returns the InitializerElementInfos for this type.
* Returns an empty array if none.
*/
public InitializerElementInfo[] getInitializers() {
int length= this.children.length;
if (length == 0)
return NO_INITIALIZERS;
InitializerElementInfo[] initializers= new InitializerElementInfo[length];
int initializerIndex= 0;
for (int i= 0; i < length; i++) {
IJavaElement child= this.children[i];
if (child instanceof Initializer) {
try {
InitializerElementInfo initializer= (InitializerElementInfo)((Initializer)child).getElementInfo();
initializers[initializerIndex++]= initializer;
} catch (JavaModelException e) {
// ignore
}
}
}
if (initializerIndex == 0)
return NO_INITIALIZERS;
System.arraycopy(initializers, 0, initializers= new InitializerElementInfo[initializerIndex], 0, initializerIndex);
return initializers;
}
/**
* @see ISourceType
*/
public char[][] getInterfaceNames() {
if (this.handle.getElementName().length() == 0) { // if anonymous type
return null;
}
return this.superInterfaceNames;
}
/**
* @see ISourceType
*/
public ISourceType[] getMemberTypes() {
SourceType[] memberTypeHandles= getMemberTypeHandles();
int length= memberTypeHandles.length;
ISourceType[] memberTypes= new ISourceType[length];
for (int i= 0; i < length; i++) {
try {
ISourceType type= (ISourceType)memberTypeHandles[i].getElementInfo();
memberTypes[i]= type;
} catch (JavaModelException e) {
// ignore
}
}
return memberTypes;
}
public SourceType[] getMemberTypeHandles() {
int length= this.children.length;
if (length == 0)
return NO_TYPES;
SourceType[] memberTypes= new SourceType[length];
int typeIndex= 0;
for (int i= 0; i < length; i++) {
IJavaElement child= this.children[i];
if (child instanceof SourceType)
memberTypes[typeIndex++]= (SourceType)child;
}
if (typeIndex == 0)
return NO_TYPES;
if (typeIndex < length)
System.arraycopy(memberTypes, 0, memberTypes= new SourceType[typeIndex], 0, typeIndex);
return memberTypes;
}
/**
* @see ISourceType
*/
public ISourceMethod[] getMethods() {
SourceMethod[] methodHandles= getMethodHandles();
int length= methodHandles.length;
ISourceMethod[] methods= new ISourceMethod[length];
int methodIndex= 0;
for (int i= 0; i < length; i++) {
try {
ISourceMethod method= (ISourceMethod)methodHandles[i].getElementInfo();
methods[methodIndex++]= method;
} catch (JavaModelException e) {
// ignore
}
}
return methods;
}
public SourceMethod[] getMethodHandles() {
int length= this.children.length;
if (length == 0)
return NO_METHODS;
SourceMethod[] methods= new SourceMethod[length];
int methodIndex= 0;
for (int i= 0; i < length; i++) {
IJavaElement child= this.children[i];
if (child instanceof SourceMethod)
methods[methodIndex++]= (SourceMethod)child;
}
if (methodIndex == 0)
return NO_METHODS;
if (methodIndex < length)
System.arraycopy(methods, 0, methods= new SourceMethod[methodIndex], 0, methodIndex);
return methods;
}
/**
* @see org.eclipse.jdt.internal.compiler.env.ISourceType#getName()
*/
public char[] getName() {
return this.handle.getElementName().toCharArray();
}
/**
* @see ISourceType
*/
public char[] getSuperclassName() {
if (this.handle.getElementName().length() == 0) { // if anonymous type
char[][] interfaceNames= this.superInterfaceNames;
if (interfaceNames != null && interfaceNames.length > 0) {
return interfaceNames[0];
}
}
return this.superclassName;
}
public char[][][] getTypeParameterBounds() {
int length= this.typeParameters.length;
char[][][] typeParameterBounds= new char[length][][];
for (int i= 0; i < length; i++) {
try {
TypeParameterElementInfo info= (TypeParameterElementInfo)((JavaElement)this.typeParameters[i]).getElementInfo();
typeParameterBounds[i]= info.bounds;
} catch (JavaModelException e) {
// type parameter does not exist: ignore
}
}
return typeParameterBounds;
}
public char[][] getTypeParameterNames() {
int length= this.typeParameters.length;
if (length == 0)
return CharOperation.NO_CHAR_CHAR;
char[][] typeParameterNames= new char[length][];
for (int i= 0; i < length; i++) {
typeParameterNames[i]= this.typeParameters[i].getElementName().toCharArray();
}
return typeParameterNames;
}
/**
* @see ISourceType
*/
public boolean isBinaryType() {
return false;
}
/*
* Returns whether the source type is an anonymous type of a member type.
*/
public boolean isAnonymousMember() {
return false;
}
/**
* Sets the handle for this type info
*/
protected void setHandle(IType handle) {
this.handle= handle;
}
/**
* Sets the (unqualified) name of this type's superclass
*/
protected void setSuperclassName(char[] superclassName) {
this.superclassName= superclassName;
}
/**
* Sets the (unqualified) names of the interfaces this type implements or extends
*/
protected void setSuperInterfaceNames(char[][] superInterfaceNames) {
this.superInterfaceNames= superInterfaceNames;
}
public String toString() {
return "Info for " + this.handle.toString(); //$NON-NLS-1$
}
}