/* * Copyright 2013-2014 Grzegorz Ligas <ligasgr@gmail.com> and other contributors * (see the CONTRIBUTORS file). * * 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 org.intellij.xquery.folding; 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.project.DumbAware; import com.intellij.openapi.util.TextRange; import com.intellij.psi.PsiElement; import org.intellij.xquery.psi.*; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; import java.util.List; public class XQueryFoldingBuilder extends FoldingBuilderEx implements DumbAware { @NotNull @Override public FoldingDescriptor[] buildFoldRegions(@NotNull PsiElement root, @NotNull Document document, boolean quick) { if (!(root instanceof XQueryFile)) return FoldingDescriptor.EMPTY; XQueryFile file = (XQueryFile) root; List<FoldingDescriptor> descriptorList = new ArrayList<FoldingDescriptor>(); updateImportFoldingDescriptors(descriptorList, new ArrayList<XQueryPsiElement>(file.getModuleImports())); updateImportFoldingDescriptors(descriptorList, new ArrayList<XQueryPsiElement>(file.getNamespaceDeclarations())); for (XQueryFunctionDecl function : file.getFunctionDeclarations()) { final XQueryFunctionBody functionBody = function.getFunctionBody(); if (functionBody != null && functionBody.getTextLength() > 2) { descriptorList.add(new FoldingDescriptor(function, functionBody.getTextRange())); } } return descriptorList.toArray(new FoldingDescriptor[descriptorList.size()]); } private void updateImportFoldingDescriptors(List<FoldingDescriptor> descriptorList, Collection<XQueryPsiElement> elementsToFold) { if (elementsToFold.size() < 2) { return; } FoldingDescriptor folding = null; int numberOfAdjacentElement = 0; for (Iterator<XQueryPsiElement> i = elementsToFold.iterator(); i.hasNext(); ) { final XQueryPsiElement element = i.next(); final TextRange elementTextRange = element.getTextRange(); if (folding == null) { folding = buildNewFoldingDescriptor(element, elementTextRange); numberOfAdjacentElement = 1; continue; } final boolean isAdjacent = folding.getRange().getEndOffset() + 1 == elementTextRange.getStartOffset(); if (isAdjacent) { final TextRange updatedRange = new TextRange(folding.getRange().getStartOffset(), elementTextRange.getEndOffset()); folding = new FoldingDescriptor(folding.getElement(), updatedRange); numberOfAdjacentElement++; } if (isAdjacent && i.hasNext()) { continue; } if (numberOfAdjacentElement > 1) { descriptorList.add(folding); folding = null; } if (!isAdjacent) { folding = buildNewFoldingDescriptor(element, elementTextRange); numberOfAdjacentElement = 1; } } } private FoldingDescriptor buildNewFoldingDescriptor(XQueryPsiElement element, TextRange elementTextRange) { FoldingDescriptor folding; folding = new FoldingDescriptor(element, elementTextRange); if (element instanceof XQueryModuleImport) { final TextRange updatedRange = new TextRange(folding.getRange().getStartOffset() + "import ".length(), folding.getRange().getEndOffset()); folding = new FoldingDescriptor(folding.getElement(), updatedRange); } if (element instanceof XQueryNamespaceDecl) { final TextRange updatedRange = new TextRange(folding.getRange().getStartOffset() + "declare namespace ".length(), folding.getRange().getEndOffset()); folding = new FoldingDescriptor(folding.getElement(), updatedRange); } return folding; } @Nullable @Override public String getPlaceholderText(@NotNull ASTNode astNode) { final PsiElement psiElement = astNode.getPsi(); if (psiElement instanceof XQueryFunctionDecl) { return "{...}"; } else if (psiElement instanceof XQueryModuleImport) { return "..."; } else if (psiElement instanceof XQueryNamespaceDecl) { return "..."; } else { return "...."; } } @Override public boolean isCollapsedByDefault(@NotNull ASTNode astNode) { if (astNode.getElementType().equals(XQueryTypes.MODULE_IMPORT)) { return true; } else if (astNode.getElementType().equals(XQueryTypes.NAMESPACE_DECL)) { return true; } return false; } }