Browse Source

Adjusted scoping to import scope and thereby imported variables and types.

tomqc86@googlemail.com 11 years ago
parent
commit
82fcc92e4c

+ 61 - 20
plugins/org.yakindu.sct.model.stext/src/org/yakindu/sct/model/stext/scoping/ContextPredicateProvider.java

@@ -32,16 +32,30 @@ import static org.yakindu.sct.model.stext.stext.StextPackage.Literals.REACTION_E
 import static org.yakindu.sct.model.stext.stext.StextPackage.Literals.REGULAR_EVENT_SPEC;
 import static org.yakindu.sct.model.stext.stext.StextPackage.Literals.TRANSITION_REACTION;
 import static org.yakindu.sct.model.stext.stext.StextPackage.Literals.TRANSITION_SPECIFICATION;
+import static org.yakindu.sct.model.stext.stext.StextPackage.Literals.VARIABLE_DEFINITION;
+import static org.yakindu.base.types.TypesPackage.Literals.TYPED_ELEMENT__TYPE;
 
+import java.io.IOException;
 import java.util.HashMap;
 import java.util.Map;
 
+import org.eclipse.emf.common.util.URI;
 import org.eclipse.emf.ecore.EClass;
+import org.eclipse.emf.ecore.EObject;
 import org.eclipse.emf.ecore.EReference;
+import org.eclipse.emf.ecore.resource.Resource;
+import org.eclipse.emf.ecore.resource.ResourceSet;
+import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;
+import org.eclipse.emf.ecore.util.EcoreUtil;
 import org.eclipse.xtext.resource.IEObjectDescription;
 import org.eclipse.xtext.util.Pair;
 import org.eclipse.xtext.util.Tuples;
+import org.yakindu.base.types.ComplexType;
+import org.yakindu.base.types.Event;
+import org.yakindu.base.types.Feature;
 import org.yakindu.base.types.TypesPackage;
+import org.yakindu.sct.model.stext.stext.StextPackage;
+import org.yakindu.sct.model.stext.stext.VariableDefinition;
 
 import com.google.common.base.Predicate;
 import com.google.common.base.Predicates;
@@ -53,12 +67,17 @@ import com.google.common.base.Predicates;
  */
 public class ContextPredicateProvider {
 
-	static class FeaturedTypePredicate implements
-			Predicate<IEObjectDescription> {
+	static class TypePredicate implements Predicate<IEObjectDescription> {
+		public boolean apply(IEObjectDescription input) {
+			return TypesPackage.Literals.TYPE.isSuperTypeOf(input.getEClass()) && 
+					!TypesPackage.Literals.TYPE_PARAMETER.isSuperTypeOf(input.getEClass());
+		}
+	}
+	
+	static class FeaturedTypePredicate implements Predicate<IEObjectDescription> {
 		public boolean apply(IEObjectDescription input) {
 			return TypesPackage.Literals.TYPE.isSuperTypeOf(input.getEClass())
-					&& TypesPackage.Literals.FEATURE.isSuperTypeOf(input
-							.getEClass());
+					&& TypesPackage.Literals.FEATURE.isSuperTypeOf(input.getEClass());
 		}
 	}
 
@@ -67,9 +86,37 @@ public class ContextPredicateProvider {
 		public boolean apply(IEObjectDescription input) {
 			if (super.apply(input))
 				return true;
-			return TypesPackage.Literals.EVENT.isSuperTypeOf(input.getEClass());
+			return TypesPackage.Literals.EVENT.isSuperTypeOf(input.getEClass()) || isVariableWithTypeContainingEvent(input);
 		}
 	}
+	
+	private static boolean isVariableWithTypeContainingEvent(IEObjectDescription input) {
+		if (StextPackage.Literals.VARIABLE_DEFINITION.isSuperTypeOf(input.getEClass())) {
+			EObject eObjectOrProxy = input.getEObjectOrProxy();
+			VariableDefinition varDef = (VariableDefinition) eObjectOrProxy;
+			if (eObjectOrProxy.eIsProxy()) {
+				URI uri = input.getEObjectURI().trimFragment();
+				ResourceSet rs = new ResourceSetImpl();
+				Resource res = rs.createResource(uri);
+				try {
+					res.load(null);
+					EObject resolved = EcoreUtil.resolve(eObjectOrProxy, res);
+					varDef = (VariableDefinition) resolved;
+				} catch (IOException e) {
+					e.printStackTrace();
+				}
+			}
+			if (varDef.getType() instanceof ComplexType) {
+				ComplexType complexType = (ComplexType) varDef.getType();
+				for (Feature feature : complexType.getAllFeatures()) {
+					if (feature instanceof Event) {
+						return true;
+					}
+				}
+			}
+		}
+		return false;
+	}
 
 	static class VariablePredicate extends FeaturedTypePredicate {
 		@Override
@@ -119,9 +166,9 @@ public class ContextPredicateProvider {
 	private static final VariablePredicate VARIABLES = new VariablePredicate();
 	private static final EventPredicate EVENTS = new EventPredicate();
 	private static final VariableOperationPredicate VARIABLES_AND_OPERATIONS = new VariableOperationPredicate();
-	public static final VariableOperationEventEnumeratorPredicate VARIABLES_OPERATIONS_EVENTS_ENUMERATORS = new VariableOperationEventEnumeratorPredicate();
-	private static final Predicate<IEObjectDescription> ALL = Predicates
-			.<IEObjectDescription> alwaysTrue();
+	private static final VariableOperationEventEnumeratorPredicate VARIABLES_OPERATIONS_EVENTS_ENUMERATORS = new VariableOperationEventEnumeratorPredicate();
+	private static final TypePredicate TYPES = new TypePredicate();
+	private static final Predicate<IEObjectDescription> ALL = Predicates.<IEObjectDescription> alwaysTrue();
 
 	private final Map<Pair<EClass, EReference>, Predicate<IEObjectDescription>> filter;
 
@@ -140,10 +187,7 @@ public class ContextPredicateProvider {
 
 	protected void initMap() {
 		filter.put(key(ASSIGNMENT_EXPRESSION), VARIABLES_OPERATIONS_EVENTS_ENUMERATORS);
-		filter.put(
-				key(ASSIGNMENT_EXPRESSION, ASSIGNMENT_EXPRESSION__EXPRESSION),
-				ALL);
-
+		filter.put(key(ASSIGNMENT_EXPRESSION, ASSIGNMENT_EXPRESSION__EXPRESSION), ALL);
 		filter.put(key(CONDITIONAL_EXPRESSION), VARIABLES_AND_OPERATIONS);
 		filter.put(key(LOGICAL_OR_EXPRESSION), VARIABLES_OPERATIONS_EVENTS_ENUMERATORS);
 		filter.put(key(LOGICAL_AND_EXPRESSION), VARIABLES_OPERATIONS_EVENTS_ENUMERATORS);
@@ -152,16 +196,12 @@ public class ContextPredicateProvider {
 		filter.put(key(BITWISE_OR_EXPRESSION), VARIABLES);
 		filter.put(key(BITWISE_AND_EXPRESSION), VARIABLES);
 		filter.put(key(SHIFT_EXPRESSION), VARIABLES);
-		filter.put(key(LOGICAL_RELATION_EXPRESSION),
-				VARIABLES_OPERATIONS_EVENTS_ENUMERATORS);
-		filter.put(key(NUMERICAL_ADD_SUBTRACT_EXPRESSION),
-				VARIABLES_AND_OPERATIONS);
-		filter.put(key(NUMERICAL_MULTIPLY_DIVIDE_EXPRESSION),
-				VARIABLES_AND_OPERATIONS);
+		filter.put(key(LOGICAL_RELATION_EXPRESSION), VARIABLES_OPERATIONS_EVENTS_ENUMERATORS);
+		filter.put(key(NUMERICAL_ADD_SUBTRACT_EXPRESSION), VARIABLES_AND_OPERATIONS);
+		filter.put(key(NUMERICAL_MULTIPLY_DIVIDE_EXPRESSION), VARIABLES_AND_OPERATIONS);
 		filter.put(key(NUMERICAL_UNARY_EXPRESSION), VARIABLES_AND_OPERATIONS);
 		filter.put(key(EVENT_RAISING_EXPRESSION), EVENTS);
-		filter.put(
-				key(EVENT_RAISING_EXPRESSION, EVENT_RAISING_EXPRESSION__VALUE),
+		filter.put(key(EVENT_RAISING_EXPRESSION, EVENT_RAISING_EXPRESSION__VALUE),
 				VARIABLES_OPERATIONS_EVENTS_ENUMERATORS);
 		filter.put(key(REGULAR_EVENT_SPEC), EVENTS);
 		filter.put(key(EVENT_VALUE_REFERENCE_EXPRESSION), EVENTS);
@@ -169,6 +209,7 @@ public class ContextPredicateProvider {
 		filter.put(key(TRANSITION_SPECIFICATION), EVENTS);
 		filter.put(key(LOCAL_REACTION), VARIABLES_AND_OPERATIONS);
 		filter.put(key(TRANSITION_REACTION), VARIABLES_AND_OPERATIONS);
+		filter.put(key(VARIABLE_DEFINITION, TYPED_ELEMENT__TYPE), TYPES);
 	}
 
 	public Predicate<IEObjectDescription> getPredicate(EClass clazz,

+ 69 - 36
plugins/org.yakindu.sct.model.stext/src/org/yakindu/sct/model/stext/scoping/STextScopeProvider.java

@@ -11,10 +11,7 @@
  */
 package org.yakindu.sct.model.stext.scoping;
 
-import java.util.ArrayList;
-import java.util.HashSet;
 import java.util.List;
-import java.util.Set;
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
@@ -23,13 +20,17 @@ import org.eclipse.emf.ecore.EObject;
 import org.eclipse.emf.ecore.EReference;
 import org.eclipse.emf.ecore.util.EcoreUtil;
 import org.eclipse.xtext.EcoreUtil2;
+import org.eclipse.xtext.naming.IQualifiedNameConverter;
+import org.eclipse.xtext.naming.QualifiedName;
 import org.eclipse.xtext.resource.IEObjectDescription;
 import org.eclipse.xtext.scoping.IScope;
 import org.eclipse.xtext.scoping.Scopes;
 import org.eclipse.xtext.scoping.impl.AbstractDeclarativeScopeProvider;
 import org.eclipse.xtext.scoping.impl.FilteringScope;
+import org.eclipse.xtext.scoping.impl.ImportNormalizer;
 import org.eclipse.xtext.scoping.impl.SimpleScope;
 import org.eclipse.xtext.util.PolymorphicDispatcher.ErrorHandler;
+import org.eclipse.xtext.util.Strings;
 import org.yakindu.base.expressions.expressions.ElementReferenceExpression;
 import org.yakindu.base.expressions.expressions.Expression;
 import org.yakindu.base.expressions.expressions.FeatureCall;
@@ -37,12 +38,12 @@ import org.yakindu.base.types.ComplexType;
 import org.yakindu.base.types.EnumerationType;
 import org.yakindu.base.types.Feature;
 import org.yakindu.base.types.ITypeSystem;
-import org.yakindu.base.types.Type;
 import org.yakindu.base.types.TypeSystemUtils;
 import org.yakindu.sct.model.sgraph.SGraphPackage;
 import org.yakindu.sct.model.sgraph.Scope;
 import org.yakindu.sct.model.sgraph.Statechart;
 import org.yakindu.sct.model.stext.scoping.ContextPredicateProvider.EmptyPredicate;
+import org.yakindu.sct.model.stext.stext.ImportScope;
 import org.yakindu.sct.model.stext.stext.InterfaceScope;
 import org.yakindu.sct.model.stext.stext.InternalScope;
 
@@ -107,14 +108,31 @@ public class STextScopeProvider extends AbstractDeclarativeScopeProvider {
 	@Inject
 	private ContextPredicateProvider predicateProvider;
 
+	/**
+	 * Scoping for types and taking imported namespaces into account e.g. in variable declarations. 
+	 */
+	public IScope scope_TypedElement_type(final EObject context, EReference reference) {
+		Statechart statechart = getStatechart(context);
+		EList<Scope> scopes = statechart.getScopes();
+		IScope scope = retrieveImportScope(context, reference, scopes);
+		
+		Predicate<IEObjectDescription> predicate = calculateFilterPredicate(context, reference);
+		return new FilteringScope(scope, predicate);
+	}
+	
 	public IScope scope_ElementReferenceExpression_reference(final EObject context, EReference reference) {
 		IScope namdScope = getNamedTopLevelScope(context, reference);
 		IScope unnamedScope = getUnnamedTopLevelScope(context, reference);
+		
+		// XXX: filter on EVENT is too restrictive because also variable definitions should be usable
 		Predicate<IEObjectDescription> predicate = calculateFilterPredicate(context, reference);
 		unnamedScope = new FilteringScope(unnamedScope, predicate);
+		
 		// add enum types
-		return new SimpleScope(Iterables.concat(namdScope.getAllElements(), unnamedScope.getAllElements(), Scopes
+		IScope scope = new SimpleScope(Iterables.concat(namdScope.getAllElements(), unnamedScope.getAllElements(), Scopes
 				.scopeFor(typeSystemUtils.getEnumerationTypes(typeSystem)).getAllElements()));
+		
+		return scope;
 	}
 
 	public IScope scope_FeatureCall_feature(final FeatureCall context, EReference reference) {
@@ -139,7 +157,7 @@ public class STextScopeProvider extends AbstractDeclarativeScopeProvider {
 		}
 
 		if (element instanceof ComplexType) {
-			scope = Scopes.scopeFor(allFeatures((Type) element), scope);
+			scope = Scopes.scopeFor(((ComplexType)element).getAllFeatures(), scope);
 			scope = new FilteringScope(scope, predicate);
 		}
 
@@ -148,8 +166,8 @@ public class STextScopeProvider extends AbstractDeclarativeScopeProvider {
 			scope = new FilteringScope(scope, predicate);
 		}
 
-		if (element instanceof Feature) {
-			scope = Scopes.scopeFor(allFeatures(((Feature) element).getType()), scope);
+		if (element instanceof Feature && ((Feature)element).getType() instanceof ComplexType) {
+			scope = Scopes.scopeFor(((ComplexType)((Feature)element).getType()).getAllFeatures(), scope);
 			scope = new FilteringScope(scope, predicate);
 		}
 
@@ -191,6 +209,27 @@ public class STextScopeProvider extends AbstractDeclarativeScopeProvider {
 		return Scopes.scopeFor(scopeCandidates);
 	}
 
+	@Inject
+	private IQualifiedNameConverter qualifiedNameConverter;
+
+	protected ImportNormalizer createImportedNamespaceResolver(final String namespace, boolean ignoreCase) {
+		if (Strings.isEmpty(namespace))
+			return null;
+		QualifiedName importedNamespace = qualifiedNameConverter.toQualifiedName(namespace);
+		if (importedNamespace == null || importedNamespace.getSegmentCount() < 1) {
+			return null;
+		}
+		boolean hasWildCard = ignoreCase ? importedNamespace.getLastSegment().equalsIgnoreCase("*") : importedNamespace
+				.getLastSegment().equals("*");
+		if (hasWildCard) {
+			if (importedNamespace.getSegmentCount() <= 1)
+				return null;
+			return new ImportNormalizer(importedNamespace.skipLast(1), true, ignoreCase);
+		} else {
+			return new ImportNormalizer(importedNamespace, false, ignoreCase);
+		}
+	}
+
 	/**
 	 * Returns a scope with all toplevel declarations of unnamed scope
 	 */
@@ -210,13 +249,32 @@ public class STextScopeProvider extends AbstractDeclarativeScopeProvider {
 				scopeCandidates.addAll(scope.getDeclarations());
 			}
 		}
-		return Scopes.scopeFor(scopeCandidates);
+		
+		// Add import scope
+		IScope scope = retrieveImportScope(context, reference, scopes);
+		return Scopes.scopeFor(scopeCandidates, scope);
+	}
+
+	private IScope retrieveImportScope(final EObject context, EReference reference, EList<Scope> scopes) {
+		IScope scope = getDelegate().getScope(context, reference);
+		Iterable<ImportScope> filter = Iterables.filter(scopes, ImportScope.class);
+		if (Iterables.size(filter) > 0) {
+			List<ImportNormalizer> normalizers = Lists.newArrayList();
+			for (ImportScope importScope : filter) {
+				EList<org.yakindu.sct.model.stext.stext.Import> imports = importScope.getImports();
+				for (org.yakindu.sct.model.stext.stext.Import import1 : imports) {
+					normalizers.add(createImportedNamespaceResolver(import1.getImportedNamespace(), false));
+				}
+			}
+			scope = new org.eclipse.xtext.scoping.impl.ImportScope(normalizers, scope, null,
+					reference.getEReferenceType(), false);
+		}
+		return scope;
 	}
 
 	/**
 	 * Returns the {@link Statechart} for a context element
 	 */
-
 	protected Statechart getStatechart(EObject context) {
 		final ContextElementAdapter provider = (ContextElementAdapter) EcoreUtil.getExistingAdapter(
 				context.eResource(), ContextElementAdapter.class);
@@ -228,30 +286,5 @@ public class STextScopeProvider extends AbstractDeclarativeScopeProvider {
 					SGraphPackage.Literals.STATECHART);
 		}
 	}
+}
 
-	/**
-	 * Returns all features including super features for the given type
-	 */
-	protected List<Feature> allFeatures(Type type) {
-		List<Feature> features = new ArrayList<Feature>();
-		collectFeatures(type, features, new HashSet<Type>());
-		return features;
-	}
-
-	/**
-	 * Performs a simple search to collect all features of the type and all
-	 * super types.
-	 * 
-	 */
-	protected void collectFeatures(Type type, List<Feature> features, Set<Type> visited) {
-		if (type == null || visited.contains(type))
-			return;
-		if (type instanceof ComplexType) {
-			for (Type superType : ((ComplexType) type).getSuperTypes()) {
-				collectFeatures(superType, features, visited);
-			}
-			features.addAll(((ComplexType) type).getFeatures());
-		}
-		visited.add(type);
-	}
-}