Package org.aspectj.org.eclipse.jdt.internal.formatter.comment

Source Code of org.aspectj.org.eclipse.jdt.internal.formatter.comment.JavaDocRegion

/*******************************************************************************
* Copyright (c) 2000, 2007 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
*     IBM Corporation - initial API and implementation
*******************************************************************************/

package org.aspectj.org.eclipse.jdt.internal.formatter.comment;

import java.io.IOException;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.Iterator;

import org.eclipse.text.edits.TextEdit;

import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.DefaultLineTracker;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.ILineTracker;
import org.eclipse.jface.text.Position;
import org.eclipse.jface.text.TextUtilities;

import org.aspectj.org.eclipse.jdt.core.formatter.CodeFormatter;
import org.aspectj.org.eclipse.jdt.internal.compiler.parser.ScannerHelper;
import org.aspectj.org.eclipse.jdt.internal.formatter.CodeFormatterVisitor;


/**
* Javadoc region in a source code document.
*
* @since 3.0
*/
public class JavaDocRegion extends MultiCommentRegion implements IJavaDocTagConstants {

  /** The positions of code ranges */
  private final ArrayList fCodePositions= new ArrayList();
  
  /** Should HTML tags be formatted? */
  private final boolean fFormatHtml;

  /** Should source code regions be formatted? */
  private final boolean fFormatSource;
 
   /**
   * Creates a new Javadoc region.
   *
   * @param document the document which contains the comment region
   * @param position the position of this comment region in the document
   * @param formatter the given formatter
   */ 
  public JavaDocRegion(final IDocument document, final Position position, final CodeFormatterVisitor formatter) {
    super(document, position, formatter);

    fFormatSource = this.preferences.comment_format_source;
    fFormatHtml = this.preferences.comment_format_html;
    fClear = this.preferences.comment_clear_blank_lines_in_javadoc_comment;
  }

  /*
   * @see org.aspectj.org.eclipse.jdt.internal.corext.text.comment.CommentRegion#canFormat(org.aspectj.org.eclipse.jdt.internal.corext.text.comment.CommentRange, org.aspectj.org.eclipse.jdt.internal.corext.text.comment.CommentRange)
   */
  protected boolean canFormat(final CommentRange previous, final CommentRange next) {
   
    if (previous != null) {
     
      final boolean isCurrentCode= next.hasAttribute(COMMENT_CODE);
      final boolean isLastCode= previous.hasAttribute(COMMENT_CODE);
     
      final int base= getOffset();
     
      if (!isLastCode && isCurrentCode)
        fCodePositions.add(new Position(base + previous.getOffset()));
      else if (isLastCode && !isCurrentCode)
        fCodePositions.add(new Position(base + next.getOffset() + next.getLength()));
     
      if (previous.hasAttribute(COMMENT_IMMUTABLE) && next.hasAttribute(COMMENT_IMMUTABLE))
        return false;
     
      return true;
    }
    return false;
  }

  /*
   * @see org.aspectj.org.eclipse.jdt.internal.corext.text.comment.CommentRegion#formatRegion(java.lang.String, int)
   */
  protected final void formatRegion(final String indentation, final int width) {
 
    super.formatRegion(indentation, width);
   
    if (fFormatSource) {
     
      try {
       
        if (fCodePositions.size() > 0) {
         
          int begin= 0;
          int end= 0;
         
          Position position= null;
         
          final IDocument document= getDocument();
         
          for (int index= fCodePositions.size() - 1; index >= 0;) {
           
            position= (Position)fCodePositions.get(index--);
            begin= position.getOffset();
           
            if (index >= 0) {
              position= (Position)fCodePositions.get(index--);
              end= position.getOffset();
            } else {
              /*
               * Handle missing closing tag
               * see: https://bugs.eclipse.org/bugs/show_bug.cgi?id=57011
               */
              position= null;
              end= getOffset() + getLength() - MultiCommentLine.MULTI_COMMENT_END_PREFIX.trim().length();
              while (end > begin && ScannerHelper.isWhitespace(document.getChar(end - 1)))
                end--;
            }
           
            String snippet= document.get(begin, end - begin);
            snippet= preprocessCodeSnippet(snippet);
            snippet= formatCodeSnippet(snippet);
            snippet= postprocessCodeSnippet(snippet, indentation);
           
            logEdit(snippet, begin - getOffset(), end - begin);
          }
        }
      } catch (BadLocationException e) {
        // Can not happen
        CommentFormatterUtil.log(e);
      }
    }
  }

  /**
   * Preprocess a given code snippet.
   *
   * @param snippet the code snippet
   * @return the preprocessed code snippet
   */
  private String preprocessCodeSnippet(String snippet) {
    // strip content prefix
    StringBuffer buffer= new StringBuffer();
    ILineTracker tracker= new DefaultLineTracker();
    String contentPrefix= MultiCommentLine.MULTI_COMMENT_CONTENT_PREFIX.trim();
   
    buffer.setLength(0);
    buffer.append(snippet);
    tracker.set(snippet);
    for (int line= tracker.getNumberOfLines() - 1; line > 0; line--) {
      int lineOffset;
      try {
        lineOffset= tracker.getLineOffset(line);
      } catch (BadLocationException e) {
        // Can not happen
        CommentFormatterUtil.log(e);
        return snippet;
      }
      int prefixOffset= buffer.indexOf(contentPrefix, lineOffset);
      if (prefixOffset >= 0 && buffer.substring(lineOffset, prefixOffset).trim().length() == 0)
        buffer.delete(lineOffset, prefixOffset + contentPrefix.length() + 1);
    }
   
    return convertHtml2Java(buffer.toString());
  }

  /**
   * Format the given code snippet
   *
   * @param snippet the code snippet
   * @return the formatted code snippet
   */
  private String formatCodeSnippet(String snippet) {
    String lineDelimiter= TextUtilities.getDefaultLineDelimiter(getDocument());
    TextEdit edit= CommentFormatterUtil.format2(CodeFormatter.K_UNKNOWN, snippet, 0, lineDelimiter, this.preferences.getMap());
    if (edit != null)
      snippet= CommentFormatterUtil.evaluateFormatterEdit(snippet, edit, null);
    return snippet;
  }

  /**
   * Postprocesses the given code snippet with the given indentation.
   *
   * @param snippet the code snippet
   * @param indentation the indentation
   * @return the postprocessed code snippet
   */
  private String postprocessCodeSnippet(String snippet, String indentation) {
    // patch content prefix
    StringBuffer buffer= new StringBuffer();
    ILineTracker tracker= new DefaultLineTracker();
    String patch= indentation + MultiCommentLine.MULTI_COMMENT_CONTENT_PREFIX;

    // remove trailing spaces
    int i= snippet.length();
    while (i > 0 && ' ' == snippet.charAt(i-1))
      i--;
    snippet= snippet.substring(0, i);
   
    buffer.setLength(0);
    String lineDelimiter= getDelimiter();
    if (lineDelimiter != null && snippet.indexOf(lineDelimiter) != 0)
      buffer.append(lineDelimiter);
    buffer.append(convertJava2Html(snippet));
    if (lineDelimiter != null && snippet.lastIndexOf(lineDelimiter) != snippet.length() - lineDelimiter.length())
      buffer.append(lineDelimiter);
    tracker.set(buffer.toString());
   
    for (int line= tracker.getNumberOfLines() - 1; line > 0; line--)
      try {
        buffer.insert(tracker.getLineOffset(line), patch);
      } catch (BadLocationException e) {
        // Can not happen
        CommentFormatterUtil.log(e);
        return snippet;
      }
   
    return buffer.toString();
  }

  /*
   * @see org.aspectj.org.eclipse.jdt.internal.corext.text.comment.MultiCommentRegion#markHtmlRanges()
   */
  protected final void markHtmlRanges() {

    markTagRanges(JAVADOC_IMMUTABLE_TAGS, COMMENT_IMMUTABLE, true);

    if (fFormatSource)
      markTagRanges(JAVADOC_CODE_TAGS, COMMENT_CODE, false);
  }

  /*
   * @see org.aspectj.org.eclipse.jdt.internal.corext.text.comment.MultiCommentRegion#markHtmlTag(org.aspectj.org.eclipse.jdt.internal.corext.text.comment.CommentRange, java.lang.String)
   */
  protected final void markHtmlTag(final CommentRange range, final char[] token) {

    if (range.hasAttribute(COMMENT_HTML)) {

      range.markHtmlTag(JAVADOC_IMMUTABLE_TAGS, token, COMMENT_IMMUTABLE, true, true);
      if (fFormatHtml) {

        range.markHtmlTag(JAVADOC_SEPARATOR_TAGS, token, COMMENT_SEPARATOR, true, true);
        range.markHtmlTag(JAVADOC_BREAK_TAGS, token, COMMENT_BREAK, false, true);
        range.markHtmlTag(JAVADOC_SINGLE_BREAK_TAG, token, COMMENT_BREAK, true, false);
        range.markHtmlTag(JAVADOC_NEWLINE_TAGS, token, COMMENT_NEWLINE, true, false);

      } else
        range.markHtmlTag(JAVADOC_CODE_TAGS, token, COMMENT_SEPARATOR, true, true);
    }
  }

  /*
   * @see org.aspectj.org.eclipse.jdt.internal.corext.text.comment.MultiCommentRegion#markJavadocTag(org.aspectj.org.eclipse.jdt.internal.corext.text.comment.CommentRange, java.lang.String)
   */
  protected final void markJavadocTag(final CommentRange range, final char[] token) {

    range.markPrefixTag(JAVADOC_PARAM_TAGS, COMMENT_TAG_PREFIX, token, COMMENT_PARAMETER);

    if (token[0] == JAVADOC_TAG_PREFIX && !range.hasAttribute(COMMENT_PARAMETER))
      range.setAttribute(COMMENT_ROOT);
  }

  /**
   * Marks the comment region with the HTML range tag.
   *
   * @param tags the HTML tag which confines the HTML range
   * @param attribute the attribute to set if the comment range is in the
   *                HTML range
   * @param html <code>true</code> iff the HTML tags in this HTML range
   *                should be marked too, <code>false</code> otherwise
   */
  protected final void markTagRanges(final char[][] tags, final int attribute, final boolean html) {
   
    int level= 0;
    int count= 0;
    char[] token= null;
    CommentRange current= null;
   
    for (int index= 0; index < tags.length; index++) {
     
      level= 0;
      for (final Iterator iterator= getRanges().iterator(); iterator.hasNext();) {
       
        current= (CommentRange)iterator.next();
        count= current.getLength();
       
        if (count > 0 || level > 0) { // PR44035: when inside a tag, mark blank lines as well to get proper snippet formatting
         
          token= getText(current.getOffset(), current.getLength()).toCharArray();
          level= current.markTagRange(token, tags[index], level, attribute, html);
        }
      }
    }
  }

  /*
   * @see org.aspectj.org.eclipse.jdt.internal.corext.text.comment.CommentRegion#canAppend(org.aspectj.org.eclipse.jdt.internal.corext.text.comment.CommentLine, org.aspectj.org.eclipse.jdt.internal.corext.text.comment.CommentRange, org.aspectj.org.eclipse.jdt.internal.corext.text.comment.CommentRange, int, int)
   */
  protected boolean canAppend(CommentLine line, CommentRange previous, CommentRange next, int index, int count) {
    // don't append code sections
    if (next.hasAttribute(COMMENT_CODE | COMMENT_FIRST_TOKEN) && line.getSize() != 0)
      return false;
    return super.canAppend(line, previous, next, index, count);
  }

  /**
   * Converts <code>formatted</code> into valid html code suitable to be
   * put inside &lt;pre&gt;&lt;/pre&gt; tags by replacing any html symbols
   * by the relevant entities.
   *
   * @param formatted the formatted java code
   * @return html version of the formatted code
   */
  private String convertJava2Html(String formatted) {
    Java2HTMLEntityReader reader= new Java2HTMLEntityReader(new StringReader(formatted));
    char[] buf= new char[256];
    StringBuffer buffer= new StringBuffer();
    int l;
    try {
      do {
        l= reader.read(buf);
        if (l != -1)
          buffer.append(buf, 0, l);
      } while (l > 0);
      return buffer.toString();
    } catch (IOException e) {
      return formatted;
    }
  }

  /**
   * Converts <code>html</code> into java code suitable for formatting
   * by replacing any html entities by their plain text representation.
   *
   * @param html html code, may contain html entities
   * @return plain textified version of <code>html</code>
   */
  private String convertHtml2Java(String html) {
    HTMLEntity2JavaReader reader= new HTMLEntity2JavaReader(new StringReader(html));
    char[] buf= new char[html.length()]; // html2text never gets longer, only shorter!
   
    try {
      int read= reader.read(buf);
      return new String(buf, 0, read);
    } catch (IOException e) {
      return html;
    }
  }
 
  /*
   * @see org.aspectj.org.eclipse.jdt.internal.corext.text.comment.CommentRegion#createLine()
   * @since 3.1
   */
  protected CommentLine createLine() {
    return new JavaDocLine(this);
  }
}
TOP

Related Classes of org.aspectj.org.eclipse.jdt.internal.formatter.comment.JavaDocRegion

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.