Jelajahi Sumber

#757 added validation rule for statechart name is a valid identifier (#830)

Andreas Mülder 9 tahun lalu
induk
melakukan
7ae0126ad5

+ 80 - 65
plugins/org.yakindu.sct.model.sgraph/src/org/yakindu/sct/model/sgraph/validation/SGraphJavaValidator.java

@@ -30,6 +30,7 @@ import org.eclipse.xtext.validation.AbstractDeclarativeValidator;
 import org.eclipse.xtext.validation.Check;
 import org.eclipse.xtext.validation.CheckType;
 import org.eclipse.xtext.validation.EValidatorRegistrar;
+import org.yakindu.base.base.BasePackage;
 import org.yakindu.sct.model.sgraph.Choice;
 import org.yakindu.sct.model.sgraph.CompositeElement;
 import org.yakindu.sct.model.sgraph.Entry;
@@ -82,6 +83,7 @@ public class SGraphJavaValidator extends AbstractDeclarativeValidator {
 	public static final String ISSUE_SYNCHRONIZATION_TRANSITION_COUNT = "A synchronization should have at least two incoming or two outgoing transitions.";
 	public static final String ISSUE_TRANSITION_ORTHOGONAL = "Source and target of a transition must not be located in orthogonal regions!";
 	public static final String ISSUE_INITIAL_ENTRY_WITH_TRANSITION_TO_CONTAINER = "Outgoing Transitions from Entries can only target to sibling or inner states.";
+	public static final String ISSUE_STATECHART_NAME_NO_IDENTIFIER = "%s is not a valid identifier!";
 
 	@Check(CheckType.FAST)
 	public void vertexNotReachable(final Vertex vertex) {
@@ -105,10 +107,8 @@ public class SGraphJavaValidator extends AbstractDeclarativeValidator {
 						if (!stateScopeSet.contains(element)) {
 							externalPredecessors.add(element);
 						} else {
-							elements.addAll(((org.yakindu.sct.model.sgraph.State) element)
-									.getRegions());
-							elements.addAll(((org.yakindu.sct.model.sgraph.State) element)
-									.getIncomingTransitions());
+							elements.addAll(((org.yakindu.sct.model.sgraph.State) element).getRegions());
+							elements.addAll(((org.yakindu.sct.model.sgraph.State) element).getIncomingTransitions());
 						}
 
 					} else if (element instanceof Region) {
@@ -117,13 +117,11 @@ public class SGraphJavaValidator extends AbstractDeclarativeValidator {
 						if (!stateScopeSet.contains(element)) {
 							externalPredecessors.add(element);
 						} else {
-							elements.addAll(((Entry) element)
-									.getIncomingTransitions());
+							elements.addAll(((Entry) element).getIncomingTransitions());
 						}
 
 					} else if (element instanceof Vertex) {
-						elements.addAll(((Vertex) element)
-								.getIncomingTransitions());
+						elements.addAll(((Vertex) element).getIncomingTransitions());
 
 					} else if (element instanceof Transition) {
 						elements.add(((Transition) element).getSource());
@@ -155,8 +153,7 @@ public class SGraphJavaValidator extends AbstractDeclarativeValidator {
 
 	@Check(CheckType.FAST)
 	public void nameIsNotEmpty(org.yakindu.sct.model.sgraph.State state) {
-		if ((state.getName() == null || state.getName().trim().length() == 0)
-				&& !(state instanceof FinalState)) {
+		if ((state.getName() == null || state.getName().trim().length() == 0) && !(state instanceof FinalState)) {
 			error(ISSUE_STATE_WITHOUT_NAME, state, null, -1);
 		}
 	}
@@ -180,16 +177,14 @@ public class SGraphJavaValidator extends AbstractDeclarativeValidator {
 
 	@Check(CheckType.FAST)
 	public void initialEntryWithoutIncomingTransitions(Entry entry) {
-		if (entry.getIncomingTransitions().size() > 0
-				&& entry.getKind().equals(EntryKind.INITIAL)) {
+		if (entry.getIncomingTransitions().size() > 0 && entry.getKind().equals(EntryKind.INITIAL)) {
 			warning(ISSUE_INITIAL_ENTRY_WITH_IN_TRANS, entry, null, -1);
 		}
 	}
 
 	@Check(CheckType.FAST)
 	public void initialEntryWithoutOutgoingTransition(Entry entry) {
-		if (entry.getOutgoingTransitions().size() == 0
-				&& ((Entry) entry).getKind().equals(EntryKind.INITIAL)) {
+		if (entry.getOutgoingTransitions().size() == 0 && ((Entry) entry).getKind().equals(EntryKind.INITIAL)) {
 			warning(ISSUE_INITIAL_ENTRY_WITHOUT_OUT_TRANS, entry, null, -1);
 		}
 	}
@@ -229,16 +224,14 @@ public class SGraphJavaValidator extends AbstractDeclarativeValidator {
 
 	@Check(CheckType.FAST)
 	public void synchronizationTransitionCount(Synchronization sync) {
-		if (sync.getIncomingTransitions().size() < 2
-				&& sync.getOutgoingTransitions().size() < 2) {
+		if (sync.getIncomingTransitions().size() < 2 && sync.getOutgoingTransitions().size() < 2) {
 			warning(ISSUE_SYNCHRONIZATION_TRANSITION_COUNT, sync, null, -1);
 		}
 	}
 
 	@Check(CheckType.FAST)
 	public void initialEntryWithTransitionToContainer(Transition t) {
-		if (t.getSource() instanceof Entry
-				&& !isChildOrSibling(t.getSource(), t.getTarget())) {
+		if (t.getSource() instanceof Entry && !isChildOrSibling(t.getSource(), t.getTarget())) {
 			error(ISSUE_INITIAL_ENTRY_WITH_TRANSITION_TO_CONTAINER, t, null, -1);
 		}
 	}
@@ -281,8 +274,7 @@ public class SGraphJavaValidator extends AbstractDeclarativeValidator {
 				for (Vertex v : r.getVertices()) {
 					if (v instanceof Entry) {
 						String name = v.getName().trim().toLowerCase();
-						if (name != null || "".equals(name)
-								|| "default".equals(name)) {
+						if (name != null || "".equals(name) || "default".equals(name)) {
 							defaultEntry = (Entry) v;
 							break;
 						}
@@ -291,11 +283,9 @@ public class SGraphJavaValidator extends AbstractDeclarativeValidator {
 
 				// now check error conditions
 				if (defaultEntry == null) {
-					error(ISSUE_REGION_CANT_BE_ENTERED_USING_SHALLOW_HISTORY_NO_DEFAULT_ENTRY,
-							r, null, -1);
+					error(ISSUE_REGION_CANT_BE_ENTERED_USING_SHALLOW_HISTORY_NO_DEFAULT_ENTRY, r, null, -1);
 				} else if (defaultEntry.getOutgoingTransitions().size() != 1) {
-					error(ISSUE_REGION_CANT_BE_ENTERED_USING_SHALLOW_HISTORY_NON_CONNECTED_DEFAULT_ENTRY,
-							r, null, -1);
+					error(ISSUE_REGION_CANT_BE_ENTERED_USING_SHALLOW_HISTORY_NON_CONNECTED_DEFAULT_ENTRY, r, null, -1);
 				}
 			}
 
@@ -303,83 +293,108 @@ public class SGraphJavaValidator extends AbstractDeclarativeValidator {
 
 	}
 
-	@Check public void orthogonalTransition(Transition transition) {
-		
+	@Check
+	public void orthogonalTransition(Transition transition) {
+
 		Vertex source = transition.getSource();
 		Vertex target = transition.getTarget();
-		
-		if ( (source instanceof Synchronization) || (target instanceof Synchronization) ) return; // ... the check does not apply.
-		
+
+		if ((source instanceof Synchronization) || (target instanceof Synchronization))
+			return; // ... the check does not apply.
+
 		EObject commonAncestor = commonAncestor(source, target);
-		
+
 		if (commonAncestor instanceof CompositeElement) {
-			
-			error(ISSUE_TRANSITION_ORTHOGONAL, transition, null, -1);	
+
+			error(ISSUE_TRANSITION_ORTHOGONAL, transition, null, -1);
 		}
 	}
-	
-	
-	@Check public void orthogonalSourceStates(Synchronization sync) {
-		
+
+	@Check
+	public void orthogonalSourceStates(Synchronization sync) {
+
 		List<Vertex> sourceVertices = sources(sync.getIncomingTransitions());
-		
-		if ( ! areOrthogonal(sourceVertices) ) {
+
+		if (!areOrthogonal(sourceVertices)) {
 			error(ISSUE_SYNCHRONIZATION_SOURCE_STATES_NOT_ORTHOGONAL, sync, null, -1);
 		}
 	}
 
-	
+	@Check
+	public void orthogonalTargetStates(Synchronization sync) {
 
-	@Check public void orthogonalTargetStates(Synchronization sync) {
-		
 		List<Vertex> sourceVertices = targets(sync.getOutgoingTransitions());
-		
-		if ( ! areOrthogonal(sourceVertices) ) {
+
+		if (!areOrthogonal(sourceVertices)) {
 			error(ISSUE_SYNCHRONIZATION_TARGET_STATES_NOT_ORTHOGONAL, sync, null, -1);
 		}
 	}
 
+	@Check
+	public void orthogonalSynchronizedTransition(Synchronization sync) {
 
-
-	@Check public void orthogonalSynchronizedTransition(Synchronization sync) {
-		
-		List<Transition> incoming = sync.getIncomingTransitions();		
+		List<Transition> incoming = sync.getIncomingTransitions();
 		List<List<EObject>> inAncestorsList = new ArrayList<List<EObject>>();
-		for (Transition trans : incoming) { inAncestorsList.add(collectAncestors(trans.getSource(), new ArrayList<EObject>())); }
+		for (Transition trans : incoming) {
+			inAncestorsList.add(collectAncestors(trans.getSource(), new ArrayList<EObject>()));
+		}
 
 		List<Transition> outgoing = sync.getOutgoingTransitions();
-		List<List<EObject>> outAncestorsList = new ArrayList<List<EObject>>(); 
-		for (Transition trans : outgoing) { outAncestorsList.add(collectAncestors(trans.getTarget(), new ArrayList<EObject>())); }
-				
-		
+		List<List<EObject>> outAncestorsList = new ArrayList<List<EObject>>();
+		for (Transition trans : outgoing) {
+			outAncestorsList.add(collectAncestors(trans.getTarget(), new ArrayList<EObject>()));
+		}
+
 		Set<Transition> inOrthogonal = new HashSet<Transition>(incoming);
 		Set<Transition> outOrthogonal = new HashSet<Transition>(outgoing);
-		
-		for ( int i=0; i<incoming.size(); i++) {
-			for ( int j=0; j<outgoing.size(); j++ ) {
-				
+
+		for (int i = 0; i < incoming.size(); i++) {
+			for (int j = 0; j < outgoing.size(); j++) {
+
 				EObject commonAncestor = findCommonAncestor(inAncestorsList.get(i), outAncestorsList.get(j));
 
-				if ( commonAncestor instanceof Region ) {					
+				if (commonAncestor instanceof Region) {
 					inOrthogonal.remove(incoming.get(i));
 					outOrthogonal.remove(outgoing.get(j));
 				}
 			}
 		}
 
-		for ( Transition trans : inOrthogonal ) {
-			error(ISSUE_SYNCHRONIZATION_SOURCE_STATES_NOT_WITHIN_SAME_PARENTSTATE, trans, null, -1);				
+		for (Transition trans : inOrthogonal) {
+			error(ISSUE_SYNCHRONIZATION_SOURCE_STATES_NOT_WITHIN_SAME_PARENTSTATE, trans, null, -1);
 		}
-		
-		for ( Transition trans : outOrthogonal ) {
-			error(ISSUE_SYNCHRONIZATION_TARGET_STATES_NOT_WITHIN_SAME_PARENTSTATE, trans, null, -1);				
+
+		for (Transition trans : outOrthogonal) {
+			error(ISSUE_SYNCHRONIZATION_TARGET_STATES_NOT_WITHIN_SAME_PARENTSTATE, trans, null, -1);
+		}
+
+	}
+
+	@Check
+	public void checkStatechartNameIsIdentifier(Statechart statechart) {
+		if (!isValidJavaIdentifier(statechart.getName())) {
+			error(String.format(ISSUE_STATECHART_NAME_NO_IDENTIFIER, statechart.getName()), statechart, BasePackage.Literals.NAMED_ELEMENT__NAME, -1);
+
 		}
-		
 	}
 	
-	
-	
+	protected boolean isValidJavaIdentifier(String s) {
+		if (s == null || s.length() == 0) {
+			return false;
+		}
+
+		char[] c = s.toCharArray();
+		if (!Character.isJavaIdentifierStart(c[0])) {
+			return false;
+		}
 
+		for (int i = 1; i < c.length; i++) {
+			if (!Character.isJavaIdentifierPart(c[i])) {
+				return false;
+			}
+		}
+		return true;
+	}
 
 	@Override
 	public boolean isLanguageSpecific() {

+ 27 - 1
test-plugins/org.yakindu.sct.model.sgraph.test/src/org/yakindu/sct/model/sgraph/test/SGraphJavaValidationTest.java

@@ -784,6 +784,31 @@ public class SGraphJavaValidationTest {
 		assertError(diagnostics,
 				ISSUE_INITIAL_ENTRY_WITH_TRANSITION_TO_CONTAINER);
 	}
+	
+	@Test
+	public void checkStatechartNameIsIdentifier(){
+		Statechart statechart = SGraphFactory.eINSTANCE.createStatechart();
+		statechart.setName("Not a valid identifier");
+		validator.validate(statechart, diagnostics,
+				new HashMap<Object, Object>());
+		assertIssueCount(diagnostics, 1);
+		assertError(diagnostics,
+				String.format(ISSUE_STATECHART_NAME_NO_IDENTIFIER, statechart.getName()));
+		
+		diagnostics = new BasicDiagnostic();
+		statechart.setName("0Notavalididentifier");
+		validator.validate(statechart, diagnostics,
+				new HashMap<Object, Object>());
+		assertIssueCount(diagnostics, 1);
+		assertError(diagnostics,
+				String.format(ISSUE_STATECHART_NAME_NO_IDENTIFIER, statechart.getName()));
+		
+		diagnostics = new BasicDiagnostic();
+		statechart.setName("ValidIdentifier");
+		validator.validate(statechart, diagnostics,
+				new HashMap<Object, Object>());
+		assertIssueCount(diagnostics, 0);
+	}
 
 	/**
 	 * checks that each @Check method of {@link STextJavaValidator} has a @Test
@@ -808,7 +833,7 @@ public class SGraphJavaValidationTest {
 					testMethod.getAnnotation(Test.class));
 		}
 	}
-
+	
 	/**
 	 * checks that no two @Check method of {@link STextJavaValidator} have the
 	 * same name. Avoiding overloaded check methods in the validator class
@@ -837,6 +862,7 @@ public class SGraphJavaValidationTest {
 		}
 	}
 
+	
 	protected Transition createTransition(Vertex source, Vertex target) {
 		Transition trans = factory.createTransition();
 		trans.setSource(source);