Jelajahi Sumber

Added xtext validations and refactoring of STextProposalProvider.

markus.muehlbrandt@itemis.de 14 tahun lalu
induk
melakukan
2864c0a70a

+ 112 - 4
plugins/org.yakindu.sct.model.stext.ui/src/org/yakindu/sct/model/stext/ui/contentassist/STextProposalProvider.java

@@ -1,11 +1,119 @@
-/*
-* generated by Xtext
-*/
+/**
+ * Copyright (c) 2011 itemis AG 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
+ * 
+ * Contributors:
+ * 	itemis AG - initial API and implementation
+ * 
+ */
 package org.yakindu.sct.model.stext.ui.contentassist;
 
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.emf.common.util.EList;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.xtext.EnumLiteralDeclaration;
+import org.eclipse.xtext.Keyword;
+import org.eclipse.xtext.ui.editor.contentassist.ContentAssistContext;
+import org.eclipse.xtext.ui.editor.contentassist.ICompletionProposalAcceptor;
+import org.yakindu.sct.model.stext.services.STextGrammarAccess;
+import org.yakindu.sct.model.stext.stext.InterfaceScope;
+import org.yakindu.sct.model.stext.stext.InternalScope;
+import org.yakindu.sct.model.stext.stext.SimpleScope;
+import org.yakindu.sct.model.stext.stext.StatechartDefinition;
+import org.yakindu.sct.model.stext.stext.TransitionReaction;
+
+import com.google.inject.Inject;
+
 /**
- * see http://www.eclipse.org/Xtext/documentation/latest/xtext.html#contentAssist on how to customize content assistant
+ * Several filters to make proposals more useful.
+ * 
+ * @author muehlbrandt
  */
 public class STextProposalProvider extends AbstractSTextProposalProvider {
 
+	@Inject
+	private STextGrammarAccess grammarAccess;
+
+	/**
+	 * Validates if a keyword should be viewed by the proposal view.
+	 * 
+	 * Builds dependent on the ContentAssistContext a list with keywords which
+	 * shouldn't be displayed by the proposal view.
+	 */
+	@Override
+	public void completeKeyword(Keyword keyword,
+			ContentAssistContext contentAssistContext,
+			ICompletionProposalAcceptor acceptor) {
+		List<Keyword> keywords = new ArrayList<Keyword>();
+		// context Transition
+		if (contentAssistContext.getRootModel() instanceof TransitionReaction) {
+			keywords.addAll(getKeywords(grammarAccess.getEntryEventAccess()
+					.getGroup().eContents()));
+			keywords.addAll(getKeywords(grammarAccess.getExitEventAccess()
+					.getGroup().eContents()));
+			keywords.addAll(getKeywords(grammarAccess.getOnCycleEventAccess()
+					.getGroup().eContents()));
+			keywords.addAll(getKeywords(grammarAccess.getAlwaysEventAccess()
+					.getGroup().eContents()));
+		}
+		// context States
+		else if (contentAssistContext.getRootModel() instanceof SimpleScope) {
+			keywords.addAll(getKeywords(grammarAccess
+					.getVariableDefinitionAccess().getGroup().eContents()));
+			keywords.addAll(getKeywords(grammarAccess
+					.getEventDefinitionAccess().getGroup().eContents()));
+			keywords.addAll(getKeywords(grammarAccess.getExitpointAccess()
+					.getGroup().eContents()));
+			keywords.addAll(getKeywords(grammarAccess.getEntrypointAccess()
+					.getGroup().eContents()));
+			keywords.addAll(getKeywords(grammarAccess.getDirectionAccess()
+					.getAlternatives().eContents()));
+		}
+		// context Statechart
+		else if (contentAssistContext.getRootModel() instanceof StatechartDefinition) {
+			keywords.addAll(getKeywords(grammarAccess.getExitEventAccess()
+					.getGroup().eContents()));
+			keywords.addAll(getKeywords(grammarAccess.getEntryEventAccess()
+					.getGroup().eContents()));
+		}
+
+		if (contentAssistContext.getCurrentModel() instanceof InterfaceScope) {
+			keywords.addAll(getKeywords(grammarAccess.getLocalReactionAccess()
+					.getGroup().eContents()));
+			keywords.addAll(getKeywords(grammarAccess.getAlwaysEventAccess()
+					.getGroup().eContents()));
+			keywords.addAll(getKeywords(grammarAccess.getClockAccess()
+					.getGroup().eContents()));
+			keywords.addAll(getKeywords(grammarAccess.getOnCycleEventAccess()
+					.getGroup().eContents()));
+			keywords.addAll(getKeywords(grammarAccess.getTimeEventTypeAccess()
+					.getAlternatives().eContents()));
+		}
+
+		if (contentAssistContext.getCurrentModel() instanceof InternalScope) {
+			keywords.addAll(getKeywords(grammarAccess.getDirectionAccess()
+					.getAlternatives().eContents()));
+		}
+
+		if (!keywords.contains(keyword)) {
+			super.completeKeyword(keyword, contentAssistContext, acceptor);
+		}
+	}
+
+	private List<Keyword> getKeywords(EList<EObject> list) {
+		final List<Keyword> keywords = new ArrayList<Keyword>();
+		for (EObject eObject : list) {
+			if (eObject instanceof Keyword) {
+				keywords.add((Keyword) eObject);
+			} else if (eObject instanceof EnumLiteralDeclaration) {
+				keywords.add(((EnumLiteralDeclaration) eObject).getLiteral());
+			}
+		}
+		return keywords;
+	}
 }

+ 101 - 11
plugins/org.yakindu.sct.model.stext/src/org/yakindu/sct/model/stext/validation/STextJavaValidator.java

@@ -1,28 +1,118 @@
+/**
+ * Copyright (c) 2011 itemis AG 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
+ * 
+ * Contributors:
+ * 	itemis AG - initial API and implementation
+ * 
+ */
 package org.yakindu.sct.model.stext.validation;
 
-import org.eclipse.emf.common.util.EList;
+import org.eclipse.emf.ecore.EObject;
 import org.eclipse.xtext.validation.Check;
 import org.eclipse.xtext.validation.CheckType;
-import org.yakindu.sct.model.sgraph.Trigger;
-import org.yakindu.sct.model.stext.stext.BuiltinEventSpec;
+import org.yakindu.sct.model.sgraph.Declaration;
+import org.yakindu.sct.model.sgraph.Event;
+import org.yakindu.sct.model.sgraph.SGraphPackage;
+import org.yakindu.sct.model.stext.stext.AlwaysEvent;
+import org.yakindu.sct.model.stext.stext.EntryEvent;
+import org.yakindu.sct.model.stext.stext.EventDefinition;
 import org.yakindu.sct.model.stext.stext.EventSpec;
+import org.yakindu.sct.model.stext.stext.ExitEvent;
+import org.yakindu.sct.model.stext.stext.InterfaceScope;
+import org.yakindu.sct.model.stext.stext.InternalScope;
+import org.yakindu.sct.model.stext.stext.LocalReaction;
+import org.yakindu.sct.model.stext.stext.OnCycleEvent;
 import org.yakindu.sct.model.stext.stext.ReactionTrigger;
+import org.yakindu.sct.model.stext.stext.RegularEventSpec;
+import org.yakindu.sct.model.stext.stext.SimpleScope;
+import org.yakindu.sct.model.stext.stext.StatechartDefinition;
 import org.yakindu.sct.model.stext.stext.StextPackage;
 import org.yakindu.sct.model.stext.stext.TransitionReaction;
 
+/**
+ * Several validations for nonsensical expressions.
+ * 
+ * @author muehlbrandt
+ * 
+ */
 public class STextJavaValidator extends AbstractSTextJavaValidator {
 
 	@Check(CheckType.FAST)
-	public void checkTransitionReactionTrigger(TransitionReaction reaction) {
-
-		Trigger trigger = reaction.getTrigger();
-		ReactionTrigger reactionTrigger = (ReactionTrigger) trigger;
-		EList<EventSpec> triggers = reactionTrigger.getTriggers();
-		for (EventSpec eventSpec : triggers) {
-			if (eventSpec instanceof BuiltinEventSpec) {
-				error("Buildin event specs are not allowed for transitions.",
+	public void checkReactionTrigger(ReactionTrigger reactionTrigger) {
+		for (EventSpec eventSpec : reactionTrigger.getTriggers()) {
+
+			// Allow only entries, exit, oncycle and always as event for local
+			// reactions.
+			if (!(reactionTrigger.eContainer() instanceof LocalReaction)
+					&& (eventSpec instanceof EntryEvent
+							|| eventSpec instanceof ExitEvent
+							|| eventSpec instanceof OnCycleEvent 
+							|| eventSpec instanceof AlwaysEvent)) {
+
+				error("entry, exit, oncycle and always events are allowed as local reactions only.",
 						StextPackage.Literals.REACTION_TRIGGER__TRIGGERS);
 			}
+			// Context Transitions
+			if (reactionTrigger.eContainer() instanceof TransitionReaction) {
+				if (eventSpec instanceof RegularEventSpec) {
+					error("Regular event specs are not allowed for transitions.",
+							StextPackage.Literals.REACTION_TRIGGER__TRIGGERS);
+				}
+			}
+
+			// Context StatechartDefiniton
+			if (isStatechartDefinitionChild(reactionTrigger)) {
+				if (eventSpec instanceof EntryEvent) {
+					error("Entry events are not allowed in statechart definition.",
+							StextPackage.Literals.REACTION_TRIGGER__TRIGGERS);
+				} else if (eventSpec instanceof ExitEvent) {
+					error("Exit events are not allowed in statechart definition.",
+							StextPackage.Literals.REACTION_TRIGGER__TRIGGERS);
+				}
+			}
+		}
+	}
+
+	@Check(CheckType.FAST)
+	public void checkSimpleScope(SimpleScope simpleScope) {
+		// Context State
+		if (simpleScope.getVariables().size() > 0) {
+			error("Variables can not be defined in states.",
+					SGraphPackage.Literals.SCOPE__VARIABLES);
+		}
+	}
+
+	@Check(CheckType.FAST)
+	public void checkInterfaceScope(InterfaceScope interfaceScope) {
+		for (Declaration declaration : interfaceScope.getDeclarations()) {
+			if (declaration instanceof LocalReaction) {
+				error("Local reactions are not allowed in interface scope.",
+						SGraphPackage.Literals.SCOPE__DECLARATIONS);
+			}
+		}
+	}
+
+	@Check(CheckType.FAST)
+	public void checkInternalScope(InternalScope internalScope) {
+		for (Event event : internalScope.getEvents()) {
+			if (event instanceof EventDefinition) {
+				error("In/Out declarations are not allowed in internal scope.",
+						SGraphPackage.Literals.SCOPE__EVENTS);
+			}
+		}
+	}
+
+	private boolean isStatechartDefinitionChild(EObject element) {
+		while (element.eContainer() != null) {
+			if (element.eContainer() instanceof StatechartDefinition) {
+				return true;
+			}
+			element = element.eContainer();
 		}
+		return false;
 	}
 }