blob: 9dca9c5b7f60144ad8eff6033ddfe9f13ca00157 [file] [log] [blame]
/*
* Copyright 2000-2013 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.ide.highlighter.custom.impl;
import com.intellij.codeInsight.highlighting.BraceMatcher;
import com.intellij.codeInsight.highlighting.BraceMatchingUtil;
import com.intellij.ide.highlighter.custom.CustomFileHighlighter;
import com.intellij.lang.ASTNode;
import com.intellij.lang.folding.CustomFoldingBuilder;
import com.intellij.lang.folding.FoldingDescriptor;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.colors.EditorColorsManager;
import com.intellij.openapi.editor.ex.util.LexerEditorHighlighter;
import com.intellij.openapi.editor.highlighter.HighlighterIterator;
import com.intellij.openapi.fileTypes.FileType;
import com.intellij.openapi.fileTypes.SyntaxHighlighter;
import com.intellij.openapi.fileTypes.impl.CustomSyntaxTableFileType;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.util.Trinity;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.PsiElement;
import com.intellij.psi.tree.IElementType;
import org.jetbrains.annotations.NotNull;
import java.util.LinkedList;
import java.util.List;
/**
* @author yole
*/
public class CustomFileTypeFoldingBuilder extends CustomFoldingBuilder {
@Override
protected void buildLanguageFoldRegions(@NotNull List<FoldingDescriptor> descriptors,
@NotNull PsiElement root,
@NotNull Document document,
boolean quick) {
FileType fileType = root.getContainingFile().getFileType();
if (!(fileType instanceof CustomSyntaxTableFileType)) {
return;
}
CustomFileHighlighter highlighter = new CustomFileHighlighter(((CustomSyntaxTableFileType) fileType).getSyntaxTable());
buildBraceMatcherBasedFolding(descriptors, root, document, highlighter);
}
public static void buildBraceMatcherBasedFolding(List<FoldingDescriptor> descriptors,
PsiElement root,
Document document,
SyntaxHighlighter highlighter) {
LexerEditorHighlighter editorHighlighter = new LexerEditorHighlighter(highlighter, EditorColorsManager.getInstance().getGlobalScheme());
editorHighlighter.setText(document.getText());
FileType fileType = root.getContainingFile().getFileType();
BraceMatcher braceMatcher = BraceMatchingUtil.getBraceMatcher(fileType, root.getLanguage());
TextRange totalRange = root.getTextRange();
final HighlighterIterator iterator = editorHighlighter.createIterator(totalRange.getStartOffset());
final LinkedList<Trinity<Integer, Integer, IElementType>> stack = new LinkedList<Trinity<Integer, Integer, IElementType>>();
String editorText = document.getText();
while (!iterator.atEnd() && iterator.getStart() < totalRange.getEndOffset()) {
final Trinity<Integer, Integer, IElementType> last;
if (braceMatcher.isLBraceToken(iterator, editorText, fileType) &&
braceMatcher.isStructuralBrace(iterator, editorText, fileType)) {
stack.addLast(Trinity.create(iterator.getStart(), iterator.getEnd(), iterator.getTokenType()));
}
else if (braceMatcher.isRBraceToken(iterator, editorText, fileType) &&
braceMatcher.isStructuralBrace(iterator, editorText, fileType)
&& !stack.isEmpty() && braceMatcher.isPairBraces((last = stack.getLast()).third, iterator.getTokenType())) {
stack.removeLast();
TextRange range = new TextRange(last.first, iterator.getEnd());
if (StringUtil.countChars(document.getText(range), '\n') >= 3) {
descriptors.add(new FoldingDescriptor(root, range));
}
}
iterator.advance();
}
}
@Override
protected String getLanguagePlaceholderText(@NotNull ASTNode node, @NotNull TextRange range) {
return "{...}";
}
@Override
protected boolean isRegionCollapsedByDefault(@NotNull ASTNode node) {
return false;
}
}