A massive organize imports and formatting of the sources using default Eclipse code...
[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 analyzed with
30          * net.sourceforge.phpdt.core.Flags
31          */
32         protected int fFlags = 0;
33
34         /**
35          * The member's comments when it has been altered from the contents in the
36          * document, otherwise <code>null</code>.
37          */
38         protected String fComment = null;
39
40         /**
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.
43          */
44         protected int[] fCommentRange;
45
46         /**
47          * The member's modifiers textual representation when the modifiers (flags)
48          * have been altered from their original contents, otherwise
49          * <code>null</code>.
50          */
51         protected char[] fModifiers = null;
52
53         /**
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).
57          */
58         protected int[] fModifierRange;
59
60         /**
61          * Constructs an empty member node.
62          */
63         DOMMember() {
64
65         }
66
67         /**
68          * Creates a new member document fragment on the given range of the
69          * document.
70          * 
71          * @param document -
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.
80          * @param name -
81          *            the identifier portion of the name of this node, or
82          *            <code>null</code> if this node does not have a name
83          * @param nameRange -
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.
94          * @param flags -
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.
105          */
106         DOMMember(char[] document, int[] sourceRange, String name, int[] nameRange,
107                         int[] commentRange, int flags, int[] modifierRange) {
108                 super(document, sourceRange, name, nameRange);
109                 fFlags = flags;
110                 fComment = null;
111                 fCommentRange = commentRange;
112                 fModifierRange = modifierRange;
113                 setHasComment(commentRange[0] >= 0);
114         }
115
116         /**
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
119          * of this node.
120          * 
121          * <p>
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
128          * whitespace.
129          * 
130          * @see DOMNode#appendFragmentedContents(CharArrayBuffer)
131          */
132         protected void appendFragmentedContents(CharArrayBuffer buffer) {
133                 if (isDetailed()) {
134                         appendMemberHeaderFragment(buffer);
135                         appendMemberDeclarationContents(buffer);
136                         appendMemberBodyContents(buffer);
137                 } else {
138                         appendSimpleContents(buffer);
139                 }
140         }
141
142         /**
143          * Appends this member's body contents to the given CharArrayBuffer. Body
144          * contents include the member body and any trailing whitespace.
145          */
146         protected abstract void appendMemberBodyContents(CharArrayBuffer buffer);
147
148         /**
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.
152          */
153         protected abstract void appendMemberDeclarationContents(
154                         CharArrayBuffer buffer);
155
156         /**
157          * Appends this member's header contents to the given CharArrayBuffer.
158          * Header contents include any preceding comments and modifiers.
159          */
160         protected void appendMemberHeaderFragment(CharArrayBuffer buffer) {
161
162                 int spaceStart, spaceEnd;
163
164                 // space before comment
165                 if (hasComment()) {
166                         spaceStart = fSourceRange[0];
167                         spaceEnd = fCommentRange[0];
168                         if (spaceEnd > 0) {
169                                 buffer.append(fDocument, spaceStart, spaceEnd - spaceStart);
170                         }
171                 }
172
173                 String fragment = getComment();
174                 if (fragment != null) {
175                         buffer.append(fragment);
176                 }
177
178                 if (fCommentRange[1] >= 0) {
179                         spaceStart = fCommentRange[1] + 1;
180                 } else {
181                         spaceStart = fSourceRange[0];
182                 }
183                 if (fModifierRange[0] >= 0) {
184                         spaceEnd = fModifierRange[0] - 1;
185                 } else {
186                         spaceEnd = getMemberDeclarationStartPosition() - 1;
187                 }
188
189                 if (spaceEnd >= spaceStart) {
190                         buffer.append(fDocument, spaceStart, spaceEnd + 1 - spaceStart);
191                 }
192                 buffer.append(getModifiersText());
193
194         }
195
196         /**
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.
201          */
202         protected abstract void appendSimpleContents(CharArrayBuffer buffer);
203
204         /**
205          * Returns a copy of the given array with the new element appended to the
206          * end of the array.
207          */
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;
212                 return copy;
213         }
214
215         /**
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.
220          */
221         protected char[] generateFlags() {
222                 char[] flags = Flags.toString(getFlags()).toCharArray();
223                 if (flags.length == 0) {
224                         return flags;
225                 } else {
226                         return CharArrayOps.concat(flags, new char[] { ' ' });
227                 }
228         }
229
230         /**
231          * @see IDOMMember#getComment()
232          */
233         public String getComment() {
234                 becomeDetailed();
235                 if (hasComment()) {
236                         if (fComment != null) {
237                                 return fComment;
238                         } else {
239                                 return CharArrayOps.substring(fDocument, fCommentRange[0],
240                                                 fCommentRange[1] + 1 - fCommentRange[0]);
241                         }
242                 } else {
243                         return null;
244                 }
245         }
246
247         /**
248          * @see IDOMMember#getFlags()
249          */
250         public int getFlags() {
251                 return fFlags;
252         }
253
254         /**
255          * Returns the location of the first character in the member's declaration
256          * section.
257          * 
258          * @see DOMMember#getMemberDeclarationContents()
259          * @see DOMMember#getFragmentedContents()
260          */
261         protected abstract int getMemberDeclarationStartPosition();
262
263         /**
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
266          * replacement value.
267          */
268         protected char[] getModifiersText() {
269                 if (fModifiers == null) {
270                         if (fModifierRange[0] < 0) {
271                                 return null;
272                         } else {
273                                 return CharArrayOps.subarray(fDocument, fModifierRange[0],
274                                                 fModifierRange[1] + 1 - fModifierRange[0]);
275                         }
276                 } else {
277                         return fModifiers;
278                 }
279         }
280
281         /**
282          * Returns true if this member currently has a body.
283          */
284         protected boolean hasBody() {
285                 return getMask(MASK_HAS_BODY);
286         }
287
288         /**
289          * Returns true if this member currently has a comment.
290          */
291         protected boolean hasComment() {
292                 return getMask(MASK_HAS_COMMENT);
293         }
294
295         /**
296          * Offsets all the source indexes in this node by the given amount.
297          */
298         protected void offset(int offset) {
299                 super.offset(offset);
300                 offsetRange(fCommentRange, offset);
301                 offsetRange(fModifierRange, offset);
302         }
303
304         /**
305          * @see IDOMMember#setComment(String)
306          */
307         public void setComment(String comment) {
308                 becomeDetailed();
309                 fComment = comment;
310                 fragment();
311                 setHasComment(comment != null);
312                 /* see 1FVIJAH */
313                 if (comment != null) {
314                         String commentString = new String(comment);
315                         if (commentString.indexOf("@deprecated") >= 0) { //$NON-NLS-1$
316                                 fFlags = fFlags | IConstants.AccDeprecated;
317                                 return;
318                         }
319
320                 }
321                 fFlags = fFlags & (~IConstants.AccDeprecated);
322
323         }
324
325         /**
326          * @see IDOMMember#setFlags(int)
327          */
328         public void setFlags(int flags) {
329                 becomeDetailed();
330                 if (Flags.isDeprecated(fFlags)) {
331                         fFlags = flags | IConstants.AccDeprecated;
332                 } else {
333                         fFlags = flags & (~IConstants.AccDeprecated);
334                 }
335                 fragment();
336                 fModifiers = generateFlags();
337         }
338
339         /**
340          * Sets the state of this member declaration as having a body.
341          */
342         protected void setHasBody(boolean hasBody) {
343                 setMask(MASK_HAS_BODY, hasBody);
344         }
345
346         /**
347          * Sets the state of this member declaration as having a preceding comment.
348          */
349         protected void setHasComment(boolean hasComment) {
350                 setMask(MASK_HAS_COMMENT, hasComment);
351         }
352
353         /**
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.
357          * 
358          * Synchronize the start of the comment position with the start of the node.
359          */
360         protected void setStartPosition(int start) {
361                 if (fCommentRange[0] >= 0) {
362                         fCommentRange[0] = start;
363                 }
364                 super.setStartPosition(start);
365         }
366
367         /**
368          * @see DOMNode#shareContents(DOMNode)
369          */
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);
378         }
379 }