summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKarsten Thoms2016-02-02 16:13:35 -0500
committerKarsten Thoms2016-02-02 16:13:35 -0500
commitc9519b7ce570dd1213b9b3e15fa31174e10f398a (patch)
treeb7427387d22f24798b03223eb9f2a174e665a77c
parent92a94d7b8671814bb5e86f4ae3b2bce7c7518e79 (diff)
downloadorg.eclipse.xpand-c9519b7ce570dd1213b9b3e15fa31174e10f398a.tar.gz
org.eclipse.xpand-c9519b7ce570dd1213b9b3e15fa31174e10f398a.tar.xz
org.eclipse.xpand-c9519b7ce570dd1213b9b3e15fa31174e10f398a.zip
[465802] Improved breakpoint support in Xtend files
Change-Id: If9a92704752282de1a658d4aa68debb62ed2b624 Signed-off-by: Karsten Thoms <karsten.thoms@itemis.de>
-rw-r--r--plugins/org.eclipse.xtend.ui/src/org/eclipse/xtend/ui/debug/ExpressionPluginAdapter.java291
1 files changed, 168 insertions, 123 deletions
diff --git a/plugins/org.eclipse.xtend.ui/src/org/eclipse/xtend/ui/debug/ExpressionPluginAdapter.java b/plugins/org.eclipse.xtend.ui/src/org/eclipse/xtend/ui/debug/ExpressionPluginAdapter.java
index 7d06f592..075d1b60 100644
--- a/plugins/org.eclipse.xtend.ui/src/org/eclipse/xtend/ui/debug/ExpressionPluginAdapter.java
+++ b/plugins/org.eclipse.xtend.ui/src/org/eclipse/xtend/ui/debug/ExpressionPluginAdapter.java
@@ -15,9 +15,11 @@ import static org.eclipse.internal.xtend.expression.debug.ExpressionElementAdapt
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
+import java.util.Stack;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
@@ -34,6 +36,7 @@ import org.eclipse.internal.xtend.expression.ast.BooleanOperation;
import org.eclipse.internal.xtend.expression.ast.Case;
import org.eclipse.internal.xtend.expression.ast.Cast;
import org.eclipse.internal.xtend.expression.ast.ChainExpression;
+import org.eclipse.internal.xtend.expression.ast.CollectionExpression;
import org.eclipse.internal.xtend.expression.ast.Expression;
import org.eclipse.internal.xtend.expression.ast.FeatureCall;
import org.eclipse.internal.xtend.expression.ast.ISyntaxElement;
@@ -120,6 +123,8 @@ public class ExpressionPluginAdapter implements PluginAdapter {
public IBreakpoint checkBreakpoints(IBreakpoint[] bps, IResource resource, int start, int end, int line) throws CoreException {
ISyntaxElement element = findElementForPosition(resource, start, line);
+ if(element == null) return null;
+
for (IBreakpoint bp1 : bps) {
MWEBreakpoint bp = (MWEBreakpoint) bp1;
if (bp.getResource().equals(resource.getFullPath().toString())
@@ -145,158 +150,196 @@ public class ExpressionPluginAdapter implements PluginAdapter {
} else if (body instanceof LetExpression) {
return getContainingElementOfLetExpression((LetExpression) body,
position);
+ } else if (body instanceof IfExpression) {
+ return getContainingElementOfIfExpression((IfExpression) body, position);
} else
- return body;
+ return getContainingElement((SyntaxElement)body,position);
}
- private boolean contains(final ISyntaxElement elem, final int position) {
- return elem.getStart() <= position && elem.getEnd() >= position;
+ private boolean containsPosition(final ISyntaxElement elem, final int position) {
+ return elem.getStart() <= position && elem.getEnd() > position;
+ }
+
+ /**
+ * @since 2.2
+ */
+ protected int shiftPositionIfInside(final int currentPosition,
+ final SyntaxElement lowerBound, final SyntaxElement upperBound) {
+ return currentPosition >= lowerBound.getStart()
+ && currentPosition <= upperBound.getStart() ? upperBound
+ .getStart() : currentPosition;
}
- private ISyntaxElement getContainingElement(final SyntaxElement se, final int position) {
- if (se instanceof ChainExpression)
+ /**
+ * @since 2.2
+ */
+ protected ISyntaxElement getContainingElement(final SyntaxElement se, final int position) {
+ if (!containsPosition(se, position)) return null;
+
+ if ( se instanceof ChainExpression )
return getContainingElementOfChainExpression((ChainExpression) se, position);
- else if (se instanceof LetExpression) {
+ else if ( se instanceof LetExpression ) {
return getContainingElementOfLetExpression((LetExpression) se, position);
- } else if (se instanceof SwitchExpression) {
+ } else if ( se instanceof SwitchExpression ) {
return getContainingElementOfSwitchExpression((SwitchExpression) se, position);
- } else if (se instanceof ListLiteral) {
+ } else if ( se instanceof ListLiteral ) {
return getContainingElementOfListLiteral((ListLiteral) se, position);
- } else if (se instanceof IfExpression) {
- return getContainingElementOfIfExpression((IfExpression) se, position);
+ } else if ( se instanceof IfExpression ) {
+ return getContainingElementOfIfExpression((IfExpression) se, position );
+ } else if ( se instanceof CollectionExpression ) {
+ return getContainingElementOfCollectionExpression((CollectionExpression)se, position);
+ } else if ( se instanceof BooleanOperation ) {
+ return getContainingElementOfBooleanOperation( (BooleanOperation)se, position );
+ } else if ( se instanceof FeatureCall ) {
+ return getContainingElementOfFeatureCall( (FeatureCall)se, position );
}
- if (contains(se, position))
- return se;
-
return null;
}
-
- private ISyntaxElement getContainingElementOfLetExpression(final LetExpression le, int position) {
+
+ /**
+ * @since 2.2
+ */
+ protected ISyntaxElement getContainingChild(final SyntaxElement parent, final Collection<SyntaxElement> children, int position) {
+ if(!containsPosition(parent, position)) return null;
+
ISyntaxElement result = null;
-
- // if bp is in "let varname = "varexpr ... we have to shift start and
- // end.
- position = shiftPositionIfInside(position, le, le.getVarExpression());
-
- result = getContainingElement(le.getVarExpression(), position);
- if (result != null)
- return result;
-
- result = getContainingElement(le.getTargetExpression(), position);
- if (result != null)
- return result;
-
- return null;
+ int newPosition = position;
+ SyntaxElement lastElem = parent;
+ for( SyntaxElement child : children) {
+ if( child == null ) continue;
+ fixBoundaries(child);
+ if( child.getEnd()==0 ) {
+ System.out.println(child.getClass().getSimpleName() + " " + child.toString());
+ }
+
+ newPosition = shiftPositionIfInside(newPosition, lastElem, child);
+
+ result = getContainingElement(child, newPosition);
+ if(result != null) return result;
+ lastElem = child;
+ }
+
+ return parent;
+ }
+
+ private ISyntaxElement getContainingElementOfLetExpression(final LetExpression le, int position) {
+ List<SyntaxElement> children = new ArrayList<SyntaxElement>();
+ children.add(le.getVarExpression());
+ children.add(le.getTargetExpression());
+ return getContainingChild(le, children, position);
}
private ISyntaxElement getContainingElementOfIfExpression(final IfExpression ie, int position) {
- ISyntaxElement result = null;
-
- // if bp is in "if( expr ) "... we have to shift start and end.
- position = shiftPositionIfInside(position, ie, ie.getCondition());
-
- result = getContainingElement(ie.getCondition(), position);
- if (result != null)
- return result;
-
- result = getContainingElement(ie.getThenPart(), position);
- if (result != null)
- return result;
-
- if (ie.getElsePart() != null) {
- result = getContainingElement(ie.getElsePart(), position);
- if (result != null)
- return result;
+ List<SyntaxElement> children = new ArrayList<SyntaxElement>();
+ children.add(ie.getCondition());
+ children.add(ie.getThenPart());
+ children.add(ie.getElsePart());
+ return getContainingChild(ie, children, position);
+ }
+
+ private ISyntaxElement getContainingElementOfCollectionExpression(final CollectionExpression ce, int position ) {
+ List<SyntaxElement> children = new ArrayList<SyntaxElement>();
+ children.add(ce.getClosure());
+ return getContainingChild(ce, children, position);
+ }
+
+ private SyntaxElement fixBoundaries(SyntaxElement e) {
+ if( !( e.getStart() == 0 && e.getEnd() == 0) )
+ return e;
+
+ if( e instanceof BooleanOperation ) {
+ BooleanOperation be = (BooleanOperation)e;
+ SyntaxElement l = fixBoundaries(be.getLeft());
+ SyntaxElement r = fixBoundaries(be.getRight());
+ be.setLine(l.getLine());
+ be.setStart(l.getStart());
+ be.setEnd(r.getEnd());
}
-
- return null;
+
+ return e;
}
-
- private int shiftPositionIfInside(final int currentPosition,
- final SyntaxElement lowerBound, final SyntaxElement upperBound) {
- return lowerBound.getLine() == upperBound.getLine()
- && currentPosition >= lowerBound.getStart()
- && currentPosition <= upperBound.getStart() ? upperBound
- .getStart() : currentPosition;
+
+ private ISyntaxElement getContainingElementOfBooleanOperation( final BooleanOperation be, int position ) {
+ fixBoundaries(be);
+
+ List<SyntaxElement> children = new ArrayList<SyntaxElement>();
+ children.add(be.getLeft());
+ children.add(be.getRight());
+ return getContainingChild(be, children, position);
}
-
- private ISyntaxElement getContainingElementOfListLiteral(final ListLiteral ll, int position) {
-
- List<Expression> list = ll.getElementsAsList();
-
- // if bp is in "{ "... we have to shift start and end.
- if (list.size() > 0) {
- Expression firstElem = list.get(0);
- if (ll.getStart() <= position && firstElem.getStart() > position) {
- position = firstElem.getStart();
+
+ private ISyntaxElement getContainingElementOfFeatureCall( final FeatureCall fe, int position ) {
+ if(!containsPosition(fe,position))
+ return null;
+
+ Stack<FeatureCall> fcStack = new Stack<FeatureCall>();
+ Expression e = fe;
+ do {
+ FeatureCall fc = (FeatureCall)e;
+ fcStack.push(fc);
+ e = fc.getTarget();
+ } while( e instanceof FeatureCall );
+
+ FeatureCall fallback = fcStack.peek();
+
+ while( !fcStack.isEmpty() ) {
+ FeatureCall fc = fcStack.pop();
+ if(fc instanceof OperationCall) {
+ ISyntaxElement result = getContainingElementOfOperationCall((OperationCall)fc, position);
+ if(result != null)
+ return result;
+ } else if( fc instanceof CollectionExpression) {
+ if(containsPosition(fc, position) ) return getContainingElement(((CollectionExpression)fc).getClosure(),position);
}
}
-
- for (Expression item : list) {
- ISyntaxElement result = getContainingElement(item, position);
- if (result != null)
- return result;
+
+ return fallback;
+ }
+
+ private ISyntaxElement getContainingElementOfOperationCall( final OperationCall oe, int position ) {
+ if(isFunctionCall(oe)) return oe;
+ List<SyntaxElement> children = new ArrayList<SyntaxElement>(oe.getParamsAsList());
+ return getContainingChild(oe, children, position);
+ }
+
+ private boolean isFunctionCall(OperationCall op) {
+ char[] name = op.getName().toString().toCharArray();
+
+ if( name.length == 0 ) return false;
+
+ for( int i=0; i<name.length; i++ ) {
+ if(i==0) {
+ if(!Character.isJavaIdentifierStart(name[i])) return false;
+ } else{
+ if(!Character.isJavaIdentifierPart(name[i])) return false;
+ }
}
+
+ return true;
+ }
- return null;
+ private ISyntaxElement getContainingElementOfListLiteral(final ListLiteral ll, int position) {
+ List<SyntaxElement> children = new ArrayList<SyntaxElement>(ll.getElementsAsList());
+ return getContainingChild(ll, children, position);
}
private ISyntaxElement getContainingElementOfSwitchExpression(final SwitchExpression se, int position) {
- ISyntaxElement result = null;
-
- Expression firstCaseExpression;
- // if bp is in "switch(expr) { case expr: "... we have to shift start
- // and end.
- if (se.getCases().size() > 0)
- firstCaseExpression = se.getCases().get(0).getThenPart();
- else
- firstCaseExpression = se.getDefaultExpr();
-
- position = shiftPositionIfInside(position, se, firstCaseExpression);
-
+ List<SyntaxElement> children = new ArrayList<SyntaxElement>();
+ children.add(se.getSwitchExpr());
for (Case caze : se.getCases()) {
- result = getContainingElement(caze.getThenPart(), position);
- if (result != null)
- return result;
+ children.add(caze.getCondition());
+ children.add(caze.getThenPart());
}
- result = getContainingElement(se.getDefaultExpr(), position);
- if (result != null)
- return result;
-
- return null;
+ children.add(se.getDefaultExpr());
+ return getContainingChild(se, children, position);
}
private ISyntaxElement getContainingElementOfChainExpression(final ChainExpression ce, final int position) {
-
- ISyntaxElement result = null;
- result = getRootOperationCall(getContainingElement(ce.getFirst(), position));
- if (result != null)
- return result;
-
- result = getRootOperationCall(getContainingElement(ce.getNext(), position));
- if (result != null)
- return result;
-
- return null;
- }
-
- /**
- * returns the first operationcall of a call chain ie: for fn3 of
- * a.b.fn1().fn2().fn3() this will return fn1().
- */
- private ISyntaxElement getRootOperationCall(final ISyntaxElement element) {
- ISyntaxElement result = element;
-
- if (element instanceof OperationCall) {
- Expression target = ((OperationCall) element).getTarget();
- while (target != null && target instanceof OperationCall) {
- result = target;
- target = ((OperationCall) target).getTarget();
- }
- }
-
- return result;
+ List<SyntaxElement> children = new ArrayList<SyntaxElement>();
+ children.add(ce.getFirst());
+ children.add(ce.getNext());
+ return getContainingChild(ce, children, position);
}
/**
@@ -307,7 +350,7 @@ public class ExpressionPluginAdapter implements PluginAdapter {
IXtendXpandResource file = getXtendXpandResource(resource);
List<ISyntaxElement> elems = collectFirstLevelElements(file);
for (ISyntaxElement elem : elems)
- if (contains(elem, position))
+ if (containsPosition(elem, position))
return elem;
return null;
@@ -348,8 +391,10 @@ public class ExpressionPluginAdapter implements PluginAdapter {
return result;
}
-
- private ISyntaxElement getBodyOfRootElement(final ISyntaxElement elem) {
+ /**
+ * @since 2.2
+ */
+ protected ISyntaxElement getBodyOfRootElement(final ISyntaxElement elem) {
if (elem instanceof ExpressionExtensionStatement)
return ((ExpressionExtensionStatement) elem).getExpression();
else if (elem instanceof CreateExtensionStatement)