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)); }