package org.jetbrains.plugins.clojure;
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.psi.PsiElement;
import com.intellij.psi.tree.IElementType;
import org.jetbrains.plugins.clojure.parser.ClojureElementTypes;
import static org.jetbrains.plugins.clojure.parser.ClojureElementTypes.*;
import org.jetbrains.plugins.clojure.psi.api.ClList;
import org.jetbrains.plugins.clojure.psi.api.ClojureFile;
import java.util.ArrayList;
import java.util.List;
/**
* Created by IntelliJ IDEA.
* User: peter
* Date: Dec 31, 2008
* Time: 10:31:02 AM
* Copyright 2007, 2008, 2009 Red Shark Technology
* <p/>
* http://www.apache.org/licenses/LICENSE-2.0
* <p/>
* 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.
*/
public class ClojureFoldingBuilder implements FoldingBuilder {
public String getPlaceholderText(ASTNode node) {
final IElementType type = node.getElementType();
final PsiElement psi = node.getPsi();
if (psi instanceof ClList) {
final String text = ((ClList) psi).getPresentableText();
return "(" + (text != null ? text + " " : "") + "...)";
}
throw new Error("Unexpected node: " + type + "-->" + node.getText());
}
public boolean isCollapsedByDefault(ASTNode node) {
return false;
}
public FoldingDescriptor[] buildFoldRegions(ASTNode node, Document document) {
touchTree(node);
List<FoldingDescriptor> descriptors = new ArrayList<FoldingDescriptor>();
appendDescriptors(node, descriptors);
return descriptors.toArray(new FoldingDescriptor[descriptors.size()]);
}
/**
* We have to touch the PSI tree to get the folding to show up when we first open a file
*
* @param node given node
*/
private void touchTree(ASTNode node) {
if (node.getElementType() == ClojureElementTypes.FILE) {
node.getPsi().getFirstChild();
}
}
private void appendDescriptors(final ASTNode node, final List<FoldingDescriptor> descriptors) {
if (isFoldableNode(node)) {
descriptors.add(new FoldingDescriptor(node, node.getTextRange()));
}
ASTNode child = node.getFirstChildNode();
while (child != null) {
appendDescriptors(child, descriptors);
child = child.getTreeNext();
}
}
private boolean isFoldableNode(ASTNode node) {
final PsiElement element = node.getPsi();
final IElementType type = node.getElementType();
if (type == LIST && element.getParent() instanceof ClojureFile &&
node.getText().contains("\n") &&
element instanceof ClList) {
return true;
}
return (type == DEF
|| type == DEFMETHOD) &&
node.getText().contains("\n")
;
}
}