new version with WorkingCopy Management
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpdt / internal / core / jdom / DOMMember.java
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
7  * 
8  * Contributors:
9  *     IBM Corporation - initial API and implementation
10  *******************************************************************************/
11 package net.sourceforge.phpdt.internal.core.jdom;
12
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;
18
19 /**
20  * DOMMember provides an implementation of IDOMMember.
21  *
22  * @see IDOMMember
23  * @see DOMNode
24  */
25
26 abstract class DOMMember extends DOMNode implements IDOMMember {
27
28         /**
29          * The modifier flags for this member that can be
30          * analyzed with org.eclipse.jdt.core.Flags
31          */
32         protected int    fFlags= 0;
33
34         /**
35          * The member's comments when it has been altered from
36          * the contents in the document, otherwise <code>null</code>.
37          */
38         protected String fComment= null;
39
40         /**
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
44          * comment.
45          */
46          protected int[] fCommentRange;
47
48
49         /**
50          * The member's modifiers textual representation when 
51          * the modifiers (flags) have been altered from
52          * their original contents, otherwise <code>null</code>.
53          */
54          protected char[] fModifiers= null;
55
56         /**
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).
61          */
62          protected int[] fModifierRange;
63
64 /**
65  * Constructs an empty member node.
66  */
67 DOMMember() {
68
69 }
70 /**
71  * Creates a new member document fragment on the given range of the document.
72  *
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
79  *              in the document.
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
98  *              contains two -1's.
99  */
100 DOMMember(char[] document, int[] sourceRange, String name, int[] nameRange, int[] commentRange, int flags, int[] modifierRange) {
101         super(document, sourceRange, name, nameRange);
102         fFlags= flags;
103         fComment= null;
104         fCommentRange= commentRange;
105         fModifierRange= modifierRange;
106         setHasComment(commentRange[0] >= 0);
107 }
108 /**
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
111  * of this node.
112  *
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
119  * whitespace.
120  *
121  * @see DOMNode#appendFragmentedContents(CharArrayBuffer)
122  */
123 protected void appendFragmentedContents(CharArrayBuffer buffer) {
124         if (isDetailed()) {
125                 appendMemberHeaderFragment(buffer);
126                 appendMemberDeclarationContents(buffer);
127                 appendMemberBodyContents(buffer);
128         } else {
129                 appendSimpleContents(buffer);
130         }
131 }
132 /**
133  * Appends this member's body contents to the given CharArrayBuffer.
134  * Body contents include the member body and any trailing whitespace.
135  */
136 protected abstract void appendMemberBodyContents(CharArrayBuffer buffer);
137 /**
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.
141  */
142 protected abstract void appendMemberDeclarationContents(CharArrayBuffer buffer);
143 /**
144  * Appends this member's header contents to the given CharArrayBuffer.
145  * Header contents include any preceding comments and modifiers.
146  */
147 protected void appendMemberHeaderFragment(CharArrayBuffer buffer) {
148
149         int spaceStart, spaceEnd;
150
151         // space before comment
152         if (hasComment()) {
153                 spaceStart= fSourceRange[0];
154                 spaceEnd= fCommentRange[0];
155                 if (spaceEnd > 0) {
156                         buffer.append(fDocument, spaceStart, spaceEnd - spaceStart);
157                 }
158         }
159         
160         String fragment= getComment();
161         if (fragment != null) {
162                 buffer.append(fragment);
163         }
164
165         if (fCommentRange[1] >= 0) {
166                 spaceStart= fCommentRange[1] + 1;
167         } else {
168                 spaceStart= fSourceRange[0];
169         }
170         if (fModifierRange[0] >= 0) {
171                 spaceEnd= fModifierRange[0] - 1;
172         } else {
173                 spaceEnd= getMemberDeclarationStartPosition() - 1;
174         }
175
176         if (spaceEnd >= spaceStart) {
177                 buffer.append(fDocument, spaceStart, spaceEnd + 1 - spaceStart);
178         }
179         buffer.append(getModifiersText());
180
181 }
182 /**
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.
187  */
188 protected abstract void appendSimpleContents(CharArrayBuffer buffer);
189 /**
190  * Returns a copy of the given array with the new element appended
191  * to the end of the array.
192  */
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;
197         return copy;
198 }
199 /**
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.
204  */
205 protected char[] generateFlags() {
206         char[] flags= Flags.toString(getFlags()).toCharArray();
207         if (flags.length == 0) {
208                 return flags;
209         } else {
210                 return CharArrayOps.concat(flags, new char[] {' '});
211         }
212 }
213 /**
214  * @see IDOMMember#getComment()
215  */
216 public String getComment() {
217         becomeDetailed();
218         if (hasComment()) {
219                 if (fComment != null) {
220                         return fComment;
221                 } else {
222                         return CharArrayOps.substring(fDocument, fCommentRange[0], fCommentRange[1] + 1 - fCommentRange[0]);
223                 }
224         } else {
225                 return null;
226         }
227 }
228 /**
229  * @see IDOMMember#getFlags()
230  */
231 public int getFlags() {
232         return fFlags;
233 }
234 /**
235  * Returns the location of the first character in the member's declaration
236  * section.
237  *
238  * @see DOMMember#getMemberDeclarationContents()
239  * @see DOMMember#getFragmentedContents()
240  */
241 protected abstract int getMemberDeclarationStartPosition();
242 /**
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.
246  */
247 protected char[] getModifiersText() {
248         if (fModifiers == null) {
249                 if (fModifierRange[0] < 0) {
250                         return null;
251                 } else {
252                         return CharArrayOps.subarray(fDocument, fModifierRange[0], fModifierRange[1] + 1 - fModifierRange[0]);
253                 }
254         } else {
255                 return fModifiers;
256         }
257 }
258 /**
259  * Returns true if this member currently has a body.
260  */
261 protected boolean hasBody() {
262         return getMask(MASK_HAS_BODY);
263 }
264 /**
265  * Returns true if this member currently has a comment.
266  */
267 protected boolean hasComment() {
268         return getMask(MASK_HAS_COMMENT);
269 }
270 /**
271  * Offsets all the source indexes in this node by the given amount.
272  */
273 protected void offset(int offset) {
274         super.offset(offset);
275         offsetRange(fCommentRange, offset);
276         offsetRange(fModifierRange, offset);
277 }
278 /**
279  * @see IDOMMember#setComment(String)
280  */
281 public void setComment(String comment) {
282         becomeDetailed();
283         fComment= comment;
284         fragment();
285         setHasComment(comment != null);
286         /* see 1FVIJAH */
287         if (comment != null) {
288                 String commentString = new String(comment);
289                 if (commentString.indexOf("@deprecated") >= 0) { //$NON-NLS-1$
290                         fFlags= fFlags | IConstants.AccDeprecated;
291                         return;
292                 }
293
294         }
295         fFlags= fFlags & (~IConstants.AccDeprecated);
296
297 }
298 /**
299  * @see IDOMMember#setFlags(int)
300  */
301 public void setFlags(int flags) {
302         becomeDetailed();
303         if (Flags.isDeprecated(fFlags)) {
304                 fFlags= flags | IConstants.AccDeprecated;
305         } else {
306                 fFlags= flags & (~IConstants.AccDeprecated);
307         }
308         fragment();
309         fModifiers= generateFlags();
310 }
311 /**
312  * Sets the state of this member declaration as having
313  * a body.
314  */
315 protected void setHasBody(boolean hasBody) {
316         setMask(MASK_HAS_BODY, hasBody);
317 }
318 /**
319  * Sets the state of this member declaration as having
320  * a preceding comment.
321  */
322 protected void setHasComment(boolean hasComment) {
323         setMask(MASK_HAS_COMMENT, hasComment);
324 }
325 /**
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.
329  *
330  * Synchronize the start of the comment position with the start of the
331  * node.
332  */
333 protected void setStartPosition(int start) {
334         if (fCommentRange[0] >= 0) {
335                 fCommentRange[0]= start;
336         }
337         super.setStartPosition(start);
338 }
339 /**
340  * @see DOMNode#shareContents(DOMNode)
341  */
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);
350 }
351 }