Ejemplo n.º 1
0
        /// <summary>
        /// Generates the class for the provided grain types.
        /// </summary>
        internal static TypeDeclarationSyntax GenerateClass(WellKnownTypes wellKnownTypes, GrainInterfaceDescription description)
        {
            var generatedTypeName = description.InvokerTypeName;
            var grainType         = description.Type;
            var baseTypes         = new List <BaseTypeSyntax> {
                SimpleBaseType(wellKnownTypes.IGrainMethodInvoker.ToTypeSyntax())
            };

            var genericTypes = grainType.GetHierarchyTypeParameters()
                               .Select(_ => TypeParameter(_.ToString()))
                               .ToArray();

            // Create the special method invoker marker attribute.
            var interfaceId         = description.InterfaceId;
            var interfaceIdArgument = interfaceId.ToHexLiteral();
            var grainTypeArgument   = TypeOfExpression(grainType.WithoutTypeParameters().ToTypeSyntax());
            var attributes          = new List <AttributeSyntax>
            {
                GeneratedCodeAttributeGenerator.GetGeneratedCodeAttributeSyntax(wellKnownTypes),
                Attribute(wellKnownTypes.MethodInvokerAttribute.ToNameSyntax())
                .AddArgumentListArguments(
                    AttributeArgument(grainTypeArgument),
                    AttributeArgument(interfaceIdArgument)),
                Attribute(wellKnownTypes.ExcludeFromCodeCoverageAttribute.ToNameSyntax())
            };

            var genericInvokerFields = GenerateGenericInvokerFields(wellKnownTypes, description.Methods);
            var members = new List <MemberDeclarationSyntax>(genericInvokerFields)
            {
                GenerateInvokeMethod(wellKnownTypes, grainType),
                GrainInterfaceCommon.GenerateInterfaceIdProperty(wellKnownTypes, description),
                GrainInterfaceCommon.GenerateInterfaceVersionProperty(wellKnownTypes, description)
            };

            // If this is an IGrainExtension, make the generated class implement IGrainExtensionMethodInvoker.
            if (grainType.HasInterface(wellKnownTypes.IGrainExtension))
            {
                baseTypes.Add(SimpleBaseType(wellKnownTypes.IGrainExtensionMethodInvoker.ToTypeSyntax()));
                members.Add(GenerateExtensionInvokeMethod(wellKnownTypes, grainType));
            }

            var classDeclaration =
                ClassDeclaration(generatedTypeName)
                .AddModifiers(Token(SyntaxKind.InternalKeyword))
                .AddBaseListTypes(baseTypes.ToArray())
                .AddConstraintClauses(grainType.GetTypeConstraintSyntax())
                .AddMembers(members.ToArray())
                .AddAttributeLists(AttributeList().AddAttributes(attributes.ToArray()));

            if (genericTypes.Length > 0)
            {
                classDeclaration = classDeclaration.AddTypeParameterListParameters(genericTypes);
            }

            return(classDeclaration);
        }
Ejemplo n.º 2
0
        private static MethodDeclarationSyntax GenerateGetMethodNameMethod(WellKnownTypes wellKnownTypes, GrainInterfaceDescription description)
        {
            var method            = wellKnownTypes.GrainReference.Method("GetMethodName");
            var methodDeclaration = method.GetDeclarationSyntax().AddModifiers(Token(SyntaxKind.OverrideKeyword));
            var parameters        = method.Parameters;

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

            var callThrowMethodNotImplemented = InvocationExpression(IdentifierName("ThrowMethodNotImplemented"))
                                                .WithArgumentList(ArgumentList(SeparatedList(new[]
            {
                Argument(interfaceIdArgument),
                Argument(methodIdArgument)
            })));

            // This method is used directly after its declaration to create blocks for each interface id, comprising
            // primarily of a nested switch statement for each of the methods in the given interface.
            BlockSyntax ComposeInterfaceBlock(INamedTypeSymbol interfaceType, SwitchStatementSyntax methodSwitch)
            {
                return(Block(methodSwitch.AddSections(SwitchSection()
                                                      .AddLabels(DefaultSwitchLabel())
                                                      .AddStatements(
                                                          ExpressionStatement(callThrowMethodNotImplemented),
                                                          ReturnStatement(LiteralExpression(SyntaxKind.NullLiteralExpression))))));
            }

            var interfaceCases = GrainInterfaceCommon.GenerateGrainInterfaceAndMethodSwitch(
                wellKnownTypes,
                description.Type,
                methodIdArgument,
                methodType => new StatementSyntax[] { ReturnStatement(methodType.Name.ToLiteralExpression()) },
                ComposeInterfaceBlock);

            // Generate the default case, which will throw a NotImplementedException.
            var callThrowInterfaceNotImplemented = InvocationExpression(IdentifierName("ThrowInterfaceNotImplemented"))
                                                   .WithArgumentList(ArgumentList(SingletonSeparatedList(Argument(interfaceIdArgument))));
            var defaultCase = SwitchSection()
                              .AddLabels(DefaultSwitchLabel())
                              .AddStatements(
                ExpressionStatement(callThrowInterfaceNotImplemented),
                ReturnStatement(LiteralExpression(SyntaxKind.NullLiteralExpression)));

            var throwInterfaceNotImplemented = GrainInterfaceCommon.GenerateMethodNotImplementedFunction(wellKnownTypes);
            var throwMethodNotImplemented    = GrainInterfaceCommon.GenerateInterfaceNotImplementedFunction(wellKnownTypes);

            var interfaceIdSwitch =
                SwitchStatement(interfaceIdArgument).AddSections(interfaceCases.ToArray()).AddSections(defaultCase);

            return(methodDeclaration.AddBodyStatements(interfaceIdSwitch, throwInterfaceNotImplemented, throwMethodNotImplemented));
        }
        /// <summary>
        /// Generates the class for the provided grain types.
        /// </summary>
        internal TypeDeclarationSyntax GenerateClass(GrainInterfaceDescription description)
        {
            var generatedTypeName = description.ReferenceTypeName;
            var grainType         = description.Type;
            var genericTypes      = grainType.GetHierarchyTypeParameters()
                                    .Select(_ => TypeParameter(_.ToString()))
                                    .ToArray();

            // Create the special marker attribute.
            var grainTypeArgument = TypeOfExpression(grainType.WithoutTypeParameters().ToTypeSyntax());

            var attributes = AttributeList()
                             .AddAttributes(
                GeneratedCodeAttributeGenerator.GetGeneratedCodeAttributeSyntax(wellKnownTypes),
                Attribute(wellKnownTypes.SerializableAttribute.ToNameSyntax()),
                Attribute(wellKnownTypes.ExcludeFromCodeCoverageAttribute.ToNameSyntax()),
                Attribute(wellKnownTypes.GrainReferenceAttribute.ToNameSyntax())
                .AddArgumentListArguments(AttributeArgument(grainTypeArgument)));

            var classDeclaration =
                ClassDeclaration(generatedTypeName)
                .AddModifiers(Token(SyntaxKind.InternalKeyword))
                .AddBaseListTypes(
                    SimpleBaseType(wellKnownTypes.GrainReference.ToTypeSyntax()),
                    SimpleBaseType(grainType.ToTypeSyntax()))
                .AddConstraintClauses(grainType.GetTypeConstraintSyntax())
                .AddMembers(GenerateConstructors(generatedTypeName))
                .AddMembers(
                    GrainInterfaceCommon.GenerateInterfaceIdProperty(this.wellKnownTypes, description).AddModifiers(Token(SyntaxKind.OverrideKeyword)),
                    GrainInterfaceCommon.GenerateInterfaceVersionProperty(this.wellKnownTypes, description).AddModifiers(Token(SyntaxKind.OverrideKeyword)),
                    GenerateInterfaceNameProperty(description),
                    GenerateIsCompatibleMethod(description),
                    GenerateGetMethodNameMethod(description))
                .AddMembers(GenerateInvokeMethods(description))
                .AddAttributeLists(attributes);

            if (genericTypes.Length > 0)
            {
                classDeclaration = classDeclaration.AddTypeParameterListParameters(genericTypes);
            }

            if (this.options.DebuggerStepThrough)
            {
                var debuggerStepThroughAttribute = Attribute(this.wellKnownTypes.DebuggerStepThroughAttribute.ToNameSyntax());
                classDeclaration = classDeclaration.AddAttributeLists(AttributeList().AddAttributes(debuggerStepThroughAttribute));
            }

            return(classDeclaration);
        }
        /// <summary>
        /// Generates syntax for an invoke method.
        /// </summary>
        private MethodDeclarationSyntax GenerateInvokeMethod(
            WellKnownTypes wellKnownTypes,
            INamedTypeSymbol grainType,
            IMethodSymbol invokeMethod,
            Dictionary <IMethodSymbol, GenericInvokerField> genericInvokerFields)
        {
            var parameters = invokeMethod.Parameters;

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

            var interfaceIdProperty = wellKnownTypes.InvokeMethodRequest.Property("InterfaceTypeCode");
            var methodIdProperty    = wellKnownTypes.InvokeMethodRequest.Property("MethodId");
            var argumentsProperty   = wellKnownTypes.InvokeMethodRequest.Property("Arguments");

            // Store the relevant values from the request in local variables.
            var interfaceIdDeclaration =
                LocalDeclarationStatement(
                    VariableDeclaration(wellKnownTypes.Int32.ToTypeSyntax())
                    .AddVariables(
                        VariableDeclarator("interfaceTypeCode")
                        .WithInitializer(EqualsValueClause(requestArgument.Member(interfaceIdProperty.Name)))));
            var interfaceIdVariable = IdentifierName("interfaceTypeCode");

            var methodIdDeclaration =
                LocalDeclarationStatement(
                    VariableDeclaration(wellKnownTypes.Int32.ToTypeSyntax())
                    .AddVariables(
                        VariableDeclarator("methodId")
                        .WithInitializer(EqualsValueClause(requestArgument.Member(methodIdProperty.Name)))));
            var methodIdVariable = IdentifierName("methodId");

            var argumentsDeclaration =
                LocalDeclarationStatement(
                    VariableDeclaration(IdentifierName("var"))
                    .AddVariables(
                        VariableDeclarator("arguments")
                        .WithInitializer(EqualsValueClause(requestArgument.Member(argumentsProperty.Name)))));
            var argumentsVariable = IdentifierName("arguments");

            var methodDeclaration = invokeMethod.GetDeclarationSyntax()
                                    .AddModifiers(Token(SyntaxKind.AsyncKeyword))
                                    .AddBodyStatements(interfaceIdDeclaration, methodIdDeclaration, argumentsDeclaration);

            var callThrowMethodNotImplemented = InvocationExpression(IdentifierName("ThrowMethodNotImplemented"))
                                                .WithArgumentList(ArgumentList(SeparatedList(new[]
            {
                Argument(interfaceIdVariable),
                Argument(methodIdVariable)
            })));

            // This method is used directly after its declaration to create blocks for each interface id, comprising
            // primarily of a nested switch statement for each of the methods in the given interface.
            BlockSyntax ComposeInterfaceBlock(INamedTypeSymbol interfaceType, SwitchStatementSyntax methodSwitch)
            {
                ExpressionSyntax targetObject;

                if (grainType.HasInterface(wellKnownTypes.IGrainExtension))
                {
                    targetObject = InvocationExpression(grainArgument.Member("GetGrainExtension", interfaceType), ArgumentList());
                }
                else
                {
                    targetObject = grainArgument.Member("GrainInstance");
                }

                var typedGrainDeclaration = LocalDeclarationStatement(
                    VariableDeclaration(IdentifierName("var"))
                    .AddVariables(
                        VariableDeclarator("casted")
                        .WithInitializer(EqualsValueClause(ParenthesizedExpression(CastExpression(interfaceType.ToTypeSyntax(), targetObject))))));

                return(Block(typedGrainDeclaration,
                             methodSwitch.AddSections(SwitchSection()
                                                      .AddLabels(DefaultSwitchLabel())
                                                      .AddStatements(
                                                          ExpressionStatement(callThrowMethodNotImplemented),
                                                          ReturnStatement(LiteralExpression(SyntaxKind.NullLiteralExpression))))));
            }

            var interfaceCases = GrainInterfaceCommon.GenerateGrainInterfaceAndMethodSwitch(
                wellKnownTypes,
                grainType,
                methodIdVariable,
                methodType => GenerateInvokeForMethod(wellKnownTypes, IdentifierName("casted"), methodType, argumentsVariable, genericInvokerFields),
                ComposeInterfaceBlock);

            var throwInterfaceNotImplemented = GrainInterfaceCommon.GenerateMethodNotImplementedFunction(wellKnownTypes);
            var throwMethodNotImplemented    = GrainInterfaceCommon.GenerateInterfaceNotImplementedFunction(wellKnownTypes);

            // Generate the default case, which will call the above local function to throw .
            var callThrowInterfaceNotImplemented = InvocationExpression(IdentifierName("ThrowInterfaceNotImplemented"))
                                                   .WithArgumentList(ArgumentList(SingletonSeparatedList(Argument(interfaceIdVariable))));
            var defaultCase = SwitchSection()
                              .AddLabels(DefaultSwitchLabel())
                              .AddStatements(
                ExpressionStatement(callThrowInterfaceNotImplemented),
                ReturnStatement(LiteralExpression(SyntaxKind.NullLiteralExpression)));

            var interfaceIdSwitch =
                SwitchStatement(interfaceIdVariable).AddSections(interfaceCases.ToArray()).AddSections(defaultCase);

            return(methodDeclaration.AddBodyStatements(interfaceIdSwitch, throwInterfaceNotImplemented, throwMethodNotImplemented));
        }