[461316] Find variables declared by preceding siblings operations

Bug: 461316
Change-Id: I4bc2ea0f10d7d5d7441e10e48141d4d40ae177b2
Signed-off-by: Cedric Brun <cedric.brun@obeo.fr>
diff --git a/plugins/org.eclipse.sirius/src/org/eclipse/sirius/business/api/dialect/description/AbstractInterpretedExpressionQuery.java b/plugins/org.eclipse.sirius/src/org/eclipse/sirius/business/api/dialect/description/AbstractInterpretedExpressionQuery.java
index 3f0aaa5..bc1bfb2 100644
--- a/plugins/org.eclipse.sirius/src/org/eclipse/sirius/business/api/dialect/description/AbstractInterpretedExpressionQuery.java
+++ b/plugins/org.eclipse.sirius/src/org/eclipse/sirius/business/api/dialect/description/AbstractInterpretedExpressionQuery.java
@@ -16,6 +16,7 @@
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
+import org.eclipse.emf.common.util.EList;
 import org.eclipse.emf.ecore.EAnnotation;
 import org.eclipse.emf.ecore.EObject;
 import org.eclipse.emf.ecore.EPackage;
@@ -294,13 +295,14 @@
      */
     private void collectContextualVariableDefinitions(Map<String, String> vars, EObject top, EObject bottom) {
         // A map with multiple values is not strictly required as we only use
-        // one value, but it is useful when debugging to have all the information.
+        // one value, but it is useful when debugging to have all the
+        // information.
         Map<String, Collection<String>> definitions = Maps.newHashMap();
         // Walk up from bottom to top and gather every definition in the scope.
         EObject context = bottom;
         do {
             appendAllLocalVariableDefinitions(definitions, context);
-            context = context.eContainer();
+            context = precedingSiblingOrContainer(context);
         } while (context != null && context != top.eContainer());
         // Merge all the definitions, by taking the one closest to
         // <code>bottom</code> when there are multiple ones.
@@ -309,6 +311,33 @@
         }
     }
 
+    private EObject precedingSiblingOrContainer(EObject context) {
+        EObject container = context.eContainer();
+        EStructuralFeature containingFeature = context.eContainingFeature();
+        if (container != null && containingFeature != null) {
+            Object val = container.eGet(containingFeature);
+            /*
+             * if val is not a collection then we have no siblings.
+             */
+            if (val instanceof EList<?>) {
+                EList<?> childs = (EList<?>) val;
+                int contextPositionInContainingList = childs.indexOf(context);
+                if (contextPositionInContainingList > 0) {
+                    /*
+                     * we have at least one sibling, we return the closest one
+                     * to our position going upward.
+                     */
+                    Object sibling = childs.get(contextPositionInContainingList - 1);
+                    if (sibling instanceof EObject) {
+                        return (EObject)sibling;
+                    }
+                }
+            }
+        }
+
+        return container;
+    }
+
     /**
      * Returns the name of the type of the given variable, as defined in the
      * meta-model annotations.