public void Execute(GeneratorExecutionContext context) { var @class = new CodeGenClass("GeneratedClass", Scope.Public, ClassType.Normal); @class.Methods.Add(new CodeGenMethod("GeneratedMethod", null, Scope.Public, MethodType.Static, null, null, @"System.Console.WriteLine(""Hello World 123"");")); var @namespace = new CodeGenNamespace("GeneratedNamespace"); @namespace.Content.Add(@class); string codeString = @namespace.GenerateCode(); // string codeString = @" //namespace GeneratedNamespace //{ // public class GeneratedClass // { // public static void GeneratedMethod() // { // System.Console.WriteLine(""Hello World once more""); // } // } //} //"; context.AddSource("myGeneratedFile.cs", SourceText.From(codeString, Encoding.UTF8)); }
private void GenerateStub(CodeGenClass @class) { @class.Methods.Add(new CodeGenMethod( MethodName, null, Scope.Public, MethodType.Static, new[] { new CodeGenGeneric("TPayload") }, new[] { "Action<TPayload> handler" }, @"// Stub. Does nothing.")); }
public void Execute(GeneratorExecutionContext context) { var generatedClass = new CodeGenClass("XmlPrinter", Scope.Public, ClassType.Static); var xmlFiles = context.AdditionalFiles.Where(f => f.Path.EndsWith(".xml")); foreach (var xmlFile in xmlFiles) { var itemElements = XDocument.Load(xmlFile.Path)?.Root?.Elements("item"); if (itemElements == null) { continue; } foreach (var itemElement in itemElements) { string name = itemElement.Attribute("name")?.Value; string value = itemElement.Value; if (!string.IsNullOrWhiteSpace(name) && !string.IsNullOrWhiteSpace(value)) { var generatedMethod = new CodeGenMethod( $"Print{name}", null, Scope.Public, MethodType.Static, null, null, $@" Console.WriteLine($""Hello, {value}""); "); generatedClass.Methods.Add(generatedMethod); } } } var generatedNamespace = new CodeGenNamespace("GeneratedNamespace"); generatedNamespace.Usings.Add("System"); generatedNamespace.Content.Add(generatedClass); var generatedCodeString = generatedNamespace.GenerateCode(); var sourceText = SourceText.From(generatedCodeString, Encoding.UTF8); context.AddSource("XmlPrinter.cs", sourceText); }
private IEnumerable <CodeGenClass> GenerateModels(ApiDefinition definition) { foreach (ApiModel model in definition.Models) { if (string.IsNullOrWhiteSpace(model.Name)) { throw new ArgumentException("Invalid model name"); } var modelClass = new CodeGenClass( model.Name, Scope.Public, ClassType.Normal); modelClass.Comment = new CodeGenComment(model.Description); foreach (ApiType prop in model.Props) { if (string.IsNullOrWhiteSpace(prop.Name)) { throw new ArgumentException("Invalid property name"); } if (string.IsNullOrWhiteSpace(prop.Type)) { throw new ArgumentException("Invalid property type"); } var propProp = new CodeGenProperty( LowerToUpperCamel(prop.Name), ResolveModelType(prop.Type), Scope.Public, true); propProp.Comment = new CodeGenComment(prop.Description); // TODO required modelClass.Properties.Add(propProp); } yield return(modelClass); } }
public void Execute(GeneratorExecutionContext context) { var generatedClass = new CodeGenClass( _ClassName, Scope.Public, ClassType.Static); generatedClass.Comment = new CodeGenComment($@"Class: {_ClassName} Description: {_ClassDescription} Auto-generated on {DateTime.Now}"); var generatedNamespace = new CodeGenNamespace(_Namespace); GenerateClassMethods(context, generatedNamespace, generatedClass); generatedNamespace.Content.Add(generatedClass); var generatedCodeString = generatedNamespace.GenerateCode(); var sourceText = SourceText.From(generatedCodeString, Encoding.UTF8); context.AddSource($"{_ClassName}.cs", sourceText); }
private void AddGetFunctionsDictionary(CodeGenClass @class, IDictionary <string, DIRegistration> registrations) { var assignmentBuilder = new StringBuilder(); assignmentBuilder.AppendLine("new Dictionary<Type, Func<object>>"); assignmentBuilder.AppendLine("{"); foreach (DIRegistration registration in registrations.Values) { assignmentBuilder.AppendLine($" [typeof({registration.IdentifierType})] = {registration.DirectGetMethodName},"); } assignmentBuilder.AppendLine("}"); @class.Variables.Add(new CodeGenVariable( "_GetFunctions", "IDictionary<Type, Func<object>>", Scope.Private, VariableType.Static, true, assignmentBuilder.ToString())); }
private CodeGenClass GenerateController(ApiDefinition definition) { if (definition is null) { throw new ArgumentNullException(nameof(definition)); } var controllerClass = new CodeGenClass( $"{definition.Name}Controller", Scope.Public, ClassType.Normal, derivedFrom: new[] { "ControllerBase" }); // class comment if (!string.IsNullOrWhiteSpace(definition.Description)) { controllerClass.Comment = new CodeGenComment(definition.Description); } // ApiController attribute controllerClass.Attributes.Add(new CodeGenAttribute("ApiController")); // Route attribute string controllerRoute = !string.IsNullOrWhiteSpace(definition.ControllerRoute) ? $"\"{definition.ControllerRoute}\"" : @"""[controller]"""; controllerClass.Attributes.Add(new CodeGenAttribute("Route", controllerRoute)); // Constructor and DI injected variables. var constructorStatements = new List <string>(); var constructorParam = new List <string>(); var constructorParamComments = new Dictionary <string, string>(); constructorParam.Add("IServiceProvider serviceProvider"); constructorParamComments.Add("serviceProvider", "The service provider to access validators and handlers."); constructorStatements.Add($"_ServiceProvider = serviceProvider ?? throw new ArgumentNullException(nameof(serviceProvider))"); controllerClass.Variables.Add(new CodeGenVariable( "_ServiceProvider", "IServiceProvider", Scope.Private, readOnly: true)); //foreach (ApiMethod method in definition.Methods) //{ // if (string.IsNullOrWhiteSpace(method.Name)) throw new ArgumentException("Invalid dependency name"); // string methodValidatorName = $"{method.Name}Validator"; // string methodHandlerName = $"{method.Name}Handler"; // constructorParam.Add($"{methodValidatorName} {methodValidatorName}"); // constructorParam.Add($"{methodHandlerName} {methodHandlerName}"); // constructorStatements.Add($"this.{methodValidatorName} = {methodValidatorName};"); // constructorStatements.Add($"this.{methodHandlerName} = {methodHandlerName};"); // constructorParamComments.Add(methodValidatorName, $"Validator for the {method.Name} method."); // constructorParamComments.Add(methodHandlerName, $"Handler for the {method.Name} method."); // controllerClass.Variables.Add(new CodeGenVariable( // dependency.Name, // dependency.Type, // Scope.Private)); //} foreach (ApiMethod apiMethod in definition.Methods) { controllerClass.Methods.Add(GenerateMethod(apiMethod)); } var constructor = new CodeGenConstructor( controllerClass.Name, Scope.Public, constructorParam, string.Join(Environment.NewLine, constructorStatements)); constructor.Comment = new CodeGenComment( "Constructor for this controller.", paramComments: constructorParamComments); controllerClass.Constructors.Add(constructor); return(controllerClass); }
protected abstract void GenerateClassMethods(GeneratorExecutionContext context, CodeGenNamespace @namespace, CodeGenClass @class);
protected override void GenerateClassMethods(GeneratorExecutionContext context, CodeGenNamespace @namespace, CodeGenClass @class) { StaticMethodCallSyntaxReceiver syntaxReceiver = (StaticMethodCallSyntaxReceiver)context.SyntaxReceiver; // singleton store @class.Variables.Add(new CodeGenVariable("_SingletonLock", "object", Scope.Private, VariableType.Static, true, "new object()")); @class.Variables.Add(new CodeGenVariable("_Singletons", "IDictionary<Type, object>", Scope.Private, VariableType.Static, true, "new Dictionary<Type, object>()")); // static methods AddRegistrationMethods(@class); AddGetTMethod(@class); // get registrations IDictionary <string, DIRegistration> registrations = ProcessCalls(context, syntaxReceiver.Calls); // Function dictionary used by get method AddGetFunctionsDictionary(@class, registrations); foreach (DIRegistration registration in registrations.Values) { // Build stack contining the initialization of this registered resource, including any dependencies. Stack <DIDependencyInitialization> initStack = BuildInitStack(registration, registrations); // Use init stack to generate body string body = BuildTypedGetMethodBody(initStack); var method = new CodeGenMethod( registration.DirectGetMethodName, registration.IdentifierType, Scope.Private, MethodType.Static, null, null, body); @class.Methods.Add(method); } ModifyNamespace(@namespace); }
protected override void GenerateClassMethods(GeneratorExecutionContext context, CodeGenNamespace @namespace, CodeGenClass @class) { StaticMethodCallSyntaxReceiver syntaxReceiver = (StaticMethodCallSyntaxReceiver)context.SyntaxReceiver; var generatedHandlers = new HashSet <string>(); GenerateStub(@class); foreach (StaticMethodCall call in syntaxReceiver.Calls) { SemanticModel semanticModel = context.Compilation.GetSemanticModel(call.Invocation.SyntaxTree); Dictionary <string, string> genericTypes = call.GenericTypes .Select(gt => semanticModel.GetTypeInfo(gt)) .ToDictionary(typeInfo => typeInfo.Type.ToString(), typeInfo => typeInfo.Type.Name); string handlerName = $"{string.Join(string.Empty, genericTypes.Values)}Handler"; string[] argList = genericTypes.Keys.Select((type, i) => $"{type} arg{i}").ToArray(); string[] argNameList = genericTypes.Select((type, i) => $"arg{i}").ToArray(); if (generatedHandlers.Contains(handlerName)) { continue; } generatedHandlers.Add(handlerName); // delegate @namespace.Content.Add(new CodeGenDelegate( handlerName, null, Scope.Public, null, argList)); // private delegate variable @class.Variables.Add(new CodeGenVariable( $"_{handlerName}", handlerName, Scope.Private, VariableType.Static)); // register method @class.Methods.Add(new CodeGenMethod( MethodName, null, Scope.Public, MethodType.Static, genericTypes.Keys.Select((gt, i) => new CodeGenGeneric($"TPayload{i}", gt)), new[] { $"Action<{string.Join(", ", genericTypes.Keys)}> handler" }, $"_{handlerName} += new {handlerName}(handler);")); // notify method @class.Methods.Add(new CodeGenMethod( "Notify", null, Scope.Public, MethodType.Static, null, argList, $"_{handlerName}?.Invoke({string.Join(", ", argNameList)});")); } @namespace.Usings.Add("System"); }
private void GenerateDecoratorMethods(ClassDeclarationSyntax classDeclaration, CodeGenClass decorator, SemanticModel semanticModel) { var methods = classDeclaration.Members.OfType <MethodDeclarationSyntax>() .Where(method => method.Modifiers.Any(m => m.Text == "public")); foreach (MethodDeclarationSyntax method in methods) { Dictionary <string, string> constraints = method.ConstraintClauses.ToDictionary( constraintClause => constraintClause.Name.Identifier.Text, constraintClause => string.Join(", ", GetConstraintNames(constraintClause, semanticModel))); IEnumerable <CodeGenGeneric> generics = method.TypeParameterList?.Parameters.Select(parameter => GenerateMethodParameter(parameter, constraints)); IEnumerable <string> parameters = method.ParameterList.Parameters.Select(parameter => $"{semanticModel.GetTypeInfo(parameter.Type).Type} {parameter.Identifier.Text}"); var returnTypeInfo = semanticModel.GetTypeInfo(method.ReturnType); decorator.Methods.Add(new CodeGenMethod( method.Identifier.Text, returnTypeInfo.Type.ToString(), Scope.Public, MethodType.Normal, generics, parameters, GenerateMethodBody(method, classDeclaration, decorator.Name))); } }
public void Execute(GeneratorExecutionContext context) { ClassWithAttributeSyntaxReciever syntaxReceiver = (ClassWithAttributeSyntaxReciever)context.SyntaxReceiver; foreach ((ClassDeclarationSyntax classDeclaration, AttributeSyntax decorateAttribute) in syntaxReceiver.Classes) { SemanticModel semanticModel = context.Compilation.GetSemanticModel(classDeclaration.SyntaxTree); ISymbol classSymbol = semanticModel.GetDeclaredSymbol(classDeclaration); TypeInfo attrType = semanticModel.GetTypeInfo(decorateAttribute.Name); AttributeData decorateAttributeData = classSymbol.GetAttributes().First(attrData => attrData.AttributeClass.Equals(attrType.Type, SymbolEqualityComparer.Default)); INamedTypeSymbol decoratedTypeSymbol = decorateAttributeData.ConstructorArguments.FirstOrDefault().Value as INamedTypeSymbol; Dictionary <string, string> constraints = classDeclaration.ConstraintClauses.ToDictionary( constraintClause => constraintClause.Name.Identifier.Text, constraintClause => constraintClause.Constraints.ToString()); IEnumerable <CodeGenGeneric> generics = classDeclaration.TypeParameterList?.Parameters.Select(parameter => GenerateMethodParameter(parameter, constraints)); string decoratorName = $"{classDeclaration.Identifier.Text}Decorator"; string decoratedType = decoratedTypeSymbol?.ToString() ?? classSymbol.ToString(); var generatedClass = new CodeGenClass( decoratorName, Scope.Public, ClassType.Normal, genericTypes: generics, derivedFrom: decoratedTypeSymbol != null ? new[] { decoratedTypeSymbol.ToString() } : null); generatedClass.Comment = new CodeGenComment($@"Class: {decoratorName} Description: Decorator for {classSymbol} Auto-generated on {DateTime.Now}"); // Constructor generatedClass.Constructors.Add(new CodeGenConstructor( decoratorName, Scope.Public, new[] { $"{decoratedType} decorated" }, "_Decorated = decorated ?? throw new ArgumentNullException(nameof(decorated));")); // Decorated variable generatedClass.Variables.Add(new CodeGenVariable( "_Decorated", decoratedType, Scope.Private, readOnly: true)); GenerateDecoratorMethods(classDeclaration, generatedClass, semanticModel); var generatedNamespace = new CodeGenNamespace($"{classSymbol.ContainingNamespace.Name}.Decorators"); generatedNamespace.Content.Add(generatedClass); generatedNamespace.Usings.Add("System"); var generatedCodeString = generatedNamespace.GenerateCode(); var sourceText = SourceText.From(generatedCodeString, Encoding.UTF8); context.AddSource($"{decoratorName}.cs", sourceText); } }
protected override void GenerateClassMethods(GeneratorExecutionContext context, CodeGenNamespace @namespace, CodeGenClass @class) { StaticMethodCallSyntaxReceiver syntaxReceiver = (StaticMethodCallSyntaxReceiver)context.SyntaxReceiver; var foundTypes = new HashSet <string>(); // No calls? Generate stub for intellisence. if (!syntaxReceiver.Calls.Any()) { @class.Methods.Add(new CodeGenMethod( MethodName, "object", Scope.Public, MethodType.Static, null, new[] { "object arg" }, @"// Stub method for intellisence. return arg;")); return; } foreach (StaticMethodCall call in syntaxReceiver.Calls) { if (call.Arguments.Length != 1) { continue; } var argExpression = call.Arguments[0]; SemanticModel semanticModel = context.Compilation.GetSemanticModel(argExpression.SyntaxTree); string argumentType = semanticModel.GetTypeInfo(argExpression).Type.ToString(); if (argumentType == null || foundTypes.Contains(argumentType)) { continue; } foundTypes.Add(argumentType); @class.Methods.Add(new CodeGenMethod( MethodName, argumentType.ToString(), Scope.Public, MethodType.Static, null, new[] { $"{argumentType} arg" }, "return arg;")); } }