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 analyzed with
30 * net.sourceforge.phpdt.core.Flags
32 protected int fFlags = 0;
35 * The member's comments when it has been altered from the contents in the
36 * document, otherwise <code>null</code>.
38 protected String fComment = null;
41 * The original inclusive source range of the member's preceding comments in
42 * the document, or -1's if the member did not originally have a comment.
44 protected int[] fCommentRange;
47 * The member's modifiers textual representation when the modifiers (flags)
48 * have been altered from their original contents, otherwise
51 protected char[] fModifiers = null;
54 * The original inclusive source range of the member's modifiers in the
55 * document, or -1's if the member did not originally have modifiers in the
56 * source code (that is, package default visibility).
58 protected int[] fModifierRange;
61 * Constructs an empty member node.
68 * Creates a new member document fragment on the given range of the
72 * the document containing this node's original contents
73 * @param sourceRange -
74 * a two element array of integers describing the entire
75 * inclusive source range of this node within its document.
76 * Contents start on and include the character at the first
77 * position. Contents end on and include the character at the
78 * last position. An array of -1's indicates this node's contents
79 * do not exist in the document.
81 * the identifier portion of the name of this node, or
82 * <code>null</code> if this node does not have a name
84 * a two element array of integers describing the entire
85 * inclusive source range of this node's name within its
86 * document, including any array qualifiers that might
87 * immediately follow the name.
88 * @param commentRange -
89 * a two element array describing the comments that precede the
90 * member declaration. The first matches the start of this node's
91 * sourceRange, and the second is the new-line or first
92 * non-whitespace character following the last comment. If no
93 * comments are present, this array contains two -1's.
95 * an integer representing the modifiers for this member. The
96 * integer can be analyzed with net.sourceforge.phpdt.core.Flags
97 * @param modifierRange -
98 * a two element array describing the location of modifiers for
99 * this member within its source range. The first integer is the
100 * first character of the first modifier for this member, and the
101 * second integer is the last whitespace character preceeding the
102 * next part of this member declaration. If there are no
103 * modifiers present in this node's source code (that is, package
104 * default visibility), this array contains two -1's.
106 DOMMember(char[] document, int[] sourceRange, String name, int[] nameRange,
107 int[] commentRange, int flags, int[] modifierRange) {
108 super(document, sourceRange, name, nameRange);
111 fCommentRange = commentRange;
112 fModifierRange = modifierRange;
113 setHasComment(commentRange[0] >= 0);
117 * Appends the contents of this node to the given CharArrayBuffer, using the
118 * original document and indicies as a form for the current attribute values
122 * To facilitate the implementation of generating contents for members, the
123 * content of members is split into three sections - the header,
124 * declaration, and body sections. The header section includes any preceding
125 * comments and modifiers. The declaration section includes the portion of
126 * the member declaration that follows any modifiers and precedes the member
127 * body. The body section includes the member body and any trailing
130 * @see DOMNode#appendFragmentedContents(CharArrayBuffer)
132 protected void appendFragmentedContents(CharArrayBuffer buffer) {
134 appendMemberHeaderFragment(buffer);
135 appendMemberDeclarationContents(buffer);
136 appendMemberBodyContents(buffer);
138 appendSimpleContents(buffer);
143 * Appends this member's body contents to the given CharArrayBuffer. Body
144 * contents include the member body and any trailing whitespace.
146 protected abstract void appendMemberBodyContents(CharArrayBuffer buffer);
149 * Appends this member's declaration contents to the given CharArrayBuffer.
150 * The declaration contents includes the portion of this member that appears
151 * after any modifiers and precedes the body.
153 protected abstract void appendMemberDeclarationContents(
154 CharArrayBuffer buffer);
157 * Appends this member's header contents to the given CharArrayBuffer.
158 * Header contents include any preceding comments and modifiers.
160 protected void appendMemberHeaderFragment(CharArrayBuffer buffer) {
162 int spaceStart, spaceEnd;
164 // space before comment
166 spaceStart = fSourceRange[0];
167 spaceEnd = fCommentRange[0];
169 buffer.append(fDocument, spaceStart, spaceEnd - spaceStart);
173 String fragment = getComment();
174 if (fragment != null) {
175 buffer.append(fragment);
178 if (fCommentRange[1] >= 0) {
179 spaceStart = fCommentRange[1] + 1;
181 spaceStart = fSourceRange[0];
183 if (fModifierRange[0] >= 0) {
184 spaceEnd = fModifierRange[0] - 1;
186 spaceEnd = getMemberDeclarationStartPosition() - 1;
189 if (spaceEnd >= spaceStart) {
190 buffer.append(fDocument, spaceStart, spaceEnd + 1 - spaceStart);
192 buffer.append(getModifiersText());
197 * Appends the contents of this node to the given CharArrayBuffer, using the
198 * original document and indicies as a form for the current attribute values
199 * of this node. This method is called when this node is know not to have
200 * detailed source indexes.
202 protected abstract void appendSimpleContents(CharArrayBuffer buffer);
205 * Returns a copy of the given array with the new element appended to the
208 protected String[] appendString(String[] list, String element) {
209 String[] copy = new String[list.length + 1];
210 System.arraycopy(list, 0, copy, 0, list.length);
211 copy[list.length] = element;
216 * Returns a <code>String</code> describing the modifiers for this member,
217 * ending with whitespace (if not empty). This value serves as a replacement
218 * value for the member's modifier range when the modifiers have been
219 * altered from their original contents.
221 protected char[] generateFlags() {
222 char[] flags = Flags.toString(getFlags()).toCharArray();
223 if (flags.length == 0) {
226 return CharArrayOps.concat(flags, new char[] { ' ' });
231 * @see IDOMMember#getComment()
233 public String getComment() {
236 if (fComment != null) {
239 return CharArrayOps.substring(fDocument, fCommentRange[0],
240 fCommentRange[1] + 1 - fCommentRange[0]);
248 * @see IDOMMember#getFlags()
250 public int getFlags() {
255 * Returns the location of the first character in the member's declaration
258 * @see DOMMember#getMemberDeclarationContents()
259 * @see DOMMember#getFragmentedContents()
261 protected abstract int getMemberDeclarationStartPosition();
264 * Returns the String to be used for this member's flags when generating
265 * contents - either the original contents in the document or the
268 protected char[] getModifiersText() {
269 if (fModifiers == null) {
270 if (fModifierRange[0] < 0) {
273 return CharArrayOps.subarray(fDocument, fModifierRange[0],
274 fModifierRange[1] + 1 - fModifierRange[0]);
282 * Returns true if this member currently has a body.
284 protected boolean hasBody() {
285 return getMask(MASK_HAS_BODY);
289 * Returns true if this member currently has a comment.
291 protected boolean hasComment() {
292 return getMask(MASK_HAS_COMMENT);
296 * Offsets all the source indexes in this node by the given amount.
298 protected void offset(int offset) {
299 super.offset(offset);
300 offsetRange(fCommentRange, offset);
301 offsetRange(fModifierRange, offset);
305 * @see IDOMMember#setComment(String)
307 public void setComment(String comment) {
311 setHasComment(comment != null);
313 if (comment != null) {
314 String commentString = new String(comment);
315 if (commentString.indexOf("@deprecated") >= 0) { //$NON-NLS-1$
316 fFlags = fFlags | IConstants.AccDeprecated;
321 fFlags = fFlags & (~IConstants.AccDeprecated);
326 * @see IDOMMember#setFlags(int)
328 public void setFlags(int flags) {
330 if (Flags.isDeprecated(fFlags)) {
331 fFlags = flags | IConstants.AccDeprecated;
333 fFlags = flags & (~IConstants.AccDeprecated);
336 fModifiers = generateFlags();
340 * Sets the state of this member declaration as having a body.
342 protected void setHasBody(boolean hasBody) {
343 setMask(MASK_HAS_BODY, hasBody);
347 * Sets the state of this member declaration as having a preceding comment.
349 protected void setHasComment(boolean hasComment) {
350 setMask(MASK_HAS_COMMENT, hasComment);
354 * Sets the original position of the first character of this node's contents
355 * in its document. This method is only used during DOM creation while
356 * normalizing the source range of each node.
358 * Synchronize the start of the comment position with the start of the node.
360 protected void setStartPosition(int start) {
361 if (fCommentRange[0] >= 0) {
362 fCommentRange[0] = start;
364 super.setStartPosition(start);
368 * @see DOMNode#shareContents(DOMNode)
370 protected void shareContents(DOMNode node) {
371 super.shareContents(node);
372 DOMMember member = (DOMMember) node;
373 fComment = member.fComment;
374 fCommentRange = rangeCopy(member.fCommentRange);
375 fFlags = member.fFlags;
376 fModifiers = member.fModifiers;
377 fModifierRange = rangeCopy(member.fModifierRange);