]> git.uio.no Git - ifi-stolz-refaktor.git/blob - case-study/jdt-after/ui/org/eclipse/jdt/internal/ui/text/javadoc/JavaDoc2HTMLTextReader.java
Case Study: adding data and statistics
[ifi-stolz-refaktor.git] / case-study / jdt-after / ui / org / eclipse / jdt / internal / ui / text / javadoc / JavaDoc2HTMLTextReader.java
1 /*******************************************************************************
2  * Copyright (c) 2000, 2011 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  *     IBM Corporation - initial API and implementation
10  *     Brock Janiczak (brockj_eclipse@ihug.com.au) - https://bugs.eclipse.org/bugs/show_bug.cgi?id=20644
11  *     Brock Janiczak (brockj_eclipse@ihug.com.au) - https://bugs.eclipse.org/bugs/show_bug.cgi?id=83607
12  *     Benjamin Muskalla <b.muskalla@gmx.net> - [navigation][hovering] Javadoc view cannot find URL with anchor - https://bugs.eclipse.org/bugs/show_bug.cgi?id=70870
13  *******************************************************************************/
14 package org.eclipse.jdt.internal.ui.text.javadoc;
15
16 import java.io.IOException;
17 import java.io.Reader;
18 import java.util.ArrayList;
19 import java.util.Iterator;
20 import java.util.List;
21
22 import org.eclipse.jface.internal.text.html.HTMLPrinter;
23 import org.eclipse.jface.internal.text.html.SubstitutionTextReader;
24
25 import org.eclipse.jdt.core.dom.TagElement;
26
27
28 /**
29  * Processes JavaDoc tags.
30  */
31 public class JavaDoc2HTMLTextReader extends SubstitutionTextReader {
32
33
34         static class Pair {
35                 String fTag;
36                 String fContent;
37
38                 Pair(String tag, String content) {
39                         fTag= tag;
40                         fContent= content;
41                 }
42
43                 public void generated_5851077662602872979(StringBuffer buffer, JavaDoc2HTMLTextReader javadoc2htmltextreader) {
44                         if (fTag != null)
45                                 buffer.append(fTag);
46                         buffer.append("</dt>"); //$NON-NLS-1$
47                         buffer.append("<dd>"); //$NON-NLS-1$
48                         if (fContent != null)
49                                 buffer.append(fContent);
50                 }
51         }
52
53         private List<String> fParameters;
54         private String fReturn;
55         private List<String> fExceptions;
56         private List<String> fAuthors;
57         private List<String> fSees;
58         private List<String> fSince;
59         private List<Pair> fRest; // list of Pair objects
60
61         public JavaDoc2HTMLTextReader(Reader reader) {
62                 super(reader);
63                 setSkipWhitespace(false);
64         }
65
66         private int getTag(StringBuffer buffer) throws IOException {
67                 int c= nextChar();
68                 while (c == '.' || c != -1 && Character.isLetter((char) c)) {
69                         buffer.append((char) c);
70                         c= nextChar();
71                 }
72                 return c;
73         }
74
75         private int getContent(StringBuffer buffer, char stopChar) throws IOException {
76                 int c= nextChar();
77                 while (c != -1 && c != stopChar) {
78                         buffer.append((char) c);
79                         c= nextChar();
80                 }
81                 return c;
82         }
83
84         private int getContentUntilNextTag(StringBuffer buffer) throws IOException {
85                 int c= nextChar();
86         boolean blockStartRead= false;
87                 while (c != -1) {
88                         if (c == '@') {
89                                 int index= buffer.length();
90                                 while (--index >= 0 && Character.isWhitespace(buffer.charAt(index))) {
91                                         switch (buffer.charAt(index)) {
92                                         case '\n':
93                                         case '\r':
94                                                 return c;
95                                         }
96                                         if (index <= 0) {
97                                                 return c;
98                                         }
99                                 }
100                         }
101             if (blockStartRead) {
102                 buffer.append(processBlockTag());
103                 blockStartRead= false;
104             } else {
105                 buffer.append((char) c);
106             }
107
108                         c= nextChar();
109             blockStartRead= c == '{';
110                 }
111                 return c;
112         }
113
114         private String substituteQualification(String qualification) {
115                 String result;
116                 if (qualification.indexOf("<a") == -1) { //$NON-NLS-1$
117                         // No tag at all, use smart way
118                         result= qualification.replace('#', '.');
119                 } else {
120                         // Handle tags
121                         int length= qualification.length();
122                         result= qualification;
123                         boolean insideTag= false;
124                         for (int i= 0; i < length; i++) {
125                                 char charAt= result.charAt(i);
126                                 if (charAt == '<' && result.charAt(i + 1) == 'a')
127                                         insideTag= true;
128                                 if (charAt == '>')
129                                         insideTag= false;
130                                 if (charAt == '#' && !insideTag)
131                                         result= result.substring(0, i) + "." + result.substring(i + 1); //$NON-NLS-1$
132                         }
133                 }
134
135                 if (result.startsWith(".")) //$NON-NLS-1$
136                         result= result.substring(1);
137                 return result;
138         }
139
140         private void printDefinitions(StringBuffer buffer, List<String> list, boolean firstword) {
141                 Iterator<String> e= list.iterator();
142                 while (e.hasNext()) {
143                         String s= e.next();
144                         buffer.append("<dd>"); //$NON-NLS-1$
145                         if (!firstword)
146                                 buffer.append(s);
147                         else {
148                                 buffer.append("<b>"); //$NON-NLS-1$
149
150                                 int i= getParamEndOffset(s);
151                                 if (i <= s.length()) {
152                                         buffer.append(HTMLPrinter.convertToHTMLContent(s.substring(0, i)));
153                                         buffer.append("</b>"); //$NON-NLS-1$
154                                         buffer.append(s.substring(i));
155                                 } else {
156                                         buffer.append("</b>"); //$NON-NLS-1$
157                                 }
158                         }
159                         buffer.append("</dd>"); //$NON-NLS-1$
160                 }
161         }
162
163         private int getParamEndOffset(String s) {
164                 int i= 0;
165                 final int length= s.length();
166                 // \s*
167                 while (i < length && Character.isWhitespace(s.charAt(i)))
168                         ++i;
169                 if (i < length && s.charAt(i) == '<') {
170                         // generic type parameter
171                         // read <\s*\w*\s*>
172                         while (i < length && Character.isWhitespace(s.charAt(i)))
173                                 ++i;
174                         while (i < length && Character.isJavaIdentifierPart(s.charAt(i)))
175                                 ++i;
176                         while (i < length && s.charAt(i) != '>')
177                                 ++i;
178                 } else {
179                         // simply read an identifier
180                         while (i < length && Character.isJavaIdentifierPart(s.charAt(i)))
181                                 ++i;
182                 }
183
184                 return i;
185         }
186
187         private void print(StringBuffer buffer, String tag, List<String> elements, boolean firstword) {
188                 if ( !elements.isEmpty()) {
189                         buffer.append("<dt>"); //$NON-NLS-1$
190                         buffer.append(tag);
191                         buffer.append("</dt>"); //$NON-NLS-1$
192                         printDefinitions(buffer, elements, firstword);
193                 }
194         }
195
196         private void print(StringBuffer buffer, String tag, String content) {
197                 if  (content != null) {
198                         buffer.append("<dt>"); //$NON-NLS-1$
199                         buffer.append(tag);
200                         buffer.append("</dt>"); //$NON-NLS-1$
201                         buffer.append("<dd>"); //$NON-NLS-1$
202                         buffer.append(content);
203                         buffer.append("</dd>"); //$NON-NLS-1$
204                 }
205         }
206
207         private void printRest(StringBuffer buffer) {
208                 if ( !fRest.isEmpty()) {
209                         Iterator<Pair> e= fRest.iterator();
210                         while (e.hasNext()) {
211                                 Pair p= e.next();
212                                 buffer.append("<dt>"); //$NON-NLS-1$
213                                 p.generated_5851077662602872979(buffer, this);
214                                 buffer.append("</dd>"); //$NON-NLS-1$
215                         }
216                 }
217         }
218
219         private String printSimpleTag() {
220                 StringBuffer buffer= new StringBuffer();
221                 buffer.append("<dl>"); //$NON-NLS-1$
222                 print(buffer, JavaDocMessages.JavaDoc2HTMLTextReader_see_section, fSees, false);
223                 print(buffer, JavaDocMessages.JavaDoc2HTMLTextReader_parameters_section, fParameters, true);
224                 print(buffer, JavaDocMessages.JavaDoc2HTMLTextReader_returns_section, fReturn);
225                 print(buffer, JavaDocMessages.JavaDoc2HTMLTextReader_throws_section, fExceptions, false);
226                 print(buffer, JavaDocMessages.JavaDoc2HTMLTextReader_author_section, fAuthors, false);
227                 print(buffer, JavaDocMessages.JavaDoc2HTMLTextReader_since_section, fSince, false);
228                 printRest(buffer);
229                 buffer.append("</dl>"); //$NON-NLS-1$
230
231                 return buffer.toString();
232         }
233
234         private void handleTag(String tag, String tagContent) {
235
236                 tagContent= tagContent.trim();
237
238                 if (TagElement.TAG_PARAM.equals(tag))
239                         fParameters.add(tagContent);
240                 else if (TagElement.TAG_RETURN.equals(tag))
241                         fReturn= tagContent;
242                 else if (TagElement.TAG_EXCEPTION.equals(tag))
243                         fExceptions.add(tagContent);
244                 else if (TagElement.TAG_THROWS.equals(tag))
245                         fExceptions.add(tagContent);
246                 else if (TagElement.TAG_AUTHOR.equals(tag))
247                         fAuthors.add(substituteQualification(tagContent));
248                 else if (TagElement.TAG_SEE.equals(tag))
249                         fSees.add(substituteQualification(tagContent));
250                 else if (TagElement.TAG_SINCE.equals(tag))
251                         fSince.add(substituteQualification(tagContent));
252                 else if (tagContent != null)
253                         fRest.add(new Pair(tag, tagContent));
254         }
255
256         /*
257          * A '@' has been read. Process a javadoc tag
258          */
259         private String processSimpleTag() throws IOException {
260
261                 fParameters= new ArrayList<String>();
262                 fExceptions= new ArrayList<String>();
263                 fAuthors= new ArrayList<String>();
264                 fSees= new ArrayList<String>();
265                 fSince= new ArrayList<String>();
266                 fRest= new ArrayList<Pair>();
267
268                 StringBuffer buffer= new StringBuffer();
269                 int c= '@';
270                 while (c != -1) {
271
272                         buffer.setLength(0);
273                         buffer.append((char) c);
274                         c= getTag(buffer);
275                         String tag= buffer.toString();
276
277                         buffer.setLength(0);
278                         if (c != -1) {
279                                 c= getContentUntilNextTag(buffer);
280                         }
281
282                         handleTag(tag, buffer.toString());
283                 }
284
285                 return printSimpleTag();
286         }
287
288         private String printBlockTag(String tag, String tagContent) {
289
290                 if (TagElement.TAG_LINK.equals(tag) || TagElement.TAG_LINKPLAIN.equals(tag)) {
291
292                         char[] contentChars= tagContent.toCharArray();
293                         boolean inParentheses= false;
294                         int labelStart= 0;
295
296                         for (int i= 0; i < contentChars.length; i++) {
297                                 char nextChar= contentChars[i];
298
299                                 // tagContent always has a leading space
300                                 if (i == 0 && Character.isWhitespace(nextChar)) {
301                                         labelStart= 1;
302                                         continue;
303                                 }
304
305                                 if (nextChar == '(') {
306                                         inParentheses= true;
307                                         continue;
308                                 }
309
310                                 if (nextChar == ')') {
311                                         inParentheses= false;
312                                         continue;
313                                 }
314
315                                 // Stop at first whitespace that is not in parentheses
316                                 if (!inParentheses && Character.isWhitespace(nextChar)) {
317                                         labelStart= i+1;
318                                         break;
319                                 }
320                         }
321                         if (TagElement.TAG_LINK.equals(tag))
322                                 return "<code>" + substituteQualification(tagContent.substring(labelStart)) + "</code>";  //$NON-NLS-1$//$NON-NLS-2$
323                         else
324                                 return substituteQualification(tagContent.substring(labelStart));
325
326                 } else if (TagElement.TAG_LITERAL.equals(tag)) {
327                         return printLiteral(tagContent);
328
329                 } else if (TagElement.TAG_CODE.equals(tag)) {
330                         return "<code>" + printLiteral(tagContent) + "</code>"; //$NON-NLS-1$//$NON-NLS-2$
331                 }
332
333                 // If something went wrong at least replace the {} with the content
334                 return substituteQualification(tagContent);
335         }
336
337         private String printLiteral(String tagContent) {
338                 int contentStart= 0;
339                 for (int i= 0; i < tagContent.length(); i++) {
340                         if (! Character.isWhitespace(tagContent.charAt(i))) {
341                                 contentStart= i;
342                                 break;
343                         }
344                 }
345                 return HTMLPrinter.convertToHTMLContent(tagContent.substring(contentStart));
346         }
347
348         /*
349          * A '{' has been read. Process a block tag
350          */
351         private String processBlockTag() throws IOException {
352
353                 int c= nextChar();
354
355                 if (c != '@') {
356                         StringBuffer buffer= new StringBuffer();
357                         buffer.append('{');
358                         buffer.append((char) c);
359                         return buffer.toString();
360                 }
361
362                 StringBuffer buffer= new StringBuffer();
363                 if (c != -1) {
364
365                         buffer.setLength(0);
366                         buffer.append((char) c);
367
368                         c= getTag(buffer);
369                         String tag= buffer.toString();
370
371                         buffer.setLength(0);
372                         if (c != -1 && c != '}') {
373                                 buffer.append((char) c);
374                                 c= getContent(buffer, '}');
375                         }
376
377                         return printBlockTag(tag, buffer.toString());
378                 }
379
380                 return null;
381         }
382
383         /*
384          * @see SubstitutionTextReaderr#computeSubstitution(int)
385          */
386         @Override
387         protected String computeSubstitution(int c) throws IOException {
388                 if (c == '@' && fWasWhiteSpace)
389                         return processSimpleTag();
390
391                 if (c == '{')
392                         return processBlockTag();
393
394                 return null;
395         }
396 }