Package com.intellij.usages

Source Code of com.intellij.usages.ChunkExtractor

/*
* Copyright 2000-2007 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.usages;

import com.intellij.lexer.Lexer;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.HighlighterColors;
import com.intellij.openapi.editor.RangeMarker;
import com.intellij.openapi.editor.colors.EditorColorsScheme;
import com.intellij.openapi.editor.colors.TextAttributesKey;
import com.intellij.openapi.editor.markup.TextAttributes;
import com.intellij.openapi.fileTypes.FileType;
import com.intellij.openapi.fileTypes.PlainSyntaxHighlighter;
import com.intellij.openapi.fileTypes.SyntaxHighlighter;
import com.intellij.psi.PsiDocumentManager;
import com.intellij.psi.PsiElement;
import com.intellij.psi.tree.IElementType;
import com.intellij.usageView.UsageTreeColors;
import com.intellij.usageView.UsageTreeColorsScheme;

import java.awt.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

/**
* @author peter
*/
public class ChunkExtractor {
  private static final Logger LOG = Logger.getInstance("#com.intellij.usages.ChunkExtractor");

  private final PsiElement myElement;
  private final Document myDocument;
  private final int myLineNumber;
  private final int myColumnNumber;

  private final List<RangeMarker> myRangeMarkers;
  private final EditorColorsScheme myColorsScheme;

  public ChunkExtractor(final PsiElement element,
                        final List<RangeMarker> rangeMarkers) {

    myElement = element;
    myRangeMarkers = new ArrayList<RangeMarker>(rangeMarkers);
    Collections.sort(myRangeMarkers, new Comparator<RangeMarker>() {
      public int compare(final RangeMarker o1, final RangeMarker o2) {
        int result = o1.getStartOffset() - o2.getStartOffset();
        if (result == 0) {
          result = o1.getEndOffset() - o2.getEndOffset();
        }
        return result;
      }
    });
    myColorsScheme = UsageTreeColorsScheme.getInstance().getScheme();

    final int absoluteStartOffset =  getStartOffset(myRangeMarkers);

    myDocument = PsiDocumentManager.getInstance(myElement.getProject()).getDocument(myElement.getContainingFile());
    myLineNumber = myDocument.getLineNumber(absoluteStartOffset);
    myColumnNumber = absoluteStartOffset - myDocument.getLineStartOffset(myLineNumber);
  }

  public static int getStartOffset(final List<RangeMarker> rangeMarkers) {
    LOG.assertTrue(!rangeMarkers.isEmpty());
    int minStart = Integer.MAX_VALUE;
    for (RangeMarker rangeMarker : rangeMarkers) {
      final int startOffset = rangeMarker.getStartOffset();
      if (startOffset < minStart) minStart = startOffset;
    }

    return minStart;
  }

  public TextChunk[] extractChunks() {
    final int lineStartOffset = myDocument.getLineStartOffset(myLineNumber);
    final int lineEndOffset = lineStartOffset < myDocument.getTextLength() ? myDocument.getLineEndOffset(myLineNumber):0;
    final FileType fileType = myElement.getContainingFile().getFileType();
    SyntaxHighlighter highlighter = fileType.getHighlighter(myElement.getProject(), myElement.getContainingFile().getVirtualFile());
    if (highlighter == null) {
      highlighter = new PlainSyntaxHighlighter();
    }
    return createTextChunks(myDocument.getCharsSequence(), highlighter, lineStartOffset, lineEndOffset);
  }

  private TextChunk[] createTextChunks(final CharSequence chars,
                                       SyntaxHighlighter highlighter,
                                       int start,
                                       int end) {
    LOG.assertTrue(start <= end);
    List<TextChunk> result = new ArrayList<TextChunk>();

    appendPrefix(result);

    Lexer lexer = highlighter.getHighlightingLexer();
    lexer.start(chars, 0, chars.length(), 0);

    for (int offset = start; offset < end; offset++) {
      if (chars.charAt(offset) == '\n') {
        end = offset;
        break;
      }
    }

    boolean isBeginning = true;

    while (lexer.getTokenType() != null) {
      try {
        int hiStart = lexer.getTokenStart();
        int hiEnd = lexer.getTokenEnd();

        if (hiStart >= end) break;

        hiStart = Math.max(hiStart, start);
        hiEnd = Math.min(hiEnd, end);
        if (hiStart >= hiEnd) { continue; }

        String text = chars.subSequence(hiStart, hiEnd).toString();
        if (isBeginning && text.trim().length() == 0) continue;
        isBeginning = false;
        IElementType tokenType = lexer.getTokenType();
        TextAttributesKey[] tokenHighlights = highlighter.getTokenHighlights(tokenType);

        processIntersectingRange(chars, hiStart, hiEnd, tokenHighlights, result);
        //result.add(new TextChunk(convertAttributes(tokenHighlights), text));
      }
      finally {
        lexer.advance();
      }
    }

    return result.toArray(new TextChunk[result.size()]);
  }

  private void processIntersectingRange(CharSequence chars,
                                        int hiStart,
                                        int hiEnd,
                                        TextAttributesKey[] tokenHighlights,
                                        List<TextChunk> result) {
    TextAttributes originalAttrs = convertAttributes(tokenHighlights);
    int lastOffset = hiStart;
    for(RangeMarker rangeMarker: myRangeMarkers) {
      int usageStart = rangeMarker.getStartOffset();
      int usageEnd = rangeMarker.getEndOffset();
      if (rangeMarker.isValid() && rangeIntersect(lastOffset, hiEnd, usageStart, usageEnd)) {
        addChunk(chars, lastOffset, Math.max(lastOffset, usageStart), originalAttrs, false, result);
        addChunk(chars, Math.max(lastOffset, usageStart), Math.min(hiEnd, usageEnd), originalAttrs, true, result);
        if (usageEnd > hiEnd) {
          return;
        }
        lastOffset = usageEnd;
      }
    }
    if (lastOffset < hiEnd) {
      addChunk(chars, lastOffset, hiEnd, originalAttrs, false, result);
    }
  }

  private static void addChunk(CharSequence chars, int start, int end, TextAttributes originalAttrs, boolean bold, List<TextChunk> result) {
    if (start >= end) return;
    String rText = chars.subSequence(start, end).toString();
    TextAttributes attrs = bold
                           ? TextAttributes.merge(originalAttrs, new TextAttributes(null, null, null, null, Font.BOLD))
                           : originalAttrs;
    result.add(new TextChunk(attrs, rText));
  }

  private static boolean rangeIntersect(int s1, int e1, int s2, int e2) {
    return s2 < s1 && s1 < e2 || s2 < e1 && e1 < e2
           || s1 < s2 && s2 < e1 || s1 < e2 && e2 < e1
           || s1 == s2 && e1 == e2;
  }

  private TextAttributes convertAttributes(TextAttributesKey[] keys) {
    TextAttributes attrs = myColorsScheme.getAttributes(HighlighterColors.TEXT);

    for (TextAttributesKey key : keys) {
      TextAttributes attrs2 = myColorsScheme.getAttributes(key);
      if (attrs2 != null) {
        attrs = TextAttributes.merge(attrs, attrs2);
      }
    }

    attrs = attrs.clone();
    attrs.setFontType(Font.PLAIN);
    return attrs;
  }

  private void appendPrefix(List<TextChunk> result) {
    StringBuilder buffer = new StringBuilder("(");
    buffer.append(myLineNumber + 1);
    buffer.append(", ");
    buffer.append(myColumnNumber + 1);
    buffer.append(") ");
    TextChunk prefixChunk = new TextChunk(myColorsScheme.getAttributes(UsageTreeColors.USAGE_LOCATION), buffer.toString());
    result.add(prefixChunk);
  }



}
TOP

Related Classes of com.intellij.usages.ChunkExtractor

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.