KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jdt > internal > ui > text > comment > MultiCommentLine


1 /*******************************************************************************
2  * Copyright (c) 2000, 2004 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
12 package org.eclipse.jdt.internal.ui.text.comment;
13
14 import java.util.HashSet JavaDoc;
15 import java.util.Set JavaDoc;
16
17 import org.eclipse.jface.text.IRegion;
18 import org.eclipse.jface.text.Region;
19
20 import org.eclipse.jdt.internal.ui.text.javadoc.IHtmlTagConstants;
21 import org.eclipse.jdt.internal.ui.text.javadoc.IJavaDocTagConstants;
22 import org.eclipse.jdt.internal.ui.text.javadoc.ILinkTagConstants;
23
24 /**
25  * Multi-line comment line in a comment region.
26  *
27  * @since 3.0
28  */

29 public class MultiCommentLine extends CommentLine implements ICommentAttributes, IHtmlTagConstants, ILinkTagConstants, IJavaDocTagConstants {
30
31     /** Line prefix of multi-line comment content lines */
32     public static final String JavaDoc MULTI_COMMENT_CONTENT_PREFIX= " * "; //$NON-NLS-1$
33

34     /** Line prefix of multi-line comment end lines */
35     public static final String JavaDoc MULTI_COMMENT_END_PREFIX= " */"; //$NON-NLS-1$
36

37     /** Line prefix of multi-line comment content lines */
38     public static final String JavaDoc MULTI_COMMENT_START_PREFIX= "/* "; //$NON-NLS-1$
39

40     /** The indentation reference of this line */
41     private String JavaDoc fReferenceIndentation= ""; //$NON-NLS-1$
42

43     /** The javadoc tag lookup. */
44     private static final Set JavaDoc fgTagLookup;
45     
46     static {
47         fgTagLookup= new HashSet JavaDoc();
48         for (int i= 0; i < JAVADOC_BREAK_TAGS.length; i++) {
49             fgTagLookup.add(JAVADOC_BREAK_TAGS[i]);
50         }
51         for (int i= 0; i < JAVADOC_SINGLE_BREAK_TAG.length; i++) {
52             fgTagLookup.add(JAVADOC_SINGLE_BREAK_TAG[i]);
53         }
54         for (int i= 0; i < JAVADOC_CODE_TAGS.length; i++) {
55             fgTagLookup.add(JAVADOC_CODE_TAGS[i]);
56         }
57         for (int i= 0; i < JAVADOC_IMMUTABLE_TAGS.length; i++) {
58             fgTagLookup.add(JAVADOC_IMMUTABLE_TAGS[i]);
59         }
60         for (int i= 0; i < JAVADOC_NEWLINE_TAGS.length; i++) {
61             fgTagLookup.add(JAVADOC_NEWLINE_TAGS[i]);
62         }
63         for (int i= 0; i < JAVADOC_SEPARATOR_TAGS.length; i++) {
64             fgTagLookup.add(JAVADOC_SEPARATOR_TAGS[i]);
65         }
66     }
67
68     /**
69      * Creates a new multi-line comment line.
70      *
71      * @param region
72      * Comment region to create the line for
73      */

74     protected MultiCommentLine(final CommentRegion region) {
75         super(region);
76     }
77
78     /*
79      * @see org.eclipse.jdt.internal.ui.text.comment.CommentLine#adapt(org.eclipse.jdt.internal.ui.text.comment.CommentLine)
80      */

81     protected void adapt(final CommentLine previous) {
82
83         if (!hasAttribute(COMMENT_ROOT) && !hasAttribute(COMMENT_PARAMETER) && !previous.hasAttribute(COMMENT_BLANKLINE))
84             fReferenceIndentation= previous.getIndentationReference();
85     }
86
87     /*
88      * @see org.eclipse.jdt.internal.ui.text.comment.CommentLine#append(org.eclipse.jdt.internal.ui.text.comment.CommentRange)
89      */

90     protected void append(final CommentRange range) {
91
92         final MultiCommentRegion parent= (MultiCommentRegion)getParent();
93
94         if (range.hasAttribute(COMMENT_PARAMETER))
95             setAttribute(COMMENT_PARAMETER);
96         else if (range.hasAttribute(COMMENT_ROOT))
97             setAttribute(COMMENT_ROOT);
98         else if (range.hasAttribute(COMMENT_BLANKLINE))
99             setAttribute(COMMENT_BLANKLINE);
100
101         final int ranges= getSize();
102         if (ranges == 1) {
103
104             if (parent.isIndentRoots()) {
105
106                 final CommentRange first= getFirst();
107                 final String JavaDoc common= parent.getText(first.getOffset(), first.getLength()) + CommentRegion.COMMENT_RANGE_DELIMITER;
108
109                 if (hasAttribute(COMMENT_ROOT))
110                     fReferenceIndentation= common;
111                 else if (hasAttribute(COMMENT_PARAMETER)) {
112                     if (parent.isIndentDescriptions())
113                         fReferenceIndentation= common + "\t"; //$NON-NLS-1$
114
else
115                         fReferenceIndentation= common;
116                 }
117             }
118         }
119         super.append(range);
120     }
121
122     /*
123      * @see org.eclipse.jdt.internal.ui.text.comment.CommentLine#getContentLinePrefix()
124      */

125     protected String JavaDoc getContentPrefix() {
126         return MULTI_COMMENT_CONTENT_PREFIX;
127     }
128
129     /*
130      * @see org.eclipse.jdt.internal.ui.text.comment.CommentLine#getEndLinePrefix()
131      */

132     protected String JavaDoc getEndingPrefix() {
133         return MULTI_COMMENT_END_PREFIX;
134     }
135
136     /**
137      * Returns the reference indentation to use for this line.
138      *
139      * @return The reference indentation for this line
140      */

141     protected final String JavaDoc getIndentationReference() {
142         return fReferenceIndentation;
143     }
144
145     /*
146      * @see org.eclipse.jdt.internal.ui.text.comment.CommentLine#getStartLinePrefix()
147      */

148     protected String JavaDoc getStartingPrefix() {
149         return MULTI_COMMENT_START_PREFIX;
150     }
151
152     /*
153      * @see org.eclipse.jdt.internal.ui.text.comment.CommentLine#scanLine(int)
154      */

155     protected void scanLine(final int line) {
156
157         final CommentRegion parent= getParent();
158         final String JavaDoc start= getStartingPrefix().trim();
159         final String JavaDoc end= getEndingPrefix().trim();
160         final String JavaDoc content= getContentPrefix().trim();
161
162         final int lines= parent.getSize();
163         final CommentRange range= getFirst();
164
165         int offset= 0;
166         int postfix= 0;
167
168         String JavaDoc text= parent.getText(range.getOffset(), range.getLength());
169         if (line == 0) {
170
171             offset= text.indexOf(start);
172             if (offset >= 0 && text.substring(0, offset).trim().length() != 0)
173                 offset= -1;
174             
175             if (offset >= 0) {
176
177                 offset += start.length();
178                 range.trimBegin(offset);
179
180                 postfix= text.lastIndexOf(end);
181                 if (postfix >= 0 && text.substring(postfix + end.length()).trim().length() != 0)
182                     postfix= -1;
183                 
184                 if (postfix >= offset)
185                     // comment ends on same line
186
range.setLength(postfix - offset);
187                 else {
188                     postfix= text.lastIndexOf(content);
189                     if (postfix >= 0 && text.substring(postfix + content.length()).trim().length() != 0)
190                         postfix= -1;
191                     
192                     if (postfix >= offset) {
193
194                         range.setLength(postfix - offset);
195                         parent.setBorder(BORDER_UPPER);
196
197                         if (postfix > offset) {
198
199                             text= parent.getText(range.getOffset(), range.getLength());
200                             final IRegion region= trimLine(text, content);
201
202                             range.move(region.getOffset());
203                             range.setLength(region.getLength());
204                         }
205                     }
206                 }
207             }
208         } else if (line == lines - 1) {
209
210             offset= text.indexOf(content);
211             if (offset >= 0 && text.substring(0, offset).trim().length() != 0)
212                 offset= -1;
213             postfix= text.lastIndexOf(end);
214             if (postfix >= 0 && text.substring(postfix + end.length()).trim().length() != 0)
215                 postfix= -1;
216             
217             if (offset >= 0 && offset == postfix)
218                 // no content on line, only the comment postfix
219
range.setLength(0);
220             else {
221                 if (offset >= 0)
222                     // omit the content prefix
223
range.trimBegin(offset + content.length());
224                 
225                 if (postfix >= 0)
226                     // omit the comment postfix
227
range.trimEnd(-end.length());
228                 
229                 text= parent.getText(range.getOffset(), range.getLength());
230                 final IRegion region= trimLine(text, content);
231                 if (region.getOffset() != 0 || region.getLength() != text.length()) {
232
233                     range.move(region.getOffset());
234                     range.setLength(region.getLength());
235
236                     parent.setBorder(BORDER_UPPER);
237                     parent.setBorder(BORDER_LOWER);
238                 }
239             }
240         } else {
241
242             offset= text.indexOf(content);
243             if (offset >= 0 && text.substring(0, offset).trim().length() != 0)
244                 offset= -1;
245             
246             if (offset >= 0) {
247
248                 offset += content.length();
249                 range.trimBegin(offset);
250             }
251         }
252     }
253
254     /*
255      * @see org.eclipse.jdt.internal.ui.text.comment.CommentLine#tokenizeLine(int)
256      */

257     protected void tokenizeLine(int line) {
258
259         int offset= 0;
260         int index= offset;
261
262         final CommentRegion parent= getParent();
263         final CommentRange range= getFirst();
264         final int begin= range.getOffset();
265
266         final String JavaDoc content= parent.getText(begin, range.getLength());
267         final int length= content.length();
268
269         while (offset < length && Character.isWhitespace(content.charAt(offset)))
270             offset++;
271
272         CommentRange result= null;
273         if (offset >= length && !parent.isClearLines() && (line > 0 && line < parent.getSize() - 1)) {
274
275             result= new CommentRange(begin, 0);
276             result.setAttribute(COMMENT_BLANKLINE);
277             result.setAttribute(COMMENT_FIRST_TOKEN);
278
279             parent.append(result);
280         }
281
282         int attribute= COMMENT_FIRST_TOKEN;
283         while (offset < length) {
284
285             while (offset < length && Character.isWhitespace(content.charAt(offset)))
286                 offset++;
287
288             index= offset;
289
290             if (index < length) {
291
292                 if (content.charAt(index) == HTML_TAG_PREFIX) {
293
294                     // in order to avoid recognizign any < in a comment, even those which are part of e.g.
295
// java source code, we validate the tag content to be one of the recognized
296
// tags (structural, breaks, pre, code).
297
int tag= ++index;
298                     while (index < length && content.charAt(index) != HTML_TAG_POSTFIX && content.charAt(index) != HTML_TAG_PREFIX)
299                         index++;
300
301                     if (index < length && content.charAt(index) == HTML_TAG_POSTFIX && isValidTag(content.substring(tag, index))) {
302                         index++;
303                         attribute |= COMMENT_HTML; // only set html attribute if postfix found
304
} else {
305                         // no tag - do the usual thing from the original offset
306
index= tag;
307                         while (index < length && !Character.isWhitespace(content.charAt(index)) && content.charAt(index) != HTML_TAG_PREFIX && !content.startsWith(LINK_TAG_PREFIX, index))
308                             index++;
309                     }
310
311
312                 } else if (content.startsWith(LINK_TAG_PREFIX, index)) {
313
314                     while (index < length && content.charAt(index) != LINK_TAG_POSTFIX)
315                         index++;
316
317                     if (index < length && content.charAt(index) == LINK_TAG_POSTFIX)
318                         index++;
319
320                     attribute |= COMMENT_OPEN | COMMENT_CLOSE;
321
322                 } else {
323
324                     while (index < length && !Character.isWhitespace(content.charAt(index)) && content.charAt(index) != HTML_TAG_PREFIX && !content.startsWith(LINK_TAG_PREFIX, index))
325                         index++;
326                 }
327             }
328
329             if (index - offset > 0) {
330
331                 result= new CommentRange(begin + offset, index - offset);
332                 result.setAttribute(attribute);
333
334                 parent.append(result);
335                 offset= index;
336             }
337             
338             attribute= 0;
339         }
340     }
341
342     /**
343      * Checks whether <code>tag</code> is a valid tag content (text inside the angular
344      * brackets &lt;, &gt;).
345      * <p>
346      * The algorithm is to see if the tag trimmed of whitespace and an optional slash
347      * starts with one of our recognized tags.
348      *
349      * @param tag
350      * @return <code>true</code> if <code>tag</code> is a valid tag content
351      */

352     private boolean isValidTag(String JavaDoc tag) {
353         // strip the slash
354
if (tag.startsWith("/")) //$NON-NLS-1$
355
tag= tag.substring(1, tag.length());
356         
357         // strip ws
358
tag= tag.trim();
359         
360         // extract first token
361
int i= 0;
362         while (i < tag.length() && !Character.isWhitespace(tag.charAt(i)))
363             i++;
364         tag= tag.substring(0, i);
365         
366         // see if it's a tag
367
return isTagName(tag.toLowerCase());
368     }
369
370     /**
371      * Checks whether <code>tag</code> is one of the configured tags.
372      *
373      * @param tag the tag to check
374      * @return <code>true</code> if <code>tag</code> is a configured tag name
375      */

376     private boolean isTagName(String JavaDoc tag) {
377         return fgTagLookup.contains(tag);
378     }
379
380     /**
381      * Removes all leading and trailing occurrences from <code>line</code>.
382      *
383      * @param line
384      * The string to remove the occurrences of <code>trimmable</code>
385      * @param trimmable
386      * The string to remove from <code>line</code>
387      * @return The region of the trimmed substring within <code>line</code>
388      */

389     protected final IRegion trimLine(final String JavaDoc line, final String JavaDoc trimmable) {
390
391         final int trim= trimmable.length();
392
393         int offset= 0;
394         int length= line.length() - trim;
395
396         while (line.startsWith(trimmable, offset))
397             offset += trim;
398
399         while (line.startsWith(trimmable, length))
400             length -= trim;
401
402         return new Region(offset, length + trim);
403     }
404 }
405
Popular Tags