/******************************************************************************* * Copyright (c) 2000, 2004 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/cpl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.rubypeople.rdt.internal.core; import org.rubypeople.rdt.core.IField; import org.rubypeople.rdt.core.IImportDeclaration; import org.rubypeople.rdt.core.IRubyElement; import org.rubypeople.rdt.core.IMethod; import org.rubypeople.rdt.core.IType; import org.rubypeople.rdt.core.ISourceImport; import org.rubypeople.rdt.core.RubyModelException; /** * Element info for an IType element that originated from source. */ public class RubyTypeElementInfo extends MemberElementInfo { protected static final ImportDeclarationElementInfo[] NO_IMPORTS = new ImportDeclarationElementInfo[0]; protected static final RubyField[] NO_FIELDS = new RubyField[0]; protected static final RubyMethod[] NO_METHODS = new RubyMethod[0]; protected static final RubyType[] NO_TYPES = new RubyType[0]; /** * 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 String superclassName; /** * The names of the module this type includes. 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 String[] includedModuleNames; /** * The name of the source file this type is declared in. */ protected String sourceFileName; /** * The name of the package this type is contained in. */ protected String namespaceName; /** * The infos of the imports in this type's compilation unit */ private ISourceImport[] imports; /** * Backpointer to my type handle - useful for translation from info to * handle. */ protected IType handle = null; /** * Returns the IRubyType that is the enclosing type for this type, or * <code>null</code> if this type is a top level type. */ public IType getEnclosingType() { IRubyElement parent = this.handle.getParent(); if (parent != null && parent.getElementType() == IRubyElement.TYPE) { try { return (IType) ((RubyElement) parent).getElementInfo(); } catch (RubyModelException e) { return null; } } return null; } /** * @see IType */ public IField[] getFields() { RubyField[] fieldHandles = getFieldHandles(); int length = fieldHandles.length; IField[] fields = new IField[length]; for (int i = 0; i < length; i++) { try { IField field = (IField) fieldHandles[i].getElementInfo(); fields[i] = field; } catch (RubyModelException e) { // ignore } } return fields; } public RubyField[] getFieldHandles() { int length = this.children.length; if (length == 0) return NO_FIELDS; RubyField[] fields = new RubyField[length]; int fieldIndex = 0; for (int i = 0; i < length; i++) { IRubyElement child = this.children[i]; if (child instanceof RubyField) fields[fieldIndex++] = (RubyField) child; } if (fieldIndex == 0) return NO_FIELDS; if (fieldIndex < length) System.arraycopy(fields, 0, fields = new RubyField[fieldIndex], 0, fieldIndex); return fields; } /** * @see org.eclipse.jdt.internal.compiler.env.IDependent#getFileName() */ public String getFileName() { return this.sourceFileName; } /** * Returns the handle for this type info */ public IType getHandle() { return this.handle; } /** * @see IType */ public ISourceImport[] getImports() { if (this.imports == null) { try { IImportDeclaration[] importDeclarations = this.handle.getRubyScript().getImports(); int length = importDeclarations.length; if (length == 0) { this.imports = NO_IMPORTS; } else { ISourceImport[] sourceImports = new ImportDeclarationElementInfo[length]; for (int i = 0; i < length; i++) { sourceImports[i] = (ImportDeclarationElementInfo) ((RubyImport) importDeclarations[i]).getElementInfo(); } this.imports = sourceImports; // only commit at the end, // once completed (bug // 36854) } } catch (RubyModelException e) { this.imports = NO_IMPORTS; } } return this.imports; } /** * @see IType */ public String[] getIncludedModuleNames() { if (this.handle.getElementName().length() == 0) { // if anonymous type return null; } return this.includedModuleNames; } /** * @see IType */ public IType[] getMemberTypes() { RubyType[] memberTypeHandles = getMemberTypeHandles(); int length = memberTypeHandles.length; IType[] memberTypes = new IType[length]; for (int i = 0; i < length; i++) { try { IType type = (IType) memberTypeHandles[i].getElementInfo(); memberTypes[i] = type; } catch (RubyModelException e) { // ignore } } return memberTypes; } public RubyType[] getMemberTypeHandles() { int length = this.children.length; if (length == 0) return NO_TYPES; RubyType[] memberTypes = new RubyType[length]; int typeIndex = 0; for (int i = 0; i < length; i++) { IRubyElement child = this.children[i]; if (child instanceof RubyType) memberTypes[typeIndex++] = (RubyType) child; } if (typeIndex == 0) return NO_TYPES; if (typeIndex < length) System.arraycopy(memberTypes, 0, memberTypes = new RubyType[typeIndex], 0, typeIndex); return memberTypes; } /** * @see IType */ public IMethod[] getMethods() { return getMethodHandles(); // RubyMethod[] methodHandles = getMethodHandles(); // int length = methodHandles.length; // IMethod[] methods = new IMethod[length]; // int methodIndex = 0; // for (int i = 0; i < length; i++) { // try { // IMethod method = (IMethod) methodHandles[i].getElementInfo(); // methods[methodIndex++] = method; // } catch (RubyModelException e) { // // ignore // } // } // return methods; } public RubyMethod[] getMethodHandles() { int length = this.children.length; if (length == 0) return NO_METHODS; RubyMethod[] methods = new RubyMethod[length]; int methodIndex = 0; for (int i = 0; i < length; i++) { IRubyElement child = this.children[i]; if (child instanceof RubyMethod) methods[methodIndex++] = (RubyMethod) child; } if (methodIndex == 0) return NO_METHODS; if (methodIndex < length) System.arraycopy(methods, 0, methods = new RubyMethod[methodIndex], 0, methodIndex); return methods; } /** * @see org.eclipse.jdt.internal.compiler.env.IType#getName() */ public char[] getName() { return this.handle.getElementName().toCharArray(); } /** * @see IType */ public String getNamespace() { return this.namespaceName; } /** * @see IType */ public String getSuperclassName() { if (this.handle.getElementName().length() == 0) { // if anonymous type String[] interfaceNames = this.includedModuleNames; if (interfaceNames != null && interfaceNames.length > 0) { return interfaceNames[0]; } } return this.superclassName; } /** * Sets the handle for this type info */ protected void setHandle(IType handle) { this.handle = handle; } /** * Sets the name of the package this type is declared in. */ protected void setNamespaceName(String name) { this.namespaceName = name; } /** * Sets the name of the source file this type is declared in. */ protected void setSourceFileName(String name) { this.sourceFileName = name; } /** * Sets the (unqualified) name of this type's superclass */ protected void setSuperclassName(String superclassName) { this.superclassName = superclassName; } /** * Sets the (unqualified) names of the modules this type includes */ protected void setIncludedModuleNames(String[] includedModuleNames) { this.includedModuleNames = includedModuleNames; } public String toString() { return "Info for " + this.handle.toString(); //$NON-NLS-1$ } }