Esempio n. 1
0
        public ClassDeclarationSyntax GeneratePartialController(INamedTypeSymbol controllerSymbol, string areaKey, string areaName, string controllerName, string projectRoot)
        {
            // build controller partial class node
            // add a default constructor if there are some but none are zero length
            var genControllerClass = SyntaxNodeHelpers.CreateClass(
                controllerSymbol.Name,
                controllerSymbol.TypeParameters.Select(tp => TypeParameter(tp.Name)).ToArray(),
                SyntaxKind.PublicKeyword,
                SyntaxKind.PartialKeyword);

            var gotCustomConstructors = controllerSymbol.Constructors
                                        .Where(c => c.DeclaredAccessibility == Accessibility.Public)
                                        .Where(SyntaxNodeHelpers.IsNotR4MVCGenerated)
                                        .Where(c => !c.IsImplicitlyDeclared)
                                        .Any();

            if (!gotCustomConstructors)
            {
                genControllerClass = genControllerClass.WithDefaultConstructor(true, SyntaxKind.PublicKeyword);
            }
            genControllerClass = genControllerClass.WithDummyConstructor(true, SyntaxKind.ProtectedKeyword);
            genControllerClass = AddRedirectMethods(genControllerClass);

            // add all method stubs, TODO criteria for this: only public virtual actionresults?
            // add subclasses, fields, properties, constants for action names
            genControllerClass = AddParameterlessMethods(genControllerClass, controllerSymbol);
            var actionsExpression = !string.IsNullOrEmpty(areaKey)
                ? SyntaxNodeHelpers.MemberAccess(_settings.HelpersPrefix + "." + areaKey, controllerName)
                : SyntaxNodeHelpers.MemberAccess(_settings.HelpersPrefix, controllerName);

            genControllerClass =
                genControllerClass
                .WithProperty("Actions", controllerSymbol.Name, actionsExpression, SyntaxKind.PublicKeyword)
                .WithStringField(
                    "Area",
                    areaName,
                    true,
                    SyntaxKind.PublicKeyword,
                    SyntaxKind.ReadOnlyKeyword)
                .WithStringField(
                    "Name",
                    controllerName,
                    true,
                    SyntaxKind.PublicKeyword,
                    SyntaxKind.ReadOnlyKeyword)
                .WithStringField(
                    "NameConst",
                    controllerName,
                    true,
                    SyntaxKind.PublicKeyword,
                    SyntaxKind.ConstKeyword)
                .WithField("s_actions", "ActionNamesClass", SyntaxKind.StaticKeyword, SyntaxKind.ReadOnlyKeyword)
                .WithProperty("ActionNames", "ActionNamesClass", IdentifierName("s_actions"), SyntaxKind.PublicKeyword)
                .WithActionNameClass(controllerSymbol)
                .WithActionConstantsClass(controllerSymbol)
                .WithViewsClass(controllerName, areaName, _viewLocator.FindViews(projectRoot));

            return(genControllerClass);
        }
Esempio n. 2
0
 private ConstructorDeclarationSyntax CreateIActionResultConstructor(string className)
 => ConstructorDeclaration(className)
 .WithModifiers(SyntaxKind.PublicKeyword)
 .AddParameterListParameters(
     Parameter(Identifier("area")).WithType(SyntaxNodeHelpers.PredefinedStringType()),
     Parameter(Identifier("controller")).WithType(SyntaxNodeHelpers.PredefinedStringType()),
     Parameter(Identifier("action")).WithType(SyntaxNodeHelpers.PredefinedStringType()),
     Parameter(Identifier("protocol")).WithType(SyntaxNodeHelpers.PredefinedStringType())
     .WithDefault(EqualsValueClause(LiteralExpression(SyntaxKind.NullLiteralExpression))))
 .WithBody(
     Block(
         ExpressionStatement(
             InvocationExpression(
                 SyntaxNodeHelpers.MemberAccess("this", "InitMVCT4Result"))
             .WithArgumentList(
                 IdentifierName("area"),
                 IdentifierName("controller"),
                 IdentifierName("action"),
                 IdentifierName("protocol")))));
Esempio n. 3
0
        private ClassDeclarationSyntax AddParameterlessMethods(ClassDeclarationSyntax node, ITypeSymbol mvcSymbol)
        {
            var methods = mvcSymbol.GetPublicNonGeneratedMethods()
                          .GroupBy(m => m.Name)
                          .Where(g => !g.Any(m => m.Parameters.Length == 0))
                          .Select(g => MethodDeclaration(IdentifierName("IActionResult"), Identifier(g.Key))
                                  .WithModifiers(SyntaxKind.PublicKeyword, SyntaxKind.VirtualKeyword)
                                  .WithAttributes(SyntaxNodeHelpers.CreateNonActionAttribute())
                                  .WithAttributes(SyntaxNodeHelpers.CreateGeneratedCodeAttribute(), SyntaxNodeHelpers.CreateDebugNonUserCodeAttribute())
                                  .WithBody(
                                      Block(
                                          // return new R4Mvc_Microsoft_AspNetCore_Mvc_ActionResult(Area, Name, ActionNames.{Action});
                                          ReturnStatement(
                                              ObjectCreationExpression(IdentifierName(Constants.ActionResultClass))
                                              .WithArgumentList(
                                                  IdentifierName("Area"),
                                                  IdentifierName("Name"),
                                                  SyntaxNodeHelpers.MemberAccess("ActionNames", g.Key))))));

            return(node.AddMembers(methods.ToArray()));
        }
Esempio n. 4
0
        public void Generate(CSharpCompilation compilation, string projectRoot)
        {
            // create static MVC class and add controller fields
            var mvcStaticClass =
                SyntaxNodeHelpers.CreateClass(_settings.HelpersPrefix, null, SyntaxKind.PublicKeyword, SyntaxKind.StaticKeyword, SyntaxKind.PartialKeyword)
                .WithAttributes(SyntaxNodeHelpers.CreateGeneratedCodeAttribute(), SyntaxNodeHelpers.CreateDebugNonUserCodeAttribute());

            // R4MVC namespace used for the areas and Dummy class
            var r4Namespace = SyntaxNodeHelpers.CreateNamespace(_settings.R4MvcNamespace)
                              // add the dummy class using in the derived controller partial class
                              .WithDummyClass();
            var areaClasses = new Dictionary <string, ClassDeclarationSyntax>();

            var controllers       = _controllerRewriter.RewriteControllers(compilation, R4MvcFileName);
            var controllerDetails = controllers
                                    .Where(c => !c.SyntaxTree.FilePath.EndsWith(".generated.cs"))
                                    .Select(c =>
            {
                var @namespace       = c.Ancestors().OfType <NamespaceDeclarationSyntax>().First().Name.ToFullString().Trim();
                var model            = compilation.GetSemanticModel(c.SyntaxTree);
                var controllerSymbol = model.GetDeclaredSymbol(c);
                var controllerName   = controllerSymbol.Name.TrimEnd("Controller");
                var areaName         = _controllerGenerator.GetControllerArea(controllerSymbol);
                return(new

                {
                    FilePath = c.SyntaxTree.FilePath,
                    Namespace = @namespace,
                    Name = controllerName,
                    Area = areaName,
                    Symbol = controllerSymbol,
                });
            });
            var namespaceGroups      = controllerDetails.GroupBy(c => c.Namespace);
            var rootControllerNames  = controllerDetails.Where(c => string.IsNullOrEmpty(c.Area)).Select(c => c.Name).ToArray();
            var allViewFiles         = _viewLocator.FindViews(projectRoot);
            var generatedControllers = new List <NamespaceDeclarationSyntax>();

            foreach (var nameGroup in namespaceGroups)
            {
                var namespaceNode = SyntaxNodeHelpers.CreateNamespace(nameGroup.Key);

                foreach (var controller in nameGroup)
                {
                    var areaKey = rootControllerNames.Contains(controller.Area)
                         ? controller.Area + "Area"
                         : controller.Area;
                    var genControllerClass = _controllerGenerator.GeneratePartialController(controller.Symbol, areaKey, controller.Area, controller.Name, projectRoot);
                    var r4ControllerClass  = _controllerGenerator.GenerateR4Controller(controller.Symbol);

                    namespaceNode = namespaceNode
                                    .AddMembers(genControllerClass, r4ControllerClass);
                    if (_settings.SplitIntoMutipleFiles)
                    {
                        var controllerFile = NewCompilationUnit()
                                             .AddMembers(namespaceNode);
                        CompleteAndWriteFile(controllerFile, controller.FilePath.TrimEnd(".cs") + ".generated.cs");
                        namespaceNode = SyntaxNodeHelpers.CreateNamespace(nameGroup.Key);
                    }

                    if (!string.IsNullOrEmpty(controller.Area))
                    {
                        if (!areaClasses.ContainsKey(controller.Area))
                        {
                            string areaClass = controller.Area + "AreaClass";
                            areaClasses[controller.Area] = SyntaxNodeHelpers.CreateClass(areaClass, null, SyntaxKind.PublicKeyword);
                            // change to field and property
                            mvcStaticClass = mvcStaticClass.AddMembers(
                                SyntaxNodeHelpers.CreateFieldWithDefaultInitializer("s_" + areaKey, areaClass, SyntaxKind.StaticKeyword, SyntaxKind.ReadOnlyKeyword),
                                SyntaxNodeHelpers.CreateProperty(areaKey, areaClass, IdentifierName("s_" + areaKey), SyntaxKind.PublicKeyword, SyntaxKind.StaticKeyword));
                        }

                        areaClasses[controller.Area] = areaClasses[controller.Area].AddMembers(
                            SyntaxNodeHelpers.CreateFieldWithDefaultInitializer(
                                controller.Name,
                                $"{nameGroup.Key}.{genControllerClass.Identifier}",
                                $"{nameGroup.Key}.{r4ControllerClass.Identifier}",
                                SyntaxKind.PublicKeyword,
                                SyntaxKind.ReadOnlyKeyword));
                    }
                    else
                    {
                        mvcStaticClass = mvcStaticClass.AddMembers(
                            SyntaxNodeHelpers.CreateFieldWithDefaultInitializer(
                                controller.Name,
                                $"{nameGroup.Key}.{genControllerClass.Identifier}",
                                $"{nameGroup.Key}.{r4ControllerClass.Identifier}",
                                SyntaxKind.PublicKeyword,
                                SyntaxKind.StaticKeyword,
                                SyntaxKind.ReadOnlyKeyword));
                    }
                }

                if (!_settings.SplitIntoMutipleFiles)
                {
                    generatedControllers.Add(namespaceNode);
                }
            }
            var views = _viewLocator.FindViews(projectRoot)
                        .GroupBy(v => new { v.AreaName, v.ControllerName });

            foreach (var viewSet in views)
            {
                if (controllerDetails.Any(c => c.Area == viewSet.Key.AreaName && c.Name == viewSet.Key.ControllerName))
                {
                    continue;
                }

                var className = !string.IsNullOrEmpty(viewSet.Key.AreaName)
                    ? $"{viewSet.Key.AreaName}Area_{viewSet.Key.ControllerName}ControllerClass"
                    : $"{viewSet.Key.ControllerName}ControllerClass";
                var controllerClass = SyntaxNodeHelpers.CreateClass(className, null, SyntaxKind.PublicKeyword)
                                      .WithViewsClass(viewSet.Key.ControllerName, viewSet.Key.AreaName, viewSet);
                r4Namespace = r4Namespace.AddMembers(controllerClass);

                if (!string.IsNullOrEmpty(viewSet.Key.AreaName))
                {
                    areaClasses[viewSet.Key.AreaName] = areaClasses[viewSet.Key.AreaName].AddMembers(
                        SyntaxNodeHelpers.CreateFieldWithDefaultInitializer(
                            viewSet.Key.ControllerName,
                            $"{_settings.R4MvcNamespace}.{className}",
                            $"{_settings.R4MvcNamespace}.{className}",
                            SyntaxKind.PublicKeyword,
                            SyntaxKind.ReadOnlyKeyword));
                }
                else
                {
                    mvcStaticClass = mvcStaticClass.AddMembers(
                        SyntaxNodeHelpers.CreateFieldWithDefaultInitializer(
                            viewSet.Key.ControllerName,
                            $"{_settings.R4MvcNamespace}.{className}",
                            $"{_settings.R4MvcNamespace}.{className}",
                            SyntaxKind.PublicKeyword,
                            SyntaxKind.StaticKeyword,
                            SyntaxKind.ReadOnlyKeyword));
                }
            }

            r4Namespace = r4Namespace.AddMembers(areaClasses.Values.ToArray());

            var staticFileNode = _staticFileGenerator.GenerateStaticFiles(projectRoot);

            var actionResultClass =
                SyntaxNodeHelpers.CreateClass(Constants.ActionResultClass, null, SyntaxKind.InternalKeyword, SyntaxKind.PartialKeyword)
                .WithBaseTypes("ActionResult", "IR4MvcActionResult")
                .WithMethods(ConstructorDeclaration(Constants.ActionResultClass)
                             .WithModifiers(SyntaxKind.PublicKeyword)
                             .AddParameterListParameters(
                                 Parameter(Identifier("area")).WithType(SyntaxNodeHelpers.PredefinedStringType()),
                                 Parameter(Identifier("controller")).WithType(SyntaxNodeHelpers.PredefinedStringType()),
                                 Parameter(Identifier("action")).WithType(SyntaxNodeHelpers.PredefinedStringType()),
                                 Parameter(Identifier("protocol")).WithType(SyntaxNodeHelpers.PredefinedStringType())
                                 .WithDefault(EqualsValueClause(LiteralExpression(SyntaxKind.NullLiteralExpression))))
                             .WithBody(
                                 Block(
                                     ExpressionStatement(
                                         InvocationExpression(
                                             SyntaxNodeHelpers.MemberAccess("this", "InitMVCT4Result"))
                                         .WithArgumentList(
                                             IdentifierName("area"),
                                             IdentifierName("controller"),
                                             IdentifierName("action"),
                                             IdentifierName("protocol"))))))
                .WithAutoStringProperty("Controller", SyntaxKind.PublicKeyword)
                .WithAutoStringProperty("Action", SyntaxKind.PublicKeyword)
                .WithAutoStringProperty("Protocol", SyntaxKind.PublicKeyword)
                .WithAutoProperty("RouteValueDictionary", IdentifierName("RouteValueDictionary"), SyntaxKind.PublicKeyword);

            var jsonResultClass =
                SyntaxNodeHelpers.CreateClass(Constants.JsonResultClass, null, SyntaxKind.InternalKeyword, SyntaxKind.PartialKeyword)
                .WithBaseTypes("JsonResult", "IR4MvcActionResult")
                .WithMethods(ConstructorDeclaration(Constants.JsonResultClass)
                             .WithModifiers(SyntaxKind.PublicKeyword)
                             .AddParameterListParameters(
                                 Parameter(Identifier("area")).WithType(SyntaxNodeHelpers.PredefinedStringType()),
                                 Parameter(Identifier("controller")).WithType(SyntaxNodeHelpers.PredefinedStringType()),
                                 Parameter(Identifier("action")).WithType(SyntaxNodeHelpers.PredefinedStringType()),
                                 Parameter(Identifier("protocol")).WithType(SyntaxNodeHelpers.PredefinedStringType())
                                 .WithDefault(EqualsValueClause(LiteralExpression(SyntaxKind.NullLiteralExpression))))
                             .WithInitializer(ConstructorInitializer(SyntaxKind.BaseConstructorInitializer, ArgumentList(SingletonSeparatedList(Argument(LiteralExpression(SyntaxKind.NullLiteralExpression))))))
                             .WithBody(
                                 Block(
                                     ExpressionStatement(
                                         InvocationExpression(
                                             SyntaxNodeHelpers.MemberAccess("this", "InitMVCT4Result"))
                                         .WithArgumentList(
                                             IdentifierName("area"),
                                             IdentifierName("controller"),
                                             IdentifierName("action"),
                                             IdentifierName("protocol"))))))
                .WithAutoStringProperty("Controller", SyntaxKind.PublicKeyword)
                .WithAutoStringProperty("Action", SyntaxKind.PublicKeyword)
                .WithAutoStringProperty("Protocol", SyntaxKind.PublicKeyword)
                .WithAutoProperty("RouteValueDictionary", IdentifierName("RouteValueDictionary"), SyntaxKind.PublicKeyword);

            var r4mvcNode = NewCompilationUnit()
                            .AddMembers(generatedControllers.Cast <MemberDeclarationSyntax>().ToArray())
                            .AddMembers(
                staticFileNode,
                r4Namespace,
                mvcStaticClass,
                actionResultClass,
                jsonResultClass);

            CompleteAndWriteFile(r4mvcNode, Path.Combine(projectRoot, R4MvcGenerator.R4MvcFileName));
        }
Esempio n. 5
0
        private ClassDeclarationSyntax AddMethodOverrides(ClassDeclarationSyntax node, ITypeSymbol mvcSymbol)
        {
            const string overrideMethodSuffix = "Override";
            var          methods = mvcSymbol.GetPublicNonGeneratedMethods()
                                   .SelectMany(m =>
            {
                var statements = new List <StatementSyntax>
                {
                    // var callInfo = new R4Mvc_Microsoft_AspNetCore_Mvc_ActionResult(Area, Name, ActionNames.{Action});
                    LocalDeclarationStatement(
                        SyntaxNodeHelpers.VariableDeclaration("callInfo",
                                                              ObjectCreationExpression(IdentifierName(Constants.ActionResultClass))
                                                              .WithArgumentList(
                                                                  IdentifierName("Area"),
                                                                  IdentifierName("Name"),
                                                                  SyntaxNodeHelpers.MemberAccess("ActionNames", m.Name)))),
                };
                foreach (var param in m.Parameters)
                {
                    statements.Add(
                        ExpressionStatement(
                            InvocationExpression(
                                SyntaxNodeHelpers.MemberAccess("ModelUnbinderHelpers", "AddRouteValues"))
                            .WithArgumentList(
                                SyntaxNodeHelpers.MemberAccess("callInfo", "RouteValueDictionary"),
                                LiteralExpression(SyntaxKind.StringLiteralExpression, Literal(param.Name)),
                                IdentifierName(param.Name))));
                }
                statements.Add(
                    // {Action}Override(callInfo, {parameters});
                    ExpressionStatement(
                        InvocationExpression(IdentifierName(m.Name + overrideMethodSuffix))
                        .WithArgumentList(
                            new[] { IdentifierName("callInfo") }
                            .Concat(m.Parameters.Select(p => IdentifierName(p.Name)))
                            .ToArray())));
                statements.Add(
                    // return callInfo;
                    m.ReturnType.ToString().Contains("Task<")
                            ? ReturnStatement(
                        InvocationExpression(
                            SyntaxNodeHelpers.MemberAccess("Task", "FromResult"))
                        .WithArgumentList(
                            BinaryExpression(
                                SyntaxKind.AsExpression,
                                IdentifierName("callInfo"),
                                IdentifierName(m.ReturnType.ToString().Substring(m.ReturnType.ToString().IndexOf('<') + 1).TrimEnd('>')))))
                            : ReturnStatement(IdentifierName("callInfo")));
                return(new[]
                {
                    MethodDeclaration(PredefinedType(Token(SyntaxKind.VoidKeyword)), Identifier(m.Name + overrideMethodSuffix))
                    .WithModifiers(SyntaxKind.PartialKeyword)
                    .WithAttributes(SyntaxNodeHelpers.CreateNonActionAttribute())
                    .AddParameterListParameters(
                        Parameter(Identifier("callInfo")).WithType(IdentifierName(Constants.ActionResultClass)))
                    .AddParameterListParameters(m.Parameters
                                                .Select(p => Parameter(Identifier(p.Name))
                                                        .WithType(IdentifierName(p.Type.ToString())))
                                                .ToArray())
                    .WithSemicolonToken(Token(SyntaxKind.SemicolonToken)),
                    MethodDeclaration(IdentifierName(m.ReturnType.ToString()), Identifier(m.Name))
                    .WithModifiers(SyntaxKind.PublicKeyword, SyntaxKind.OverrideKeyword)
                    .WithAttributes(SyntaxNodeHelpers.CreateNonActionAttribute())
                    .AddParameterListParameters(m.Parameters
                                                .Select(p => Parameter(Identifier(p.Name))
                                                        .WithType(IdentifierName(p.Type.ToString())))
                                                .ToArray())
                    .WithBody(
                        Block(statements.ToArray())),
                });
            });

            return(node.AddMembers(methods.ToArray()));
        }
Esempio n. 6
0
        private ClassDeclarationSyntax AddRedirectMethods(ClassDeclarationSyntax node)
        {
            var methods = new[]
            {
                MethodDeclaration(IdentifierName("RedirectToRouteResult"), Identifier("RedirectToAction"))
                .WithModifiers(SyntaxKind.ProtectedKeyword)
                .WithAttributes(SyntaxNodeHelpers.CreateGeneratedCodeAttribute(), SyntaxNodeHelpers.CreateDebugNonUserCodeAttribute())
                .AddParameterListParameters(
                    Parameter(Identifier("result")).WithType(IdentifierName("IActionResult")))
                .WithBody(
                    Block(
                        // var callInfo = result.GetR4MvcResult();
                        LocalDeclarationStatement(
                            SyntaxNodeHelpers.VariableDeclaration("callInfo",
                                                                  InvocationExpression(SyntaxNodeHelpers.MemberAccess("result", "GetR4MvcResult")))),
                        // return RedirectToRoute(callInfo.RouteValueDictionary);
                        ReturnStatement(
                            InvocationExpression(IdentifierName("RedirectToRoute"))
                            .WithArgumentList(
                                SyntaxNodeHelpers.MemberAccess("callInfo", "RouteValueDictionary"))))),
                MethodDeclaration(IdentifierName("RedirectToRouteResult"), Identifier("RedirectToAction"))
                .WithModifiers(SyntaxKind.ProtectedKeyword)
                .WithAttributes(SyntaxNodeHelpers.CreateGeneratedCodeAttribute(), SyntaxNodeHelpers.CreateDebugNonUserCodeAttribute())
                .AddParameterListParameters(
                    Parameter(Identifier("taskResult")).WithGenericType("Task", "IActionResult"))
                .WithBody(
                    Block(
                        // return RedirectToAction(taskResult.Result);
                        ReturnStatement(
                            InvocationExpression(IdentifierName("RedirectToAction"))
                            .WithArgumentList(
                                SyntaxNodeHelpers.MemberAccess("taskResult", "Result"))))),
                MethodDeclaration(IdentifierName("RedirectToRouteResult"), Identifier("RedirectToActionPermanent"))
                .WithModifiers(SyntaxKind.ProtectedKeyword)
                .WithAttributes(SyntaxNodeHelpers.CreateGeneratedCodeAttribute(), SyntaxNodeHelpers.CreateDebugNonUserCodeAttribute())
                .AddParameterListParameters(
                    Parameter(Identifier("result")).WithType(IdentifierName("IActionResult")))
                .WithBody(
                    Block(
                        // var callInfo = result.GetR4MvcResult();
                        LocalDeclarationStatement(
                            SyntaxNodeHelpers.VariableDeclaration("callInfo",
                                                                  InvocationExpression(SyntaxNodeHelpers.MemberAccess("result", "GetR4MvcResult")))),
                        // return RedirectToRoutePermanent(callInfo.RouteValueDictionary);
                        ReturnStatement(
                            InvocationExpression(IdentifierName("RedirectToRoutePermanent"))
                            .WithArgumentList(
                                SyntaxNodeHelpers.MemberAccess("callInfo", "RouteValueDictionary"))))),
                MethodDeclaration(IdentifierName("RedirectToRouteResult"), Identifier("RedirectToActionPermanent"))
                .WithModifiers(SyntaxKind.ProtectedKeyword)
                .WithAttributes(SyntaxNodeHelpers.CreateGeneratedCodeAttribute(), SyntaxNodeHelpers.CreateDebugNonUserCodeAttribute())
                .AddParameterListParameters(
                    Parameter(Identifier("taskResult")).WithGenericType("Task", "IActionResult"))
                .WithBody(
                    Block(
                        // return RedirectToActionPermanent(taskResult.Result);
                        ReturnStatement(
                            InvocationExpression(IdentifierName("RedirectToActionPermanent"))
                            .WithArgumentList(
                                SyntaxNodeHelpers.MemberAccess("taskResult", "Result"))))),
            };

            return(node.AddMembers(methods));
        }
Esempio n. 7
0
        public ClassDeclarationSyntax GeneratePartialController(ControllerDefinition controller)
        {
            // build controller partial class node
            // add a default constructor if there are some but none are zero length
            var genControllerClass = ClassDeclaration(controller.Symbol.Name)
                                     .WithModifiers(SyntaxKind.PublicKeyword, SyntaxKind.PartialKeyword);
            var controllerTypeParams = controller.Symbol.TypeParameters.Select(tp => TypeParameter(tp.Name)).ToArray();

            if (controllerTypeParams.Length > 0)
            {
                genControllerClass = genControllerClass.AddTypeParameterListParameters(controllerTypeParams);
            }

            var gotCustomConstructors = controller.Symbol.Constructors
                                        .Where(c => c.DeclaredAccessibility == Accessibility.Public)
                                        .Where(SyntaxNodeHelpers.IsNotR4MVCGenerated)
                                        .Where(c => !c.IsImplicitlyDeclared)
                                        .Any();

            if (!gotCustomConstructors)
            {
                genControllerClass = genControllerClass.WithDefaultConstructor(true, SyntaxKind.PublicKeyword);
            }
            genControllerClass = genControllerClass.WithDummyConstructor(true, SyntaxKind.ProtectedKeyword);
            genControllerClass = AddRedirectMethods(genControllerClass);

            // add all method stubs, TODO criteria for this: only public virtual actionresults?
            // add subclasses, fields, properties, constants for action names
            genControllerClass = AddParameterlessMethods(genControllerClass, controller.Symbol);
            var actionsExpression = controller.AreaKey != null
                ? SyntaxNodeHelpers.MemberAccess(_settings.HelpersPrefix + "." + controller.AreaKey, controller.Name)
                : SyntaxNodeHelpers.MemberAccess(_settings.HelpersPrefix, controller.Name);

            genControllerClass =
                genControllerClass
                .WithProperty("Actions", controller.Symbol.Name, actionsExpression, SyntaxKind.PublicKeyword)
                .WithStringField(
                    "Area",
                    controller.Area,
                    true,
                    SyntaxKind.PublicKeyword,
                    SyntaxKind.ReadOnlyKeyword)
                .WithStringField(
                    "Name",
                    controller.Name,
                    true,
                    SyntaxKind.PublicKeyword,
                    SyntaxKind.ReadOnlyKeyword)
                .WithStringField(
                    "NameConst",
                    controller.Name,
                    true,
                    SyntaxKind.PublicKeyword,
                    SyntaxKind.ConstKeyword)
                .WithStaticFieldBackedProperty("ActionNames", "ActionNamesClass", SyntaxKind.PublicKeyword)
                .WithActionNameClass(controller.Symbol)
                .WithActionConstantsClass(controller.Symbol)
                .WithViewsClass(controller.Name, controller.Area, controller.Views);

            return(genControllerClass);
        }
Esempio n. 8
0
        private ClassDeclarationSyntax AddMethodOverrides(ClassDeclarationSyntax node, ITypeSymbol mvcSymbol)
        {
            const string overrideMethodSuffix = "Override";
            var          methods = mvcSymbol.GetPublicNonGeneratedMethods()
                                   .SelectMany(m =>
            {
                var callInfoType = Constants.ActionResultClass;
                if (m.ReturnType.InheritsFrom <JsonResult>())
                {
                    callInfoType = Constants.JsonResultClass;
                }
                else if (m.ReturnType.InheritsFrom <ContentResult>())
                {
                    callInfoType = Constants.ContentResultClass;
                }
                else if (m.ReturnType.InheritsFrom <RedirectResult>())
                {
                    callInfoType = Constants.RedirectResultClass;
                }
                else if (m.ReturnType.InheritsFrom <RedirectToActionResult>())
                {
                    callInfoType = Constants.RedirectToActionResultClass;
                }
                else if (m.ReturnType.InheritsFrom <RedirectToRouteResult>())
                {
                    callInfoType = Constants.RedirectToRouteResultClass;
                }

                var statements = new List <StatementSyntax>
                {
                    // var callInfo = new R4Mvc_Microsoft_AspNetCore_Mvc_ActionResult(Area, Name, ActionNames.{Action});
                    LocalDeclarationStatement(
                        SyntaxNodeHelpers.VariableDeclaration("callInfo",
                                                              ObjectCreationExpression(IdentifierName(callInfoType))
                                                              .WithArgumentList(
                                                                  IdentifierName("Area"),
                                                                  IdentifierName("Name"),
                                                                  SyntaxNodeHelpers.MemberAccess("ActionNames", m.Name)))),
                };
                foreach (var param in m.Parameters)
                {
                    statements.Add(
                        ExpressionStatement(
                            InvocationExpression(
                                SyntaxNodeHelpers.MemberAccess("ModelUnbinderHelpers", "AddRouteValues"))
                            .WithArgumentList(
                                SyntaxNodeHelpers.MemberAccess("callInfo", "RouteValueDictionary"),
                                LiteralExpression(SyntaxKind.StringLiteralExpression, Literal(param.Name)),
                                IdentifierName(param.Name))));
                }
                statements.Add(
                    // {Action}Override(callInfo, {parameters});
                    ExpressionStatement(
                        InvocationExpression(IdentifierName(m.Name + overrideMethodSuffix))
                        .WithArgumentList(
                            new[] { IdentifierName("callInfo") }
                            .Concat(m.Parameters.Select(p => IdentifierName(p.Name)))
                            .ToArray())));
                var returnType = m.ReturnType as INamedTypeSymbol;
                statements.Add(
                    // return callInfo;
                    returnType.InheritsFrom <Task>() == true
                            ? ReturnStatement(
                        InvocationExpression(
                            SyntaxNodeHelpers.MemberAccess(typeof(Task).FullName, "FromResult"))
                        .WithArgumentList(
                            returnType.TypeArguments.Length > 0
                                            ? (ExpressionSyntax)BinaryExpression(
                                SyntaxKind.AsExpression,
                                IdentifierName("callInfo"),
                                IdentifierName(returnType.TypeArguments[0].ToString()))
                                            : IdentifierName("callInfo")
                            ))
                            : ReturnStatement(IdentifierName("callInfo")));
                return(new[]
                {
                    MethodDeclaration(PredefinedType(Token(SyntaxKind.VoidKeyword)), Identifier(m.Name + overrideMethodSuffix))
                    .WithModifiers(SyntaxKind.PartialKeyword)
                    .WithNonActionAttribute()
                    .AddParameterListParameters(
                        Parameter(Identifier("callInfo")).WithType(IdentifierName(callInfoType)))
                    .AddParameterListParameters(m.Parameters
                                                .Select(p => Parameter(Identifier(p.Name))
                                                        .WithType(IdentifierName(p.Type.ToString())))
                                                .ToArray())
                    .WithSemicolonToken(Token(SyntaxKind.SemicolonToken)),
                    MethodDeclaration(IdentifierName(m.ReturnType.ToString()), Identifier(m.Name))
                    .WithModifiers(SyntaxKind.PublicKeyword, SyntaxKind.OverrideKeyword)
                    .WithNonActionAttribute()
                    .AddParameterListParameters(m.Parameters
                                                .Select(p => Parameter(Identifier(p.Name))
                                                        .WithType(IdentifierName(p.Type.ToString())))
                                                .ToArray())
                    .WithBody(
                        Block(statements.ToArray())),
                });
            });

            return(node.AddMembers(methods.ToArray()));
        }