Package com.intellij.coldFusion.UI.folding

Source Code of com.intellij.coldFusion.UI.folding.CfmlFoldingBuilder

/*
* 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.coldFusion.UI.folding;

import com.intellij.codeInsight.folding.CodeFoldingSettings;
import com.intellij.coldFusion.model.files.CfmlFile;
import com.intellij.coldFusion.model.lexer.CfmlTokenTypes;
import com.intellij.coldFusion.model.parsers.CfmlElementTypes;
import com.intellij.coldFusion.model.psi.CfmlCompositeElement;
import com.intellij.coldFusion.model.psi.CfmlFunction;
import com.intellij.coldFusion.model.psi.CfmlTag;
import com.intellij.lang.ASTNode;
import com.intellij.lang.folding.FoldingBuilder;
import com.intellij.lang.folding.FoldingDescriptor;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.project.DumbAware;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.PsiComment;
import com.intellij.psi.PsiElement;
import com.intellij.psi.impl.source.SourceTreeToPsiMap;
import com.intellij.psi.tree.IElementType;
import org.jetbrains.annotations.NotNull;

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

/**
* @author vnikolaenko
*/
public class CfmlFoldingBuilder implements FoldingBuilder, DumbAware {
  @NotNull
  public FoldingDescriptor[] buildFoldRegions(@NotNull ASTNode node, @NotNull Document document) {
    final PsiElement element = node.getPsi();
    if (element instanceof CfmlFile) {
      final CfmlFile file = (CfmlFile)element;
      final PsiElement[] children = file.getChildren();
      Collection<FoldingDescriptor> result = new LinkedList<FoldingDescriptor>();
      for (PsiElement child : children) {
        if (child != null && (child instanceof CfmlCompositeElement ||
                              child instanceof PsiComment)) {
          List<FoldingDescriptor> descriptors = new ArrayList<FoldingDescriptor>();
          addFoldingDescriptors(descriptors, child, document);
          result.addAll(descriptors);
        }
      }
      return result.toArray(FoldingDescriptor.EMPTY);
    }
    return FoldingDescriptor.EMPTY;
  }

  private static void addFoldingDescriptorsFromChildren(List<FoldingDescriptor> descriptors,
                                                        PsiElement tag, @NotNull Document document) {
    for (PsiElement child = tag.getFirstChild(); child != null; child = child.getNextSibling()) {
      if (child instanceof CfmlCompositeElement || child instanceof PsiComment) {
        addFoldingDescriptors(descriptors, child, document);
      }
    }
  }

  private static void addFoldingDescriptors(final List<FoldingDescriptor> descriptors,
                                            final PsiElement tag,
                                            @NotNull Document document) {

    TextRange elementRange = tag.getTextRange();
    final int start = elementRange.getStartOffset();
    final int end = elementRange.getEndOffset();

    if (start + 1 < end) {
      TextRange range = null;
      ASTNode astNode = tag.getNode();
      if (tag instanceof CfmlTag) {
        //if (tag instanceof CfmlTagFunctionImpl || tag instanceof CfmlTagComponentImpl || tag instanceof CfmlTagScriptImpl) {
        range = buildRangeForBraces(range, astNode, CfmlTokenTypes.R_ANGLEBRACKET, CfmlTokenTypes.LSLASH_ANGLEBRACKET);
        //}
      }
      else if (tag instanceof CfmlFunction) {
        final ASTNode body = astNode.findChildByType(CfmlElementTypes.FUNCTIONBODY);
        if (body != null) {
          range = buildRange(range, body.getStartOffset(), body.getTextRange().getEndOffset());
        }
      }
      else if (tag instanceof PsiComment) {
        boolean isColdFusionComment = astNode.getElementType() == CfmlTokenTypes.COMMENT;
        int endIndex = astNode.getText().lastIndexOf(isColdFusionComment ? "--->" : "*/");
        if (endIndex != -1) {
          String commentText = astNode.getText().substring(0, endIndex);
          if (commentText.contains("\n")) {
            int startOffset = tag.getTextRange().getStartOffset();
            range = buildRange(range, startOffset + (isColdFusionComment ? "<!---" : "/*").length(), startOffset + commentText.length());
          }
        }
      }

      if (range != null) {
        descriptors.add(new FoldingDescriptor(astNode, range));
      }

      // TODO: insert condition
      addFoldingDescriptorsFromChildren(descriptors, tag, document);
    }
  }

  private static TextRange buildRangeForBraces(TextRange range,
                                               @NotNull ASTNode astNode,
                                               IElementType lbraceType,
                                               IElementType rbraceType) {
    ASTNode lBrace = astNode.findChildByType(lbraceType);
    ASTNode rBrace = astNode.findChildByType(rbraceType);
    if (lBrace != null && rBrace != null) {
      range = buildRange(range, lBrace.getStartOffset() + 1, rBrace.getStartOffset());
    }
    return range;
  }

  private static TextRange buildRange(TextRange range, int leftOffset, int rightOffset) {
    if (leftOffset + 1 < rightOffset) range = new TextRange(leftOffset, rightOffset);
    return range;
  }

  public String getPlaceholderText(@NotNull ASTNode node) {
    if (node.getElementType() == CfmlElementTypes.FUNCTION_DEFINITION) {
      return "{...}";
    }
    return "...";
  }

  public boolean isCollapsedByDefault(@NotNull ASTNode node) {
    CodeFoldingSettings settings = CodeFoldingSettings.getInstance();
    final PsiElement element = SourceTreeToPsiMap.treeElementToPsi(node);

    if (node.getPsi() instanceof PsiComment) {
      // find out if file header
      final ASTNode parent = node.getTreeParent();
      ASTNode treePrev = node.getTreePrev();

      if (parent.getElementType() == CfmlElementTypes.CFML_FILE && treePrev == null) {
        return CodeFoldingSettings.getInstance().COLLAPSE_FILE_HEADER;
      }
      else {
        return CodeFoldingSettings.getInstance().COLLAPSE_DOC_COMMENTS;
      }
    }
    else if (element instanceof CfmlFunction) {
      return settings.COLLAPSE_METHODS;
    }/* else if (element instanceof CfmlComponent) {
      return settings.isCollapseClasses();
    }*/

    return false;
  }
}
TOP

Related Classes of com.intellij.coldFusion.UI.folding.CfmlFoldingBuilder

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.