Exemple #1
0
        /// <summary>
        /// Visits the state transition graph to find and return
        /// the node for the given summary.
        /// </summary>
        /// <param name="summary">MethodSummary</param>
        /// <param name="visited">Already visited nodes</param>
        /// <returns>StateTransitionGraphNode</returns>
        private StateTransitionGraphNode GetGraphNodeForSummary(MethodSummary summary,
                                                                HashSet <StateTransitionGraphNode> visited)
        {
            visited.Add(this);

            StateTransitionGraphNode stateNode = null;

            if ((this.OnEntry != null && this.OnEntry.Equals(summary)) ||
                (this.OnExit != null && this.OnExit.Equals(summary)) ||
                this.Actions.Any(v => v.Equals(summary)))
            {
                stateNode = this;
            }
            else
            {
                foreach (var successor in this.ISuccessors.Where(v => !visited.Contains(v)))
                {
                    var node = successor.GetGraphNodeForSummary(summary, visited);
                    if (node != null)
                    {
                        stateNode = node;
                        break;
                    }
                }
            }

            return(stateNode);
        }
Exemple #2
0
        /// <summary>
        /// Constructs the node using information from the given state transitions
        /// and action bindings.
        /// </summary>
        /// <param name="stateTransitions">State transitions</param>
        /// <param name="actionBindings">Action bindings</param>
        /// <param name="visited">Already visited nodes</param>
        private void Construct(Dictionary <ClassDeclarationSyntax, HashSet <ClassDeclarationSyntax> > stateTransitions,
                               Dictionary <ClassDeclarationSyntax, HashSet <MethodDeclarationSyntax> > actionBindings,
                               HashSet <StateTransitionGraphNode> visited)
        {
            visited.Add(this);

            foreach (var method in this.State.ChildNodes().OfType <MethodDeclarationSyntax>())
            {
                var summary = MethodSummary.Factory.Summarize(method);
                if (method.Modifiers.Any(SyntaxKind.OverrideKeyword) &&
                    method.Identifier.ValueText.Equals("OnEntry"))
                {
                    this.OnEntry = summary;
                }
                else if (method.Modifiers.Any(SyntaxKind.OverrideKeyword) &&
                         method.Identifier.ValueText.Equals("OnExit"))
                {
                    this.OnExit = summary;
                }
            }

            var actions = new HashSet <MethodDeclarationSyntax>();

            if (actionBindings.ContainsKey(this.State))
            {
                actions = actionBindings[this.State];
            }

            foreach (var action in actions)
            {
                var actionSummary = MethodSummary.Factory.Summarize(action);
                this.Actions.Add(actionSummary);
            }

            var transitions = new HashSet <ClassDeclarationSyntax>();

            if (stateTransitions.ContainsKey(this.State))
            {
                transitions = stateTransitions[this.State];
            }

            foreach (var successorState in transitions)
            {
                var successor = visited.FirstOrDefault(v => v.State.Equals(successorState));
                if (successor != null)
                {
                    this.ISuccessors.Add(successor);
                    successor.IPredecessors.Add(this);
                }
                else
                {
                    successor = new StateTransitionGraphNode(successorState, this.Machine);
                    this.ISuccessors.Add(successor);
                    successor.IPredecessors.Add(this);
                    successor.Construct(stateTransitions, actionBindings, visited);
                }
            }
        }
        /// <summary>
        /// Query checking if the field is accessed before being reset
        /// in the given state transition node.
        /// </summary>
        /// <param name="node">StateTransitionGraphNode</param>
        /// <param name="input">Input</param>
        /// <param name="isFirstVisit">True if first node to visit</param>
        /// <returns>Boolean value</returns>
        private static bool IsAccessedBeforeBeingReset(StateTransitionGraphNode node,
                                                       object input, bool isFirstVisit)
        {
            var summary     = ((Tuple <MethodSummary, ISymbol>)input).Item1;
            var fieldSymbol = ((Tuple <MethodSummary, ISymbol>)input).Item2;
            var result      = false;

            if (isFirstVisit && node.OnExit != null && !summary.Equals(node.OnExit))
            {
                foreach (var action in node.Actions)
                {
                    result = action.FieldAccessSet.ContainsKey(fieldSymbol as IFieldSymbol);
                    if (result)
                    {
                        break;
                    }
                }

                if (!result && node.OnExit != null)
                {
                    result = node.OnExit.FieldAccessSet.ContainsKey(fieldSymbol as IFieldSymbol);
                }
            }
            else if (!isFirstVisit)
            {
                if (node.OnEntry != null)
                {
                    result = node.OnEntry.FieldAccessSet.ContainsKey(fieldSymbol as IFieldSymbol);
                }

                if (!result)
                {
                    foreach (var action in node.Actions)
                    {
                        result = action.FieldAccessSet.ContainsKey(fieldSymbol as IFieldSymbol);
                        if (result)
                        {
                            break;
                        }
                    }
                }

                if (!result && node.OnExit != null)
                {
                    result = node.OnExit.FieldAccessSet.ContainsKey(fieldSymbol as IFieldSymbol);
                }
            }

            return(result);
        }
        /// <summary>
        /// Query checking if the field is accessed before being reset
        /// in the given state transition node.
        /// </summary>
        /// <param name="node">StateTransitionGraphNode</param>
        /// <param name="input">Input</param>
        /// <param name="isFirstVisit">True if first node to visit</param>
        /// <returns>Boolean value</returns>
        private static bool IsAccessedBeforeBeingReset(StateTransitionGraphNode node,
            object input, bool isFirstVisit)
        {
            var summary = ((Tuple<MethodSummary, ISymbol>)input).Item1;
            var fieldSymbol = ((Tuple<MethodSummary, ISymbol>)input).Item2;
            var result = false;

            if (isFirstVisit && node.OnExit != null && !summary.Equals(node.OnExit))
            {
                foreach (var action in node.Actions)
                {
                    result = action.FieldAccessSet.ContainsKey(fieldSymbol as IFieldSymbol);
                    if (result)
                    {
                        break;
                    }
                }

                if (!result && node.OnExit != null)
                {
                    result = node.OnExit.FieldAccessSet.ContainsKey(fieldSymbol as IFieldSymbol);
                }
            }
            else if (!isFirstVisit)
            {
                if (node.OnEntry != null)
                {
                    result = node.OnEntry.FieldAccessSet.ContainsKey(fieldSymbol as IFieldSymbol);
                }

                if (!result)
                {
                    foreach (var action in node.Actions)
                    {
                        result = action.FieldAccessSet.ContainsKey(fieldSymbol as IFieldSymbol);
                        if (result)
                        {
                            break;
                        }
                    }
                }

                if (!result && node.OnExit != null)
                {
                    result = node.OnExit.FieldAccessSet.ContainsKey(fieldSymbol as IFieldSymbol);
                }
            }

            return result;
        }
        /// <summary>
        /// Tries to construct the state transition graph for the given machine.
        /// </summary>
        /// <param name="machine">Machine</param>
        private static void ConstructGraphForMachine(ClassDeclarationSyntax machine)
        {
            var model = AnalysisContext.Compilation.GetSemanticModel(machine.SyntaxTree);

            Dictionary <ClassDeclarationSyntax, HashSet <ClassDeclarationSyntax> > stateTransitions = null;

            StateTransitionAnalysis.TryParseStateTransitions(out stateTransitions, machine, model);

            Dictionary <ClassDeclarationSyntax, HashSet <MethodDeclarationSyntax> > actionBindings = null;

            StateTransitionAnalysis.TryParseActionBindings(out actionBindings, machine, model);

            StateTransitionAnalysis.ComputeStatistics(stateTransitions, actionBindings);

            ClassDeclarationSyntax initState = null;

            foreach (var state in stateTransitions)
            {
                foreach (var attributeList in state.Key.AttributeLists)
                {
                    foreach (var attribute in attributeList.Attributes)
                    {
                        if (attribute.Name.ToString().Equals("Microsoft.PSharp.Start"))
                        {
                            initState = state.Key;
                        }
                    }
                }
            }

            if (initState == null)
            {
                return;
            }

            var initNode = new StateTransitionGraphNode(initState, machine);

            initNode.IsStartNode = true;
            initNode.Construct(stateTransitions, actionBindings);

            AnalysisContext.StateTransitionGraphs.Add(machine, initNode);
        }
Exemple #6
0
        /// <summary>
        /// Returns true if the given field symbol is being accessed
        /// before being reset.
        /// </summary>
        /// <param name="field">Field</param>
        /// <param name="summary">MethodSummary</param>
        /// <returns>Boolean value</returns>
        internal static bool IsAccessedBeforeBeingReset(ISymbol field, MethodSummary summary)
        {
            StateTransitionGraphNode stateTransitionNode = null;

            if (!AnalysisContext.StateTransitionGraphs.ContainsKey(summary.Machine))
            {
                return(true);
            }

            stateTransitionNode = AnalysisContext.StateTransitionGraphs[summary.Machine].
                                  GetGraphNodeForSummary(summary);
            if (stateTransitionNode == null)
            {
                return(true);
            }

            var result = stateTransitionNode.VisitSelfAndSuccessors(IsAccessedBeforeBeingReset,
                                                                    new Tuple <MethodSummary, ISymbol>(summary, field));

            return(false);
        }
        /// <summary>
        /// Tries to construct the state transition graph for the given machine.
        /// </summary>
        /// <param name="machine">Machine</param>
        private void ConstructGraphForMachine(ClassDeclarationSyntax machine)
        {
            var model = AnalysisContext.Compilation.GetSemanticModel(machine.SyntaxTree);

            Dictionary<ClassDeclarationSyntax, HashSet<ClassDeclarationSyntax>> stateTransitions = null;
            this.TryParseStateTransitions(out stateTransitions, machine, model);

            Dictionary<ClassDeclarationSyntax, HashSet<MethodDeclarationSyntax>> actionBindings = null;
            this.TryParseActionBindings(out actionBindings, machine, model);

            this.ComputeStatistics(stateTransitions, actionBindings);

            ClassDeclarationSyntax initState = null;
            foreach (var state in stateTransitions)
            {
                foreach (var attributeList in state.Key.AttributeLists)
                {
                    foreach (var attribute in attributeList.Attributes)
                    {
                        if (attribute.Name.ToString().Equals("Microsoft.PSharp.Start"))
                        {
                            initState = state.Key;
                        }
                    }
                }
            }

            if (initState == null)
            {
                return;
            }

            var initNode = new StateTransitionGraphNode(this.AnalysisContext, initState, machine);
            initNode.IsStartNode = true;
            initNode.Construct(stateTransitions, actionBindings);

            AnalysisContext.StateTransitionGraphs.Add(machine, initNode);
        }
        /// <summary>
        /// Constructs the node using information from the given state transitions
        /// and action bindings.
        /// </summary>
        /// <param name="stateTransitions">State transitions</param>
        /// <param name="actionBindings">Action bindings</param>
        /// <param name="visited">Already visited nodes</param>
        private void Construct(Dictionary<ClassDeclarationSyntax, HashSet<ClassDeclarationSyntax>> stateTransitions,
            Dictionary<ClassDeclarationSyntax, HashSet<MethodDeclarationSyntax>> actionBindings,
            HashSet<StateTransitionGraphNode> visited)
        {
            visited.Add(this);

            foreach (var method in this.State.ChildNodes().OfType<MethodDeclarationSyntax>())
            {
                var summary = MethodSummary.Factory.Summarize(this.AnalysisContext, method);
                if (method.Modifiers.Any(SyntaxKind.OverrideKeyword) &&
                    method.Identifier.ValueText.Equals("OnEntry"))
                {
                    this.OnEntry = summary;
                }
                else if (method.Modifiers.Any(SyntaxKind.OverrideKeyword) &&
                    method.Identifier.ValueText.Equals("OnExit"))
                {
                    this.OnExit = summary;
                }
            }

            var actions = new HashSet<MethodDeclarationSyntax>();
            if (actionBindings.ContainsKey(this.State))
            {
                actions = actionBindings[this.State];
            }

            foreach (var action in actions)
            {
                var actionSummary = MethodSummary.Factory.Summarize(this.AnalysisContext, action);
                this.Actions.Add(actionSummary);
            }

            var transitions = new HashSet<ClassDeclarationSyntax>();
            if (stateTransitions.ContainsKey(this.State))
            {
                transitions = stateTransitions[this.State];
            }

            foreach (var successorState in transitions)
            {
                var successor = visited.FirstOrDefault(v => v.State.Equals(successorState));
                if (successor != null)
                {
                    this.ISuccessors.Add(successor);
                    successor.IPredecessors.Add(this);
                }
                else
                {
                    successor = new StateTransitionGraphNode(this.AnalysisContext, successorState, this.Machine);
                    this.ISuccessors.Add(successor);
                    successor.IPredecessors.Add(this);
                    successor.Construct(stateTransitions, actionBindings, visited);
                }
            }
        }