Package krasa.formatter.plugin.processor

Source Code of krasa.formatter.plugin.processor.JSCommentsFormatterProcessor

package krasa.formatter.plugin.processor;

import com.google.gwt.eclipse.core.editors.java.GWTPartitions;
import com.intellij.openapi.editor.Document;
import com.intellij.psi.PsiFile;
import krasa.formatter.eclipse.JSCodeFormatterFacade;
import krasa.formatter.plugin.Range;
import krasa.formatter.settings.Settings;
import krasa.formatter.utils.FileUtils;
import org.eclipse.jdt.core.formatter.IndentManipulation;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.ITypedRegion;
import org.eclipse.jface.text.TypedPosition;
import org.eclipse.jface.text.TypedRegion;
import org.eclipse.text.edits.MultiTextEdit;
import org.eclipse.text.edits.ReplaceEdit;
import org.eclipse.text.edits.TextEdit;
import org.eclipse.wst.jsdt.core.formatter.CodeFormatter;

import java.util.ArrayList;

/**
* @author Vojtech Krasa
*/
public class JSCommentsFormatterProcessor implements Processor {
  private Settings settings;
  private JSCodeFormatterFacade jsCodeFormatterFacade;

  public JSCommentsFormatterProcessor(Settings settings) {
    this.settings = settings;
    jsCodeFormatterFacade = new JSCodeFormatterFacade(settings.getJSProperties());
  }

  @Override
  public boolean process(Document documentIJ, PsiFile file, Range range) {
    if (FileUtils.isJavaScript(file) && settings.isEnableJSProcessor()) {
      try {
        String text = documentIJ.getText();
        IDocument document = new org.eclipse.jface.text.Document(text);

        TextEdit formatEdit = format(document, range);


        formatEdit.apply(document);
        documentIJ.setText(document.get());
      } catch (Exception e) {
        throw new RuntimeException(e);
      }
    }
    return true;
  }

  private TextEdit format(IDocument document, Range range) {
    TextEdit combinedEdit = new MultiTextEdit();
    ITypedRegion[] regions = computePartitioning(document, range);

    // Format all JSNI blocks in the document
    int i = 0;
    for (ITypedRegion region : regions) {
      if (region.getType().equals(GWTPartitions.JSNI_METHOD)) {
        TextEdit edit = format(document, new TypedPosition(region));
        if (edit != null) {
          combinedEdit.addChild(edit);
        }
        i++;
      }
    }
    return combinedEdit;

  }

  public TextEdit format(IDocument document, TypedPosition partition) {
    try {
      // Extract the JSNI block out of the document
      int offset = partition.getOffset();
      int length = partition.getLength();

      // Determine the line delimiter, indent string, and tab/indent widths
      String lineDelimiter = Settings.LINE_SEPARATOR;
      int tabWidth = IndentManipulation.getTabWidth(settings.getJSProperties().get());
      int indentWidth = IndentManipulation.getIndentWidth(settings.getJSProperties().get());

      // Get indentation level of the first line of the JSNI block (this should
      // be the line containing the JSNI method declaration)
      int methodDeclarationOffset = getMethodDeclarationOffset(document, offset);

      int jsniLine1 = document.getLineOfOffset(methodDeclarationOffset);
      int methodIndentLevel = getLineIndentLevel(document, jsniLine1, tabWidth, indentWidth);
//      String indentLine = defaultCodeFormatter.createIndentationString(methodIndentLevel);

      // Extract the JSNI body out of the block and split it up by line
      String jsniSource = document.get(offset, length);

      String formattedJs;


      TextEdit formatEdit = jsCodeFormatterFacade.format(CodeFormatter.K_JAVA_DOC, jsniSource, 0, jsniSource.length(),
          methodIndentLevel, lineDelimiter);

      org.eclipse.jface.text.Document d = new org.eclipse.jface.text.Document(jsniSource);
      formatEdit.apply(d);

      formattedJs = d.get();

//      if (!formattedJs.startsWith(lineDelimiter)) {
//        formattedJs = indentLine+formattedJs  ;
//        formattedJs = lineDelimiter + formattedJs;
//      }
//
      if (!formattedJs.endsWith(lineDelimiter)) {
        formattedJs = formattedJs + lineDelimiter;
      }

//      formattedJs = formattedJs + indentLine;

      return new ReplaceEdit(offset, length, formattedJs);

    } catch (Exception e) {
      throw new RuntimeException(e);
    }
  }

  private static int getLineIndentLevel(IDocument document, int line, int tabWidth, int indentWidth)
      throws BadLocationException {
    int lineOffset = document.getLineOffset(line);
    return getLineIndentLevel(document.get(lineOffset, document.getLineLength(line)), tabWidth, indentWidth);
  }

  private static int getLineIndentLevel(String line, int tabWidth, int indentWidth) {
    return IndentManipulation.measureIndentUnits(line, tabWidth, indentWidth);
  }

  private static int getMethodDeclarationOffset(IDocument document, int offset) {
    int methodDeclarationOffset = offset;

    // jsniMethodWithDeclarationLineThatWraps
    String s = document.get();
    int i = s.lastIndexOf("\n", offset);
    String substring = s.substring(i + 1, offset);
    substring = substring.trim();
    if (!substring.isEmpty() && !substring.contains("(")) {
      methodDeclarationOffset = i - 2;
    }
    return methodDeclarationOffset;
  }

  private static ITypedRegion[] computePartitioning(IDocument document, Range range) {
    ArrayList<ITypedRegion> iTypedRegions = new ArrayList<ITypedRegion>();
    String str = document.get();
    String prefix = "/**";
    String postfix = "*/";
    int startIndex = 0;
    int endIndex = 0;

    while (startIndex != -1) {
      startIndex = str.indexOf(prefix, startIndex);
      endIndex = str.indexOf(postfix, startIndex);

      if (startIndex != -1 && endIndex != -1) {
        endIndex = endIndex + 3;
        if (isInRange(range, startIndex, endIndex)) {
          iTypedRegions.add(new TypedRegion(startIndex, endIndex - startIndex, GWTPartitions.JSNI_METHOD));
        }
        startIndex += prefix.length();
      }
    }
    return iTypedRegions.toArray(new ITypedRegion[iTypedRegions.size()]);

  }

  private static boolean isInRange(Range range, int startIndex, int endIndex) {
    boolean b = range.getStartOffset() < startIndex && range.getEndOffset() > endIndex;
    boolean b1 = startIndex < range.getEndOffset() && range.getEndOffset() < endIndex;
    boolean b2 = startIndex < range.getStartOffset() && range.getStartOffset() < endIndex;
    return range.isWholeFile() || b || b1 || b2;
  }
}
TOP

Related Classes of krasa.formatter.plugin.processor.JSCommentsFormatterProcessor

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.