コード例 #1
0
ファイル: R4MvcGenerator.cs プロジェクト: wwwlicious/R4MVC
        public SyntaxNode Generate(CompilationContext context, ISettings settings)
        {
            // Create the root node and add usings, header, pragma
            var r4mvcNode =
                SyntaxFactory.CompilationUnit()
                .WithUsings("System.CodeDom.Compiler", "System.Diagnostics", "Microsoft.AspNet.Mvc")
                .WithHeader(_headerText)
                .WithPragmaCodes(false, pramaCodes);

            var controllers          = _controllerRewriter.RewriteControllers(context.Compilation, R4MvcFileName);
            var generatedControllers = _controllerGenerator.GenerateControllers(context.Compilation, controllers).ToImmutableArray();
            var staticFileNode       = _staticFileGenerator.GenerateStaticFiles(settings);

            // add the dummy class using in the derived controller partial class
            var r4Namespace = SyntaxNodeHelpers.CreateNamespace(settings.R4MvcNamespace).WithDummyClass();

            // 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())
                .WithControllerFields(controllers);

            r4mvcNode =
                r4mvcNode.AddMembers(generatedControllers.Cast <MemberDeclarationSyntax>().ToArray())
                .AddMembers(staticFileNode)
                .AddMembers(r4Namespace)
                .AddMembers(mvcStaticClass)
                .NormalizeWhitespace()
                .WithPragmaCodes(true, pramaCodes);

            // NOTE reenable pragma codes after normalizing whitespace or it doesn't place on newline
            return(r4mvcNode);
        }
コード例 #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));
        }
コード例 #3
0
        public IEnumerable <NamespaceDeclarationSyntax> GenerateControllers(
            CSharpCompilation compiler,
            IEnumerable <ClassDeclarationSyntax> controllerNodes)
        {
            // controllers might be in different namespaces so should group by namespace
            var namespaceGroups =
                controllerNodes.GroupBy(x => x.Ancestors().OfType <NamespaceDeclarationSyntax>().First().Name.ToFullString());

            foreach (var namespaceControllers in namespaceGroups)
            {
                // create the namespace for the controllers
                var namespaceNode = SyntaxNodeHelpers.CreateNamespace(namespaceControllers.Key);

                // loop through the controllers and create a partial node for each
                foreach (var mvcControllerNode in namespaceControllers)
                {
                    var model     = compiler.GetSemanticModel(mvcControllerNode.SyntaxTree);
                    var mvcSymbol = model.GetDeclaredSymbol(mvcControllerNode);

                    // build controller partial class node
                    // add a default constructor if there are some but none are zero length
                    var genControllerClass = SyntaxNodeHelpers.CreateClass(
                        mvcSymbol.Name,
                        mvcControllerNode.TypeParameterList?.Parameters.ToArray(),
                        SyntaxKind.PublicKeyword,
                        SyntaxKind.PartialKeyword);

                    if (!mvcSymbol.Constructors.IsEmpty || !mvcSymbol.Constructors.Any(x => x.Parameters.Length == 0))
                    {
                        genControllerClass = genControllerClass.WithDefaultConstructor(true, SyntaxKind.PublicKeyword);
                    }

                    // add all method stubs, TODO criteria for this: only public virtual actionresults?
                    // add subclasses, fields, properties, constants for action names
                    genControllerClass =
                        genControllerClass.WithMethods(mvcSymbol)
                        .WithStringField(
                            "Name",
                            mvcControllerNode.Identifier.ToString(),
                            true,
                            SyntaxKind.PublicKeyword,
                            SyntaxKind.ReadOnlyKeyword)
                        .WithStringField(
                            "NameConst",
                            mvcControllerNode.Identifier.ToString(),
                            true,
                            SyntaxKind.PublicKeyword,
                            SyntaxKind.ConstKeyword)
                        .WithStringField(
                            "Area",
                            mvcControllerNode.Identifier.ToString(),
                            true,
                            SyntaxKind.PublicKeyword,
                            SyntaxKind.ReadOnlyKeyword)
                        .WithField("s_actions", "ActionNamesClass", SyntaxKind.StaticKeyword, SyntaxKind.ReadOnlyKeyword)
                        .WithActionNameClass(mvcControllerNode)
                        .WithActionConstantsClass(mvcControllerNode)
                        .WithField("s_views", "ViewsClass", SyntaxKind.StaticKeyword, SyntaxKind.ReadOnlyKeyword)
                        .WithViewsClass(_viewLocator.FindViews());

                    // create R4MVC_[Controller] class inheriting from partial
                    // TODO chain base constructor call : base(Dummy.Instance)
                    // TODO create [method]overrides(T4MVC_System_Web_Mvc_ActionResult callInfo)
                    // TODO create method overrides that call above
                    var r4ControllerClass =
                        SyntaxNodeHelpers.CreateClass(
                            GetR4MVCControllerClassName(genControllerClass),
                            null,
                            SyntaxKind.PublicKeyword,
                            SyntaxKind.PartialKeyword)
                        .WithAttributes(SyntaxNodeHelpers.CreateGeneratedCodeAttribute(), SyntaxNodeHelpers.CreateDebugNonUserCodeAttribute())
                        .WithBaseTypes(mvcControllerNode.ToQualifiedName())
                        .WithDefaultConstructor(false, SyntaxKind.PublicKeyword);

                    namespaceNode = namespaceNode.AddMembers(genControllerClass).AddMembers(r4ControllerClass);
                }
                yield return(namespaceNode);
            }
        }