private static ObjectCreationExpressionSyntax CallConstuctor(ClassDeclarationSyntax @class)
        {
            var typeName = F.ParseName(@class.Identifier.Text);
            var args = F.ArgumentList();

            var ctor = @class.DescendantNodes().OfType<ConstructorDeclarationSyntax>().FirstOrDefault();

            if(ctor != null)
            {
                var parameters = ctor.ParameterList.DescendantNodes().OfType<ParameterSyntax>().ToList();

                foreach (var parameter in parameters)
                {
                    var ident = parameter.DescendantNodes().OfType<IdentifierNameSyntax>().Single();
                    var parameterType = ident.Identifier.Text;

                    var invocation = F.InvocationExpression(F.MemberAccessExpression(
                        K.SimpleMemberAccessExpression,
                        F.IdentifierName(parameterType),
                        F.IdentifierName("Factory")));

                    args = args.AddArguments(F.Argument(invocation));
                }
            }

            return F.ObjectCreationExpression(typeName)
                    .WithNewKeyword(F.Token(F.TriviaList(), K.NewKeyword, F.TriviaList(F.Space)))
                    .WithArgumentList(args);
        }
 private static bool IsOverridingMethod(ClassDeclarationSyntax classDeclaration, string identifierName)
 {
     var methodDeclarations =
         classDeclaration.DescendantNodes()
             .Where(node => node.IsKind(SyntaxKind.MethodDeclaration))
             .Cast<MethodDeclarationSyntax>();
     var publicOverrideMethods = methodDeclarations.Where(node => node.Modifiers.Any(SyntaxKind.OverrideKeyword)
                                                                  && node.Modifiers.Any(SyntaxKind.PublicKeyword));
     return publicOverrideMethods.Any(node => node.Identifier.Text == identifierName);
 }
Example #3
0
        private static ClassNode CreateClassNode(SemanticModel model, ClassDeclarationSyntax c)
        {
            var declaredSymbol = model.GetDeclaredSymbol(c);

            var subnodes = c.DescendantNodes();
            var symbols = subnodes.Select(node => model.GetSymbolInfo(node).Symbol).ToList();

            var dependencies = symbols.OfType<INamedTypeSymbol>();
            var nrOfMethods = subnodes.OfType<MethodDeclarationSyntax>().Count();

            IEnumerable<TypeSyntax> basetypes = new List<TypeSyntax>();
            if (c.BaseList != null && c.BaseList.Types.Any())
                basetypes = c.BaseList.Types.Select(x => x.Type);
            return new ClassNode(declaredSymbol, basetypes, nrOfMethods) {SymbolDependencies = dependencies};
        }
        public override void VisitClassDeclaration(ClassDeclarationSyntax node)
        {
             
                LookForAggregates(node);
                LookForCommands(node);
                LookForCommandHandlers(node);
                LookForEvents(node);
                LookForEventHandlers(node);

                var methods = node.DescendantNodes().OfType<MethodDeclarationSyntax>();
                foreach (var method in methods.Where(x => x.Body != null))
                {
                    Visit(method);
                }
            
        }
Example #5
0
 /// <summary>
 /// checks if a property with the given name is enclosed
 /// by a region with the given name
 /// </summary>
 /// <param name="classDeclaration"></param>
 /// <param name="regionName"></param>
 /// <param name="propertyName"></param>
 /// <returns>true if there is a property between the region,
 /// false otherwise</returns>
 public static bool IsPropertyBetweenRegion(
     ClassDeclarationSyntax classDeclaration, 
     string regionName,
     string propertyName)
 {
     // assert: the method must be between the region
     // get begin and end region
     var beginRegion = classDeclaration.FindRegionByText(regionName);
     var endRegion = classDeclaration.FindEndRegion(regionName);
     // get all nodes between the regions
     var span = new TextSpan(beginRegion.Span.End, endRegion.Span.Start);
     var nodesBetweenRegion = classDeclaration.DescendantNodes(span);
     // check that a property declaration for a "Name" property is there
     var isPropertyBetweenRegion = nodesBetweenRegion
         .OfType<PropertyDeclarationSyntax>()
         .Any(x => x.Identifier.ToString() == propertyName);
     return isPropertyBetweenRegion;
 }
Example #6
0
        /// <summary>
        /// Checks that machine fields are non-internal.
        /// </summary>
        /// <param name="machine">Machine</param>
        private void CheckForInternalFields(ClassDeclarationSyntax machine)
        {
            var fieldIdentifiers = machine.DescendantNodes().OfType<FieldDeclarationSyntax>().
                Where(val => val.Modifiers.Any(SyntaxKind.InternalKeyword)).
                SelectMany(val => val.Declaration.Variables).
                Select(val => val.Identifier).
                ToList();

            foreach (var identifier in fieldIdentifiers)
            {
                base.ErrorLog.Add(Tuple.Create(identifier, "Not allowed to declare field '" +
                    identifier.ValueText + "' of " + this.GetTypeOfMachine().ToLower() + " '" +
                    machine.Identifier.ValueText + "' as internal."));
            }
        }
Example #7
0
        /// <summary>
        /// Checks that machine methods are non-public.
        /// </summary>
        /// <param name="machine">Machine</param>
        private void CheckForPublicMethods(ClassDeclarationSyntax machine)
        {
            var methodIdentifiers = machine.DescendantNodes().OfType<MethodDeclarationSyntax>().
                Where(val => val.Modifiers.Any(SyntaxKind.PublicKeyword)).
                Select(val => val.Identifier).
                ToList();

            foreach (var identifier in methodIdentifiers)
            {
                base.ErrorLog.Add(Tuple.Create(identifier, "Not allowed to declare method '" +
                    identifier.ValueText + "' of " + this.GetTypeOfMachine().ToLower() + " '" +
                    machine.Identifier.ValueText + "' as public."));
            }
        }
Example #8
0
        /// <summary>
        /// Checks that no structs are declared inside the state.
        /// </summary>
        /// <param name="state">State</param>
        private void CheckForStructs(ClassDeclarationSyntax state)
        {
            var structs = state.DescendantNodes().OfType<StructDeclarationSyntax>().
                ToList();

            if (structs.Count > 0)
            {
                base.ErrorLog.Add(Tuple.Create(state.Identifier, "State '" +
                    state.Identifier.ValueText + "' cannot declare structs."));
            }
        }
            public override ClassDeclarationSyntax ProcessApplyToClassDeclaration(ClassDeclarationSyntax applyTo)
            {
                applyTo = base.ProcessApplyToClassDeclaration(applyTo);

                if (this.applyTo.IsRecursiveParentOrDerivative)
                {
                    // Add the lookupTable parameter to the constructor's signature.
                    var origCtor = applyTo.Members.OfType<ConstructorDeclarationSyntax>().Single();
                    var alteredCtor = origCtor.AddParameterListParameters(SyntaxFactory.Parameter(LookupTableFieldName.Identifier).WithType(Syntax.OptionalOf(this.lookupTableType)));

                    // If this type isn't itself the recursive parent then we derive from it. And we must propagate the value to the chained base type.
                    if (!this.applyTo.IsRecursiveParent)
                    {
                        Assumes.NotNull(alteredCtor.Initializer); // we expect a chained call to the base constructor.
                        alteredCtor = alteredCtor.WithInitializer(
                            alteredCtor.Initializer.AddArgumentListArguments(
                                SyntaxFactory.Argument(SyntaxFactory.NameColon(LookupTableFieldName), NoneToken, LookupTableFieldName)));
                    }

                    // Apply the updated constructor back to the generated type.
                    applyTo = applyTo.ReplaceNode(origCtor, alteredCtor);

                    // Search for invocations of the constructor that we now have to update.
                    var invocations = (
                        from n in applyTo.DescendantNodes()
                        let ctorInvocation = n as ObjectCreationExpressionSyntax
                        let instantiatedTypeName = ctorInvocation?.Type?.ToString()
                        where instantiatedTypeName == this.applyTo.TypeSyntax.ToString() || instantiatedTypeName == this.applyTo.TypeSymbol.Name
                        select ctorInvocation).ToImmutableArray();
                    var trackedTree = applyTo.TrackNodes(invocations);

                    var recursiveField = this.applyTo.RecursiveParent.RecursiveField;
                    foreach (var ctorInvocation in invocations)
                    {
                        var currentInvocation = trackedTree.GetCurrentNode(ctorInvocation);

                        ExpressionSyntax lookupTableValue = SyntaxFactory.LiteralExpression(SyntaxKind.NullLiteralExpression);
                        var containingMethod = currentInvocation.FirstAncestorOrSelf<MethodDeclarationSyntax>();
                        if (containingMethod != null)
                        {
                            if (containingMethod.ParameterList.Parameters.Any(p => p.Identifier.ToString() == recursiveField.Name))
                            {
                                // We're in a method that accepts the recursive field as a parameter.
                                // The value we want to pass in for the lookup table is:
                                // (children.IsDefined && children.Value != this.Children) ? default(Optional<ImmutableDictionary<uint, KeyValuePair<RecursiveType, uint>>>) : Optional.For(this.lookupTable);
                                lookupTableValue = SyntaxFactory.ConditionalExpression(
                                    SyntaxFactory.ParenthesizedExpression(
                                        SyntaxFactory.BinaryExpression(
                                            SyntaxKind.LogicalAndExpression,
                                            Syntax.OptionalIsDefined(recursiveField.NameAsField),
                                            SyntaxFactory.BinaryExpression(
                                                SyntaxKind.NotEqualsExpression,
                                                Syntax.OptionalValue(recursiveField.NameAsField),
                                                Syntax.ThisDot(recursiveField.NameAsProperty)))),
                                    SyntaxFactory.DefaultExpression(Syntax.OptionalOf(this.lookupTableType)),
                                    Syntax.OptionalFor(Syntax.ThisDot(LookupTableFieldName)));
                            }
                        }

                        var alteredInvocation = currentInvocation.AddArgumentListArguments(
                            SyntaxFactory.Argument(SyntaxFactory.NameColon(LookupTableFieldName), NoneToken, lookupTableValue));

                        trackedTree = trackedTree.ReplaceNode(currentInvocation, alteredInvocation);
                    }

                    applyTo = trackedTree;
                }

                return applyTo;
            }
Example #10
0
        /// <summary>
        /// Checks that at least one state is declared inside the machine.
        /// </summary>
        /// <param name="machine">Machine</param>
        /// <param name="compilation">Compilation</param>
        private void CheckForAtLeastOneState(ClassDeclarationSyntax machine,
            CodeAnalysis.Compilation compilation)
        {
            var states = machine.DescendantNodes().OfType<ClassDeclarationSyntax>().
                Where(val => this.IsState(compilation, val)).
                ToList();

            if (states.Count == 0)
            {
                base.WarningLog.Add(Tuple.Create(machine.Identifier, $"{this.GetTypeOfMachine().ToLower()} " +
                    $"'{machine.Identifier.ValueText}' must declare at least one state (unless the machine " +
                    "inherits at least one state from a base machine, or is partial, and one state has " +
                    "been already declared in another part of the declaration)."));
            }
        }
Example #11
0
        /// <summary>
        /// Checks that no methods are declared inside the machine (beside the P# API ones).
        /// </summary>
        /// <param name="state">State</param>
        private void CheckForMethods(ClassDeclarationSyntax state)
        {
            var methods = state.DescendantNodes().OfType<MethodDeclarationSyntax>().
                Where(val => !val.Modifiers.Any(SyntaxKind.OverrideKeyword)).
                ToList();

            if (methods.Count > 0)
            {
                base.ErrorLog.Add(Tuple.Create(state.Identifier, "State '" +
                    state.Identifier.ValueText + "' cannot declare methods."));
            }
        }
Example #12
0
        /// <summary>
        /// Checks that a machine has an start state.
        /// </summary>
        /// <param name="machine">Machine</param>
        /// <param name="compilation">Compilation</param>
        private void CheckForStartState(ClassDeclarationSyntax machine, CodeAnalysis.Compilation compilation)
        {
            var model = compilation.GetSemanticModel(machine.SyntaxTree);
            
            var stateAttributes = machine.DescendantNodes().OfType<ClassDeclarationSyntax>().
                Where(val => this.IsState(compilation, val)).
                SelectMany(val => val.AttributeLists).
                SelectMany(val => val.Attributes).
                Where(val => model.GetTypeInfo(val).Type.ToDisplayString().Equals("Microsoft.PSharp.Start")).
                ToList();

            if (stateAttributes.Count == 0)
            {
                base.ErrorLog.Add(Tuple.Create(machine.Identifier, this.GetTypeOfMachine().ToLower() + " '" +
                    machine.Identifier.ValueText + "' must declare a start state."));
            }
            else if (stateAttributes.Count > 1)
            {
                base.ErrorLog.Add(Tuple.Create(machine.Identifier, this.GetTypeOfMachine().ToLower() + " '" +
                    machine.Identifier.ValueText + "' must declare only one start state."));
            }
        }
Example #13
0
        /// <summary>
        /// Checks that a machine has an start state.
        /// </summary>
        /// <param name="machine">Machine</param>
        /// <param name="compilation">Compilation</param>
        private void CheckForStartState(ClassDeclarationSyntax machine, CodeAnalysis.Compilation compilation)
        {
            var model = compilation.GetSemanticModel(machine.SyntaxTree);

            var stateAttributes = machine.DescendantNodes().OfType<ClassDeclarationSyntax>().
                Where(val => this.IsState(compilation, val)).
                SelectMany(val => val.AttributeLists).
                SelectMany(val => val.Attributes).
                Where(val => model.GetTypeInfo(val).Type.ToDisplayString().Equals("Microsoft.PSharp.Start")).
                ToList();

            if (stateAttributes.Count == 0)
            {
                base.WarningLog.Add(Tuple.Create(machine.Identifier, $"{this.GetTypeOfMachine().ToLower()} " +
                    $"'{machine.Identifier.ValueText}' must declare a start state (unless the machine " +
                    "inherits a start state from a base machine, or is partial, and one state has been " +
                    "already declared in another part of the declaration)."));
            }
            else if (stateAttributes.Count > 1)
            {
                base.ErrorLog.Add(Tuple.Create(machine.Identifier, $"{this.GetTypeOfMachine().ToLower()} " +
                    $"'{machine.Identifier.ValueText}' must declare only one start state."));
            }
        }
        private static IEnumerable<ObjectCreationExpressionSyntax> GetObjectCreations(SyntaxNodeAnalysisContext context, ClassDeclarationSyntax classDeclaration, PropertyDeclarationSyntax propertyDeclarationSyntax, IPropertySymbol propertySymbol)
        {
            var objectCreations = classDeclaration.DescendantNodes()
                            .OfType<AssignmentExpressionSyntax>()
                            .Where(a => context.SemanticModel.GetSymbolInfo(a.Left).Symbol.Equals(propertySymbol) && a.Right is ObjectCreationExpressionSyntax)
                            .Select(a => a.Right as ObjectCreationExpressionSyntax).ToList();

            var arrowExpressionClause = propertyDeclarationSyntax.DescendantNodes()
                .OfType<ArrowExpressionClauseSyntax>()
                .SingleOrDefault(a => a.Expression is ObjectCreationExpressionSyntax)
                ?.Expression as ObjectCreationExpressionSyntax;
            if (arrowExpressionClause != null)
            {
                objectCreations.Add(arrowExpressionClause);
            }

            var getAcessorDeclararion = propertyDeclarationSyntax.DescendantNodes()
                .OfType<AccessorDeclarationSyntax>()
                .SingleOrDefault(a => a.IsKind(SyntaxKind.GetAccessorDeclaration));
            if (getAcessorDeclararion != null)
            {
                objectCreations.AddRange(getAcessorDeclararion.DescendantNodes()
                            .OfType<ObjectCreationExpressionSyntax>());
            }

            return objectCreations;
        }
Example #15
0
        /// <summary>
        /// Checks that no non-state or non-event classes are declared inside the machine.
        /// </summary>
        /// <param name="machine">Machine</param>
        /// <param name="compilation">Compilation</param>
        private void CheckForNonStateNonEventClasses(ClassDeclarationSyntax machine, CodeAnalysis.Compilation compilation)
        {
            var classIdentifiers = machine.DescendantNodes().OfType<ClassDeclarationSyntax>().
                Where(val => !this.IsState(compilation, val) && !Querying.IsEventDeclaration(compilation, val)).
                Select(val => val.Identifier).
                ToList();

            foreach (var identifier in classIdentifiers)
            {
                base.ErrorLog.Add(Tuple.Create(identifier, "Not allowed to declare non-state class '" +
                    identifier.ValueText + "' inside " + this.GetTypeOfMachine().ToLower() + " '" +
                    machine.Identifier.ValueText + "'."));
            }
        }
 private static bool ClassIsCallingRaiseCanExecuteChanged(ClassDeclarationSyntax classDeclaration)
 {
     return classDeclaration.DescendantNodes()
         .OfType<InvocationExpressionSyntax>()
         .Any(i =>
             (((i.Expression as MemberAccessExpressionSyntax)?.Name
               ?? (i.Expression as MemberBindingExpressionSyntax)?.Name
                 ) as IdentifierNameSyntax)?.Identifier.Value.Equals("RaiseCanExecuteChanged") ?? false);
 }
        /// <summary>
        /// Determine if the given class decaration has a missing method variant (e.g. it missing an async method for sync method or vise-versa)
        /// </summary>
        /// <param name="document">The code analysis document.</param>
        /// <param name="classDecl">The class declaration.</param>
        /// <param name="semanticModel">A semantic model to look for the type in.</param>
        /// <param name="cancellationToken">A cancellation token.</param>
        /// <returns>Boolean value indicates whether the class has missing method variant or not.</returns>
        private async Task<bool> ClassDeclarationHasMissingVariant(Document document, ClassDeclarationSyntax classDecl, SemanticModel semanticModel, CancellationToken cancellationToken)
        {
            var classMethods = classDecl
                .DescendantNodes()
                .OfType<MethodDeclarationSyntax>();

            foreach (var method in classMethods)
            {
                if (await AsyncAnalysis.IsAsyncMethod(document, method, cancellationToken))
                {
                    if (!(await AsyncAnalysis.MethodHasSyncVariant(document, method, semanticModel, cancellationToken)))
                    {
                        return true;
                    }
                }
                else
                {
                    if (!(await AsyncAnalysis.MethodHasAsyncVariant(document, method, semanticModel, cancellationToken)))
                    {
                        return true;
                    }
                }
            }

            return false;
        }
        /// <summary>
        /// Add to the given class its missing method(s) variant.
        /// </summary>
        /// <param name="document">The code analysis document.</param>
        /// <param name="classDecl">The class.</param>
        /// <param name="semanticModel">A semantic model to look for the type in.</param>
        /// <param name="cancellationToken">A cancellation token.</param>
        /// <returns>The modified document.</returns>
        private async Task<Document> CompleteClassMissingMethodVariants(Document document, ClassDeclarationSyntax classDecl, SemanticModel semanticModel, CancellationToken cancellationToken)
        {
            var classMethods = classDecl
                .DescendantNodes()
                .OfType<MethodDeclarationSyntax>().ToList();

            if (classMethods.Count < 1)
            {
                return document;
            }

            var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);

            /**
             * Note:
             * I'd rather add each method at the right place. However, currently it seems impossible (a bug, prehaps).
             * So we need to collect all of the methods and insert them in the end of the class/interface.
             */
            var methodsList = new List<MethodDeclarationSyntax>();

            foreach (var methodDecl in classMethods)
            {
                if (await AsyncAnalysis.IsAsyncMethod(document, methodDecl, cancellationToken))
                {
                    if (!(await AsyncAnalysis.MethodHasSyncVariant(document, methodDecl, semanticModel, cancellationToken)))
                    {
                        // Create a sync variant
                        var syncVariant = await CodeGeneration.ImplementSyncMethodVariant(document, methodDecl, semanticModel, cancellationToken);
                        methodsList.Add(syncVariant);
                    }
                }
                else
                {
                    if (!(await AsyncAnalysis.MethodHasAsyncVariant(document, methodDecl, semanticModel, cancellationToken)))
                    {
                        // Create an async variant
                        var asyncVariant = await CodeGeneration.ImplementAsyncMethodVariant(document, methodDecl, semanticModel, cancellationToken);
                        methodsList.Add(asyncVariant);
                    }
                }
            }

            if (methodsList.Count < 1)
            {
                return document;
            }

            //  In case there's no carridge return trivia at the end of the last method declaration,
            // Add a carridge return trivia to the first method in the methodsList
            var lastMethod = classDecl.Members.OfType<MethodDeclarationSyntax>().Last();
            var lastMethodTrailingTrivia = lastMethod.GetTrailingTrivia();

            if (!lastMethodTrailingTrivia.Contains(SyntaxFactory.CarriageReturn)
                && !lastMethodTrailingTrivia.Contains(SyntaxFactory.CarriageReturnLineFeed)
                && !lastMethodTrailingTrivia.Contains(SyntaxFactory.ElasticCarriageReturn)
                && !lastMethodTrailingTrivia.Contains(SyntaxFactory.ElasticCarriageReturnLineFeed))
            {
                methodsList[0] = methodsList.ElementAt(0).WithLeadingTrivia(methodsList.ElementAt(0).GetLeadingTrivia().WithCarriageReturn());
            }

            //  Insert
            root = root.InsertNodesAfter(classDecl.Members.OfType<MethodDeclarationSyntax>().Last(), methodsList);
            document = document.WithSyntaxRoot(root);

            //  Format
            document = await Simplifier.ReduceAsync(document, Simplifier.Annotation, cancellationToken: cancellationToken).ConfigureAwait(false);
            document = await Formatter.FormatAsync(document, Formatter.Annotation, cancellationToken: cancellationToken).ConfigureAwait(false);

            return document;
        }
Example #19
0
        /// <summary>
        /// Discovers the available actions of the given machine.
        /// </summary>
        /// <param name="machine">Machine</param>
        /// <param name="compilation">Compilation</param>
        private void DiscoverMachineActions(ClassDeclarationSyntax machine, CodeAnalysis.Compilation compilation)
        {
            var model = compilation.GetSemanticModel(machine.SyntaxTree);

            var onEntryActionNames = machine.DescendantNodes().OfType<ClassDeclarationSyntax>().
                Where(val => this.IsState(compilation, val)).
                SelectMany(val => val.AttributeLists).
                SelectMany(val => val.Attributes).
                Where(val => model.GetTypeInfo(val).Type.ToDisplayString().Equals("Microsoft.PSharp.OnEntry")).
                Where(val => val.ArgumentList != null).
                Where(val => val.ArgumentList.Arguments.Count == 1).
                Where(val => val.ArgumentList.Arguments[0].Expression is LiteralExpressionSyntax).
                Select(val => val.ArgumentList.Arguments[0].Expression as LiteralExpressionSyntax).
                Select(val => val.Token.ValueText).
                ToList();

            var onEntryNameOfActionNames = machine.DescendantNodes().OfType<ClassDeclarationSyntax>().
                Where(val => this.IsState(compilation, val)).
                SelectMany(val => val.AttributeLists).
                SelectMany(val => val.Attributes).
                Where(val => model.GetTypeInfo(val).Type.ToDisplayString().Equals("Microsoft.PSharp.OnEntry")).
                Where(val => val.ArgumentList != null).
                Where(val => val.ArgumentList.Arguments.Count == 1).
                Where(val => val.ArgumentList.Arguments[0].Expression is InvocationExpressionSyntax).
                Select(val => val.ArgumentList.Arguments[0].Expression as InvocationExpressionSyntax).
                Where(val => val.Expression is IdentifierNameSyntax).
                Where(val => (val.Expression as IdentifierNameSyntax).Identifier.ValueText.Equals("nameof")).
                Where(val => val.ArgumentList != null).
                Where(val => val.ArgumentList.Arguments.Count == 1).
                Where(val => val.ArgumentList.Arguments[0].Expression is IdentifierNameSyntax).
                Select(val => val.ArgumentList.Arguments[0].Expression as IdentifierNameSyntax).
                Select(val => val.Identifier.ValueText).
                ToList();

            var onExitActionNames = machine.DescendantNodes().OfType<ClassDeclarationSyntax>().
                Where(val => this.IsState(compilation, val)).
                SelectMany(val => val.AttributeLists).
                SelectMany(val => val.Attributes).
                Where(val => model.GetTypeInfo(val).Type.ToDisplayString().Equals("Microsoft.PSharp.OnExit")).
                Where(val => val.ArgumentList != null).
                Where(val => val.ArgumentList.Arguments.Count == 1).
                Where(val => val.ArgumentList.Arguments[0].Expression is LiteralExpressionSyntax).
                Select(val => val.ArgumentList.Arguments[0].Expression as LiteralExpressionSyntax).
                Select(val => val.Token.ValueText).
                ToList();

            var onExitNameOfActionNames = machine.DescendantNodes().OfType<ClassDeclarationSyntax>().
                Where(val => this.IsState(compilation, val)).
                SelectMany(val => val.AttributeLists).
                SelectMany(val => val.Attributes).
                Where(val => model.GetTypeInfo(val).Type.ToDisplayString().Equals("Microsoft.PSharp.OnExit")).
                Where(val => val.ArgumentList != null).
                Where(val => val.ArgumentList.Arguments.Count == 1).
                Where(val => val.ArgumentList.Arguments[0].Expression is InvocationExpressionSyntax).
                Select(val => val.ArgumentList.Arguments[0].Expression as InvocationExpressionSyntax).
                Where(val => val.Expression is IdentifierNameSyntax).
                Where(val => (val.Expression as IdentifierNameSyntax).Identifier.ValueText.Equals("nameof")).
                Where(val => val.ArgumentList != null).
                Where(val => val.ArgumentList.Arguments.Count == 1).
                Where(val => val.ArgumentList.Arguments[0].Expression is IdentifierNameSyntax).
                Select(val => val.ArgumentList.Arguments[0].Expression as IdentifierNameSyntax).
                Select(val => val.Identifier.ValueText).
                ToList();
            
            var onEventDoActionNames = machine.DescendantNodes().OfType<ClassDeclarationSyntax>().
                Where(val => this.IsState(compilation, val)).
                SelectMany(val => val.AttributeLists).
                SelectMany(val => val.Attributes).
                Where(val => model.GetTypeInfo(val).Type.ToDisplayString().Equals("Microsoft.PSharp.OnEventDoAction")).
                Where(val => val.ArgumentList != null).
                Where(val => val.ArgumentList.Arguments.Count == 2).
                Where(val => val.ArgumentList.Arguments[1].Expression is LiteralExpressionSyntax).
                Select(val => val.ArgumentList.Arguments[1].Expression as LiteralExpressionSyntax).
                Select(val => val.Token.ValueText).
                ToList();

            var onEventDoNameOfActionNames = machine.DescendantNodes().OfType<ClassDeclarationSyntax>().
                Where(val => this.IsState(compilation, val)).
                SelectMany(val => val.AttributeLists).
                SelectMany(val => val.Attributes).
                Where(val => model.GetTypeInfo(val).Type.ToDisplayString().Equals("Microsoft.PSharp.OnEventDoAction")).
                Where(val => val.ArgumentList != null).
                Where(val => val.ArgumentList.Arguments.Count == 2).
                Where(val => val.ArgumentList.Arguments[1].Expression is InvocationExpressionSyntax).
                Select(val => val.ArgumentList.Arguments[1].Expression as InvocationExpressionSyntax).
                Where(val => val.Expression is IdentifierNameSyntax).
                Where(val => (val.Expression as IdentifierNameSyntax).Identifier.ValueText.Equals("nameof")).
                Where(val => val.ArgumentList != null).
                Where(val => val.ArgumentList.Arguments.Count == 1).
                Where(val => val.ArgumentList.Arguments[0].Expression is IdentifierNameSyntax).
                Select(val => val.ArgumentList.Arguments[0].Expression as IdentifierNameSyntax).
                Select(val => val.Identifier.ValueText).
                ToList();

            var actionNames = new HashSet<string>();
            actionNames.UnionWith(onEntryActionNames);
            actionNames.UnionWith(onEntryNameOfActionNames);
            actionNames.UnionWith(onExitActionNames);
            actionNames.UnionWith(onExitNameOfActionNames);
            actionNames.UnionWith(onEventDoActionNames);
            actionNames.UnionWith(onEventDoNameOfActionNames);

            this.Actions.Add(machine, new List<MethodDeclarationSyntax>());

            foreach (var actionName in actionNames)
            {
                var action = machine.DescendantNodes().OfType<MethodDeclarationSyntax>().
                    Where(val => val.ParameterList != null).
                    Where(val => val.ParameterList.Parameters.Count == 0).
                    Where(val => val.Identifier.ValueText.Equals(actionName)).
                    FirstOrDefault();

                if (action != null)
                {
                    this.Actions[machine].Add(action);
                }
            }

            var states = machine.DescendantNodes().OfType<ClassDeclarationSyntax>().
                Where(val => this.IsState(compilation, val)).
                ToList();

            var stateMethods = states.SelectMany(val => val.DescendantNodes().OfType<MethodDeclarationSyntax>()).
                Where(val => val.Modifiers.Any(SyntaxKind.OverrideKeyword)).
                ToList();

            foreach (var method in stateMethods)
            {
                this.Actions[machine].Add(method);
            }
        }
Example #20
0
        /// <summary>
        /// Checks that at least one state or group is declared inside a group.
        /// </summary>
        /// <param name="machine">Machine</param>
        /// <param name="compilation">Compilation</param>
        private void CheckForAtLeastOneStateOrGroup(ClassDeclarationSyntax machine,
            CodeAnalysis.Compilation compilation)
        {
            var stateGroups = machine.DescendantNodes().OfType<ClassDeclarationSyntax>().
                Where(val => Querying.IsMachineStateGroup(compilation, val)).
                ToList();

            foreach (var stateGroup in stateGroups)
            {
                var contents = stateGroup.DescendantNodes().OfType<ClassDeclarationSyntax>().
                Where(val => Querying.IsMachineState(compilation, val) ||
                    Querying.IsMachineStateGroup(compilation, val)).
                ToList();

                if (contents.Count == 0)
                {
                    base.WarningLog.Add(Tuple.Create(stateGroup.Identifier, "State group " +
                        $"'{stateGroup.Identifier.ValueText}' must declare at least one state or group."));
                }
            }
        }
Example #21
0
        /// <summary>
        /// Checks that at least one state is declared inside the machine.
        /// </summary>
        /// <param name="machine">Machine</param>
        /// <param name="compilation">Compilation</param>
        private void CheckForAtLeastOneState(ClassDeclarationSyntax machine, CodeAnalysis.Compilation compilation)
        {
            var states = machine.DescendantNodes().OfType<ClassDeclarationSyntax>().
                Where(val => this.IsState(compilation, val)).
                ToList();

            if (states.Count == 0)
            {
                base.ErrorLog.Add(Tuple.Create(machine.Identifier, this.GetTypeOfMachine().ToLower() + " '" +
                    machine.Identifier.ValueText + "' must declare at least one state."));
            }
        }
Example #22
0
        /// <summary>
        /// Checks that a raise statement is not used in a machine method.
        /// </summary>
        /// <param name="machine">Machine</param>
        private void CheckForRaiseStatementsInMethods(ClassDeclarationSyntax machine)
        {
            var methods = machine.DescendantNodes().OfType<MethodDeclarationSyntax>().
                Where(val => !this.Actions[machine].Contains(val)).
                ToList();

            foreach (var method in methods)
            {
                var hasRaise = method.DescendantNodes().OfType<InvocationExpressionSyntax>().
                    Where(val => val.Expression is IdentifierNameSyntax).
                    Select(val => val.Expression as IdentifierNameSyntax).
                    Any(val => val.Identifier.ValueText.Equals("Raise"));

                if (!hasRaise)
                {
                    hasRaise = method.DescendantNodes().OfType<InvocationExpressionSyntax>().
                        Where(val => val.Expression is MemberAccessExpressionSyntax).
                        Select(val => val.Expression as MemberAccessExpressionSyntax).
                        Any(val => val.Name.Identifier.ValueText.Equals("Raise"));
                }

                if (hasRaise)
                {
                    base.WarningLog.Add(Tuple.Create(method.Identifier, $"Method '{method.Identifier.ValueText}' " +
                        $"of {this.GetTypeOfMachine().ToLower()} '{machine.Identifier.ValueText}' " +
                        "must not raise an event."));
                }

                var hasNestedRaise = method.DescendantNodes().OfType<InvocationExpressionSyntax>().
                    Where(val => val.Expression is IdentifierNameSyntax).
                    Select(val => val.Expression as IdentifierNameSyntax).
                    Select(val => val.Identifier.ValueText).
                    Any(val => this.ActionsThatRaise[machine].Any(a => a.Identifier.ValueText.Equals(val)));

                if (!hasNestedRaise)
                {
                    hasNestedRaise = method.DescendantNodes().OfType<InvocationExpressionSyntax>().
                        Where(val => val.Expression is MemberAccessExpressionSyntax).
                        Select(val => val.Expression as MemberAccessExpressionSyntax).
                        Select(val => val.Name.Identifier.ValueText).
                        Any(val => this.ActionsThatRaise[machine].Any(a => a.Identifier.ValueText.Equals(val)));
                }

                if (hasNestedRaise)
                {
                    base.WarningLog.Add(Tuple.Create(method.Identifier, $"Method '{method.Identifier.ValueText}' " +
                        $"of {this.GetTypeOfMachine().ToLower()} '{machine.Identifier.ValueText}' " +
                        "must not call a method that raises an event."));
                }
            }
        }
Example #23
0
        /// <summary>
        /// Checks that no structs are declared inside the machine.
        /// </summary>
        /// <param name="machine">Machine</param>
        private void CheckForStructs(ClassDeclarationSyntax machine)
        {
            var structIdentifiers = machine.DescendantNodes().OfType<StructDeclarationSyntax>().
                Select(val => val.Identifier).
                ToList();

            foreach (var identifier in structIdentifiers)
            {
                base.ErrorLog.Add(Tuple.Create(identifier, "Not allowed to declare struct '" +
                    identifier.ValueText + "' inside " + this.GetTypeOfMachine().ToLower() + " '" +
                    machine.Identifier.ValueText + "'."));
            }
        }
		public static async Task<Solution> MoveTypeToFileAsync(this Document document, ClassDeclarationSyntax typeDecl, CancellationToken cancellationToken = default(CancellationToken))
		{
			CompilationUnitSyntax compilationUnitSyntax = (CompilationUnitSyntax)(await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false));
			IEnumerable<MemberDeclarationSyntax> arg_B5_0 = compilationUnitSyntax.Members;
			Func<MemberDeclarationSyntax, bool> arg_B5_1;
			if ((arg_B5_1 = MoveTypeToFileFunction) == null)
			{
				arg_B5_1 = (MoveTypeToFileFunction = new Func<MemberDeclarationSyntax, bool>(m => Microsoft.CodeAnalysis.CSharpExtensions.IsKind(m, SyntaxKind.NamespaceDeclaration)));
			}

			var semanticModel = await document.GetSemanticModelAsync(cancellationToken);

			MethodDeclarationSyntax initializeComponentMethod = typeDecl.DescendantNodes().OfType<MethodDeclarationSyntax>().Single(m => m.Identifier.ValueText == "InitializeComponent" && m.ParameterList.Parameters.Count == 0);

			var localVars = typeDecl.DescendantNodes().OfType<FieldDeclarationSyntax>().ToDictionary(fds => fds.DescendantNodes().OfType<VariableDeclaratorSyntax>().Single().Identifier.Text);

			var simpleAssigns = initializeComponentMethod.Body.DescendantNodes().OfType<MemberAccessExpressionSyntax>().Where(mea => mea.Kind() == SyntaxKind.SimpleMemberAccessExpression && mea.ChildNodes().OfType<ThisExpressionSyntax>().Any()).SelectMany(id => id.DescendantNodes().OfType<IdentifierNameSyntax>()).Select(i => i.Identifier.Text).Distinct().ToList();

			NamespaceDeclarationSyntax namespaceDeclarationSyntax = (NamespaceDeclarationSyntax)arg_B5_0.Single(arg_B5_1);
			Solution solution = document.Project.Solution;

			DocumentId documentId = DocumentId.CreateNewId(document.Project.Id, null);

			List<SyntaxNode> toBeDeleted = new List<SyntaxNode>();
			toBeDeleted.Add(initializeComponentMethod);

			foreach (var item in localVars)
			{
				if (simpleAssigns.Contains(item.Key))
				{
					toBeDeleted.Add(item.Value);
				}
			}

			var oldType = SyntaxNodeExtensions.RemoveNodes(typeDecl, toBeDeleted, SyntaxRemoveOptions.KeepDirectives).AddModifiers(SyntaxFactory.Token(SyntaxKind.PartialKeyword));

			solution = document.ReplaceFromDocumentAsync(typeDecl, oldType, cancellationToken).Result.Project.Solution;

			var modifiers = SyntaxFactory.TokenList(new SyntaxToken[] { SyntaxFactory.Token(SyntaxKind.PartialKeyword) });
			var newType = SyntaxFactory.ClassDeclaration(typeDecl.Identifier).WithModifiers(modifiers);
			var method1 = SyntaxFactory.MethodDeclaration(SyntaxFactory.PredefinedType(SyntaxFactory.Token(SyntaxKind.VoidKeyword)), "InitializeComponent");
			method1 = method1.WithBody(initializeComponentMethod.Body);
			newType = newType.AddMembers(method1);

			foreach (var item in localVars)
			{
				if (simpleAssigns.Contains(item.Key))
				{
					var varMod = SyntaxFactory.TokenList(item.Value.Modifiers.Select(t => SyntaxFactory.Token(t.Kind())).ToArray());
					newType = newType.AddMembers(SyntaxFactory.FieldDeclaration(item.Value.AttributeLists, varMod, item.Value.Declaration));
				}
			}

			solution = solution.AddDocument(documentId, Path.GetFileNameWithoutExtension(document.Name) + ".designer"+ Path.GetExtension(document.Name), newType.GetText(), document.Folders, null, true);
			CompilationUnitSyntax compilationUnitSyntax2 = SyntaxFactory.CompilationUnit().AddUsings(compilationUnitSyntax.Usings.ToArray()).AddMembers(new MemberDeclarationSyntax[]
			{
				SyntaxNodeExtensions.WithLeadingTrivia(SyntaxNodeExtensions.NormalizeWhitespace(SyntaxFactory.NamespaceDeclaration(namespaceDeclarationSyntax.Name), "    ", false), new SyntaxTrivia[]
				{
					SyntaxFactory.Whitespace("\r\n")
				}).AddMembers(new MemberDeclarationSyntax[] { newType })
			});
			return solution.WithDocumentSyntaxRoot(documentId, compilationUnitSyntax2, 0);
		}
Example #25
0
        /// <summary>
        /// Checks that a pop statement is not used in a machine method.
        /// </summary>
        /// <param name="machine">Machine</param>
        private void CheckForPopStatementsInMethods(ClassDeclarationSyntax machine)
        {
            var methods = machine.DescendantNodes().OfType<MethodDeclarationSyntax>().
                Where(val => !this.Actions[machine].Contains(val)).
                ToList();

            foreach (var method in methods)
            {
                var hasPop = method.DescendantNodes().OfType<InvocationExpressionSyntax>().
                    Where(val => val.Expression is IdentifierNameSyntax).
                    Select(val => val.Expression as IdentifierNameSyntax).
                    Any(val => val.Identifier.ValueText.Equals("Pop"));

                if (!hasPop)
                {
                    hasPop = method.DescendantNodes().OfType<InvocationExpressionSyntax>().
                        Where(val => val.Expression is MemberAccessExpressionSyntax).
                        Select(val => val.Expression as MemberAccessExpressionSyntax).
                        Any(val => val.Name.Identifier.ValueText.Equals("Pop"));
                }

                if (hasPop)
                {
                    base.ErrorLog.Add(Tuple.Create(method.Identifier, "Method '" + method.Identifier.ValueText +
                        "' of " + this.GetTypeOfMachine().ToLower() + " `" + machine.Identifier.ValueText +
                        "` must not pop a state."));
                }

                var hasNestedPop = method.DescendantNodes().OfType<InvocationExpressionSyntax>().
                    Where(val => val.Expression is IdentifierNameSyntax).
                    Select(val => val.Expression as IdentifierNameSyntax).
                    Select(val => val.Identifier.ValueText).
                    Any(val => this.ActionsThaPop[machine].Any(a => a.Identifier.ValueText.Equals(val)));

                if (!hasNestedPop)
                {
                    hasNestedPop = method.DescendantNodes().OfType<InvocationExpressionSyntax>().
                        Where(val => val.Expression is MemberAccessExpressionSyntax).
                        Select(val => val.Expression as MemberAccessExpressionSyntax).
                        Select(val => val.Name.Identifier.ValueText).
                        Any(val => this.ActionsThaPop[machine].Any(a => a.Identifier.ValueText.Equals(val)));
                }

                if (hasNestedPop)
                {
                    base.ErrorLog.Add(Tuple.Create(method.Identifier, "Method '" + method.Identifier.ValueText +
                        "' of " + this.GetTypeOfMachine().ToLower() + " `" + machine.Identifier.ValueText +
                        "` must not call a method that pops a state."));
                }
            }
        }
Example #26
0
        /// <summary>
        /// Checks that a state does not have a duplicate exit action.
        /// </summary>
        /// <param name="state">State</param>
        /// <param name="compilation">Compilation</param>
        private void CheckForDuplicateOnExit(ClassDeclarationSyntax state, CodeAnalysis.Compilation compilation)
        {
            var model = compilation.GetSemanticModel(state.SyntaxTree);

            var onExitAttribute = state.AttributeLists.
                SelectMany(val => val.Attributes).
                Where(val => model.GetTypeInfo(val).Type.ToDisplayString().Equals("Microsoft.PSharp.OnExit")).
                FirstOrDefault();

            var onExitMethod = state.DescendantNodes().OfType<MethodDeclarationSyntax>().
                Where(val => val.Modifiers.Any(SyntaxKind.OverrideKeyword)).
                Where(val => val.Identifier.ValueText.Equals("OnExit")).
                FirstOrDefault();

            if (onExitAttribute != null && onExitMethod != null)
            {
                base.ErrorLog.Add(Tuple.Create(state.Identifier, "State '" +
                    state.Identifier.ValueText + "' cannot have two exit actions."));
            }
        }
        private IEnumerable<PropertyModel> GetProperty(ClassDeclarationSyntax cs, CompilationUnitSyntax root)
        {
            List<PropertyModel> result = new List<PropertyModel>();

            foreach (PropertyDeclarationSyntax ps in cs.DescendantNodes().OfType<PropertyDeclarationSyntax>())
            {
                PropertyModel prop = new PropertyModel();
                prop.Name = ps.Identifier.ToFullString().Trim();
                prop.Modifier = ps.Modifiers.ToFullString().Trim();
                prop.TypeName = ps.Type.ToFullString().Trim();
                foreach (var accessor in ps.AccessorList.Accessors)
                {
                    if (accessor.Keyword.ValueText == "set")
                    {
                        prop.HasSetAccess = true;
                        if (accessor.Body != null)
                        {
                            prop.SetAccessor = accessor.Body.ToFullString();
                        }
                    }

                    if (accessor.Keyword.ValueText == "get")
                    {
                        prop.HasGetAccess = true;
                        if (accessor.Body != null)
                        {
                            prop.GetAccessor = accessor.Body.ToFullString();
                        }
                    }
                }

                result.Add(prop);
            }

            return result;
        }
        private TestFixtureDetails ExtractTests(ClassDeclarationSyntax testClass, ISemanticModel semanticModel)
        {
            var testFixture = new TestFixtureDetails();
            testFixture.FullClassName = semanticModel.GetFullName(testClass);

            foreach (MethodDeclarationSyntax methodNode in testClass.DescendantNodes().OfType<MethodDeclarationSyntax>())
            {
                ExtractMethodTests(testFixture, methodNode, semanticModel);
            }

            return testFixture;
        }