コード例 #1
0
        private static MethodDeclarationSyntax GenerateGetMethodNameMethod(Type grainType)
        {
            var method            = TypeUtils.Method((GrainReference _) => _.GetMethodName(default(int), default(int)));
            var methodDeclaration =
                method.GetDeclarationSyntax()
                .AddModifiers(SF.Token(SyntaxKind.OverrideKeyword));
            var parameters = method.GetParameters();

            var interfaceIdArgument = parameters[0].Name.ToIdentifierName();
            var methodIdArgument    = parameters[1].Name.ToIdentifierName();

            var interfaceCases = CodeGeneratorCommon.GenerateGrainInterfaceAndMethodSwitch(
                grainType,
                methodIdArgument,
                methodType => new StatementSyntax[] { SF.ReturnStatement(methodType.Name.GetLiteralExpression()) });

            // Generate the default case, which will throw a NotImplementedException.
            var errorMessage = SF.BinaryExpression(
                SyntaxKind.AddExpression,
                "interfaceId=".GetLiteralExpression(),
                interfaceIdArgument);
            var throwStatement =
                SF.ThrowStatement(
                    SF.ObjectCreationExpression(typeof(NotImplementedException).GetTypeSyntax())
                    .AddArgumentListArguments(SF.Argument(errorMessage)));
            var defaultCase       = SF.SwitchSection().AddLabels(SF.DefaultSwitchLabel()).AddStatements(throwStatement);
            var interfaceIdSwitch =
                SF.SwitchStatement(interfaceIdArgument).AddSections(interfaceCases.ToArray()).AddSections(defaultCase);

            return(methodDeclaration.AddBodyStatements(interfaceIdSwitch));
        }
コード例 #2
0
        /// <summary>
        /// The generate method.
        /// </summary>
        /// <param name="actor">
        /// The actor.
        /// </param>
        /// <returns>
        /// The <see cref="MethodDeclarationSyntax"/>.
        /// </returns>
        private static MethodDeclarationSyntax GenerateInvokeMethod(ActorDescription actor)
        {
            // Get the method with the correct type.
            var method =
                TypeUtil.GenericTypeMethod(
                    (IEventInvoker <IGrain> x) => x.Invoke(default(IGrain), default(Event)),
                    new[] { actor.Type });

            var methodDeclaration = method.GetMethodDeclarationSyntax();
            var parameters        = method.GetParameters();

            var @event =
                SF.IdentifierName(parameters.First(_ => typeof(Event) == _.ParameterType).Name);

            var instance =
                SF.IdentifierName(parameters.First(_ => actor.Type == _.ParameterType).Name);

            var switchCases    = GenerateSwitchCases(actor, m => GenerateDispatchBlockForMethod(m, instance, @event)).ToArray();
            var returnNull     = SF.ReturnStatement(SF.LiteralExpression(SyntaxKind.NullLiteralExpression));
            var defaultSection = SF.SwitchSection().AddLabels(SF.DefaultSwitchLabel()).AddStatements(returnNull);
            var kindSwitch     =
                SF.SwitchStatement(@event.Member((Event _) => _.Type))
                .AddSections(switchCases)
                .AddSections(defaultSection);

            return
                (methodDeclaration
                 .AddBodyStatements(kindSwitch));
        }
コード例 #3
0
            public override SyntaxList <StatementSyntax> VisitSelectBlock(VBSyntax.SelectBlockSyntax node)
            {
                var expr = (ExpressionSyntax)node.SelectStatement.Expression.Accept(_nodesVisitor);
                var exprWithoutTrivia = expr.WithoutTrivia().WithoutAnnotations();
                var sections          = new List <SwitchSectionSyntax>();

                foreach (var block in node.CaseBlocks)
                {
                    var labels = new List <SwitchLabelSyntax>();
                    foreach (var c in block.CaseStatement.Cases)
                    {
                        if (c is VBSyntax.SimpleCaseClauseSyntax s)
                        {
                            var expressionSyntax = (ExpressionSyntax)s.Value.Accept(_nodesVisitor);
                            SwitchLabelSyntax caseSwitchLabelSyntax = SyntaxFactory.CaseSwitchLabel(expressionSyntax);
                            if (!_semanticModel.GetConstantValue(s.Value).HasValue)
                            {
                                caseSwitchLabelSyntax =
                                    WrapInCasePatternSwitchLabelSyntax(expressionSyntax);
                            }

                            labels.Add(caseSwitchLabelSyntax);
                        }
                        else if (c is VBSyntax.ElseCaseClauseSyntax)
                        {
                            labels.Add(SyntaxFactory.DefaultSwitchLabel());
                        }
                        else if (c is VBSyntax.RelationalCaseClauseSyntax relational)
                        {
                            var operatorKind     = VBasic.VisualBasicExtensions.Kind(relational);
                            var cSharpSyntaxNode = SyntaxFactory.BinaryExpression(operatorKind.ConvertToken(TokenContext.Local), exprWithoutTrivia, (ExpressionSyntax)relational.Value.Accept(_nodesVisitor));
                            labels.Add(WrapInCasePatternSwitchLabelSyntax(cSharpSyntaxNode));
                        }
                        else if (c is VBSyntax.RangeCaseClauseSyntax range)
                        {
                            var lowerBoundCheck = SyntaxFactory.BinaryExpression(SyntaxKind.LessThanOrEqualExpression, (ExpressionSyntax)range.LowerBound.Accept(_nodesVisitor), exprWithoutTrivia);
                            var upperBoundCheck = SyntaxFactory.BinaryExpression(SyntaxKind.LessThanOrEqualExpression, exprWithoutTrivia, (ExpressionSyntax)range.UpperBound.Accept(_nodesVisitor));
                            var withinBounds    = SyntaxFactory.BinaryExpression(SyntaxKind.LogicalAndExpression, lowerBoundCheck, upperBoundCheck);
                            labels.Add(WrapInCasePatternSwitchLabelSyntax(withinBounds));
                        }
                        else
                        {
                            throw new NotSupportedException(c.Kind().ToString());
                        }
                    }

                    var csBlockStatements = block.Statements.SelectMany(s => s.Accept(CommentConvertingVisitor)).ToList();
                    if (csBlockStatements.LastOrDefault()
                        ?.IsKind(SyntaxKind.ReturnStatement) != true)
                    {
                        csBlockStatements.Add(SyntaxFactory.BreakStatement());
                    }
                    var list = SingleStatement(SyntaxFactory.Block(csBlockStatements));
                    sections.Add(SyntaxFactory.SwitchSection(SyntaxFactory.List(labels), list));
                }

                var switchStatementSyntax = SyntaxFactory.SwitchStatement(expr, SyntaxFactory.List(sections));

                return(SingleStatement(switchStatementSyntax));
            }
コード例 #4
0
        /// <summary>
        /// Returns syntax for dispatching <paramref name="event"/> to <paramref name="actor"/>.
        /// </summary>
        /// <param name="event">
        /// The event.
        /// </param>
        /// <param name="actor">
        /// The actor description.
        /// </param>
        /// <returns>
        /// Syntax for dispatching <paramref name="event"/> to <paramref name="actor"/>.
        /// </returns>
        private static StatementSyntax GenerateActorBlock(
            ExpressionSyntax @event,
            ActorDescription actor)
        {
            var @var      = SF.IdentifierName("var");
            var grainType = actor.Type.GetTypeSyntax();
            var getGrain  =
                SF.InvocationExpression(SF.IdentifierName("GrainFactory").Member("GetGrain", grainType))
                .AddArgumentListArguments(SF.Argument(@event.Member("To").Member("Id")));
            var grain            = SF.VariableDeclarator("grain").WithInitializer(SF.EqualsValueClause(getGrain));
            var grainDeclaration = SF.LocalDeclarationStatement(SF.VariableDeclaration(@var).AddVariables(grain));

            var returnNull = SF.ReturnStatement(SF.LiteralExpression(SyntaxKind.NullLiteralExpression));

            var defaultSection = SF.SwitchSection().AddLabels(SF.DefaultSwitchLabel()).AddStatements(returnNull);
            var methodSwitch   =
                SF.SwitchStatement(@event.Member("Type"))
                .AddSections(
                    actor.Methods.Values.Where(_ => _.Visible)
                    .Select(method => GetMethodSwitchCase(@event, method))
                    .ToArray())
                .AddSections(defaultSection);
            var methodDispatcher = SF.Block().AddStatements(grainDeclaration, methodSwitch);

            return(methodDispatcher);
        }
コード例 #5
0
        /// <summary>
        /// Returns method syntax for dispatching events to the provided <paramref name="actors"/>.
        /// </summary>
        /// <param name="actors">
        /// The actor descriptions.
        /// </param>
        /// <returns>
        /// Method syntax for dispatching events to the provided <paramref name="actors"/>.
        /// </returns>
        private static MethodDeclarationSyntax GenerateMethod(IEnumerable <ActorDescription> actors)
        {
            // Types
            var eventType  = typeof(Event).GetTypeSyntax();
            var returnType = typeof(Task <object>).GetTypeSyntax();

            // Local variables
            var @event = SF.IdentifierName("@event");

            // Parameters
            var eventParam = SF.Parameter(@event.Identifier).WithType(eventType);

            // Body statements
            var returnNull     = SF.ReturnStatement(SF.LiteralExpression(SyntaxKind.NullLiteralExpression));
            var defaultSection = SF.SwitchSection().AddLabels(SF.DefaultSwitchLabel()).AddStatements(returnNull);
            var kindSwitch     =
                SF.SwitchStatement(@event.Member("To").Member("Kind"))
                .AddSections(
                    actors.Where(actor => actor.Methods.Any())
                    .Select(actor => GetActorSwitch(actor, @event))
                    .ToArray())
                .AddSections(defaultSection);

            // Build and return the method.
            return
                (SF.MethodDeclaration(returnType, "Dispatch")
                 .AddModifiers(SF.Token(SyntaxKind.PublicKeyword))
                 .AddParameterListParameters(eventParam)
                 .AddBodyStatements(kindSwitch));
        }
コード例 #6
0
            private bool ConvertToSwitch(ExpressionSyntax expr, SyntaxList <VBSyntax.CaseBlockSyntax> caseBlocks, out SwitchStatementSyntax switchStatement)
            {
                switchStatement = null;

                var sections = new List <SwitchSectionSyntax>();

                foreach (var block in caseBlocks)
                {
                    var labels = new List <SwitchLabelSyntax>();
                    foreach (var c in block.CaseStatement.Cases)
                    {
                        if (c is VBSyntax.SimpleCaseClauseSyntax)
                        {
                            var s = (VBSyntax.SimpleCaseClauseSyntax)c;
                            labels.Add(SyntaxFactory.CaseSwitchLabel((ExpressionSyntax)s.Value.Accept(nodesVisitor)));
                        }
                        else if (c is VBSyntax.ElseCaseClauseSyntax)
                        {
                            labels.Add(SyntaxFactory.DefaultSwitchLabel());
                        }
                        else
                        {
                            return(false);
                        }
                    }
                    var list = SingleStatement(SyntaxFactory.Block(block.Statements.SelectMany(s => s.Accept(this)).Concat(SyntaxFactory.BreakStatement())));
                    sections.Add(SyntaxFactory.SwitchSection(SyntaxFactory.List(labels), list));
                }
                switchStatement = SyntaxFactory.SwitchStatement(expr, SyntaxFactory.List(sections));
                return(true);
            }
コード例 #7
0
        /// <summary>
        /// Generates syntax for an invoke method.
        /// </summary>
        /// <param name="grainType">
        /// The grain type.
        /// </param>
        /// <param name="invokeMethod">
        /// The invoke method to generate.
        /// </param>
        /// <returns>
        /// Syntax for an invoke method.
        /// </returns>
        private static MethodDeclarationSyntax GenerateInvokeMethod(Type grainType, MethodInfo invokeMethod)
        {
            var methodDeclaration = invokeMethod.GetDeclarationSyntax();
            var parameters        = invokeMethod.GetParameters();

            var grainArgument       = parameters[0].Name.ToIdentifierName();
            var interfaceIdArgument = parameters[1].Name.ToIdentifierName();
            var methodIdArgument    = parameters[2].Name.ToIdentifierName();
            var argumentsArgument   = parameters[3].Name.ToIdentifierName();

            var interfaceCases = CodeGeneratorCommon.GenerateGrainInterfaceAndMethodSwitch(
                grainType,
                methodIdArgument,
                methodType => GenerateInvokeForMethod(grainType, grainArgument, methodType, argumentsArgument));

            // Generate the default case, which will throw a NotImplementedException.
            var errorMessage = SF.BinaryExpression(
                SyntaxKind.AddExpression,
                "interfaceId=".GetLiteralExpression(),
                interfaceIdArgument);
            var throwStatement =
                SF.ThrowStatement(
                    SF.ObjectCreationExpression(typeof(NotImplementedException).GetTypeSyntax())
                    .AddArgumentListArguments(SF.Argument(errorMessage)));
            var defaultCase       = SF.SwitchSection().AddLabels(SF.DefaultSwitchLabel()).AddStatements(throwStatement);
            var interfaceIdSwitch =
                SF.SwitchStatement(interfaceIdArgument).AddSections(interfaceCases.ToArray()).AddSections(defaultCase);

            // If the provided grain is null, throw an argument exception.
            var argumentNullException =
                SF.ObjectCreationExpression(typeof(ArgumentNullException).GetTypeSyntax())
                .AddArgumentListArguments(SF.Argument(parameters[0].Name.GetLiteralExpression()));
            var grainArgumentCheck =
                SF.IfStatement(
                    SF.BinaryExpression(
                        SyntaxKind.EqualsExpression,
                        grainArgument,
                        SF.LiteralExpression(SyntaxKind.NullLiteralExpression)),
                    SF.ThrowStatement(argumentNullException));

            // Wrap everything in a try-catch block.
            var          faulted   = (Expression <Func <Task <object> > >)(() => TaskUtility.Faulted(null));
            const string Exception = "exception";
            var          exception = SF.Identifier(Exception);
            var          body      =
                SF.TryStatement()
                .AddBlockStatements(grainArgumentCheck, interfaceIdSwitch)
                .AddCatches(
                    SF.CatchClause()
                    .WithDeclaration(
                        SF.CatchDeclaration(typeof(Exception).GetTypeSyntax()).WithIdentifier(exception))
                    .AddBlockStatements(
                        SF.ReturnStatement(
                            faulted.Invoke().AddArgumentListArguments(SF.Argument(SF.IdentifierName(Exception))))));

            return(methodDeclaration.AddBodyStatements(body));
        }
コード例 #8
0
        /// <summary>
        /// Returns syntax for the <see cref="IEventInvoker{T}.GetArgumentTypes"/> method.
        /// </summary>
        /// <param name="actor">
        /// The actor description.
        /// </param>
        /// <returns>
        /// Syntax for the <see cref="IEventInvoker{T}.GetArgumentTypes"/> method.
        /// </returns>
        private static MemberDeclarationSyntax GenerateGetTypeArgumentsMethod(ActorDescription actor)
        {
            var method = TypeUtil.GenericTypeMethod(
                (IEventInvoker <IGrain> m) => m.GetArgumentTypes(default(string)),
                new[] { actor.Type });
            var methodDeclaration = method.GetMethodDeclarationSyntax();
            var parameters        = method.GetParameters();

            var eventTypeArg =
                SF.IdentifierName(parameters.First(_ => typeof(string) == _.ParameterType).Name);

            var switchCases    = GenerateSwitchCases(actor, GenerateGetTypeArgumentsSwitchBlock).ToArray();
            var returnNull     = SF.ReturnStatement(SF.LiteralExpression(SyntaxKind.NullLiteralExpression));
            var defaultSection = SF.SwitchSection().AddLabels(SF.DefaultSwitchLabel()).AddStatements(returnNull);
            var kindSwitch     =
                SF.SwitchStatement(eventTypeArg)
                .AddSections(switchCases)
                .AddSections(defaultSection);

            return(methodDeclaration.AddBodyStatements(kindSwitch));
        }
コード例 #9
0
        /// <summary>
        /// Generates switch cases for the provided grain type.
        /// </summary>
        /// <param name="grainType">
        /// The grain type.
        /// </param>
        /// <param name="methodIdArgument">
        /// The method id argument, which is used to select the correct switch label.
        /// </param>
        /// <param name="generateMethodHandler">
        /// The function used to generate switch block statements for each method.
        /// </param>
        /// <returns>
        /// The switch cases for the provided grain type.
        /// </returns>
        public static SwitchSectionSyntax[] GenerateGrainInterfaceAndMethodSwitch(
            Type grainType,
            IdentifierNameSyntax methodIdArgument,
            Func <MethodInfo, StatementSyntax[]> generateMethodHandler)
        {
            var interfaces = GrainInterfaceData.GetRemoteInterfaces(grainType);

            interfaces[GrainInterfaceData.GetGrainInterfaceId(grainType)] = grainType;

            // Switch on interface id.
            var interfaceCases = new List <SwitchSectionSyntax>();

            foreach (var @interface in interfaces)
            {
                var interfaceType = @interface.Value;
                var interfaceId   = @interface.Key;
                var methods       = GrainInterfaceData.GetMethods(interfaceType);

                var methodCases = new List <SwitchSectionSyntax>();

                // Switch on method id.
                foreach (var method in methods)
                {
                    // Generate switch case.
                    var methodId   = GrainInterfaceData.ComputeMethodId(method);
                    var methodType = method;

                    // Generate the switch label for this interface id.
                    var methodIdSwitchLabel =
                        SF.CaseSwitchLabel(
                            SF.LiteralExpression(SyntaxKind.NumericLiteralExpression, SF.Literal(methodId)));

                    // Generate the switch body.
                    var methodInvokeStatement = generateMethodHandler(methodType);

                    methodCases.Add(
                        SF.SwitchSection().AddLabels(methodIdSwitchLabel).AddStatements(methodInvokeStatement));
                }

                // Generate the switch label for this interface id.
                var interfaceIdSwitchLabel =
                    SF.CaseSwitchLabel(
                        SF.LiteralExpression(SyntaxKind.NumericLiteralExpression, SF.Literal(interfaceId)));

                // Generate the default case, which will throw a NotImplementedException.
                var errorMessage = SF.BinaryExpression(
                    SyntaxKind.AddExpression,
                    "interfaceId=".GetLiteralExpression(),
                    SF.BinaryExpression(
                        SyntaxKind.AddExpression,
                        SF.LiteralExpression(SyntaxKind.NumericLiteralExpression, SF.Literal(interfaceId)),
                        SF.BinaryExpression(
                            SyntaxKind.AddExpression,
                            ",methodId=".GetLiteralExpression(),
                            methodIdArgument)));
                var throwStatement =
                    SF.ThrowStatement(
                        SF.ObjectCreationExpression(typeof(NotImplementedException).GetTypeSyntax())
                        .AddArgumentListArguments(SF.Argument(errorMessage)));
                var defaultCase = SF.SwitchSection().AddLabels(SF.DefaultSwitchLabel()).AddStatements(throwStatement);

                // Generate switch statements for the methods in this interface.
                var methodSwitchStatements =
                    SF.SwitchStatement(methodIdArgument).AddSections(methodCases.ToArray()).AddSections(defaultCase);

                // Generate the switch section for this interface.
                interfaceCases.Add(
                    SF.SwitchSection().AddLabels(interfaceIdSwitchLabel).AddStatements(methodSwitchStatements));
            }

            return(interfaceCases.ToArray());
        }
コード例 #10
0
        /// <summary>
        /// Generates syntax for an invoke method.
        /// </summary>
        /// <param name="grainType">
        /// The grain type.
        /// </param>
        /// <param name="invokeMethod">
        /// The invoke method to generate.
        /// </param>
        /// <returns>
        /// Syntax for an invoke method.
        /// </returns>
        private static MethodDeclarationSyntax GenerateInvokeMethod(Type grainType, MethodInfo invokeMethod)
        {
            var parameters = invokeMethod.GetParameters();

            var grainArgument   = parameters[0].Name.ToIdentifierName();
            var requestArgument = parameters[1].Name.ToIdentifierName();

            // Store the relevant values from the request in local variables.
            var interfaceIdDeclaration =
                SF.LocalDeclarationStatement(
                    SF.VariableDeclaration(typeof(int).GetTypeSyntax())
                    .AddVariables(
                        SF.VariableDeclarator("interfaceId")
                        .WithInitializer(SF.EqualsValueClause(requestArgument.Member((InvokeMethodRequest _) => _.InterfaceId)))));
            var interfaceIdVariable = SF.IdentifierName("interfaceId");

            var methodIdDeclaration =
                SF.LocalDeclarationStatement(
                    SF.VariableDeclaration(typeof(int).GetTypeSyntax())
                    .AddVariables(
                        SF.VariableDeclarator("methodId")
                        .WithInitializer(SF.EqualsValueClause(requestArgument.Member((InvokeMethodRequest _) => _.MethodId)))));
            var methodIdVariable = SF.IdentifierName("methodId");

            var argumentsDeclaration =
                SF.LocalDeclarationStatement(
                    SF.VariableDeclaration(typeof(object[]).GetTypeSyntax())
                    .AddVariables(
                        SF.VariableDeclarator("arguments")
                        .WithInitializer(SF.EqualsValueClause(requestArgument.Member((InvokeMethodRequest _) => _.Arguments)))));
            var argumentsVariable = SF.IdentifierName("arguments");

            var methodDeclaration = invokeMethod.GetDeclarationSyntax()
                                    .AddBodyStatements(interfaceIdDeclaration, methodIdDeclaration, argumentsDeclaration);

            var interfaceCases = CodeGeneratorCommon.GenerateGrainInterfaceAndMethodSwitch(
                grainType,
                methodIdVariable,
                methodType => GenerateInvokeForMethod(grainType, grainArgument, methodType, argumentsVariable));

            // Generate the default case, which will throw a NotImplementedException.
            var errorMessage = SF.BinaryExpression(
                SyntaxKind.AddExpression,
                "interfaceId=".GetLiteralExpression(),
                interfaceIdVariable);
            var throwStatement =
                SF.ThrowStatement(
                    SF.ObjectCreationExpression(typeof(NotImplementedException).GetTypeSyntax())
                    .AddArgumentListArguments(SF.Argument(errorMessage)));
            var defaultCase       = SF.SwitchSection().AddLabels(SF.DefaultSwitchLabel()).AddStatements(throwStatement);
            var interfaceIdSwitch =
                SF.SwitchStatement(interfaceIdVariable).AddSections(interfaceCases.ToArray()).AddSections(defaultCase);

            // If the provided grain is null, throw an argument exception.
            var argumentNullException =
                SF.ObjectCreationExpression(typeof(ArgumentNullException).GetTypeSyntax())
                .AddArgumentListArguments(SF.Argument(parameters[0].Name.GetLiteralExpression()));
            var grainArgumentCheck =
                SF.IfStatement(
                    SF.BinaryExpression(
                        SyntaxKind.EqualsExpression,
                        grainArgument,
                        SF.LiteralExpression(SyntaxKind.NullLiteralExpression)),
                    SF.ThrowStatement(argumentNullException));

            return(methodDeclaration.AddBodyStatements(grainArgumentCheck, interfaceIdSwitch));
        }