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