blob: 64633c0e13f72f911c2ef37504ffe6af73c479d5 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2005, 2007 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
*******************************************************************************/
package org.eclipse.dltk.ruby.internal.ui.text.folding;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Stack;
import org.eclipse.core.runtime.ILog;
import org.eclipse.dltk.ast.ASTNode;
import org.eclipse.dltk.ast.declarations.FakeModuleDeclaration;
import org.eclipse.dltk.ast.declarations.MethodDeclaration;
import org.eclipse.dltk.ast.declarations.ModuleDeclaration;
import org.eclipse.dltk.ast.declarations.TypeDeclaration;
import org.eclipse.dltk.ast.parser.ISourceParser;
import org.eclipse.dltk.ruby.core.RubyNature;
import org.eclipse.dltk.ruby.internal.ui.RubyPreferenceConstants;
import org.eclipse.dltk.ruby.internal.ui.RubyUI;
import org.eclipse.dltk.ruby.internal.ui.text.IRubyPartitions;
import org.eclipse.dltk.ruby.internal.ui.text.RubyPartitionScanner;
import org.eclipse.dltk.ui.text.folding.AbstractASTFoldingStructureProvider;
import org.eclipse.dltk.ui.text.folding.DefaultElementCommentResolver;
import org.eclipse.dltk.ui.text.folding.IElementCommentResolver;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.rules.IPartitionTokenScanner;
public class RubyFoldingStructureProvider extends
AbstractASTFoldingStructureProvider {
/* preferences */
private boolean fInitCollapseComments;
private boolean fInitCollapseHeaderComments;
private boolean fInitCollapseMethods;
private IElementCommentResolver fElementCommentResolver = new DefaultElementCommentResolver();
protected void initializePreferences(IPreferenceStore store) {
super.initializePreferences(store);
fFoldNewLines = true;
fCommentsFolding = true;
fInitCollapseComments = store
.getBoolean(RubyPreferenceConstants.EDITOR_FOLDING_INIT_COMMENTS);
fInitCollapseHeaderComments = store
.getBoolean(RubyPreferenceConstants.EDITOR_FOLDING_INIT_HEADER_COMMENTS);
fInitCollapseMethods = store
.getBoolean(RubyPreferenceConstants.EDITOR_FOLDING_INIT_METHODS);
}
protected boolean initiallyCollapse(ASTNode s,
FoldingStructureComputationContext ctx) {
return ctx.allowCollapsing() && s instanceof MethodDeclaration
&& fInitCollapseMethods;
}
protected boolean initiallyCollapseComments(IRegion commentRegion,
FoldingStructureComputationContext ctx) {
if (ctx.allowCollapsing()) {
return isHeaderRegion(commentRegion, ctx) ? fInitCollapseHeaderComments
: fInitCollapseComments;
}
return false;
}
protected boolean mayCollapse(ASTNode s,
FoldingStructureComputationContext ctx) {
return s instanceof MethodDeclaration || s instanceof TypeDeclaration;
}
protected String getCommentPartition() {
return IRubyPartitions.RUBY_COMMENT;
}
protected String getPartition() {
return IRubyPartitions.RUBY_PARTITIONING;
}
protected IPartitionTokenScanner getPartitionScanner() {
return new RubyPartitionScanner();
}
protected String[] getPartitionTypes() {
return IRubyPartitions.RUBY_PARTITION_TYPES;
}
protected String getNatureId() {
return RubyNature.NATURE_ID;
}
protected ILog getLog() {
return RubyUI.getDefault().getLog();
}
protected CodeBlock[] getCodeBlocks(String code, int offset) {
ISourceParser parser = getSourceParser();
ModuleDeclaration decl = parser.parse(null, code.toCharArray(), null);
if (decl instanceof FakeModuleDeclaration) {
return null;
}
return buildCodeBlocks(decl, offset);
}
protected static class RubyFoldingASTVisitor extends FoldingASTVisitor {
static class TypeContainer {
final List children = new ArrayList();
final TypeDeclaration type;
public TypeContainer(TypeDeclaration type) {
this.type = type;
}
}
final Stack types = new Stack();
protected RubyFoldingASTVisitor(int offset) {
super(offset);
types.push(new TypeContainer(null));
}
public boolean visit(TypeDeclaration s) throws Exception {
final TypeContainer child = new TypeContainer(s);
((TypeContainer) types.peek()).children.add(child);
types.push(child);
return visitGeneral(s);
}
public boolean endvisit(TypeDeclaration s) throws Exception {
types.pop();
return super.endvisit(s);
}
private void processType(TypeContainer container, int level,
boolean collapsible) {
if (collapsible) {
add(container.type);
}
for (Iterator i = container.children.iterator(); i.hasNext();) {
final TypeContainer child = (TypeContainer) i.next();
processType(child, level + 1, collapsible
|| (level > 0 && container.children.size() > 1));
}
}
public boolean endvisit(ModuleDeclaration s) throws Exception {
TypeContainer container = (TypeContainer) types.peek();
processType(container, 0, false);
return super.endvisit(s);
}
}
protected FoldingASTVisitor getFoldingVisitor(int offset) {
return new RubyFoldingASTVisitor(0);
}
public IElementCommentResolver getElementCommentResolver() {
return fElementCommentResolver;
}
}