package com.redhat.ceylon.eclipse.code.editor;
import static com.redhat.ceylon.eclipse.code.editor.EditorActionIds.SELECT_ENCLOSING;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.text.IRegion;
import org.eclipse.ui.texteditor.ITextEditor;
import com.redhat.ceylon.compiler.typechecker.tree.Node;
import com.redhat.ceylon.compiler.typechecker.tree.Tree.ArgumentList;
import com.redhat.ceylon.compiler.typechecker.tree.Tree.Body;
import com.redhat.ceylon.compiler.typechecker.tree.Tree.CompilationUnit;
import com.redhat.ceylon.compiler.typechecker.tree.Tree.Condition;
import com.redhat.ceylon.compiler.typechecker.tree.Tree.ConditionList;
import com.redhat.ceylon.compiler.typechecker.tree.Tree.ControlClause;
import com.redhat.ceylon.compiler.typechecker.tree.Tree.Expression;
import com.redhat.ceylon.compiler.typechecker.tree.Tree.Identifier;
import com.redhat.ceylon.compiler.typechecker.tree.Tree.ImportMemberOrType;
import com.redhat.ceylon.compiler.typechecker.tree.Tree.ImportMemberOrTypeList;
import com.redhat.ceylon.compiler.typechecker.tree.Tree.ParameterList;
import com.redhat.ceylon.compiler.typechecker.tree.Tree.SpecifierOrInitializerExpression;
import com.redhat.ceylon.compiler.typechecker.tree.Tree.StatementOrArgument;
import com.redhat.ceylon.compiler.typechecker.tree.Tree.Term;
import com.redhat.ceylon.compiler.typechecker.tree.Tree.Type;
import com.redhat.ceylon.compiler.typechecker.tree.Visitor;
class SelectEnclosingAction extends Action {
private CeylonEditor editor;
public SelectEnclosingAction() {
this(null);
}
public SelectEnclosingAction(CeylonEditor editor) {
super("Select Enclosing");
setActionDefinitionId(SELECT_ENCLOSING);
setEditor(editor);
}
private void setEditor(ITextEditor editor) {
if (editor instanceof CeylonEditor) {
this.editor = (CeylonEditor) editor;
}
else {
this.editor = null;
}
setEnabled(this.editor!=null);
}
private static class EnclosingVisitor extends Visitor {
private Node result;
private int startOffset;
private int endOffset;
private EnclosingVisitor(int startOffset, int endOffset) {
this.startOffset = startOffset;
this.endOffset = endOffset;
}
private boolean expandsSelection(Node that) {
Integer nodeStart = that.getStartIndex();
Integer nodeStop = that.getEndIndex();
if (nodeStart!=null && nodeStop!=null) {
return nodeStart<startOffset && nodeStop>=endOffset ||
nodeStart<=startOffset && nodeStop>endOffset;
}
else {
return false;
}
}
@Override
public void visit(CompilationUnit that) {
if (expandsSelection(that)) {
result = that;
}
super.visit(that);
}
@Override
public void visit(Body that) {
if (expandsSelection(that)) {
result = that;
}
super.visit(that);
}
@Override
public void visit(ArgumentList that) {
if (expandsSelection(that)) {
result = that;
}
super.visit(that);
}
@Override
public void visit(ParameterList that) {
if (expandsSelection(that)) {
result = that;
}
super.visit(that);
}
@Override
public void visit(ControlClause that) {
if (expandsSelection(that)) {
result = that;
}
super.visit(that);
}
@Override
public void visit(ConditionList that) {
if (expandsSelection(that)) {
result = that;
}
super.visit(that);
}
@Override
public void visit(Condition that) {
if (expandsSelection(that)) {
result = that;
}
super.visit(that);
}
@Override
public void visit(Type that) {
if (expandsSelection(that)) {
result = that;
}
super.visit(that);
}
@Override
public void visit(Identifier that) {
if (expandsSelection(that)) {
result = that;
}
super.visit(that);
}
@Override
public void visit(Term that) {
if (expandsSelection(that)) {
result = that;
}
super.visit(that);
}
@Override
public void visit(ImportMemberOrTypeList that) {
if (expandsSelection(that)) {
result = that;
}
super.visit(that);
}
@Override
public void visit(ImportMemberOrType that) {
if (expandsSelection(that)) {
result = that;
}
super.visit(that);
}
@Override
public void visit(SpecifierOrInitializerExpression that) {
if (expandsSelection(that)) {
result = that;
}
super.visit(that);
}
@Override
public void visit(Expression that) {
if (expandsSelection(that)) {
result = that;
}
super.visit(that);
}
@Override
public void visit(StatementOrArgument that) {
if (expandsSelection(that)) {
result = that;
}
super.visit(that);
}
}
@Override
public void run() {
IRegion selection = editor.getSelection();
int startOffset = selection.getOffset();
int endOffset = startOffset + selection.getLength();
CompilationUnit rootNode = editor.getParseController().getParsedRootNode();
if (rootNode!=null) {
EnclosingVisitor ev = new EnclosingVisitor(startOffset, endOffset);
ev.visit(rootNode);
Node result = ev.result;
if (result!=null) {
editor.selectAndReveal(result.getStartIndex(),
result.getDistance());
}
}
}
}