Package de.balpha.varsity

Source Code of de.balpha.varsity.VarFoldingBuilder

package de.balpha.varsity;

import com.intellij.ide.util.PropertiesComponent;
import com.intellij.lang.ASTNode;
import com.intellij.lang.folding.FoldingBuilderEx;
import com.intellij.lang.folding.FoldingDescriptor;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.FoldingGroup;
import com.intellij.openapi.util.Ref;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.*;
import com.intellij.psi.util.PsiTreeUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

public class VarFoldingBuilder extends FoldingBuilderEx {

    private static int mMinChars;

    @NotNull
    @Override
    public FoldingDescriptor[] buildFoldRegions(@NotNull PsiElement root, @NotNull Document document, boolean quick) {

        boolean noFoldPrimitives = !PropertiesComponent.getInstance().getBoolean("foldprimitives", true);
        mMinChars = PropertiesComponent.getInstance().getOrInitInt("minchars", 3);
        boolean foldToVal = PropertiesComponent.getInstance().getBoolean("val", false);

        List<FoldingDescriptor> descriptors = new ArrayList<FoldingDescriptor>();

        Collection<PsiMethod> methods = PsiTreeUtil.findChildrenOfType(root, PsiMethod.class);

        for (final PsiMethod method : methods) {

            Collection<PsiLocalVariable> vars = PsiTreeUtil.findChildrenOfType(method, PsiLocalVariable.class);
            Collection<PsiForeachStatement> iters = PsiTreeUtil.findChildrenOfType(method, PsiForeachStatement.class);
            FoldingGroup group = FoldingGroup.newGroup(method.getName());

            for (final PsiVariable var : vars) {
                PsiTypeElement typeElem = var.getTypeElement();
                if (typeElem == null)
                    continue;
                PsiType vartype = var.getType();
                PsiExpression initializer = var.getInitializer();

                if (initializer == null)
                    continue;

                PsiType rightType = initializer.getType();

                if (rightType == null)
                    continue;

                if (noFoldPrimitives && !(rightType instanceof PsiClassType || rightType instanceof PsiArrayType))
                    continue;

                boolean doFold = false;

                if (rightType instanceof PsiClassType) {
                    PsiClass rightClass = ((PsiClassType)rightType).resolve();
                    if (rightClass instanceof PsiAnonymousClass) {
                        if (((PsiAnonymousClass)rightClass).getBaseClassType().equals(vartype))
                            doFold = true;
                    }
                }

                doFold |= rightType.equals(vartype);

                Ref<TextRange> range = new Ref<TextRange>(typeElem.getTextRange());
                Ref<ASTNode> node = new Ref<ASTNode>(typeElem.getNode());

                if (foldToVal)
                    checkFoldToVal(var, range, node);

                if (doFold && rangeMakesSenseToFold(range.get())) {
                    descriptors.add(new FoldingDescriptor(node.get(), range.get(), group));
                }
            }

            for (final PsiForeachStatement iter : iters) {
                PsiParameter param = iter.getIterationParameter();
                PsiType vartype = param.getType();
                PsiType iterType = (PsiType)iter.getIteratedValue().getType();

                if ((iterType instanceof PsiClassType && isIterableOf((PsiClassType)iterType, vartype))
                        ||
                        (iterType instanceof PsiArrayType && ((PsiArrayType)iterType).getComponentType().equals(vartype))
                    ) {
                    Ref<TextRange> range = new Ref<TextRange>(param.getTypeElement().getTextRange());
                    Ref<ASTNode> node = new Ref<ASTNode>(param.getTypeElement().getNode());
                    if (foldToVal)
                        checkFoldToVal(param, range, node);
                    if (rangeMakesSenseToFold(range.get()))
                        descriptors.add(new FoldingDescriptor(node.get(), range.get(), group));
                }
            }
        }
        return descriptors.toArray(new FoldingDescriptor[descriptors.size()]);
    }

    private static boolean rangeMakesSenseToFold(TextRange range) {
        return range.getLength() >= mMinChars;
    }

    private static void checkFoldToVal(PsiVariable var, Ref<TextRange> range, Ref<ASTNode> node) {
        PsiModifierList modifiers = ((PsiVariable) var).getModifierList();

        if (modifiers != null && modifiers.getChildren().length == 1 && modifiers.hasExplicitModifier("final")) {
            range.set(range.get().union(modifiers.getTextRange()));
            node.set(modifiers.getFirstChild().getNode());
        }

    }

    private static boolean isIterableOf(PsiClassType iter, PsiType var) {
        if (iter.resolve() != null
                && "java.lang.Iterable".equals(iter.resolve().getQualifiedName())) {

            if (iter.getParameters().length > 0) {
                return iter.getParameters()[0].equals(var);
            } else {
                if (var instanceof PsiClassType) {
                    PsiClass resolved = ((PsiClassType) var).resolve();
                    return resolved != null && "java.lang.Object".equals(resolved.getQualifiedName());
                }
                return false;
            }
        }

        for (PsiType interf : iter.getSuperTypes()) {
            if (interf instanceof PsiClassType && isIterableOf((PsiClassType)interf, var))
                return true;
        }
        return false;

    }

    @Nullable
    @Override
    public String getPlaceholderText(@NotNull ASTNode node) {
        if (node instanceof PsiKeyword && node.getText().equals("final"))
            return "val";
        return "var";
    }

    @Override
    public boolean isCollapsedByDefault(@NotNull ASTNode node) {
        return true;
    }
}
TOP

Related Classes of de.balpha.varsity.VarFoldingBuilder

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.