package org.eclipse.jdt.internal.core.jdom; | |
/* | |
* (c) Copyright IBM Corp. 2000, 2001. | |
* All Rights Reserved. | |
*/ | |
import org.eclipse.core.resources.*; | |
import org.eclipse.jdt.internal.compiler.env.IConstants; | |
import org.eclipse.jdt.core.Flags; | |
import org.eclipse.jdt.core.jdom.*; | |
import org.eclipse.jdt.internal.core.util.*; | |
/** | |
* DOMMember provides an implementation of IDOMMember. | |
* | |
* @see IDOMMember | |
* @see DOMNode | |
*/ | |
abstract class DOMMember extends DOMNode implements IDOMMember { | |
/** | |
* The modifier flags for this member that can be | |
* analyzed with org.eclipse.jdt.core.Flags | |
*/ | |
protected int fFlags= 0; | |
/** | |
* The member's comments when it has been altered from | |
* the contents in the document, otherwise <code>null</code>. | |
*/ | |
protected String fComment= null; | |
/** | |
* The original inclusive source range of the | |
* member's preceding comments in the document, | |
* or -1's if the member did not originally have a | |
* comment. | |
*/ | |
protected int[] fCommentRange; | |
/** | |
* The member's modifiers textual representation when | |
* the modifiers (flags) have been altered from | |
* their original contents, otherwise <code>null</code>. | |
*/ | |
protected char[] fModifiers= null; | |
/** | |
* The original inclusive source range of the | |
* member's modifiers in the document, or -1's if | |
* the member did not originally have modifiers in | |
* the source code (i.e. default protection). | |
*/ | |
protected int[] fModifierRange; | |
/** | |
* Constructs an empty member node. | |
*/ | |
DOMMember() { | |
} | |
/** | |
* Creates a new member document fragment on the given range of the document. | |
* | |
* @param document - the document containing this node's original contents | |
* @param sourceRange - a two element array of integers describing the | |
* entire inclusive source range of this node within its document. | |
* Contents start on and include the character at the first position. | |
* Contents end on and include the character at the last position. | |
* An array of -1's indicates this node's contents do not exist | |
* in the document. | |
* @param name - the identifier portion of the name of this node, or | |
* <code>null</code> if this node does not have a name | |
* @param nameRange - a two element array of integers describing the | |
* entire inclusive source range of this node's name within its document, | |
* including any array qualifiers that might immediately follow the name. | |
* @param commentRange - a two element array describing the comments that precede | |
* the member declaration. The first matches the start of this node's | |
* sourceRange, and the second is the new-line or first non-whitespace | |
* character following the last comment. If no comments are present, | |
* this array contains two -1's. | |
* @param flags - an integer representing the modifiers for this member. The | |
* integer can be analyzed with org.eclipse.jdt.core.Flags | |
* @param modifierRange - a two element array describing the location of | |
* modifiers for this member within its source range. The first integer | |
* is the first character of the first modifier for this member, and | |
* the second integer is the last whitespace character preceeding the | |
* next part of this member declaration. If there are no modifiers present | |
* in this node's source code (i.e. default protection), this array | |
* contains two -1's. | |
*/ | |
DOMMember(char[] document, int[] sourceRange, String name, int[] nameRange, int[] commentRange, int flags, int[] modifierRange) { | |
super(document, sourceRange, name, nameRange); | |
fFlags= flags; | |
fComment= null; | |
fCommentRange= commentRange; | |
fModifierRange= modifierRange; | |
setHasComment(commentRange[0] >= 0); | |
} | |
/** | |
* Appends the contents of this node to the given CharArrayBuffer, using | |
* the original document and indicies as a form for the current attribute values | |
* of this node. | |
* | |
* <p>To facilitate the implementation of generating contents for members, | |
* the content of members is split into three sections - the header, | |
* declaration, and body sections. The header section includes any preceding | |
* comments and modifiers. The declaration section includes the portion of | |
* the member declaration that follows any modifiers and precedes the | |
* member body. The body section includes the member body and any trailing | |
* whitespace. | |
* | |
* @see DOMNode#appendFragmentedContents(CharArrayBuffer) | |
*/ | |
protected void appendFragmentedContents(CharArrayBuffer buffer) { | |
if (isDetailed()) { | |
appendMemberHeaderFragment(buffer); | |
appendMemberDeclarationContents(buffer); | |
appendMemberBodyContents(buffer); | |
} else { | |
appendSimpleContents(buffer); | |
} | |
} | |
/** | |
* Appends this member's body contents to the given CharArrayBuffer. | |
* Body contents include the member body and any trailing whitespace. | |
*/ | |
protected abstract void appendMemberBodyContents(CharArrayBuffer buffer); | |
/** | |
* Appends this member's declaration contents to the given CharArrayBuffer. | |
* The declaration contents includes the portion of this member that | |
* appears after any modifiers and precedes the body. | |
*/ | |
protected abstract void appendMemberDeclarationContents(CharArrayBuffer buffer); | |
/** | |
* Appends this member's header contents to the given CharArrayBuffer. | |
* Header contents include any preceding comments and modifiers. | |
*/ | |
protected void appendMemberHeaderFragment(CharArrayBuffer buffer) { | |
int spaceStart, spaceEnd; | |
// space before comment | |
if (hasComment()) { | |
spaceStart= fSourceRange[0]; | |
spaceEnd= fCommentRange[0]; | |
if (spaceEnd > 0) { | |
buffer.append(fDocument, spaceStart, spaceEnd - spaceStart); | |
} | |
} | |
String fragment= getComment(); | |
if (fragment != null) { | |
buffer.append(fragment); | |
} | |
if (fCommentRange[1] >= 0) { | |
spaceStart= fCommentRange[1] + 1; | |
} else { | |
spaceStart= fSourceRange[0]; | |
} | |
if (fModifierRange[0] >= 0) { | |
spaceEnd= fModifierRange[0] - 1; | |
} else { | |
spaceEnd= getMemberDeclarationStartPosition() - 1; | |
} | |
if (spaceEnd >= spaceStart) { | |
buffer.append(fDocument, spaceStart, spaceEnd + 1 - spaceStart); | |
} | |
buffer.append(getModifiersText()); | |
} | |
/** | |
* Appends the contents of this node to the given CharArrayBuffer, using | |
* the original document and indicies as a form for the current attribute values | |
* of this node. This method is called when this node is know not to have | |
* detailed source indexes. | |
*/ | |
protected abstract void appendSimpleContents(CharArrayBuffer buffer); | |
/** | |
* Returns a copy of the given array with the new element appended | |
* to the end of the array. | |
*/ | |
protected String[] appendString(String[] list, String element) { | |
String[] copy= new String[list.length + 1]; | |
System.arraycopy(list, 0, copy, 0, list.length); | |
copy[list.length]= element; | |
return copy; | |
} | |
/** | |
* Returns a <code>String</code> describing the modifiers for this member, | |
* ending with whitespace (if not empty). This value serves as a replacement | |
* value for the member's modifier range when the modifiers have been altered | |
* from their original contents. | |
*/ | |
protected char[] generateFlags() { | |
char[] flags= Flags.toString(getFlags()).toCharArray(); | |
if (flags.length == 0) { | |
return flags; | |
} else { | |
return CharArrayOps.concat(flags, new char[] {' '}); | |
} | |
} | |
/** | |
* @see IDOMMember#getComment() | |
*/ | |
public String getComment() { | |
becomeDetailed(); | |
if (hasComment()) { | |
if (fComment != null) { | |
return fComment; | |
} else { | |
return CharArrayOps.substring(fDocument, fCommentRange[0], fCommentRange[1] + 1 - fCommentRange[0]); | |
} | |
} else { | |
return null; | |
} | |
} | |
/** | |
* @see IDOMMember#getFlags() | |
*/ | |
public int getFlags() { | |
return fFlags; | |
} | |
/** | |
* Returns the location of the first character in the member's declaration | |
* section. | |
* | |
* @see DOMMember#getMemberDeclarationContents() | |
* @see DOMMember#getFragmentedContents() | |
*/ | |
protected abstract int getMemberDeclarationStartPosition(); | |
/** | |
* Returns the String to be used for this member's flags when | |
* generating contents - either the original contents in the document | |
* or the replacement value. | |
*/ | |
protected char[] getModifiersText() { | |
if (fModifiers == null) { | |
if (fModifierRange[0] < 0) { | |
return null; | |
} else { | |
return CharArrayOps.subarray(fDocument, fModifierRange[0], fModifierRange[1] + 1 - fModifierRange[0]); | |
} | |
} else { | |
return fModifiers; | |
} | |
} | |
/** | |
* Returns true if this member currently has a body. | |
*/ | |
protected boolean hasBody() { | |
return getMask(MASK_HAS_BODY); | |
} | |
/** | |
* Returns true if this member currently has a comment. | |
*/ | |
protected boolean hasComment() { | |
return getMask(MASK_HAS_COMMENT); | |
} | |
/** | |
* Offsets all the source indexes in this node by the given amount. | |
*/ | |
protected void offset(int offset) { | |
super.offset(offset); | |
offsetRange(fCommentRange, offset); | |
offsetRange(fModifierRange, offset); | |
} | |
/** | |
* @see IDOMMember#setComment(String) | |
*/ | |
public void setComment(String comment) { | |
becomeDetailed(); | |
fComment= comment; | |
fragment(); | |
setHasComment(comment != null); | |
/* see 1FVIJAH */ | |
if (comment != null) { | |
String commentString = new String(comment); | |
if (commentString.indexOf("@deprecated"/*nonNLS*/) >= 0) { | |
fFlags= fFlags | IConstants.AccDeprecated; | |
return; | |
} | |
} | |
fFlags= fFlags & (~IConstants.AccDeprecated); | |
} | |
/** | |
* @see IDOMMember#setFlags(int) | |
*/ | |
public void setFlags(int flags) { | |
becomeDetailed(); | |
if (Flags.isDeprecated(fFlags)) { | |
fFlags= flags | IConstants.AccDeprecated; | |
} else { | |
fFlags= flags & (~IConstants.AccDeprecated); | |
} | |
fragment(); | |
fModifiers= generateFlags(); | |
} | |
/** | |
* Sets the state of this member declaration as having | |
* a body. | |
*/ | |
protected void setHasBody(boolean hasBody) { | |
setMask(MASK_HAS_BODY, hasBody); | |
} | |
/** | |
* Sets the state of this member declaration as having | |
* a preceding comment. | |
*/ | |
protected void setHasComment(boolean hasComment) { | |
setMask(MASK_HAS_COMMENT, hasComment); | |
} | |
/** | |
* Sets the original position of the first character of this node's contents | |
* in its document. This method is only used during DOM creation while | |
* normalizing the source range of each node. | |
* | |
* Synchronize the start of the comment position with the start of the | |
* node. | |
*/ | |
protected void setStartPosition(int start) { | |
if (fCommentRange[0] >= 0) { | |
fCommentRange[0]= start; | |
} | |
super.setStartPosition(start); | |
} | |
/** | |
* @see DOMNode#shareContents(DOMNode) | |
*/ | |
protected void shareContents(DOMNode node) { | |
super.shareContents(node); | |
DOMMember member= (DOMMember)node; | |
fComment= member.fComment; | |
fCommentRange= rangeCopy(member.fCommentRange); | |
fFlags= member.fFlags; | |
fModifiers= member.fModifiers; | |
fModifierRange= rangeCopy(member.fModifierRange); | |
} | |
} |