improved PHP parser
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpdt / internal / core / jdom / DOMType.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 java.util.Enumeration;
14
15 import net.sourceforge.phpdt.core.ICompilationUnit;
16 import net.sourceforge.phpdt.core.IJavaElement;
17 import net.sourceforge.phpdt.core.IType;
18 import net.sourceforge.phpdt.core.compiler.ITerminalSymbols;
19 import net.sourceforge.phpdt.core.compiler.InvalidInputException;
20 import net.sourceforge.phpdt.core.jdom.IDOMMethod;
21 import net.sourceforge.phpdt.core.jdom.IDOMNode;
22 import net.sourceforge.phpdt.core.jdom.IDOMType;
23 import net.sourceforge.phpdt.internal.compiler.parser.Scanner;
24 import net.sourceforge.phpdt.internal.compiler.util.Util;
25 import net.sourceforge.phpdt.internal.core.util.CharArrayBuffer;
26 import net.sourceforge.phpdt.internal.core.util.CharArrayOps;
27
28 /**
29  * DOMType provides an implementation of IDOMType.
30  *
31  * @see IDOMType
32  * @see DOMNode
33  */
34  
35 /* package */ class DOMType extends DOMMember implements IDOMType {
36
37         /**
38          * The 'class' or 'interface' keyword if altered
39          * from the documents contents, otherwise <code>null</code>.
40          */
41         protected String fTypeKeyword;
42
43         /**
44          * The original inclusive source range of the 'class'
45          * or 'interface' keyword in the document.
46          */
47         protected int[]  fTypeRange;
48
49         /**
50          * The superclass name for the class declaration
51          * if altered from the document's contents, otherwise
52          * <code>null</code>. Also <code>null</code> when this
53          * type represents an interface.
54          */
55         protected String fSuperclass;
56
57         /**
58          * The original inclusive source range of the superclass
59          * name in the document, or -1's of no superclass was
60          * specified in the document.
61          */
62         protected int[]  fSuperclassRange;
63
64
65         /**
66          * The original inclusive souce range of the 'extends' keyword
67          * in the document, including surrounding whitespace, or -1's if
68          * the keyword was not present in the document.
69          */
70         protected int[]  fExtendsRange;
71
72         /**
73          * The original inclusive souce range of the 'implements' keyword
74          * in the document, including surrounding whitespace, or -1's if
75          * the keyword was not present in the document.
76          */     
77         protected int[]  fImplementsRange;
78
79         /**
80          * The comma delimited list of interfaces this type implements
81          * or extends, if altered from the document's contents, otherwise
82          * <code>null</code>. Also <code>null</code> if this type does
83          * not implement or extend any interfaces.
84          */
85         protected char[] fInterfaces;
86
87         /**
88          * The original inclusive source range of the list of interfaces this
89          * type implements or extends, not including any surrouding whitespace.
90          * If the document did not specify interfaces, this array contains -1's.
91          */
92         protected int[]  fInterfacesRange;
93
94         
95
96         /** 
97          * The original source range of the first character following the
98          * type name superclass name, or interface list, up to and including
99          * the first character before the first type member.
100          */     
101         protected int[]  fOpenBodyRange;
102
103         /** 
104          * The original source range of the first new line or non whitespace
105          * character preceding the close brace of the type's body, up to the
106          * and including the first character before the next node (if there are
107          * no following nodes, the range ends at the position of the last
108          * character in the document).
109          */     
110         protected int[]  fCloseBodyRange;
111
112         /**
113          * A list of interfaces this type extends or implements.
114          * <code>null</code> when this type does not extend
115          * or implement any interfaces.
116          */
117         protected String[] fSuperInterfaces= new String[0];
118         
119         /**
120          * This position is the position of the end of the last line separator before the closing brace starting
121          * position of the receiver.
122          */
123 //      protected int fInsertionPosition;
124
125 /**
126  * Constructs an empty type node.
127  */
128 DOMType() {
129
130 }
131 /**
132  * Creates a new detailed TYPE document fragment on the given range of the document.
133  *
134  * @param document - the document containing this node's original contents
135  * @param sourceRange - a two element array of integers describing the
136  *              entire inclusive source range of this node within its document.
137  *              Contents start on and include the character at the first position.
138  *              Contents end on and include the character at the last position.
139  *              An array of -1's indicates this node's contents do not exist
140  *              in the document.
141  * @param name - the identifier portion of the name of this node, or
142  *              <code>null</code> if this node does not have a name
143  * @param nameRange - a two element array of integers describing the
144  *              entire inclusive source range of this node's name within its document,
145  *              including any array qualifiers that might immediately follow the name
146  *              or -1's if this node does not have a name.
147  * @param commentRange - a two element array describing the comments that precede
148  *              the member declaration. The first matches the start of this node's
149  *              sourceRange, and the second is the new-line or first non-whitespace
150  *              character following the last comment. If no comments are present,
151  *              this array contains two -1's.
152  * @param flags - an integer representing the modifiers for this member. The
153  *              integer can be analyzed with net.sourceforge.phpdt.core.Flags
154  * @param modifierRange - a two element array describing the location of
155  *              modifiers for this member within its source range. The first integer
156  *              is the first character of the first modifier for this member, and
157  *              the second integer is the last whitespace character preceeding the
158  *              next part of this member declaration. If there are no modifiers present
159  *              in this node's source code (that is, package default visibility), this array
160  *              contains two -1's.
161  * @param typeRange - a two element array describing the location of the 'class'
162  *              or 'interface' keyword in the type declaration - first and last character
163  *              positions.
164  * @param superclassRange - a two element array describing the location of the
165  *              superclass name in the type declaration - first and last character
166  *              positions or two -1's if a superclass is not present in the document.
167  * @param extendsRange - a two element array describing the location of the
168  *              'extends' keyword in the type declaration, including any surrounding
169  *              whitespace, or -1's if the 'extends' keyword is not present in the document.
170  * @param implementsList - an array of names of the interfaces this type implements
171  *              or extends, or <code>null</code> if this type does not implement or extend
172  *              any interfaces.
173  * @param implementsRange - a two element array describing the location of the
174  *              comment delimited list of interfaces this type implements or extends,
175  *              not including any surrounding whitespace, or -1's if no interface list
176  *              is present in the document.
177  * @param implementsKeywordRange - a two element array describing the location of the
178  *              'implements' keyword, including any surrounding whitespace, or -1's if no
179  *              'implements' keyword is present in the document.
180  * @param openBodyRange - a two element array describing the location of the
181  *      open brace of the type's body and whitespace following the type declaration
182  *              and preceeding the first member in the type.
183  * @param closeBodyRange - a two element array describing the source range of the
184  *              first new line or non whitespace character preceeding the close brace of the
185  *              type's body, up to the close brace
186  * @param isClass - true is the type is a class, false if it is an interface
187  */
188 DOMType(char[] document, int[] sourceRange, String name, int[] nameRange, int[] commentRange, int flags, int[] modifierRange, int[] typeRange, int[] superclassRange, int[] extendsRange, String[] implementsList, int[] implementsRange, int[] implementsKeywordRange, int[] openBodyRange, int[] closeBodyRange, boolean isClass) {
189         super(document, sourceRange, name, nameRange, commentRange, flags, modifierRange);
190
191         fTypeRange= typeRange;
192         setMask(MASK_TYPE_IS_CLASS, isClass);
193
194         fExtendsRange= extendsRange;
195         fImplementsRange= implementsKeywordRange;
196         fSuperclassRange= superclassRange;
197         fInterfacesRange= implementsRange;
198         fCloseBodyRange= closeBodyRange;
199         setMask(MASK_TYPE_HAS_SUPERCLASS, superclassRange[0] > 0);
200         setMask(MASK_TYPE_HAS_INTERFACES, implementsList != null);
201         fSuperInterfaces= implementsList;
202         fOpenBodyRange= openBodyRange;
203         fCloseBodyRange= closeBodyRange;
204         setMask(MASK_DETAILED_SOURCE_INDEXES, true);
205
206 }
207 /**
208  * Creates a new simple TYPE document fragment on the given range of the document.
209  *
210  * @param document - the document containing this node's original contents
211  * @param sourceRange - a two element array of integers describing the
212  *              entire inclusive source range of this node within its document.
213  *              Contents start on and include the character at the first position.
214  *              Contents end on and include the character at the last position.
215  *              An array of -1's indicates this node's contents do not exist
216  *              in the document.
217  * @param name - the identifier portion of the name of this node, or
218  *              <code>null</code> if this node does not have a name
219  * @param nameRange - a two element array of integers describing the
220  *              entire inclusive source range of this node's name within its document,
221  *              including any array qualifiers that might immediately follow the name
222  *              or -1's if this node does not have a name.
223  * @param flags - an integer representing the modifiers for this member. The
224  *              integer can be analyzed with net.sourceforge.phpdt.core.Flags
225  * @param implementsList - an array of names of the interfaces this type implements
226  *              or extends, or <code>null</code> if this type does not implement or extend
227  *              any interfaces.
228  * @param isClass - true is the type is a class, false if it is an interface
229  */
230 DOMType(char[] document, int[] sourceRange, String name, int[] nameRange, int flags, String[] implementsList, boolean isClass) {
231         this(document, sourceRange, name, nameRange, new int[] {-1, -1}, flags,
232                 new int[] {-1, -1}, new int[] {-1, -1}, new int[] {-1, -1}, new int[] {-1, -1},
233                 implementsList, new int[] {-1, -1}, new int[] {-1, -1}, new int[] {-1, -1}, new int[] {sourceRange[1], sourceRange[1]}, isClass);
234         setMask(MASK_DETAILED_SOURCE_INDEXES, false);
235 }
236 /**
237  * @see IDOMType#addSuperInterface(String)
238  */
239 public void addSuperInterface(String name) throws IllegalArgumentException {
240         if (name == null) {
241                 throw new IllegalArgumentException(Util.bind("dom.addNullInterface")); //$NON-NLS-1$
242         }
243         if (fSuperInterfaces == null) {
244                 fSuperInterfaces= new String[1];
245                 fSuperInterfaces[0]= name;
246         } else {
247                 fSuperInterfaces= appendString(fSuperInterfaces, name);
248         }
249         setSuperInterfaces(fSuperInterfaces);
250 }
251 /**
252  * @see DOMMember#appendMemberBodyContents(CharArrayBuffer)
253  */
254 protected void appendMemberBodyContents(CharArrayBuffer buffer) {
255         buffer.append(fDocument, fOpenBodyRange[0], fOpenBodyRange[1] + 1 - fOpenBodyRange[0]);
256         appendContentsOfChildren(buffer);
257         buffer.append(fDocument, fCloseBodyRange[0], fCloseBodyRange[1] + 1 - fCloseBodyRange[0]);
258         buffer.append(fDocument, fCloseBodyRange[1] + 1, fSourceRange[1] - fCloseBodyRange[1]);
259 }
260 /**
261  * @see DOMMember#appendMemberDeclarationContents(CharArrayBuffer )
262  */
263 protected void appendMemberDeclarationContents(CharArrayBuffer  buffer) {
264         
265         if (fTypeKeyword != null) {
266                 buffer.append(fTypeKeyword);
267                 buffer.append(fDocument, fTypeRange[1], fNameRange[0] - fTypeRange[1] );
268         } else {
269                 buffer.append(fDocument, fTypeRange[0], fTypeRange[1] + 1 - fTypeRange[0]);
270         }
271
272         buffer.append(getName());
273
274         if (isClass()) {
275                 boolean hasSuperclass = false, hasInterfaces = false;
276                 if (getMask(MASK_TYPE_HAS_SUPERCLASS)) {
277                         hasSuperclass = true;
278                         if (fExtendsRange[0] < 0) {
279                                 buffer.append(" extends "); //$NON-NLS-1$
280                         } else {
281                                 buffer.append(fDocument, fExtendsRange[0], fExtendsRange[1] + 1 - fExtendsRange[0]);
282                         }
283                         if (fSuperclass != null) {
284                                 buffer.append(fSuperclass);
285                         } else {
286                                 buffer.append(fDocument, fSuperclassRange[0], fSuperclassRange[1] + 1 - fSuperclassRange[0]);
287                         }
288                 }
289                 if (getMask(MASK_TYPE_HAS_INTERFACES)) {
290                         hasInterfaces = true;
291                         if (fImplementsRange[0] < 0) {
292                                 buffer.append(" implements "); //$NON-NLS-1$
293                         } else {
294                                 buffer.append(fDocument, fImplementsRange[0], fImplementsRange[1] + 1 - fImplementsRange[0]);
295                         }
296                         if (fInterfaces != null) {
297                                 buffer.append(fInterfaces);
298                         } else {
299                                 buffer.append(fDocument, fInterfacesRange[0], fInterfacesRange[1] + 1 - fInterfacesRange[0]);
300                         }
301                 }
302                 if (hasInterfaces) {
303                         if (fImplementsRange[0] < 0) {
304                                 buffer.append(' ');
305                         } else {
306                                 buffer.append(fDocument, fInterfacesRange[1] + 1, fOpenBodyRange[0] - fInterfacesRange[1] - 1);
307                         }
308                 } else {
309                         if (hasSuperclass) {
310                                 if (fSuperclassRange[0] < 0) {
311                                         buffer.append(' ');
312                                 } else {
313                                         buffer.append(fDocument, fSuperclassRange[1] + 1, fOpenBodyRange[0] - fSuperclassRange[1] - 1);
314                                 }
315                         } else {
316                                 buffer.append(fDocument, fNameRange[1] + 1, fOpenBodyRange[0] - fNameRange[1] - 1);
317                         }
318                 }
319         } else {
320                 if (getMask(MASK_TYPE_HAS_INTERFACES)) {
321                         if (fExtendsRange[0] < 0) {
322                                 buffer.append(" extends "); //$NON-NLS-1$
323                         } else {
324                                 buffer.append(fDocument, fExtendsRange[0], fExtendsRange[1] + 1 - fExtendsRange[0]);
325                         }
326                         if (fInterfaces != null) {
327                                 buffer.append(fInterfaces);
328                                 buffer.append(' ');
329                         } else {
330                                 buffer.append(fDocument, fInterfacesRange[0], fInterfacesRange[1] + 1 - fInterfacesRange[0]);
331                         }
332                 } else {
333                         buffer.append(fDocument, fNameRange[1] + 1, fOpenBodyRange[0] - fNameRange[1] - 1);
334                 }
335         }
336         
337 }
338 /**
339  * @see DOMNode#appendSimpleContents(CharArrayBuffer)
340  */
341 protected void appendSimpleContents(CharArrayBuffer buffer) {
342         // append eveything before my name
343         buffer.append(fDocument, fSourceRange[0], fNameRange[0] - fSourceRange[0]);
344         // append my name
345         buffer.append(fName);
346
347         
348         // append everything after my name and before my first child
349         buffer.append(fDocument, fNameRange[1] + 1, fOpenBodyRange[1] - fNameRange[1]);
350         // append my children
351         appendContentsOfChildren(buffer);
352         // append from my last child to my end
353         buffer.append(fDocument, fCloseBodyRange[0], fSourceRange[1] - fCloseBodyRange[0] + 1);
354
355
356 }
357 /**
358  * @see IDOMNode#canHaveChildren()
359  */
360 public boolean canHaveChildren() {
361         return true;
362 }
363 /**
364  * Returns the position of the closing brace for the body of this type.
365  * This value this method returns is only valid before the type has
366  * been normalized and is present only for normalization.
367  */
368 int getCloseBodyPosition() {
369         return fCloseBodyRange[0];
370 }
371 /**
372  * @see DOMNode#getDetailedNode()
373  */
374 //protected DOMNode getDetailedNode() {
375 //      return (DOMNode)getFactory().createType(getContents());
376 //}
377 /**
378  * @see DOMNode#getInsertionPosition()
379  */
380 public int getInsertionPosition() {
381         // this should return the position of the end of the last line separator before the closing brace of the type
382         // See PR 1GELSDQ: ITPJUI:WINNT - JDOM: IType.createMethod does not insert nicely for inner types
383         return fInsertionPosition;
384 }
385 /**
386  * @see IDOMNode#getJavaElement
387  */
388 public IJavaElement getJavaElement(IJavaElement parent) throws IllegalArgumentException {
389         if (parent.getElementType() == IJavaElement.TYPE) {
390                 return ((IType)parent).getType(getName());
391         } else if (parent.getElementType() == IJavaElement.COMPILATION_UNIT) {
392                 return ((ICompilationUnit)parent).getType(getName());
393         } else {
394                 throw new IllegalArgumentException(Util.bind("element.illegalParent")); //$NON-NLS-1$
395         }
396 }
397 /**
398  * @see DOMMember#getMemberDeclarationStartPosition()
399  */
400 protected int getMemberDeclarationStartPosition() {
401         return fTypeRange[0];
402 }
403 /**
404  * @see IDOMNode#getNodeType()
405  */
406 public int getNodeType() {
407         return IDOMNode.TYPE;
408 }
409 /**
410  * Answers the open body range end position.
411  */
412 int getOpenBodyEnd() {
413         return fOpenBodyRange[1];
414 }
415 /**
416  * @see IDOMType#getSuperclass()
417  */
418 public String getSuperclass() {
419         becomeDetailed();
420         if (getMask(MASK_TYPE_HAS_SUPERCLASS)) {
421                 if (fSuperclass != null) {
422                         return fSuperclass;
423                 } else {
424                         return CharArrayOps.substring(fDocument, fSuperclassRange[0], fSuperclassRange[1] + 1 - fSuperclassRange[0]);
425                 }
426         } else {
427                 return null;
428         }
429 }
430 /**
431  * @see IDOMType#getSuperInterfaces()
432  */
433 public String[] getSuperInterfaces() {
434         return fSuperInterfaces;
435 }
436 /**
437  * @see IDOMNode
438  */
439 public boolean isAllowableChild(IDOMNode node) {
440         if (node != null) {
441                 int type= node.getNodeType();
442                 return type == IDOMNode.TYPE || type == IDOMNode.FIELD|| type == IDOMNode.METHOD || 
443                         type == IDOMNode.INITIALIZER; 
444         } else {
445                 return false;
446         }
447         
448 }
449 /**
450  * @see IDOMType#isClass()
451  */
452 public boolean isClass() {
453         return getMask(MASK_TYPE_IS_CLASS);
454 }
455 /**
456  * @see DOMNode
457  */
458 protected DOMNode newDOMNode() {
459         return new DOMType();
460 }
461 /**
462  * Normalizes this <code>DOMNode</code>'s source positions to include whitespace preceeding
463  * the node on the line on which the node starts, and all whitespace after the node up to
464  * the next node's start
465  */
466 void normalize(ILineStartFinder finder) {
467         // perform final changes to the open and close body ranges
468         int openBodyEnd, openBodyStart, closeBodyStart, closeBodyEnd;
469         DOMNode first = (DOMNode) getFirstChild();
470         DOMNode lastNode = null;
471         // look for the open body
472         Scanner scanner = new Scanner();
473         scanner.setSource(fDocument);
474         scanner.resetTo(fNameRange[1] + 1, fDocument.length);
475         
476         try {
477                 int currentToken = scanner.getNextToken();
478                 while(currentToken != ITerminalSymbols.TokenNameLBRACE &&
479                                 currentToken != ITerminalSymbols.TokenNameEOF) {
480                         currentToken = scanner.getNextToken();
481                 }
482                 if(currentToken == ITerminalSymbols.TokenNameLBRACE) {          
483                         openBodyEnd = scanner.currentPosition - 1;
484                         openBodyStart = scanner.startPosition;
485                 } else {
486                         openBodyEnd = fDocument.length;
487                         openBodyStart = fDocument.length;
488                 }
489         } catch(InvalidInputException e) {
490                 openBodyEnd = fDocument.length;
491                 openBodyStart = fDocument.length;
492         }
493         if (first != null) {
494                 int lineStart = finder.getLineStart(first.getStartPosition());
495                 if (lineStart > openBodyEnd) {
496                         openBodyEnd = lineStart - 1;
497                 } else {
498                         openBodyEnd = first.getStartPosition() - 1;
499                 }               
500                 lastNode = (DOMNode) first.getNextNode();
501                 if (lastNode == null) {
502                         lastNode = first;
503                 } else {
504                         while (lastNode.getNextNode() != null) {
505                                 lastNode = (DOMNode) lastNode.getNextNode();
506                         }
507                 }
508                 scanner.setSource(fDocument);
509                 scanner.resetTo(lastNode.getEndPosition() + 1, fDocument.length);
510                 try {
511                         int currentToken = scanner.getNextToken();
512                         while(currentToken != ITerminalSymbols.TokenNameRBRACE &&
513                                         currentToken != ITerminalSymbols.TokenNameEOF) {
514                                 currentToken = scanner.getNextToken();
515                         }
516                         if(currentToken == ITerminalSymbols.TokenNameRBRACE) {          
517                                 closeBodyStart = scanner.startPosition;
518                                 closeBodyEnd = scanner.currentPosition - 1;
519                         } else {
520                                 closeBodyStart = fDocument.length;
521                                 closeBodyEnd = fDocument.length;
522                         }
523                 } catch(InvalidInputException e) {
524                         closeBodyStart = fDocument.length;
525                         closeBodyEnd = fDocument.length;
526                 }
527         } else {
528                 scanner.resetTo(openBodyEnd, fDocument.length);
529                 try {
530                         int currentToken = scanner.getNextToken();
531                         while(currentToken != ITerminalSymbols.TokenNameRBRACE &&
532                                         currentToken != ITerminalSymbols.TokenNameEOF) {
533                                 currentToken = scanner.getNextToken();
534                         }
535                         if(currentToken == ITerminalSymbols.TokenNameRBRACE) {          
536                                 closeBodyStart = scanner.startPosition;
537                                 closeBodyEnd = scanner.currentPosition - 1;
538                         } else {
539                                 closeBodyStart = fDocument.length;
540                                 closeBodyEnd = fDocument.length;
541                         }
542                 } catch(InvalidInputException e) {
543                         closeBodyStart = fDocument.length;
544                         closeBodyEnd = fDocument.length;
545                 }
546                 openBodyEnd = closeBodyEnd - 1;
547         }
548         setOpenBodyRangeEnd(openBodyEnd);
549         setOpenBodyRangeStart(openBodyStart);
550         setCloseBodyRangeStart(closeBodyStart);
551         setCloseBodyRangeEnd(closeBodyEnd);
552         fInsertionPosition = finder.getLineStart(closeBodyStart);
553         if (lastNode != null && fInsertionPosition < lastNode.getEndPosition()) {
554                 fInsertionPosition = getCloseBodyPosition();
555         }
556         if (fInsertionPosition <= openBodyEnd) {
557                 fInsertionPosition = getCloseBodyPosition();
558         }
559         super.normalize(finder);
560 }
561
562 /**
563  * Normalizes this <code>DOMNode</code>'s end position.
564  */
565 void normalizeEndPosition(ILineStartFinder finder, DOMNode next) {
566         if (next == null) {
567                 // this node's end position includes all of the characters up
568                 // to the end of the enclosing node
569                 DOMNode parent = (DOMNode) getParent();
570                 if (parent == null || parent instanceof DOMCompilationUnit) {
571                         setSourceRangeEnd(fDocument.length - 1);
572                 } else {
573                         // parent is a type
574                         setSourceRangeEnd(((DOMType)parent).getCloseBodyPosition() - 1);
575                 }
576         } else {
577                 // this node's end position is just before the start of the next node
578                 next.normalizeStartPosition(getEndPosition(), finder);
579                 setSourceRangeEnd(next.getStartPosition() - 1);
580         }
581 }
582
583 /**
584  * Offsets all the source indexes in this node by the given amount.
585  */
586 protected void offset(int offset) {
587         super.offset(offset);
588         offsetRange(fCloseBodyRange, offset);
589         offsetRange(fExtendsRange, offset);
590         offsetRange(fImplementsRange, offset);
591         offsetRange(fInterfacesRange, offset);
592         offsetRange(fOpenBodyRange, offset);
593         offsetRange(fSuperclassRange, offset);
594         offsetRange(fTypeRange, offset);
595 }
596 /**
597  * @see IDOMType#setClass(boolean)
598  */
599 public void setClass(boolean b) {
600         becomeDetailed();
601         fragment();
602         setMask(MASK_TYPE_IS_CLASS, b);
603         if (b) {
604                 fTypeKeyword= "class"; //$NON-NLS-1$
605         } else {
606                 fTypeKeyword= "interface"; //$NON-NLS-1$
607                 setSuperclass(null);
608         }
609 }
610 /**
611  * Sets the end of the close body range 
612  */
613 void setCloseBodyRangeEnd(int end) {
614         fCloseBodyRange[1] = end;
615 }
616 /**
617  * Sets the start of the close body range 
618  */
619 void setCloseBodyRangeStart(int start) {
620         fCloseBodyRange[0] = start;
621 }
622 /**
623  * Sets the name of this node.
624  *
625  * <p>When the name of a type is set, all of its constructors must be marked
626  * as fragmented, since the names of the constructors must reflect the name
627  * of this type.
628  *
629  * @see IDOMNode#setName(char[])
630  */
631 public void setName(String name) throws IllegalArgumentException {
632         if (name == null) {
633                 throw new IllegalArgumentException(Util.bind("element.nullName")); //$NON-NLS-1$
634         }
635         super.setName(name);
636         Enumeration children= getChildren();
637         while (children.hasMoreElements()) {
638                 IDOMNode child= (IDOMNode)children.nextElement();
639                 if (child.getNodeType() == IDOMNode.METHOD && ((IDOMMethod)child).isConstructor()) {
640                         ((DOMNode)child).fragment();
641                 }
642         }
643 }
644 /**
645  * Sets the end of the open body range 
646  */
647 void setOpenBodyRangeEnd(int end) {
648         fOpenBodyRange[1] = end;
649 }
650 /**
651  * Sets the start of the open body range 
652  */
653 void setOpenBodyRangeStart(int start) {
654         fOpenBodyRange[0] = start;
655 }
656 /**
657  * @see IDOMType#setSuperclass(char[])
658  */
659 public void setSuperclass(String superclassName) {
660         becomeDetailed();
661         fragment();
662         fSuperclass= superclassName;
663         setMask(MASK_TYPE_HAS_SUPERCLASS, superclassName != null);
664 }
665 /**
666  * @see IDOMType#setSuperInterfaces(String[])
667  */
668 public void setSuperInterfaces(String[] names) {
669         becomeDetailed();
670         if (names == null) {
671                 throw new IllegalArgumentException(Util.bind("dom.nullInterfaces")); //$NON-NLS-1$
672         }
673         fragment();
674         fSuperInterfaces= names;
675         if (names == null || names.length == 0) {
676                 fInterfaces= null;
677                 fSuperInterfaces= null;
678                 setMask(MASK_TYPE_HAS_INTERFACES, false);
679         } else {
680                 setMask(MASK_TYPE_HAS_INTERFACES, true);
681                 CharArrayBuffer buffer = new CharArrayBuffer();
682                 for (int i = 0; i < names.length; i++) {
683                         if (i > 0) {
684                                 buffer.append(", "); //$NON-NLS-1$
685                         }
686                         buffer.append(names[i]);
687                 }
688                 fInterfaces = buffer.getContents();
689         }
690 }
691 /**
692  * Sets the type keyword
693  */
694 void setTypeKeyword(String keyword) {
695         fTypeKeyword = keyword;
696 }
697 /**
698  * @see DOMNode#shareContents(DOMNode)
699  */
700 protected void shareContents(DOMNode node) {
701         super.shareContents(node);
702         DOMType type= (DOMType)node;
703         fCloseBodyRange= rangeCopy(type.fCloseBodyRange);
704         fExtendsRange= type.fExtendsRange;
705         fImplementsRange= rangeCopy(type.fImplementsRange);
706         fInterfaces= type.fInterfaces;
707         fInterfacesRange= rangeCopy(type.fInterfacesRange);
708         fOpenBodyRange= rangeCopy(type.fOpenBodyRange);
709         fSuperclass= type.fSuperclass;
710         fSuperclassRange= rangeCopy(type.fSuperclassRange);
711         fSuperInterfaces= type.fSuperInterfaces;
712         fTypeKeyword= type.fTypeKeyword;
713         fTypeRange= rangeCopy(type.fTypeRange);
714 }
715 /**
716  * @see IDOMNode#toString()
717  */
718 public String toString() {
719         return "TYPE: " + getName(); //$NON-NLS-1$
720 }
721 }