コード例 #1
0
        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));
        }
コード例 #2
0
 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."));
 }
コード例 #3
0
        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);
        }
コード例 #4
0
        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);
            }
        }
コード例 #5
0
        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);
        }
コード例 #6
0
        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()));
        }
コード例 #7
0
        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);
        }
コード例 #8
0
 protected abstract void GenerateClassMethods(GeneratorExecutionContext context, CodeGenNamespace @namespace, CodeGenClass @class);
コード例 #9
0
        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);
        }
コード例 #10
0
        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");
        }
コード例 #11
0
        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)));
            }
        }
コード例 #12
0
        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);
            }
        }
コード例 #13
0
        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;"));
            }
        }