OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libjava/] [classpath/] [tools/] [gnu/] [classpath/] [tools/] [gjdoc/] [DocImpl.java] - Blame information for rev 779

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 779 jeremybenn
/* gnu.classpath.tools.gjdoc.DocImpl
2
   Copyright (C) 2001 Free Software Foundation, Inc.
3
 
4
This file is part of GNU Classpath.
5
 
6
GNU Classpath is free software; you can redistribute it and/or modify
7
it under the terms of the GNU General Public License as published by
8
the Free Software Foundation; either version 2, or (at your option)
9
any later version.
10
 
11
GNU Classpath is distributed in the hope that it will be useful, but
12
WITHOUT ANY WARRANTY; without even the implied warranty of
13
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
General Public License for more details.
15
 
16
You should have received a copy of the GNU General Public License
17
along with GNU Classpath; see the file COPYING.  If not, write to the
18
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
19
02111-1307 USA.
20
 
21
Linking this library statically or dynamically with other modules is
22
making a combined work based on this library.  Thus, the terms and
23
conditions of the GNU General Public License cover the whole
24
combination.
25
 
26
As a special exception, the copyright holders of this library give you
27
permission to link this library with independent modules to produce an
28
executable, regardless of the license terms of these independent
29
modules, and to copy and distribute the resulting executable under
30
terms of your choice, provided that you also meet, for each linked
31
independent module, the terms and conditions of the license of that
32
module.  An independent module is a module which is not derived from
33
or based on this library.  If you modify this library, you may extend
34
this exception to your version of the library, but you are not
35
obligated to do so.  If you do not wish to do so, delete this
36
exception statement from your version. */
37
 
38
package gnu.classpath.tools.gjdoc;
39
 
40
import com.sun.javadoc.*;
41
import java.util.*;
42
import java.text.*;
43
import java.io.File;
44
import javax.swing.text.Segment;
45
 
46
/**
47
 *  Represents the least common denominator of all Javadoc
48
 *  comment classes.
49
 */
50
public abstract class DocImpl implements Doc, TagContainer {
51
 
52
   protected static Tag[] seeTagEmptyArr = new SeeTagImpl[0];
53
   protected static Tag[] linkTagEmptyArr = new LinkTagImpl[0];
54
   protected static Tag[] paramTagEmptyArr = new ParamTagImpl[0];
55
   protected static Tag[] throwsTagEmptyArr = new ThrowsTagImpl[0];
56
   protected SourcePosition position;
57
   private String boilerplateComment;
58
 
59
   // Return the text of the comment for this doc item.
60
   public String commentText() {
61
 
62
      StringBuffer rc=new StringBuffer();
63
 
64
      Tag[] textTags=(Tag[])tagMap.get("text");
65
      if (textTags!=null) {
66
         for (int i=0; i<textTags.length; ++i) {
67
            rc.append(textTags[i].text());
68
         }
69
      }
70
      return rc.toString();
71
   }
72
 
73
   // Compares this Object with the specified Object for order.
74
   public int compareTo(java.lang.Object o) {
75
      return Main.getInstance().getCollator().compare(name(), ((Doc)o).name());
76
   }
77
 
78
   // Return the first sentence of the comment as tags.
79
   public Tag[] firstSentenceTags() {
80
 
81
      Tag[] rc=(Tag[])tagMap.get("first");
82
      if (rc==null) rc=new Tag[0];
83
      return rc;
84
   }
85
 
86
   // Return the full unprocessed text of the comment.
87
   public String getRawCommentText() {
88
      if (rawDocumentation!=null)
89
          return rawDocumentation;
90
      else if (rawDocOffset>=0)
91
         return Main.getRootDoc().readRawComment(rawDocOffset);
92
      else
93
         return null;
94
   }
95
 
96
   // Return comment as tags.
97
   public Tag[] inlineTags() {
98
 
99
      Tag[] rc=(Tag[])tagMap.get("inline");
100
      if (rc==null) rc=new Tag[0];
101
      return rc;
102
   }
103
 
104
   // Is this Doc item a class.
105
   public boolean isClass() {
106
      return false;
107
   }
108
 
109
   // Is this Doc item a constructor? False until overridden.
110
   public boolean isConstructor() {
111
      return false;
112
   }
113
 
114
   // Is this Doc item a error class? False until overridden.
115
   public boolean isError() {
116
      return false;
117
   }
118
 
119
   // Is this Doc item a exception class? False until overridden.
120
   public boolean isException() {
121
      return false;
122
   }
123
 
124
   // Is this Doc item a field? False until overridden.
125
   public boolean isField() {
126
      return false;
127
   }
128
 
129
   // return true if this Doc is include in the active set.
130
   public boolean isIncluded() {
131
      return false;
132
   }
133
 
134
   // Is this Doc item a interface? False until overridden.
135
   public boolean isInterface() {
136
      return false;
137
   }
138
 
139
   // Is this Doc item a simple method (i.e.
140
   public boolean isMethod() {
141
      return false;
142
   }
143
 
144
   public boolean isPackage() {
145
      return false;
146
   }
147
 
148
   // Is this Doc item a ordinary class (i.e.
149
   public boolean isOrdinaryClass() {
150
      return false;
151
   }
152
 
153
   // Return the see also tags in this Doc item.
154
   public SeeTag[] seeTags() {
155
      return (SeeTag[])getTagArr("see", seeTagEmptyArr);
156
   }
157
 
158
   protected Tag[] getTagArr(String kindOfTag, Tag[] defaultRc) {
159
      Tag[] rc=(Tag[])tagMap.get(kindOfTag);
160
      if (rc==null) rc=defaultRc;
161
      return rc;
162
   }
163
 
164
   // Set the full unprocessed text of the comment.
165
   public void setRawCommentText(String rawDocumentation) {
166
      this.rawDocumentation=rawDocumentation;
167
   }
168
 
169
   public void resolveComments() {
170
 
171
      if (rawDocumentation!=null && tagMap.isEmpty()) {
172
         char[] charArray = rawDocumentation.toCharArray();
173
         int length = rawDocumentation.length();
174
         int startOffset = 0;
175
         int endOffset = 0;
176
         if (charArray[0] == '/'
177
             && charArray[1] == '*'
178
             && charArray[2] == '*'
179
             && charArray[length - 2] == '*'
180
             && charArray[length - 1] == '/') {
181
 
182
            startOffset = 3;
183
            endOffset = 2;
184
         }
185
 
186
         this.tagMap=parseCommentTags(charArray,
187
                                      startOffset,
188
                                      length - endOffset,
189
                                      getContextClass(),
190
                                      getContextMember(),
191
                                      null,
192
                                      boilerplateComment);
193
 
194
         if (Main.getInstance().isCacheRawComments()) {
195
            rawDocOffset=Main.getRootDoc().writeRawComment(rawDocumentation);
196
            rawDocumentation=null;
197
         }
198
 
199
         resolveTags();
200
      }
201
      else if (tagMap.isEmpty() && null != boilerplateComment) {
202
         tagMap.put("all", new Tag[] { new TagImpl("@boilerplate", boilerplateComment,getContextClass(),null) });
203
         tagMap.put("@boilerplate", new Tag[] { new TagImpl("@boilerplate", boilerplateComment,getContextClass(),null) });
204
      }
205
   }
206
 
207
   public static int skipHtmlWhitespace(char[] buffer, int startIndex) {
208
      while (startIndex < buffer.length) {
209
         char c=buffer[startIndex];
210
         if (!Parser.isWhitespace(c)) {
211
            break;
212
         }
213
         else {
214
            ++ startIndex;
215
         }
216
      }
217
      return startIndex;
218
   }
219
 
220
   /**
221
    *  Looks for an end-of-sentence marker in <code>text</code>,
222
    *  starting at <code>startIndex</code> and stopping at
223
    *  <code>endIndex</code>.
224
    *
225
    *  @param text  the text to be searched
226
    *  @param startIndex  index in <code>text</code> at which to start
227
    *  @param endIndex  index in <code>text</code> at which to stop
228
    *
229
    *  @return the index of the character following the end-of-sentence
230
    *    marker, <code>endIndex</code> if no end-of-sentence
231
    *    marker could be found, or -1 if not implemented.
232
    */
233
   private static int findEndOfSentence(char[] text, int startIndex,
234
                                        int endIndex)
235
   {
236
      if (Main.getInstance().isUseBreakIterator()) {
237
         Segment segment = new Segment(text, startIndex, endIndex - startIndex);
238
         BreakIterator breakIterator = BreakIterator.getSentenceInstance(Main.getInstance().getLocale());
239
         breakIterator.setText(segment);
240
         int result = breakIterator.next();
241
         if (BreakIterator.DONE == result) {
242
            return endIndex;
243
         }
244
         else {
245
            return result;
246
         }
247
      }
248
      else {
249
         while (startIndex < endIndex) {
250
            if (text[startIndex] == '.'
251
                && (startIndex+1 == endIndex
252
                    || Character.isWhitespace(text[startIndex+1])
253
                    || isHTMLBreakTag(text, startIndex+1, endIndex)
254
                    )) {
255
               return startIndex;
256
            }
257
 
258
            startIndex++;
259
         }
260
         return endIndex;
261
      }
262
   }
263
 
264
   /**
265
    * Returns true is the text from start to end begins with a 'p' or 'br' tag.
266
    */
267
   private static boolean isHTMLBreakTag(char[] text, int start, int end)
268
   {
269
      String[] breakTags = {
270
         "p>", "/p>", "h1>", "h2>", "h3>", "h4>", "h5>", "h6>", "hr>",
271
         "pre>", "/pre>"
272
      };
273
 
274
      if (text[start] == '<') {
275
 
276
      outer:
277
         for (int i=0; i<breakTags.length; ++i) {
278
            String tag = breakTags[i];
279
            int len = tag.length();
280
            if (start + len < end) {
281
               for (int j=0; j<len; ++j) {
282
                  char c = tag.charAt(j);
283
                  if (Character.toLowerCase(text[start + 1 + j]) != c) {
284
                     continue outer;
285
                  }
286
               }
287
               return true;
288
            }
289
         }
290
      }
291
      return false;
292
   }
293
 
294
   //private static final StringBuffer buf=new StringBuffer(32768);
295
   private static final StringBuffer whitespaceBuf=new StringBuffer();
296
   private static char[] charBuf = new char[60000];
297
   private static int bufPos = 0;
298
 
299
   private static void appendToBuf(char c)
300
   {
301
      if (bufPos < charBuf.length) {
302
         charBuf[bufPos++] = c;
303
      }
304
      else {
305
         //
306
      }
307
   }
308
 
309
   private static void appendToBuf(StringBuffer s)
310
   {
311
      if (bufPos + s.length() <= charBuf.length) {
312
         s.getChars(0, s.length(), charBuf, bufPos);
313
         bufPos += s.length();
314
      }
315
      else {
316
         //
317
      }
318
   }
319
 
320
   private static void setBufLength(int length)
321
   {
322
      bufPos = 0;
323
   }
324
 
325
   private static String bufToString()
326
   {
327
      return new String(charBuf, 0, bufPos);
328
   }
329
 
330
   private static int bufLength()
331
   {
332
      return bufPos;
333
   }
334
 
335
   public static Map parseCommentTags(char[] comment, int startIndex, int endIndex,
336
                                      ClassDocImpl contextClass, MemberDocImpl contextMember,
337
                                      AbstractTagImpl contextTag, String boilerplateComment) {
338
 
339
      int rawDocStart=skipHtmlWhitespace(comment, startIndex);
340
 
341
      int firstSentenceEnd = 0;
342
 
343
      if (comment.length>rawDocStart) {
344
 
345
         firstSentenceEnd = findEndOfSentence(comment, rawDocStart, comment.length);
346
 
347
         if (firstSentenceEnd < 0) {
348
            BreakIterator boundary = BreakIterator.getSentenceInstance(Locale.ENGLISH);
349
            boundary.setText(new ArrayCharacterIterator(comment, rawDocStart));
350
            boundary.first();
351
            boundary.next();
352
            firstSentenceEnd = boundary.current();
353
         }
354
 
355
         // Always include period at end of sentence if there is one.
356
         if (firstSentenceEnd < comment.length
357
                         && '.' == comment[firstSentenceEnd]) {
358
            ++ firstSentenceEnd;
359
         }
360
      }
361
 
362
      final int STATE_BEGOFLINE            = 1;
363
      final int STATE_TEXT                 = 2;
364
      final int STATE_PARAM                = 3;
365
      final int STATE_PARAMVALUE           = 4;
366
      final int STATE_PARAMWRAP            = 5;
367
      final int STATE_INLINEPARAM          = 6;
368
      final int STATE_INLINEPARAMVALUE     = 7;
369
      final int STATE_WHITESPACE           = 8;
370
      final int STATE_INLINEPARAMVALUE_BOL = 9;
371
      final int STATE_IPV_WHITESPACE       = 10;
372
 
373
      int state=STATE_BEGOFLINE;
374
      int prevState=STATE_TEXT;
375
 
376
      setBufLength(0);
377
      whitespaceBuf.setLength(0);
378
 
379
      String paramName="", paramValue="";
380
 
381
      Map tags=new HashMap();
382
      tags.put("inline", new LinkedList());
383
      tags.put("first", new LinkedList());
384
      tags.put("all", new LinkedList());
385
 
386
      final char EOL=(char)-1;
387
 
388
      for (int i=rawDocStart; i<=endIndex; ++i) {
389
         char c=(i<endIndex)?comment[i]:EOL;
390
         char peek=(i<endIndex-1)?comment[i+1]:EOL;
391
 
392
         switch (state){
393
 
394
         case STATE_BEGOFLINE:
395
            if (i==firstSentenceEnd) {
396
               AbstractTagImpl newTag = addTag(tags, "text", bufToString(), true, contextClass, contextMember, contextTag, false);
397
               if (null != newTag) {
398
                  contextTag = newTag;
399
               }
400
               setBufLength(0);
401
            }
402
 
403
            if (Parser.isWhitespace(c)) {
404
               // ignore
405
            }
406
            else if (c=='*') {
407
               // ignore, but go to STATE_TEXT
408
               if (peek!='*' && peek!='@' && peek!=EOL) {
409
                  state=STATE_WHITESPACE;
410
               }
411
            }
412
            else if (c=='@' || (c=='{' && peek=='@') || c==EOL) {
413
               if (bufLength()>0) {
414
                  addTag(tags, "text", bufToString(), i<firstSentenceEnd, contextClass, contextMember, contextTag, false);
415
                  setBufLength(0);
416
               }
417
               if (c=='{') {
418
                  ++i;
419
                  state=STATE_INLINEPARAM;
420
               }
421
               else {
422
                  state=STATE_PARAM;
423
               }
424
            }
425
            else {
426
               state=STATE_TEXT;
427
               appendToBuf(whitespaceBuf);
428
               whitespaceBuf.setLength(0);
429
               appendToBuf(c);
430
            }
431
            break;
432
 
433
         case STATE_WHITESPACE:
434
            if (i==firstSentenceEnd) {
435
               AbstractTagImpl newTag = addTag(tags, "text", bufToString(), true, contextClass, contextMember, contextTag, false);
436
               if (null != newTag) {
437
                  contextTag = newTag;
438
               }
439
               setBufLength(0);
440
            }
441
 
442
            if (c=='\n') {
443
               whitespaceBuf.append(c);
444
               state=STATE_BEGOFLINE;
445
            }
446
            else if (Parser.isWhitespace(c)) {
447
               whitespaceBuf.append(c);
448
            }
449
            else if (c=='@' || (c=='{' && peek=='@') || c==EOL) {
450
               if (bufLength()>0) {
451
                  AbstractTagImpl newTag = addTag(tags, "text", bufToString(), i<firstSentenceEnd, contextClass, contextMember, contextTag, false);
452
                  if (null != newTag) {
453
                     contextTag = newTag;
454
                  }
455
                  setBufLength(0);
456
               }
457
               if (c=='{') {
458
                  ++i;
459
                  state=STATE_INLINEPARAM;
460
               }
461
               else {
462
                  state=STATE_PARAM;
463
               }
464
            }
465
            else {
466
               appendToBuf(whitespaceBuf);
467
               whitespaceBuf.setLength(0);
468
               appendToBuf(c);
469
               state=STATE_TEXT;
470
            }
471
            break;
472
 
473
         case STATE_PARAMWRAP:
474
            if (c=='\n') {
475
               appendToBuf(c);
476
            }
477
            else if (Parser.isWhitespace(c)) {
478
               // ignore
479
            }
480
            else if (c=='*') {
481
               // ignore, but go to STATE_TEXT
482
               /*
483
               if (i<endIndex && comment[i+1]!='*' && comment[i+1]!='@') {
484
                  state=STATE_PARAMVALUE;
485
               }
486
               */
487
            }
488
            else if (c=='@' || c==EOL) {
489
               paramValue=bufToString();
490
               AbstractTagImpl newTag = addTag(tags, paramName, paramValue, i<firstSentenceEnd, contextClass, contextMember, contextTag, false);
491
               if (null != newTag) {
492
                  contextTag = newTag;
493
               }
494
               setBufLength(0);
495
               if (c=='{') {
496
                  ++i;
497
                  state=STATE_INLINEPARAM;
498
               }
499
               else {
500
                  state=STATE_PARAM;
501
               }
502
            }
503
            else {
504
               state=STATE_PARAMVALUE;
505
               appendToBuf(c);
506
            }
507
            break;
508
 
509
         case STATE_PARAM:
510
            if (!(c==EOL || Parser.isWhitespace(c))) {
511
               appendToBuf(c);
512
            }
513
            else if (c=='\n') {
514
               paramName=bufToString();
515
               setBufLength(0);
516
               state=STATE_PARAMWRAP;
517
            }
518
            else {
519
               paramName=bufToString();
520
               setBufLength(0);
521
               state=STATE_PARAMVALUE;
522
            }
523
            break;
524
 
525
         case STATE_INLINEPARAM:
526
            if (c=='}') {
527
               // tag without value
528
               paramName=bufToString();
529
               AbstractTagImpl newTag = addTag(tags, paramName, "", i<firstSentenceEnd, contextClass, contextMember, contextTag, true);
530
               if (null != newTag) {
531
                  contextTag = newTag;
532
               }
533
               state=prevState;
534
               setBufLength(0);
535
            }
536
            else if (!(c==EOL || Parser.isWhitespace(c))) {
537
               appendToBuf(c);
538
            }
539
            else if (c=='\n') {
540
               paramName=bufToString();
541
               setBufLength(0);
542
               state=STATE_INLINEPARAMVALUE_BOL;
543
            }
544
            else {
545
               paramName=bufToString();
546
               setBufLength(0);
547
               state=STATE_INLINEPARAMVALUE;
548
            }
549
            break;
550
 
551
         case STATE_PARAMVALUE:
552
            if (c==EOL) {
553
               paramValue=bufToString();
554
               AbstractTagImpl newTag = addTag(tags, paramName, paramValue, i<firstSentenceEnd, contextClass, contextMember, contextTag, false);
555
               if (null != newTag) {
556
                  contextTag = newTag;
557
               }
558
            }
559
            else if (c=='\n') {
560
               appendToBuf(c);
561
               state=STATE_PARAMWRAP;
562
            }
563
            else {
564
               appendToBuf(c);
565
            }
566
            break;
567
 
568
         case STATE_INLINEPARAMVALUE:
569
            if (c=='\n') {
570
               appendToBuf(c);
571
               state=STATE_INLINEPARAMVALUE_BOL;
572
            }
573
            else if (c==EOL || c=='}') {
574
               paramValue=bufToString();
575
               AbstractTagImpl newTag = addTag(tags, paramName, paramValue, i<firstSentenceEnd, contextClass, contextMember, contextTag, true);
576
               if (null != newTag) {
577
                  contextTag = newTag;
578
               }
579
               state=prevState;
580
               setBufLength(0);
581
            }
582
            else {
583
               appendToBuf(c);
584
            }
585
            break;
586
 
587
         case STATE_INLINEPARAMVALUE_BOL:
588
            if (Parser.isWhitespace(c)) {
589
               // ignore
590
            }
591
            else if (c=='*') {
592
               // ignore, but go to STATE_TEXT
593
               if (i<endIndex && peek!='*') {
594
                  state=STATE_IPV_WHITESPACE;
595
               }
596
            }
597
            else if (c==EOL) {
598
               if (bufLength()>0) {
599
                  AbstractTagImpl newTag = addTag(tags, "text", bufToString(), i<firstSentenceEnd, contextClass, contextMember, contextTag, false);
600
                  if (null != newTag) {
601
                     contextTag = newTag;
602
                  }
603
               }
604
            }
605
            else {
606
               state=STATE_INLINEPARAMVALUE;
607
               appendToBuf(whitespaceBuf);
608
               whitespaceBuf.setLength(0);
609
               appendToBuf(c);
610
            }
611
            break;
612
 
613
         case STATE_IPV_WHITESPACE:
614
            if (c=='\n') {
615
               whitespaceBuf.append(c);
616
               state=STATE_INLINEPARAMVALUE_BOL;
617
            }
618
            else if (Parser.isWhitespace(c)) {
619
               whitespaceBuf.append(c);
620
            }
621
            else if (c==EOL) {
622
               if (bufLength()>0) {
623
                  AbstractTagImpl newTag = addTag(tags, "text", bufToString(), i<firstSentenceEnd, contextClass, contextMember, contextTag, false);
624
                  if (null != newTag) {
625
                     contextTag = newTag;
626
                  }
627
                  setBufLength(0);
628
               }
629
            }
630
            else {
631
               appendToBuf(whitespaceBuf);
632
               whitespaceBuf.setLength(0);
633
               appendToBuf(c);
634
               state=STATE_INLINEPARAMVALUE;
635
            }
636
            break;
637
 
638
         case STATE_TEXT:
639
            if (i==firstSentenceEnd) {
640
               AbstractTagImpl newTag = addTag(tags, "text", bufToString(), true, contextClass, contextMember, contextTag, false);
641
               if (null != newTag) {
642
                  contextTag = newTag;
643
               }
644
               setBufLength(0);
645
            }
646
 
647
            if (c==EOL) {
648
               paramValue=bufToString();
649
               AbstractTagImpl newTag = addTag(tags, "text", paramValue, i<firstSentenceEnd, contextClass, contextMember, contextTag, false);
650
               if (null != newTag) {
651
                  contextTag = newTag;
652
               }
653
            }
654
            else if (c=='\n') {
655
               appendToBuf(c);
656
               state=STATE_BEGOFLINE;
657
            }
658
            else if (c=='{' && peek=='@') {
659
               paramValue=bufToString();
660
               AbstractTagImpl newTag = addTag(tags, "text", paramValue, i<firstSentenceEnd, contextClass, contextMember, contextTag, false);
661
               if (null != newTag) {
662
                  contextTag = newTag;
663
               }
664
               ++i;
665
               setBufLength(0);
666
               state=STATE_INLINEPARAM;
667
            }
668
            else {
669
               appendToBuf(c);
670
            }
671
            break;
672
 
673
         default:
674
            throw new Error("illegal state "+state);
675
         }
676
      }
677
 
678
 
679
      if (null == contextMember && null != boilerplateComment && Main.getInstance().isCopyLicenseText()) {
680
         addTag(tags, "@boilerplate", boilerplateComment, false, contextClass, null, null, false);
681
      }
682
 
683
      Map rc=new HashMap();
684
 
685
      for (Iterator it=tags.keySet().iterator(); it.hasNext(); ) {
686
         String key=(String)it.next();
687
         Tag[] templateArr;
688
         List list=(List)tags.get(key);
689
 
690
         if ("see".equals(key))
691
            templateArr=new SeeTag[list.size()];
692
         else if ("param".equals(key))
693
            templateArr=new ParamTag[list.size()];
694
         else if ("serialField".equals(key))
695
            templateArr=new SerialFieldTag[list.size()];
696
         else if ("throws".equals(key) || "exception".equals(key))
697
            templateArr=new ThrowsTag[list.size()];
698
         else {
699
            templateArr=new Tag[list.size()];
700
         }
701
 
702
         rc.put(key, list.toArray(templateArr));
703
      }
704
 
705
      return rc;
706
   }
707
 
708
   private ClassDocImpl getContextClass() {
709
      if (isClass() || isInterface()) {
710
         return (ClassDocImpl)this;
711
      }
712
      else if (isField() || isMethod() || isConstructor()) {
713
         return (ClassDocImpl)((MemberDocImpl)this).containingClass();
714
      }
715
      else {
716
         return null;
717
      }
718
   }
719
 
720
   private MemberDocImpl getContextMember() {
721
      if (isField() || isMethod() || isConstructor()) {
722
         return (MemberDocImpl)this;
723
      }
724
      else {
725
         return null;
726
      }
727
   }
728
 
729
   protected static AbstractTagImpl addTag(Map tags, String name,
730
                                           String value, boolean isFirstSentence,
731
                                           ClassDocImpl contextClass,
732
                                           MemberDocImpl contextMember,
733
                                           AbstractTagImpl contextTag,
734
                                           boolean isInline) {
735
 
736
      AbstractTagImpl tag = null;
737
 
738
      boolean haveValue = (0 != value.trim().length());
739
 
740
      String emptyWarning = "Empty @" + name + " tag.";
741
 
742
      if (name.equals("param")) {
743
         if (haveValue) {
744
            tag=new ParamTagImpl(value, contextClass, contextMember);
745
         }
746
         else {
747
            //printWarning(emptyWarning);
748
         }
749
      }
750
      else if (name.equals("see")) {
751
         if (haveValue) {
752
            tag=new SeeTagImpl(value, contextClass);
753
         }
754
         else {
755
            //printWarning(emptyWarning);
756
         }
757
      }
758
      else if (name.equals("link") || name.equals("linkplain")) {
759
         if (haveValue) {
760
            tag=new LinkTagImpl("@" + name, value, contextClass);
761
            isInline = true;
762
         }
763
         else {
764
            //printWarning(emptyWarning);
765
         }
766
      }
767
      else if (name.equals("value")) {
768
         if (haveValue) {
769
            tag=new ValueTagImpl(value, contextClass);
770
            isInline = true;
771
         }
772
         else {
773
            //printWarning(emptyWarning);
774
         }
775
      }
776
      else if (name.equals("inheritDoc")) {
777
         if (haveValue) {
778
            //printWarning("@inheritDoc tags are not supposed to have any content.");
779
         }
780
         tag=new InheritDocTagImpl(contextClass, contextMember, contextTag);
781
         isInline = true;
782
      }
783
      else if (name.equals("serialField")) {
784
         if (haveValue) {
785
            tag=new SerialFieldTagImpl(value, contextClass, contextMember);
786
         }
787
         else {
788
            //printWarning(emptyWarning);
789
         }
790
      }
791
      else if (name.equals("throws") || name.equals("exception")) {
792
         if (haveValue) {
793
            tag=new ThrowsTagImpl(value, contextClass, contextMember);
794
         }
795
         else {
796
            //printWarning(emptyWarning);
797
         }
798
         name="throws";
799
      }
800
      else if (name.equals("text")) {
801
         tag=new TextTagImpl(value);
802
         isInline = true;
803
      }
804
      else {
805
         tag=new TagImpl("@"+name, value.trim(), contextClass, contextMember);
806
         // FIXME: consider taglets
807
      }
808
 
809
      if (tag != null) {
810
         if (isInline) {
811
            ((List)tags.get("inline")).add(tag);
812
            if (isFirstSentence) {
813
               if (name.equals("text")) {
814
                  String txt = ((TextTagImpl)tag).getText();
815
                  Tag newTag;
816
                  if (txt.startsWith("<p>")) {
817
                     newTag = new TextTagImpl(txt.substring(3));
818
                  }
819
                  else if (txt.endsWith("</p>")) {
820
                     newTag = new TextTagImpl(txt.substring(0, txt.length() - 4));
821
                  }
822
                  else {
823
                     newTag = tag;
824
                  }
825
                  ((List)tags.get("first")).add(newTag);
826
 
827
               }
828
               else {
829
                  ((List)tags.get("first")).add(tag);
830
               }
831
            }
832
         }
833
         else {
834
            ((List)tags.get("all")).add(tag);
835
         }
836
 
837
         List l=((List)tags.get(name));
838
         if (l==null) {
839
            l=new LinkedList();
840
            tags.put(name,l);
841
         }
842
         l.add(tag);
843
 
844
         return isInline ? tag : contextTag;
845
      }
846
      else {
847
         return null;
848
      }
849
   }
850
 
851
   // Return all tags in this Doc item.
852
   public Tag[] tags() {
853
      Tag[] rc=(Tag[])tagMap.get("all");
854
      if (rc==null) rc=new Tag[0];
855
      return rc;
856
   }
857
 
858
   // Return tags of the specified kind in this Doc item.
859
   public Tag[] tags(java.lang.String tagname) {
860
      Tag[] rc=(Tag[])tagMap.get(tagname);
861
      if (rc==null) rc=new Tag[0];
862
      return rc;
863
   }
864
 
865
   protected String rawDocumentation;
866
   protected long rawDocOffset=-1;
867
 
868
   protected Map tagMap = new HashMap();
869
 
870
   public Map getTagMap() { return tagMap; }
871
 
872
   protected void resolveTags() {
873
 
874
      Tag[] tags=tags();
875
      for (int i=0; i<tags.length; ++i) {
876
         ((AbstractTagImpl)tags[i]).resolve();
877
      }
878
 
879
      Tag[] inlineTags=inlineTags();
880
      for (int i=0; i<inlineTags.length; ++i) {
881
         ((AbstractTagImpl)inlineTags[i]).resolve();
882
      }
883
   }
884
 
885
   private static Map classDocToFileMap = new HashMap();
886
 
887
   private static File getFile(ClassDoc classDoc) {
888
      File result = (File)classDocToFileMap.get(classDoc);
889
      if (null == result) {
890
         result = new File(((GjdocPackageDoc)classDoc.containingPackage()).packageDirectory(),
891
                           classDoc.name() + ".java");
892
         classDocToFileMap.put(classDoc, result);
893
      }
894
      return result;
895
   }
896
 
897
   public static SourcePosition getPosition(ClassDoc classDoc)
898
   {
899
      return new SourcePositionImpl(getFile(classDoc), 0, 0);
900
   }
901
 
902
   public static SourcePosition getPosition(ClassDoc classDoc, char[] source, int startIndex)
903
   {
904
      int column = 0;
905
      int line = 0;
906
      for (int i=0; i<startIndex; ++i) {
907
         if (10 == source[i]) {
908
            ++ line;
909
            column = 0;
910
         }
911
         else if (13 != source[i]) {
912
            ++ column;
913
         }
914
      }
915
      while (true) {
916
         ClassDoc containingClassDoc = classDoc.containingClass();
917
         if (null != containingClassDoc) {
918
            classDoc = containingClassDoc;
919
         }
920
         else {
921
            break;
922
         }
923
      }
924
 
925
      File file = getFile(classDoc);
926
 
927
      return new SourcePositionImpl(file, line + 1, column + 1);
928
   }
929
 
930
   public SourcePosition position()
931
   {
932
      return this.position;
933
   }
934
 
935
   public DocImpl(SourcePosition position)
936
   {
937
      this.position = position;
938
   }
939
 
940
   public void setPosition(SourcePosition position)
941
   {
942
      this.position = position;
943
   }
944
 
945
   private static TagContainer checkForInheritedDoc(ClassDoc classDoc,
946
                                                    MemberDocImpl memberDoc,
947
                                                    AbstractTagImpl tag)
948
   {
949
      DocImpl result;
950
 
951
      if (!(classDoc instanceof ClassDocImpl)) {
952
         result = null;
953
      }
954
      else if (null == memberDoc) {
955
         result = (DocImpl)classDoc;
956
      }
957
      else if (memberDoc.isField()) {
958
         result = (DocImpl)((ClassDocImpl)classDoc).getFieldDoc(memberDoc.name());
959
      }
960
      else if (memberDoc.isMethod()) {
961
         result = (DocImpl)((ClassDocImpl)classDoc).getMethodDoc(memberDoc.name(),
962
                                                                 ((MethodDoc)memberDoc).signature());
963
      }
964
      else if (memberDoc.isConstructor()) {
965
         result = (DocImpl)((ClassDocImpl)classDoc).getConstructorDoc(((ConstructorDoc)memberDoc).signature());
966
      }
967
      else {
968
         //assert(false);
969
         throw new RuntimeException("memberDoc is supposed to be field, method or constructor");
970
      }
971
 
972
      if (null != result
973
          && null != memberDoc
974
          && null != tag) {
975
 
976
         TagContainer tagDoc = null;
977
 
978
         Tag[] tags = result.tags();
979
         for (int i=0; i<tags.length; ++i) {
980
            if (tags[i].kind().equals(tag.kind())) {
981
               if ("@param".equals(tag.kind())) {
982
                  if (((ParamTagImpl)tags[i]).parameterName().equals(((ParamTagImpl)tag).parameterName())) {
983
                     tagDoc = (TagContainer)tags[i];
984
                     break;
985
                  }
986
               }
987
               else if ("@throws".equals(tag.kind())) {
988
                  if (((ThrowsTagImpl)tags[i]).exceptionName().equals(((ThrowsTagImpl)tag).exceptionName())) {
989
                     tagDoc = (TagContainer)tags[i];
990
                     break;
991
                  }
992
               }
993
               else if ("@return".equals(tag.kind())) {
994
                  tagDoc = (TagContainer)tags[i];
995
               }
996
            }
997
         }
998
 
999
         return tagDoc;
1000
      }
1001
 
1002
      if (null == result || result.isEmptyDoc()) {
1003
         return null;
1004
      }
1005
      else {
1006
         return result;
1007
      }
1008
   }
1009
 
1010
   public static TagContainer findInheritedDoc(ClassDoc classDoc,
1011
                                               MemberDocImpl memberDoc,
1012
                                               AbstractTagImpl tag)
1013
   {
1014
      TagContainer result;
1015
 
1016
      // (Taken from Javadoc Solaris Tool documentation 1.5,
1017
      // section "Automatic Copying of Method Comments")
1018
 
1019
      // Algorithm for Inheriting Method Comments - If a method does
1020
      // not have a doc comment, or has an {@inheritDoc} tag, the
1021
      // Javadoc tool searches for an applicable comment using the
1022
      // following algorithm, which is designed to find the most
1023
      // specific applicable doc comment, giving preference to
1024
      // interfaces over superclasses:
1025
 
1026
      // 1. Look in each directly implemented (or extended) interface
1027
      // in the order they appear following the word implements (or
1028
      // extends) in the method declaration. Use the first doc comment
1029
      // found for this method.
1030
 
1031
      ClassDoc[] interfaces = classDoc.interfaces();
1032
      if (null != interfaces) {
1033
         for (int i=0; i<interfaces.length; ++i) {
1034
            result = checkForInheritedDoc(interfaces[i], memberDoc, tag);
1035
            if (null != result) {
1036
               return result;
1037
            }
1038
         }
1039
      }
1040
 
1041
      // 2. If step 1 failed to find a doc comment, recursively apply
1042
      // this entire algorithm to each directly implemented (or
1043
      // extended) interface, in the same order they were examined
1044
      // in step 1.
1045
 
1046
      if (null != interfaces) {
1047
         for (int i=0; i<interfaces.length; ++i) {
1048
            result = findInheritedDoc(interfaces[i], memberDoc, tag);
1049
            if (null != result) {
1050
               return result;
1051
            }
1052
         }
1053
      }
1054
 
1055
      ClassDoc superclassDoc = classDoc.superclass();
1056
 
1057
      // 3. If step 2 failed to find a doc comment and this is a class
1058
      // other than Object (not an interface):
1059
      if (!classDoc.isInterface()
1060
          && null != superclassDoc
1061
          && !"java.lang.Object".equals(classDoc.qualifiedTypeName())) {
1062
 
1063
         // 3a. If the superclass has a doc comment for this method, use it.
1064
 
1065
         result = checkForInheritedDoc(superclassDoc, memberDoc, tag);
1066
         if (null != result) {
1067
            return result;
1068
         }
1069
 
1070
         // 3b. If step 3a failed to find a doc comment, recursively
1071
         // apply this entire algorithm to the superclass.
1072
 
1073
         return findInheritedDoc(superclassDoc,
1074
                                 memberDoc, tag);
1075
      }
1076
      else {
1077
         return null;
1078
      }
1079
   }
1080
 
1081
   public boolean isEmptyDoc()
1082
   {
1083
      return tagMap.isEmpty();
1084
   }
1085
 
1086
   void setBoilerplateComment(String boilerplateComment)
1087
   {
1088
      this.boilerplateComment = boilerplateComment;
1089
   }
1090
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.