Package net.cakenet.jsaton.ui.tools.script.ruby

Source Code of net.cakenet.jsaton.ui.tools.script.ruby.RubyFoldParser

package net.cakenet.jsaton.ui.tools.script.ruby;

import net.cakenet.jsaton.script.ruby.RubyScript;
import org.fife.ui.rsyntaxtextarea.RSyntaxTextArea;
import org.fife.ui.rsyntaxtextarea.folding.Fold;
import org.fife.ui.rsyntaxtextarea.folding.FoldParser;
import org.fife.ui.rsyntaxtextarea.folding.FoldType;
import org.jruby.ast.Node;
import org.jruby.lexer.yacc.ISourcePosition;

import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

public class RubyFoldParser implements FoldParser {
    private Map<RSyntaxTextArea, List<Fold>> foldCache = new HashMap<>();

    public List getFolds(RSyntaxTextArea textArea) {
        if (!(textArea instanceof RubyScriptEditorPane))
            return null;

        RubyScriptEditorPane rsp = (RubyScriptEditorPane) textArea;
        RubyScript script = (RubyScript) rsp.script;
        script.setScript(rsp.getText());
        Node root = script.getAST();
        if(root == null) {
            if (foldCache.containsKey(textArea))
                return foldCache.get(textArea);
            return null;
        }
        //debug(root, "  ");
        List<Fold> folds = new LinkedList<>();
        getFolds(folds, rsp, root, null);
        foldCache.put(textArea, folds);
        return folds;
    }

    private void getFolds(List<Fold> folds, RSyntaxTextArea area, Node node, Fold parent) {
        try {
            Fold passItOn = parent;
            int line = node.getPosition().getLine();
            if (line == -1)
                return; // nilnode...
            int offs = area.getLineStartOffset(line);

            // update parents end position...
            if (parent != null) {
                int pend = parent.getEndOffset();
                if (pend == Integer.MAX_VALUE || offs >= pend)
                    parent.setEndOffset(offs);
            }

            // Create new if needed...
            if (isFoldable(node)) {
                if (parent == null) {
                    passItOn = new Fold(FoldType.CODE, area, offs);
                    folds.add(passItOn);
                } else
                    passItOn = parent.createChild(FoldType.CODE, offs);
            }

            // Get children folds...
            for (Node child : node.childNodes()) {
                getFolds(folds, area, child, passItOn);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private static void debug(Node node, String indent) {
        ISourcePosition pos = node.getPosition();
        int line = pos.getStartLine();
        System.out.println(String.format("%03d", line) + indent + node.getNodeType() + "(" + pos.getClass().getCanonicalName() + ")");
        for (Node child : node.childNodes())
            debug(child, indent + "  ");
    }

    private static boolean isFoldable(Node node) {
        switch (node.getNodeType()) {
            case WHILENODE:
            case IFNODE:
            case FORNODE:
            case CASENODE:
            case DEFNNODE:
            case DEFSNODE:
            case CLASSNODE:
            case SCLASSNODE:
            case RESCUEBODYNODE:
            case MODULENODE:
                return true;
        }
        return false;
    }
}
TOP

Related Classes of net.cakenet.jsaton.ui.tools.script.ruby.RubyFoldParser

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.