/*******************************************************************************
* Copyright (c) 2012 BMW Car IT 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.jnario.feature.ui.editor;
import static org.eclipse.xtext.nodemodel.util.NodeModelUtils.findNodesForFeature;
import static org.eclipse.xtext.nodemodel.util.NodeModelUtils.getNode;
import static org.jnario.util.Strings.countWhitespaceAtEnd;
import java.util.List;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.common.util.TreeIterator;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.xtend.core.xtend.XtendMember;
import org.eclipse.xtend.core.xtend.XtendPackage;
import org.eclipse.xtext.nodemodel.ICompositeNode;
import org.eclipse.xtext.nodemodel.INode;
import org.eclipse.xtext.nodemodel.util.NodeModelUtils;
import org.eclipse.xtext.parser.IParseResult;
import org.eclipse.xtext.resource.XtextResource;
import org.eclipse.xtext.ui.editor.folding.DefaultFoldingRegionProvider;
import org.eclipse.xtext.ui.editor.folding.IFoldingRegionAcceptor;
import org.eclipse.xtext.util.ITextRegion;
import org.eclipse.xtext.xtype.XImportSection;
import org.jnario.feature.feature.Background;
import org.jnario.feature.feature.FeatureFile;
import org.jnario.feature.feature.Scenario;
import org.jnario.feature.feature.Step;
import org.jnario.feature.feature.StepImplementation;
/**
* @author Birgit Engelmann - Initial contribution and API
*/
public class FeatureFoldingRegionProvider extends DefaultFoldingRegionProvider {
protected void computeObjectFolding(XtextResource xtextResource,
IFoldingRegionAcceptor<ITextRegion> foldingRegionAcceptor) {
IParseResult parseResult = xtextResource.getParseResult();
if (parseResult != null) {
EObject rootASTElement = parseResult.getRootASTElement();
if (rootASTElement != null) {
computeObjectFolding(rootASTElement, foldingRegionAcceptor);
TreeIterator<EObject> allContents = rootASTElement
.eAllContents();
while (allContents.hasNext()) {
EObject eObject = allContents.next();
if (isHandled(eObject)) {
computeObjectFolding(eObject, foldingRegionAcceptor);
}
if (!shouldProcessContent(eObject)) {
allContents.prune();
}
}
}
}
}
@Override
protected void computeObjectFolding(EObject eObject,
IFoldingRegionAcceptor<ITextRegion> foldingRegionAcceptor) {
if (eObject instanceof FeatureFile) {
calculateFolding((FeatureFile) eObject, foldingRegionAcceptor);
} else if (eObject instanceof Scenario) {
calculateFolding((Scenario) eObject, foldingRegionAcceptor);
} else if (eObject instanceof StepImplementation) {
calculateFolding((Step) eObject, foldingRegionAcceptor);
} else if (eObject instanceof Background) {
calculateFolding((Background) eObject, foldingRegionAcceptor);
}
}
private void calculateFolding(FeatureFile featureFile,
IFoldingRegionAcceptor<ITextRegion> foldingRegionAcceptor) {
XImportSection importSection = featureFile.getImportSection();
if (importSection == null
|| importSection.getImportDeclarations().isEmpty()) {
return;
}
int begin = 0;
setFoldingRegion(importSection, begin, foldingRegionAcceptor);
}
private void calculateFolding(Scenario scenario,
IFoldingRegionAcceptor<ITextRegion> foldingRegionAcceptor) {
int begin = getBegin(scenario);
EList<XtendMember> members = scenario.getMembers();
XtendMember previous = null;
for (XtendMember xtendMember : members) {
if (xtendMember instanceof Step) {
if (previous != null && getNode(previous) != null) {
setFoldingRegion(previous, begin, foldingRegionAcceptor);
break;
}
} else {
previous = xtendMember;
}
}
}
private void calculateFolding(Step step,
IFoldingRegionAcceptor<ITextRegion> foldingRegionAcceptor) {
List<INode> nodes = findNodesForFeature(step,
XtendPackage.Literals.XTEND_FUNCTION__NAME);
if (nodes.isEmpty()) {
return;
}
INode last = nodes.get(nodes.size() - 1);
int length = last.getLength() - countWhitespaceAtEnd(last.getText());
setFoldingRegion(step.getExpression(), last.getOffset() + length, foldingRegionAcceptor);
}
private int getBegin(EObject object) {
ITextRegion beginRegion = getLocationInFileProvider()
.getSignificantTextRegion(object);
if (beginRegion == null) {
return -1;
}
return beginRegion.getOffset() + beginRegion.getLength() - 1;
}
private void setFoldingRegion(EObject object, int begin,
IFoldingRegionAcceptor<ITextRegion> foldingRegionAcceptor) {
ICompositeNode node = NodeModelUtils.getNode(object);
if (node != null) {
int offset = node.getOffset() + node.getLength() - begin;
foldingRegionAcceptor.accept(begin, offset);
}
}
}