1 /*******************************************************************************
2 * Copyright (c) 2000, 2003 IBM Corporation and others.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Common Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/cpl-v10.html
9 * IBM Corporation - initial API and implementation
10 *******************************************************************************/
11 package net.sourceforge.phpdt.internal.core.jdom;
13 import net.sourceforge.phpdt.core.Flags;
14 import net.sourceforge.phpdt.core.jdom.IDOMMember;
15 import net.sourceforge.phpdt.internal.compiler.env.IConstants;
16 import net.sourceforge.phpdt.internal.core.util.CharArrayBuffer;
17 import net.sourceforge.phpdt.internal.core.util.CharArrayOps;
20 * DOMMember provides an implementation of IDOMMember.
26 abstract class DOMMember extends DOMNode implements IDOMMember {
29 * The modifier flags for this member that can be
30 * analyzed with org.eclipse.jdt.core.Flags
32 protected int fFlags= 0;
35 * The member's comments when it has been altered from
36 * the contents in the document, otherwise <code>null</code>.
38 protected String fComment= null;
41 * The original inclusive source range of the
42 * member's preceding comments in the document,
43 * or -1's if the member did not originally have a
46 protected int[] fCommentRange;
50 * The member's modifiers textual representation when
51 * the modifiers (flags) have been altered from
52 * their original contents, otherwise <code>null</code>.
54 protected char[] fModifiers= null;
57 * The original inclusive source range of the
58 * member's modifiers in the document, or -1's if
59 * the member did not originally have modifiers in
60 * the source code (that is, package default visibility).
62 protected int[] fModifierRange;
65 * Constructs an empty member node.
71 * Creates a new member document fragment on the given range of the document.
73 * @param document - the document containing this node's original contents
74 * @param sourceRange - a two element array of integers describing the
75 * entire inclusive source range of this node within its document.
76 * Contents start on and include the character at the first position.
77 * Contents end on and include the character at the last position.
78 * An array of -1's indicates this node's contents do not exist
80 * @param name - the identifier portion of the name of this node, or
81 * <code>null</code> if this node does not have a name
82 * @param nameRange - a two element array of integers describing the
83 * entire inclusive source range of this node's name within its document,
84 * including any array qualifiers that might immediately follow the name.
85 * @param commentRange - a two element array describing the comments that precede
86 * the member declaration. The first matches the start of this node's
87 * sourceRange, and the second is the new-line or first non-whitespace
88 * character following the last comment. If no comments are present,
89 * this array contains two -1's.
90 * @param flags - an integer representing the modifiers for this member. The
91 * integer can be analyzed with org.eclipse.jdt.core.Flags
92 * @param modifierRange - a two element array describing the location of
93 * modifiers for this member within its source range. The first integer
94 * is the first character of the first modifier for this member, and
95 * the second integer is the last whitespace character preceeding the
96 * next part of this member declaration. If there are no modifiers present
97 * in this node's source code (that is, package default visibility), this array
100 DOMMember(char[] document, int[] sourceRange, String name, int[] nameRange, int[] commentRange, int flags, int[] modifierRange) {
101 super(document, sourceRange, name, nameRange);
104 fCommentRange= commentRange;
105 fModifierRange= modifierRange;
106 setHasComment(commentRange[0] >= 0);
109 * Appends the contents of this node to the given CharArrayBuffer, using
110 * the original document and indicies as a form for the current attribute values
113 * <p>To facilitate the implementation of generating contents for members,
114 * the content of members is split into three sections - the header,
115 * declaration, and body sections. The header section includes any preceding
116 * comments and modifiers. The declaration section includes the portion of
117 * the member declaration that follows any modifiers and precedes the
118 * member body. The body section includes the member body and any trailing
121 * @see DOMNode#appendFragmentedContents(CharArrayBuffer)
123 protected void appendFragmentedContents(CharArrayBuffer buffer) {
125 appendMemberHeaderFragment(buffer);
126 appendMemberDeclarationContents(buffer);
127 appendMemberBodyContents(buffer);
129 appendSimpleContents(buffer);
133 * Appends this member's body contents to the given CharArrayBuffer.
134 * Body contents include the member body and any trailing whitespace.
136 protected abstract void appendMemberBodyContents(CharArrayBuffer buffer);
138 * Appends this member's declaration contents to the given CharArrayBuffer.
139 * The declaration contents includes the portion of this member that
140 * appears after any modifiers and precedes the body.
142 protected abstract void appendMemberDeclarationContents(CharArrayBuffer buffer);
144 * Appends this member's header contents to the given CharArrayBuffer.
145 * Header contents include any preceding comments and modifiers.
147 protected void appendMemberHeaderFragment(CharArrayBuffer buffer) {
149 int spaceStart, spaceEnd;
151 // space before comment
153 spaceStart= fSourceRange[0];
154 spaceEnd= fCommentRange[0];
156 buffer.append(fDocument, spaceStart, spaceEnd - spaceStart);
160 String fragment= getComment();
161 if (fragment != null) {
162 buffer.append(fragment);
165 if (fCommentRange[1] >= 0) {
166 spaceStart= fCommentRange[1] + 1;
168 spaceStart= fSourceRange[0];
170 if (fModifierRange[0] >= 0) {
171 spaceEnd= fModifierRange[0] - 1;
173 spaceEnd= getMemberDeclarationStartPosition() - 1;
176 if (spaceEnd >= spaceStart) {
177 buffer.append(fDocument, spaceStart, spaceEnd + 1 - spaceStart);
179 buffer.append(getModifiersText());
183 * Appends the contents of this node to the given CharArrayBuffer, using
184 * the original document and indicies as a form for the current attribute values
185 * of this node. This method is called when this node is know not to have
186 * detailed source indexes.
188 protected abstract void appendSimpleContents(CharArrayBuffer buffer);
190 * Returns a copy of the given array with the new element appended
191 * to the end of the array.
193 protected String[] appendString(String[] list, String element) {
194 String[] copy= new String[list.length + 1];
195 System.arraycopy(list, 0, copy, 0, list.length);
196 copy[list.length]= element;
200 * Returns a <code>String</code> describing the modifiers for this member,
201 * ending with whitespace (if not empty). This value serves as a replacement
202 * value for the member's modifier range when the modifiers have been altered
203 * from their original contents.
205 protected char[] generateFlags() {
206 char[] flags= Flags.toString(getFlags()).toCharArray();
207 if (flags.length == 0) {
210 return CharArrayOps.concat(flags, new char[] {' '});
214 * @see IDOMMember#getComment()
216 public String getComment() {
219 if (fComment != null) {
222 return CharArrayOps.substring(fDocument, fCommentRange[0], fCommentRange[1] + 1 - fCommentRange[0]);
229 * @see IDOMMember#getFlags()
231 public int getFlags() {
235 * Returns the location of the first character in the member's declaration
238 * @see DOMMember#getMemberDeclarationContents()
239 * @see DOMMember#getFragmentedContents()
241 protected abstract int getMemberDeclarationStartPosition();
243 * Returns the String to be used for this member's flags when
244 * generating contents - either the original contents in the document
245 * or the replacement value.
247 protected char[] getModifiersText() {
248 if (fModifiers == null) {
249 if (fModifierRange[0] < 0) {
252 return CharArrayOps.subarray(fDocument, fModifierRange[0], fModifierRange[1] + 1 - fModifierRange[0]);
259 * Returns true if this member currently has a body.
261 protected boolean hasBody() {
262 return getMask(MASK_HAS_BODY);
265 * Returns true if this member currently has a comment.
267 protected boolean hasComment() {
268 return getMask(MASK_HAS_COMMENT);
271 * Offsets all the source indexes in this node by the given amount.
273 protected void offset(int offset) {
274 super.offset(offset);
275 offsetRange(fCommentRange, offset);
276 offsetRange(fModifierRange, offset);
279 * @see IDOMMember#setComment(String)
281 public void setComment(String comment) {
285 setHasComment(comment != null);
287 if (comment != null) {
288 String commentString = new String(comment);
289 if (commentString.indexOf("@deprecated") >= 0) { //$NON-NLS-1$
290 fFlags= fFlags | IConstants.AccDeprecated;
295 fFlags= fFlags & (~IConstants.AccDeprecated);
299 * @see IDOMMember#setFlags(int)
301 public void setFlags(int flags) {
303 if (Flags.isDeprecated(fFlags)) {
304 fFlags= flags | IConstants.AccDeprecated;
306 fFlags= flags & (~IConstants.AccDeprecated);
309 fModifiers= generateFlags();
312 * Sets the state of this member declaration as having
315 protected void setHasBody(boolean hasBody) {
316 setMask(MASK_HAS_BODY, hasBody);
319 * Sets the state of this member declaration as having
320 * a preceding comment.
322 protected void setHasComment(boolean hasComment) {
323 setMask(MASK_HAS_COMMENT, hasComment);
326 * Sets the original position of the first character of this node's contents
327 * in its document. This method is only used during DOM creation while
328 * normalizing the source range of each node.
330 * Synchronize the start of the comment position with the start of the
333 protected void setStartPosition(int start) {
334 if (fCommentRange[0] >= 0) {
335 fCommentRange[0]= start;
337 super.setStartPosition(start);
340 * @see DOMNode#shareContents(DOMNode)
342 protected void shareContents(DOMNode node) {
343 super.shareContents(node);
344 DOMMember member= (DOMMember)node;
345 fComment= member.fComment;
346 fCommentRange= rangeCopy(member.fCommentRange);
347 fFlags= member.fFlags;
348 fModifiers= member.fModifiers;
349 fModifierRange= rangeCopy(member.fModifierRange);