mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
chunk extractor
This commit is contained in:
@@ -0,0 +1,178 @@
|
||||
/*
|
||||
* Copyright (c) 2000-2005 by JetBrains s.r.o. All Rights Reserved.
|
||||
* Use is subject to license terms.
|
||||
*/
|
||||
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.SyntaxHighlighter;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
import com.intellij.usageView.UsageTreeColors;
|
||||
import com.intellij.usageView.UsageTreeColorsScheme;
|
||||
import com.intellij.util.text.CharArrayUtil;
|
||||
|
||||
import java.awt.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author peter
|
||||
*/
|
||||
public class ChunkExtractor {
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.usages.ChunkExtractor");
|
||||
private Document myDocument;
|
||||
private int myLineNumber;
|
||||
private PsiFile myPsiFile;
|
||||
private List<RangeMarker> myRangeMarkers;
|
||||
private EditorColorsScheme myColorsScheme;
|
||||
private int myColumnNumber;
|
||||
|
||||
public ChunkExtractor(final Document document,
|
||||
final int lineNumber,
|
||||
final PsiFile psiFile,
|
||||
final List<RangeMarker> rangeMarkers,
|
||||
final int columnNumber) {
|
||||
myDocument = document;
|
||||
myLineNumber = lineNumber;
|
||||
myPsiFile = psiFile;
|
||||
myRangeMarkers = rangeMarkers;
|
||||
myColumnNumber = columnNumber;
|
||||
myColorsScheme = UsageTreeColorsScheme.getInstance().getScheme();
|
||||
}
|
||||
|
||||
|
||||
public TextChunk[] extractChunks() {
|
||||
int lineStartOffset = myDocument.getLineStartOffset(myLineNumber);
|
||||
int lineEndOffset = myDocument.getLineEndOffset(myLineNumber);
|
||||
return createTextChunks(myDocument.getCharsSequence(), myPsiFile.getFileType().getHighlighter(myPsiFile.getProject()), 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(CharArrayUtil.fromSequence(chars));
|
||||
|
||||
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);
|
||||
|
||||
RangeMarker intersectionMarker = getIntersectingMarker(hiStart, hiEnd);
|
||||
if (intersectionMarker != null) {
|
||||
processIntersectingRange(chars, hiStart, hiEnd, tokenHighlights, result, intersectionMarker);
|
||||
}
|
||||
else {
|
||||
result.add(new TextChunk(convertAttributes(tokenHighlights), text));
|
||||
}
|
||||
}
|
||||
finally {
|
||||
lexer.advance();
|
||||
}
|
||||
}
|
||||
|
||||
return result.toArray(new TextChunk[result.size()]);
|
||||
}
|
||||
|
||||
private RangeMarker getIntersectingMarker(int hiStart, int hiEnd) {
|
||||
for (int i = 0; i < myRangeMarkers.size(); i++) {
|
||||
RangeMarker marker = myRangeMarkers.get(i);
|
||||
if (marker.isValid() && rangeIntersect(hiStart, hiEnd, marker.getStartOffset(), marker.getEndOffset())) return marker;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private void processIntersectingRange(CharSequence chars,
|
||||
int hiStart,
|
||||
int hiEnd,
|
||||
TextAttributesKey[] tokenHighlights,
|
||||
List<TextChunk> result,
|
||||
RangeMarker rangeMarker) {
|
||||
int usageStart = rangeMarker.getStartOffset();
|
||||
int usageEnd = rangeMarker.getEndOffset();
|
||||
|
||||
TextAttributes originalAttrs = convertAttributes(tokenHighlights);
|
||||
addChunk(chars, hiStart, Math.max(hiStart, usageStart), originalAttrs, false, result);
|
||||
addChunk(chars, Math.max(hiStart, usageStart), Math.min(hiEnd, usageEnd), originalAttrs, true, result);
|
||||
addChunk(chars, Math.min(hiEnd, usageEnd), 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 (int i = 0; i < keys.length; i++) {
|
||||
TextAttributesKey key = keys[i];
|
||||
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) {
|
||||
StringBuffer buffer = new StringBuffer("(");
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -1,17 +1,12 @@
|
||||
package com.intellij.usages;
|
||||
|
||||
import com.intellij.ide.SelectInEditorManager;
|
||||
import com.intellij.lexer.Lexer;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
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.fileEditor.*;
|
||||
import com.intellij.openapi.fileTypes.SyntaxHighlighter;
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.roots.*;
|
||||
@@ -21,15 +16,10 @@ import com.intellij.psi.PsiCompiledElement;
|
||||
import com.intellij.psi.PsiDocumentManager;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
import com.intellij.usageView.UsageInfo;
|
||||
import com.intellij.usageView.UsageTreeColors;
|
||||
import com.intellij.usageView.UsageTreeColorsScheme;
|
||||
import com.intellij.usages.rules.*;
|
||||
import com.intellij.util.text.CharArrayUtil;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@@ -54,7 +44,6 @@ public class UsageInfo2UsageAdapter implements Usage, UsageInModule, UsageInLibr
|
||||
private EditorColorsScheme myColorsScheme;
|
||||
|
||||
public UsageInfo2UsageAdapter(final UsageInfo usageInfo) {
|
||||
myColorsScheme = UsageTreeColorsScheme.getInstance().getScheme();
|
||||
myUsageInfo = usageInfo;
|
||||
PsiElement element = myUsageInfo.getElement();
|
||||
myPsiFile = element.getContainingFile();
|
||||
@@ -91,9 +80,7 @@ public class UsageInfo2UsageAdapter implements Usage, UsageInModule, UsageInLibr
|
||||
}
|
||||
|
||||
private void initChunks() {
|
||||
int lineStartOffset = myDocument.getLineStartOffset(myLineNumber);
|
||||
int lineEndOffset = myDocument.getLineEndOffset(myLineNumber);
|
||||
myTextChunks = createTextChunks(myDocument.getCharsSequence(), myPsiFile.getFileType().getHighlighter(myPsiFile.getProject()), lineStartOffset, lineEndOffset);
|
||||
myTextChunks = new ChunkExtractor(myDocument, myLineNumber, myPsiFile, myRangeMarkers, myColumnNumber).extractChunks();
|
||||
}
|
||||
|
||||
public UsagePresentation getPresentation() {
|
||||
@@ -247,124 +234,6 @@ public class UsageInfo2UsageAdapter implements Usage, UsageInModule, UsageInLibr
|
||||
}
|
||||
}
|
||||
|
||||
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(CharArrayUtil.fromSequence(chars));
|
||||
|
||||
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);
|
||||
|
||||
RangeMarker intersectionMarker = getIntersectingMarker(hiStart, hiEnd);
|
||||
if (intersectionMarker != null) {
|
||||
processIntersectingRage(chars, hiStart, hiEnd, tokenHighlights, result, intersectionMarker);
|
||||
}
|
||||
else {
|
||||
result.add(new TextChunk(convertAttributes(tokenHighlights), text));
|
||||
}
|
||||
}
|
||||
finally {
|
||||
lexer.advance();
|
||||
}
|
||||
}
|
||||
|
||||
return result.toArray(new TextChunk[result.size()]);
|
||||
}
|
||||
|
||||
private RangeMarker getIntersectingMarker(int hiStart, int hiEnd) {
|
||||
for (int i = 0; i < myRangeMarkers.size(); i++) {
|
||||
RangeMarker marker = myRangeMarkers.get(i);
|
||||
if (marker.isValid() && rangeIntersect(hiStart, hiEnd, marker.getStartOffset(), marker.getEndOffset())) return marker;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private void processIntersectingRage(CharSequence chars,
|
||||
int hiStart,
|
||||
int hiEnd,
|
||||
TextAttributesKey[] tokenHighlights,
|
||||
List<TextChunk> result,
|
||||
RangeMarker rangeMarker) {
|
||||
int usageStart = rangeMarker.getStartOffset();
|
||||
int usageEnd = rangeMarker.getEndOffset();
|
||||
|
||||
TextAttributes originalAttrs = convertAttributes(tokenHighlights);
|
||||
addChunk(chars, hiStart, Math.max(hiStart, usageStart), originalAttrs, false, result);
|
||||
addChunk(chars, Math.max(hiStart, usageStart), Math.min(hiEnd, usageEnd), originalAttrs, true, result);
|
||||
addChunk(chars, Math.min(hiEnd, usageEnd), 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 (int i = 0; i < keys.length; i++) {
|
||||
TextAttributesKey key = keys[i];
|
||||
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) {
|
||||
StringBuffer buffer = new StringBuffer("(");
|
||||
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);
|
||||
}
|
||||
|
||||
public PsiElement getElement() {
|
||||
return myUsageInfo.getElement();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user