1 11 12 package org.eclipse.jdt.internal.formatter.comment; 13 14 import java.io.IOException ; 15 import java.io.StringReader ; 16 import java.util.ArrayList ; 17 import java.util.Iterator ; 18 19 import org.eclipse.text.edits.TextEdit; 20 21 import org.eclipse.jface.text.BadLocationException; 22 import org.eclipse.jface.text.DefaultLineTracker; 23 import org.eclipse.jface.text.IDocument; 24 import org.eclipse.jface.text.ILineTracker; 25 import org.eclipse.jface.text.Position; 26 import org.eclipse.jface.text.TextUtilities; 27 28 import org.eclipse.jdt.core.formatter.CodeFormatter; 29 import org.eclipse.jdt.internal.compiler.parser.ScannerHelper; 30 import org.eclipse.jdt.internal.formatter.CodeFormatterVisitor; 31 32 33 38 public class JavaDocRegion extends MultiCommentRegion implements IJavaDocTagConstants { 39 40 41 private final ArrayList fCodePositions= new ArrayList (); 42 43 44 private final boolean fFormatHtml; 45 46 47 private final boolean fFormatSource; 48 49 56 public JavaDocRegion(final IDocument document, final Position position, final CodeFormatterVisitor formatter) { 57 super(document, position, formatter); 58 59 fFormatSource = this.preferences.comment_format_source; 60 fFormatHtml = this.preferences.comment_format_html; 61 fClear = this.preferences.comment_clear_blank_lines_in_javadoc_comment; 62 } 63 64 67 protected boolean canFormat(final CommentRange previous, final CommentRange next) { 68 69 if (previous != null) { 70 71 final boolean isCurrentCode= next.hasAttribute(COMMENT_CODE); 72 final boolean isLastCode= previous.hasAttribute(COMMENT_CODE); 73 74 final int base= getOffset(); 75 76 if (!isLastCode && isCurrentCode) 77 fCodePositions.add(new Position(base + previous.getOffset())); 78 else if (isLastCode && !isCurrentCode) 79 fCodePositions.add(new Position(base + next.getOffset() + next.getLength())); 80 81 if (previous.hasAttribute(COMMENT_IMMUTABLE) && next.hasAttribute(COMMENT_IMMUTABLE)) 82 return false; 83 84 return true; 85 } 86 return false; 87 } 88 89 92 protected final void formatRegion(final String indentation, final int width) { 93 94 super.formatRegion(indentation, width); 95 96 if (fFormatSource) { 97 98 try { 99 100 if (fCodePositions.size() > 0) { 101 102 int begin= 0; 103 int end= 0; 104 105 Position position= null; 106 107 final IDocument document= getDocument(); 108 109 for (int index= fCodePositions.size() - 1; index >= 0;) { 110 111 position= (Position)fCodePositions.get(index--); 112 begin= position.getOffset(); 113 114 if (index >= 0) { 115 position= (Position)fCodePositions.get(index--); 116 end= position.getOffset(); 117 } else { 118 122 position= null; 123 end= getOffset() + getLength() - MultiCommentLine.MULTI_COMMENT_END_PREFIX.trim().length(); 124 while (end > begin && ScannerHelper.isWhitespace(document.getChar(end - 1))) 125 end--; 126 } 127 128 String snippet= document.get(begin, end - begin); 129 snippet= preprocessCodeSnippet(snippet); 130 snippet= formatCodeSnippet(snippet); 131 snippet= postprocessCodeSnippet(snippet, indentation); 132 133 logEdit(snippet, begin - getOffset(), end - begin); 134 } 135 } 136 } catch (BadLocationException e) { 137 CommentFormatterUtil.log(e); 139 } 140 } 141 } 142 143 149 private String preprocessCodeSnippet(String snippet) { 150 StringBuffer buffer= new StringBuffer (); 152 ILineTracker tracker= new DefaultLineTracker(); 153 String contentPrefix= MultiCommentLine.MULTI_COMMENT_CONTENT_PREFIX.trim(); 154 155 buffer.setLength(0); 156 buffer.append(snippet); 157 tracker.set(snippet); 158 for (int line= tracker.getNumberOfLines() - 1; line > 0; line--) { 159 int lineOffset; 160 try { 161 lineOffset= tracker.getLineOffset(line); 162 } catch (BadLocationException e) { 163 CommentFormatterUtil.log(e); 165 return snippet; 166 } 167 int prefixOffset= buffer.indexOf(contentPrefix, lineOffset); 168 if (prefixOffset >= 0 && buffer.substring(lineOffset, prefixOffset).trim().length() == 0) 169 buffer.delete(lineOffset, prefixOffset + contentPrefix.length() + 1); 170 } 171 172 return convertHtml2Java(buffer.toString()); 173 } 174 175 181 private String formatCodeSnippet(String snippet) { 182 String lineDelimiter= TextUtilities.getDefaultLineDelimiter(getDocument()); 183 TextEdit edit= CommentFormatterUtil.format2(CodeFormatter.K_UNKNOWN, snippet, 0, lineDelimiter, this.preferences.getMap()); 184 if (edit != null) 185 snippet= CommentFormatterUtil.evaluateFormatterEdit(snippet, edit, null); 186 return snippet; 187 } 188 189 196 private String postprocessCodeSnippet(String snippet, String indentation) { 197 StringBuffer buffer= new StringBuffer (); 199 ILineTracker tracker= new DefaultLineTracker(); 200 String patch= indentation + MultiCommentLine.MULTI_COMMENT_CONTENT_PREFIX; 201 202 int i= snippet.length(); 204 while (i > 0 && ' ' == snippet.charAt(i-1)) 205 i--; 206 snippet= snippet.substring(0, i); 207 208 buffer.setLength(0); 209 String lineDelimiter= getDelimiter(); 210 if (lineDelimiter != null && snippet.indexOf(lineDelimiter) != 0) 211 buffer.append(lineDelimiter); 212 buffer.append(convertJava2Html(snippet)); 213 if (lineDelimiter != null && snippet.lastIndexOf(lineDelimiter) != snippet.length() - lineDelimiter.length()) 214 buffer.append(lineDelimiter); 215 tracker.set(buffer.toString()); 216 217 for (int line= tracker.getNumberOfLines() - 1; line > 0; line--) 218 try { 219 buffer.insert(tracker.getLineOffset(line), patch); 220 } catch (BadLocationException e) { 221 CommentFormatterUtil.log(e); 223 return snippet; 224 } 225 226 return buffer.toString(); 227 } 228 229 232 protected final void markHtmlRanges() { 233 234 markTagRanges(JAVADOC_IMMUTABLE_TAGS, COMMENT_IMMUTABLE, true); 235 236 if (fFormatSource) 237 markTagRanges(JAVADOC_CODE_TAGS, COMMENT_CODE, false); 238 } 239 240 243 protected final void markHtmlTag(final CommentRange range, final char[] token) { 244 245 if (range.hasAttribute(COMMENT_HTML)) { 246 247 range.markHtmlTag(JAVADOC_IMMUTABLE_TAGS, token, COMMENT_IMMUTABLE, true, true); 248 if (fFormatHtml) { 249 250 range.markHtmlTag(JAVADOC_SEPARATOR_TAGS, token, COMMENT_SEPARATOR, true, true); 251 range.markHtmlTag(JAVADOC_BREAK_TAGS, token, COMMENT_BREAK, false, true); 252 range.markHtmlTag(JAVADOC_SINGLE_BREAK_TAG, token, COMMENT_BREAK, true, false); 253 range.markHtmlTag(JAVADOC_NEWLINE_TAGS, token, COMMENT_NEWLINE, true, false); 254 255 } else 256 range.markHtmlTag(JAVADOC_CODE_TAGS, token, COMMENT_SEPARATOR, true, true); 257 } 258 } 259 260 263 protected final void markJavadocTag(final CommentRange range, final char[] token) { 264 265 range.markPrefixTag(JAVADOC_PARAM_TAGS, COMMENT_TAG_PREFIX, token, COMMENT_PARAMETER); 266 267 if (token[0] == JAVADOC_TAG_PREFIX && !range.hasAttribute(COMMENT_PARAMETER)) 268 range.setAttribute(COMMENT_ROOT); 269 } 270 271 280 protected final void markTagRanges(final char[][] tags, final int attribute, final boolean html) { 281 282 int level= 0; 283 int count= 0; 284 char[] token= null; 285 CommentRange current= null; 286 287 for (int index= 0; index < tags.length; index++) { 288 289 level= 0; 290 for (final Iterator iterator= getRanges().iterator(); iterator.hasNext();) { 291 292 current= (CommentRange)iterator.next(); 293 count= current.getLength(); 294 295 if (count > 0 || level > 0) { 297 token= getText(current.getOffset(), current.getLength()).toCharArray(); 298 level= current.markTagRange(token, tags[index], level, attribute, html); 299 } 300 } 301 } 302 } 303 304 307 protected boolean canAppend(CommentLine line, CommentRange previous, CommentRange next, int index, int count) { 308 if (next.hasAttribute(COMMENT_CODE | COMMENT_FIRST_TOKEN) && line.getSize() != 0) 310 return false; 311 return super.canAppend(line, previous, next, index, count); 312 } 313 314 322 private String convertJava2Html(String formatted) { 323 Java2HTMLEntityReader reader= new Java2HTMLEntityReader(new StringReader (formatted)); 324 char[] buf= new char[256]; 325 StringBuffer buffer= new StringBuffer (); 326 int l; 327 try { 328 do { 329 l= reader.read(buf); 330 if (l != -1) 331 buffer.append(buf, 0, l); 332 } while (l > 0); 333 return buffer.toString(); 334 } catch (IOException e) { 335 return formatted; 336 } 337 } 338 339 346 private String convertHtml2Java(String html) { 347 HTMLEntity2JavaReader reader= new HTMLEntity2JavaReader(new StringReader (html)); 348 char[] buf= new char[html.length()]; 350 try { 351 int read= reader.read(buf); 352 return new String (buf, 0, read); 353 } catch (IOException e) { 354 return html; 355 } 356 } 357 358 362 protected CommentLine createLine() { 363 return new JavaDocLine(this); 364 } 365 } 366 | Popular Tags |