Example #1
0
 public IEnumerable <ClassDeclarationSyntax> CreateAreaClasses(ILookup <string, ControllerDefinition> areaControllers)
 {
     foreach (var area in areaControllers.Where(a => !string.IsNullOrEmpty(a.Key)).OrderBy(a => a.Key))
     {
         var areaClass = ClassDeclaration(area.Key + "AreaClass")
                         .WithModifiers(SyntaxKind.PublicKeyword, SyntaxKind.PartialKeyword)
                         .WithGeneratedNonUserCodeAttributes()
                         .WithStringField("Name", area.Key, false, SyntaxKind.PublicKeyword, SyntaxKind.ReadOnlyKeyword)
                         .AddMembers(area
                                     .OrderBy(c => c.Namespace == null).ThenBy(c => c.Name)
                                     .Select(c => SyntaxNodeHelpers.CreateFieldWithDefaultInitializer(
                                                 c.Name,
                                                 c.FullyQualifiedGeneratedName,
                                                 c.FullyQualifiedR4ClassName ?? c.FullyQualifiedGeneratedName,
                                                 SyntaxKind.PublicKeyword,
                                                 SyntaxKind.ReadOnlyKeyword))
                                     .ToArray <MemberDeclarationSyntax>());
         yield return(areaClass);
     }
 }
Example #2
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));
        }
Example #3
0
        public void Generate(string projectRoot, IList <ControllerDefinition> controllers)
        {
            var areaControllers = controllers.ToLookup(c => c.Area);

            // Processing controllers, generating partial and derived controller classes for R4Mvc
            var generatedControllers = new List <NamespaceDeclarationSyntax>();

            foreach (var namespaceGroup in controllers.Where(c => c.Namespace != null).GroupBy(c => c.Namespace).OrderBy(c => c.Key))
            {
                var namespaceNode = NamespaceDeclaration(ParseName(namespaceGroup.Key));
                foreach (var controller in namespaceGroup.OrderBy(c => c.Name))
                {
                    namespaceNode = namespaceNode.AddMembers(
                        _controllerGenerator.GeneratePartialController(controller),
                        _controllerGenerator.GenerateR4Controller(controller));

                    // If SplitIntoMultipleFiles is set, store the generated classes alongside the controller files.
                    if (_settings.SplitIntoMultipleFiles)
                    {
                        var controllerFile = NewCompilationUnit()
                                             .AddMembers(namespaceNode);
                        CompleteAndWriteFile(controllerFile, controller.GetFilePath().TrimEnd(".cs") + ".generated.cs");
                        namespaceNode = NamespaceDeclaration(ParseName(namespaceGroup.Key));
                    }
                }

                // If SplitIntoMultipleFiles is NOT set, bundle them all in R4Mvc
                if (!_settings.SplitIntoMultipleFiles)
                {
                    generatedControllers.Add(namespaceNode);
                }
            }

            // R4MVC namespace used for the areas and Dummy class
            var r4Namespace = NamespaceDeclaration(ParseName(_settings.R4MvcNamespace))
                              // add the dummy class using in the derived controller partial class
                              .WithDummyClass()
                              .AddMembers(CreateViewOnlyControllerClasses(controllers).ToArray <MemberDeclarationSyntax>())
                              .AddMembers(CreateAreaClasses(areaControllers).ToArray <MemberDeclarationSyntax>());

            // create static MVC class and add the area and controller fields
            var mvcStaticClass = ClassDeclaration(_settings.HelpersPrefix)
                                 .WithModifiers(SyntaxKind.PublicKeyword, SyntaxKind.StaticKeyword, SyntaxKind.PartialKeyword)
                                 .WithGeneratedNonUserCodeAttributes();

            foreach (var area in areaControllers.Where(a => !string.IsNullOrEmpty(a.Key)).OrderBy(a => a.Key))
            {
                mvcStaticClass = mvcStaticClass.WithStaticFieldBackedProperty(area.First().AreaKey, $"{_settings.R4MvcNamespace}.{area.Key}AreaClass", SyntaxKind.PublicKeyword, SyntaxKind.StaticKeyword);
            }
            foreach (var controller in areaControllers[string.Empty].OrderBy(c => c.Namespace == null).ThenBy(c => c.Name))
            {
                mvcStaticClass = mvcStaticClass.AddMembers(
                    SyntaxNodeHelpers.CreateFieldWithDefaultInitializer(
                        controller.Name,
                        controller.FullyQualifiedGeneratedName,
                        controller.FullyQualifiedR4ClassName ?? controller.FullyQualifiedGeneratedName,
                        SyntaxKind.PublicKeyword,
                        SyntaxKind.StaticKeyword,
                        SyntaxKind.ReadOnlyKeyword));
            }

            // Generate a list of all static files from the wwwroot path
            var staticFileNode = _staticFileGenerator.GenerateStaticFiles(projectRoot);

            var r4mvcNode = NewCompilationUnit()
                            .AddMembers(
                mvcStaticClass,
                r4Namespace,
                staticFileNode,
                ActionResultClass(),
                JsonResultClass(),
                ContentResultClass(),
                RedirectResultClass(),
                RedirectToActionResultClass(),
                RedirectToRouteResultClass())
                            .AddMembers(generatedControllers.ToArray <MemberDeclarationSyntax>());

            CompleteAndWriteFile(r4mvcNode, Path.Combine(projectRoot, R4MvcGeneratorService.R4MvcFileName));
        }