internal Transition(ITaskDefinitionSymbol containingTask, 
                            TransitionDefinitionSyntax syntax, 
                            NodeReferenceSymbol source, 
                            EdgeModeSymbol edgeMode, 
                            NodeReferenceSymbol target, 
                            SymbolCollection<TriggerSymbol> triggers)  {

            if (containingTask == null) {
                throw new ArgumentNullException(nameof(containingTask));
            }

            if (syntax == null) {
                throw new ArgumentNullException(nameof(syntax));
            }

            ContainingTask = containingTask;
            Syntax   = syntax;
            Source   = source;
            EdgeMode = edgeMode;
            Target   = target;
            Triggers = triggers??new SymbolCollection<TriggerSymbol>();

            foreach (var trigger in Triggers) {
                trigger.Transition = this;
            }
        }
        internal Transition(TransitionDefinitionSyntax syntax, 
                            NodeReferenceSymbol source, 
                            EdgeModeSymbol edgeMode, 
                            NodeReferenceSymbol target, 
                            SymbolCollection<TriggerSymbol> triggers)  {

            if (syntax == null) {
                throw new ArgumentNullException(nameof(syntax));
            }

            Syntax   = syntax;
            Source   = source;
            EdgeMode = edgeMode;
            Target   = target;
            Triggers = triggers??new SymbolCollection<TriggerSymbol>();
        }
        public override void VisitExitTransitionDefinition(ExitTransitionDefinitionSyntax exitTransitionDefinitionSyntax) {
            // Source
            ITaskNodeSymbol sourceTaskNodeSymbol = null;
            NodeReferenceSymbol sourceNodeReference = null;
            var sourceNodeSyntax = exitTransitionDefinitionSyntax.SourceNode;
            if (sourceNodeSyntax != null) {

                // Source in Exit Transition muss immer ein Task sein
                sourceTaskNodeSymbol = _taskDefinition.NodeDeclarations.TryFindSymbol(sourceNodeSyntax.Name) as ITaskNodeSymbol;
                var location         = sourceNodeSyntax.GetLocation();

                if (location != null) {
                    sourceNodeReference = new NodeReferenceSymbol(sourceNodeSyntax.Name, location, sourceTaskNodeSymbol);
                }
            }

            // ConnectionPoint
            ConnectionPointReferenceSymbol connectionPointReference = null;
            var exitIdentifier = exitTransitionDefinitionSyntax.ExitIdentifier;
            if (!exitIdentifier.IsMissing && sourceTaskNodeSymbol != null) {

                var exitIdentifierName  = exitIdentifier.ToString();
                var exitConnectionPoint = sourceTaskNodeSymbol.Declaration?.ConnectionPoints.TryFindSymbol(exitIdentifierName) as IExitConnectionPointSymbol;
                var location            = exitIdentifier.GetLocation();

                if (location != null) {
                    connectionPointReference = new ConnectionPointReferenceSymbol(exitIdentifierName, location, exitConnectionPoint);
                }
            }

            // Target
            NodeReferenceSymbol targetNodeReference = null;
            var targetNodeSyntax = exitTransitionDefinitionSyntax.TargetNode;
            if (targetNodeSyntax != null) {

                var targetNode = _taskDefinition.NodeDeclarations.TryFindSymbol(targetNodeSyntax.Name);
                var location   = targetNodeSyntax.GetLocation();

                if(location != null) {
                    targetNodeReference = new NodeReferenceSymbol(targetNodeSyntax.Name, location, targetNode);
                }
            }

            // Edge
            EdgeModeSymbol edgeMode = null;
            var edgeSyntax = exitTransitionDefinitionSyntax.Edge;
            if (edgeSyntax != null) {

                var location = edgeSyntax.GetLocation();

                if(location != null) {
                    edgeMode = new EdgeModeSymbol(edgeSyntax.ToString(), location, edgeSyntax.Mode);
                }
            }

            var exitTransition = new ExitTransition(exitTransitionDefinitionSyntax, _taskDefinition, sourceNodeReference, connectionPointReference, edgeMode, targetNodeReference);

            AddExitTransition(exitTransition);
        }
        public override void VisitTransitionDefinition(TransitionDefinitionSyntax transitionDefinitionSyntax) {
            
            // Source
            NodeReferenceSymbol sourceNodeReference = null;
            var sourceNodeSyntax = transitionDefinitionSyntax.SourceNode;
            if (sourceNodeSyntax != null) {

                var sourceNode = _taskDefinition.NodeDeclarations.TryFindSymbol(sourceNodeSyntax.Name);

                // Special case "init": Hier ist implizit auch Großschreibung erlaubt
                // TODO Keyword in eigene Klasse
                if (sourceNode == null && sourceNodeSyntax.Name=="init") {
                    sourceNode = _taskDefinition.NodeDeclarations.TryFindSymbol("Init");
                }

                var location   = sourceNodeSyntax.GetLocation();
                if(location != null) {
                    sourceNodeReference = new NodeReferenceSymbol(sourceNodeSyntax.Name, location, sourceNode);
                }
            }

            // Target
            NodeReferenceSymbol targetNodeReference = null;
            var targetNodeSyntax = transitionDefinitionSyntax.TargetNode;
            if (targetNodeSyntax != null) {

                var targetNode = _taskDefinition.NodeDeclarations.TryFindSymbol(targetNodeSyntax.Name);
                var location = targetNodeSyntax.GetLocation();
                if (location != null) {
                    targetNodeReference = new NodeReferenceSymbol(targetNodeSyntax.Name, location, targetNode);                
                }
            }
            
            // Edge
            EdgeModeSymbol edgeMode=null;
            var edgeSyntax = transitionDefinitionSyntax.Edge;
            if (edgeSyntax != null) {

                var location = edgeSyntax.GetLocation();
                if(location != null) {
                    edgeMode = new EdgeModeSymbol(edgeSyntax.ToString(), location, edgeSyntax.Mode);
                }
            }

            // Triggers
            var triggers = GetTriggers(transitionDefinitionSyntax);

            var transition = new Transition(_taskDefinition, transitionDefinitionSyntax, sourceNodeReference, edgeMode, targetNodeReference, triggers);
            
            AddTransition(transition);
        }