/******************************************************************************* * Copyright (c) 2015, 2016 Google, Inc 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: * Stefan Xenos (Google) - Initial implementation *******************************************************************************/ package org.eclipse.jdt.internal.core.nd.java; import java.util.List; import org.eclipse.core.runtime.CoreException; import org.eclipse.jdt.internal.core.nd.INdVisitor; import org.eclipse.jdt.internal.core.nd.Nd; import org.eclipse.jdt.internal.core.nd.db.IString; import org.eclipse.jdt.internal.core.nd.field.FieldByte; import org.eclipse.jdt.internal.core.nd.field.FieldLong; import org.eclipse.jdt.internal.core.nd.field.FieldManyToOne; import org.eclipse.jdt.internal.core.nd.field.FieldOneToMany; import org.eclipse.jdt.internal.core.nd.field.FieldString; import org.eclipse.jdt.internal.core.nd.field.StructDef; import org.eclipse.jdt.internal.core.nd.util.CharArrayUtils; public class NdType extends NdBinding { public static final FieldManyToOne<NdTypeId> TYPENAME; public static final FieldManyToOne<NdTypeSignature> SUPERCLASS; public static final FieldOneToMany<NdTypeInterface> INTERFACES; public static final FieldManyToOne<NdTypeId> DECLARING_TYPE; public static final FieldManyToOne<NdMethodId> DECLARING_METHOD; public static final FieldOneToMany<NdMethod> METHODS; public static final FieldOneToMany<NdTypeAnnotationInType> TYPE_ANNOTATIONS; public static final FieldOneToMany<NdAnnotationInType> ANNOTATIONS; public static final FieldString MISSING_TYPE_NAMES; public static final FieldString SOURCE_FILE_NAME; public static final FieldString INNER_CLASS_SOURCE_NAME; public static final FieldByte FLAGS; public static final FieldLong TAG_BITS; /** * Binary name that was recorded in the .class file if different from the binary * name that was determined by the .class's name and location. This is only set for * .class files that have been moved to the wrong folder. */ public static final FieldString FIELD_DESCRIPTOR_FROM_CLASS; @SuppressWarnings("hiding") public static final StructDef<NdType> type; static { type = StructDef.create(NdType.class, NdBinding.type); TYPENAME = FieldManyToOne.create(type, NdTypeId.TYPES); DECLARING_TYPE = FieldManyToOne.create(type, NdTypeId.DECLARED_TYPES); INTERFACES = FieldOneToMany.create(type, NdTypeInterface.APPLIES_TO); SUPERCLASS = FieldManyToOne.create(type, NdTypeSignature.SUBCLASSES); DECLARING_METHOD = FieldManyToOne.create(type, NdMethodId.DECLARED_TYPES); METHODS = FieldOneToMany.create(type, NdMethod.PARENT, 6); TYPE_ANNOTATIONS = FieldOneToMany.create(type, NdTypeAnnotationInType.OWNER); ANNOTATIONS = FieldOneToMany.create(type, NdAnnotationInType.OWNER); MISSING_TYPE_NAMES = type.addString(); SOURCE_FILE_NAME = type.addString(); INNER_CLASS_SOURCE_NAME = type.addString(); FLAGS = type.addByte(); TAG_BITS = type.addLong(); FIELD_DESCRIPTOR_FROM_CLASS = type.addString(); type.done(); } public static final byte FLG_TYPE_ANONYMOUS = 0x0001; public static final byte FLG_TYPE_LOCAL = 0x0002; public static final byte FLG_TYPE_MEMBER = 0x0004; public static final byte FLG_GENERIC_SIGNATURE_PRESENT = 0x0008; public NdType(Nd nd, long address) { super(nd, address); } public NdType(Nd nd, NdResourceFile resource) { super(nd, resource); } /** * Called to populate the cache for the bindings in the class scope. */ public void acceptUncached(INdVisitor visitor) throws CoreException { super.accept(visitor); } public NdTypeId getTypeId() { return TYPENAME.get(getNd(), this.address); } public void setTypeId(NdTypeId typeId) { TYPENAME.put(getNd(), this.address, typeId); } /** * Sets the source name for this type. */ public void setSourceNameOverride(char[] sourceName) { char[] oldSourceName = getSourceName(); if (!CharArrayUtils.equals(oldSourceName, sourceName)) { INNER_CLASS_SOURCE_NAME.put(getNd(), this.address, sourceName); } } public IString getSourceNameOverride() { return INNER_CLASS_SOURCE_NAME.get(getNd(), this.address); } public long getResourceAddress() { return FILE.getAddress(getNd(), this.address); } public void setSuperclass(NdTypeSignature superclassTypeName) { SUPERCLASS.put(getNd(), this.address, superclassTypeName); } public NdTypeSignature getSuperclass() { return SUPERCLASS.get(getNd(), this.address); } public List<NdTypeInterface> getInterfaces() { return INTERFACES.asList(getNd(), this.address); } public NdResourceFile getResourceFile() { return FILE.get(getNd(), this.address); } public void setDeclaringMethod(NdMethodId createMethodId) { DECLARING_METHOD.put(getNd(), this.address, createMethodId); } /** * @param createTypeIdFromBinaryName */ public void setDeclaringType(NdTypeId createTypeIdFromBinaryName) { DECLARING_TYPE.put(getNd(), this.address, createTypeIdFromBinaryName); } public NdTypeId getDeclaringType() { return DECLARING_TYPE.get(getNd(), this.address); } /** * Sets the missing type names (if any) for this class. The names are encoded in a comma-separated list. */ public void setMissingTypeNames(char[] contents) { MISSING_TYPE_NAMES.put(getNd(), this.address, contents); } /** * Returns the missing type names as a comma-separated list */ public IString getMissingTypeNames() { return MISSING_TYPE_NAMES.get(getNd(), this.address); } public void setSourceFileName(char[] sourceFileName) { SOURCE_FILE_NAME.put(getNd(), this.address, sourceFileName); } public IString getSourceFileName() { return SOURCE_FILE_NAME.get(getNd(), this.address); } public void setAnonymous(boolean anonymous) { setFlag(FLG_TYPE_ANONYMOUS, anonymous); } public void setIsLocal(boolean local) { setFlag(FLG_TYPE_LOCAL, local); } public void setIsMember(boolean member) { setFlag(FLG_TYPE_MEMBER, member); } public boolean isAnonymous() { return getFlag(FLG_TYPE_ANONYMOUS); } public boolean isLocal() { return getFlag(FLG_TYPE_LOCAL); } public boolean isMember() { return getFlag(FLG_TYPE_MEMBER); } public void setFlag(byte flagConstant, boolean value) { int oldFlags = FLAGS.get(getNd(), this.address); int newFlags = ((oldFlags & ~flagConstant) | (value ? flagConstant : 0)); FLAGS.put(getNd(), this.address, (byte)newFlags); } public boolean getFlag(byte flagConstant) { return (FLAGS.get(getNd(), this.address) & flagConstant) != 0; } public char[] getSourceName() { IString sourceName = getSourceNameOverride(); if (sourceName.length() != 0) { return sourceName.getChars(); } char[] simpleName = getTypeId().getSimpleNameCharArray(); return JavaNames.simpleNameToSourceName(simpleName); } public NdMethodId getDeclaringMethod() { return DECLARING_METHOD.get(getNd(), this.address); } @Override public List<NdTypeParameter> getTypeParameters() { return TYPE_PARAMETERS.asList(getNd(), this.address); } public List<NdTypeAnnotationInType> getTypeAnnotations() { return TYPE_ANNOTATIONS.asList(getNd(), this.address); } public List<NdAnnotationInType> getAnnotations() { return ANNOTATIONS.asList(getNd(), this.address); } public List<NdMethod> getMethods() { return METHODS.asList(getNd(), this.address); } @Override public String toString() { try { return "class " + new String(getSourceName()); //$NON-NLS-1$ } catch (RuntimeException e) { return super.toString(); } } public void setTagBits(long tagBits) { TAG_BITS.put(getNd(), this.address, tagBits); } public long getTagBits() { return TAG_BITS.get(getNd(), this.address); } public void setFieldDescriptorFromClass(char[] fieldDescriptorFromClass) { FIELD_DESCRIPTOR_FROM_CLASS.put(getNd(), this.address, fieldDescriptorFromClass); } /** * Returns the field descriptor for this type, based on the binary type information stored in the * .class file itself. Note that this may differ from the field descriptor of this type's typeId in * the event that the .class file has been moved. */ public IString getFieldDescriptor() { IString descriptorFromClass = FIELD_DESCRIPTOR_FROM_CLASS.get(getNd(), this.address); if (descriptorFromClass.length() == 0) { return getTypeId().getFieldDescriptor(); } return descriptorFromClass; } }