Exemple #1
0
    public void BeforeCompile(IBeforeCompileContext context)
    {
        // Firstly, I need to resolve the namespace of the ModuleProvider instance in this current compilation.
        string ns = GetModuleProviderNamespace(context.Compilation.SyntaxTrees);
        // Next, get all the available modules in assembly and compilation references.
        var modules = GetAvailableModules(context.Compilation).ToList();
        // Map them to a collection of statements
        var statements = modules.Select(m => F.ParseStatement("AddModule<" + module + ">();")).ToList();
        // Now, I'll create the dynamic implementation as a private class.
        var cu = F.CompilationUnit()
                 .AddMembers(
            F.NamespaceDeclaration(F.IdentifierName(ns))
            .AddMembers(
                F.ClassDeclaration("ModuleProvider")
                .WithModifiers(F.TokenList(F.Token(K.PartialKeyword)))
                .AddMembers(
                    F.MethodDeclaration(F.PredefinedType(F.Token(K.VoidKeyword)), "Setup")
                    .WithModifiers(
                        F.TokenList(
                            F.Token(K.ProtectedKeyword),
                            F.Token(K.OverrideKeyword)))
                    .WithBody(F.Block(statements))
                    )
                )
            )
                 .NormalizeWhitespace(indentation("\t"));
        var tree = T.Create(cu);

        context.Compilation = context.Compilation.AddSyntaxTrees(tree);
    }
        private static string GenerateCodeBehindClass(string className, string contents, RazorCodeDocument razorCodeDocument)
        {
            var namespaceNode = (NamespaceDeclarationIntermediateNode)razorCodeDocument
                                .GetDocumentIntermediateNode()
                                .FindDescendantNodes <IntermediateNode>()
                                .FirstOrDefault(n => n is NamespaceDeclarationIntermediateNode);

            var mock   = (ClassDeclarationSyntax)CSharpSyntaxFactory.ParseMemberDeclaration($"class Class {contents}");
            var @class = CSharpSyntaxFactory
                         .ClassDeclaration(className)
                         .AddModifiers(CSharpSyntaxFactory.Token(CSharpSyntaxKind.PublicKeyword), CSharpSyntaxFactory.Token(CSharpSyntaxKind.PartialKeyword))
                         .AddMembers(mock.Members.ToArray());

            var @namespace = CSharpSyntaxFactory
                             .NamespaceDeclaration(CSharpSyntaxFactory.ParseName(namespaceNode.Content))
                             .AddMembers(@class);

            var usings = FindUsings(razorCodeDocument)
                         .Select(u => CSharpSyntaxFactory.UsingDirective(CSharpSyntaxFactory.ParseName(u)))
                         .ToArray();
            var compilationUnit = CSharpSyntaxFactory
                                  .CompilationUnit()
                                  .AddUsings(usings)
                                  .AddMembers(@namespace);

            return(compilationUnit.NormalizeWhitespace().ToFullString());
        }
Exemple #3
0
 public static CompilationUnitSyntax GenUnit(NamespaceDeclarationSyntax @namespace, IEnumerable <UsingDirectiveSyntax> usings, IEnumerable <AttributeListSyntax> attributes)
 {
     return(SF.CompilationUnit(
                externs: SF.List <ExternAliasDirectiveSyntax>(),
                usings: SF.List(usings),
                attributeLists: SF.List(attributes),
                members: SF.List <MemberDeclarationSyntax>(new[] { @namespace }))
            .NormalizeWhitespace("    ", true));
 }
        private SyntaxTree CreateSyntaxTree()
        {
            var compilationUnit = SF
                                  .CompilationUnit()
                                  .AddUsings
                                  (
                SF.UsingDirective
                    (SF.ParseName("System"))
                                  );

            var ns = SF
                     .NamespaceDeclaration(SF.IdentifierName("SynTreeFred"));

            var cls = SF
                      .ClassDeclaration("Henry")
                      .AddModifiers(SF.Token(SyntaxKind.PublicKeyword));

            // How to define base class and interfaces, with/without generics
            //
            //cls = cls.AddBaseListTypes(
            //    SF.SimpleBaseType(SF.ParseTypeName("Object")),
            //    SF.SimpleBaseType(SF.ParseTypeName("IEnumerable<string>")));

            var inti = SF
                       .VariableDeclaration(SF.ParseTypeName("int"))
                       .AddVariables
                       (
                SF.VariableDeclarator
                (
                    SF.Identifier("i"),
                    null,
                    SF.EqualsValueClause
                    (
                        SF.LiteralExpression
                        (
                            SyntaxKind.NumericLiteralExpression,
                            SF.Literal(12)
                        )
                    )
                )
                       );

            var field = SF.FieldDeclaration(inti)
                        .AddModifiers(SF.Token(SyntaxKind.PrivateKeyword));

            var syntax            = SF.ParseStatement("return ++i;");
            var methodDeclaration = SF
                                    .MethodDeclaration(SF.ParseTypeName("int"), "GetNextInt")
                                    .AddModifiers(SF.Token(SyntaxKind.PublicKeyword))
                                    .WithBody(SF.Block(syntax));

            cls             = cls.AddMembers(field, methodDeclaration);
            ns              = ns.AddMembers(cls);
            compilationUnit = compilationUnit.AddMembers(ns);
            return(compilationUnit.SyntaxTree);
        }
        private static CompilationUnitSyntax GenerateCompilationUnit(IList <ActorDescription> actors)
        {
            var usings =
                TypeUtil.GetNamespaces(actors, typeof(TaskUtility)).Select(SF.UsingDirective).ToList();
            var ns =
                SF.NamespaceDeclaration(SF.ParseName("Generated" + DateTime.UtcNow.Ticks))
                .AddUsings(usings.ToArray())
                .AddMembers(actors.Select(GenerateClass).ToArray());

            return(SF.CompilationUnit().AddMembers(ns));
        }
Exemple #6
0
        public static CompilationUnitSyntax GenUnit(MemberDeclarationSyntax @class, string nameSpace, IEnumerable <UsingDirectiveSyntax> usings, IEnumerable <AttributeListSyntax> attributes)
        {
            var @namespace = SF.NamespaceDeclaration(SF.ParseName(nameSpace))
                             .AddMembers(@class);

            return(SF.CompilationUnit(
                       externs: SF.List <ExternAliasDirectiveSyntax>(),
                       usings: SF.List(usings),
                       attributeLists: SF.List(attributes),
                       members: SF.List <MemberDeclarationSyntax>(new[] { @namespace }))
                   .NormalizeWhitespace("    ", true));
        }
Exemple #7
0
 /// <summary>
 ///     Create the <see cref="CompilationUnitSyntax"/> of the current <see cref="_classes"/>.
 /// </summary>
 /// <returns>The <see cref="CompilationUnitSyntax"/>.</returns>
 private CompilationUnitSyntax CreateCompilationUnit()
 {
     return(S.CompilationUnit()
            .AddUsings(
                S.UsingDirective(S.ParseName("System")),
                S.UsingDirective(S.ParseName(typeof(Task).Namespace)),
                S.UsingDirective(S.ParseName(typeof(MessageContext).Namespace)),
                S.UsingDirective(S.ParseName(typeof(IArgumentReader).Namespace)),
                S.UsingDirective(S.ParseName(typeof(ICommand).Namespace)),
                S.UsingDirective(S.ParseName(typeof(IDiscordUser).Namespace)),
                S.UsingDirective(S.ParseName(typeof(ServiceProviderServiceExtensions).Namespace))
                )
            .AddMembers(
                S.NamespaceDeclaration(S.IdentifierName(Namespace))
                .AddMembers(_classes.Select(kv => kv.Value.DeclarationSyntax).Cast <MemberDeclarationSyntax>().ToArray())
                ));
 }
Exemple #8
0
 internal ClassGenerator(Builder builder)
 {
     _compilationUnit = SF.CompilationUnit()
                        .WithUsings(GenerateUsings(builder._usings))
                        .WithMembers(SF.SingletonList <MemberDeclarationSyntax>(SF.NamespaceDeclaration(GenerateNamespaceSyntax(builder._namespace))
                                                                                .WithMembers(
                                                                                    SF.SingletonList <MemberDeclarationSyntax>(
                                                                                        SF.ClassDeclaration(builder._className)
                                                                                        .WithModifiers(
                                                                                            SF.TokenList(
                                                                                                SF.Token(SyntaxKind.PublicKeyword)))
                                                                                        .WithAttributeLists(
                                                                                            SF.SingletonList(
                                                                                                SF.AttributeList(
                                                                                                    GenerateAttributes(builder._attributes))))
                                                                                        .WithMembers(GenerateProperties(builder._properties))))))
                        .NormalizeWhitespace();
 }
Exemple #9
0
        public CompilationUnitSyntax GetCompilationUnitForContext(WebContext context)
        {
            var cu = SF.CompilationUnit()
                     .WithUsings(
                SF.List(
                    new List <UsingDirectiveSyntax>
            {
                SF.UsingDirective(SF.ParseName(WebInfoAssemblyName)),
                SF.UsingDirective(SF.ParseName("System.Collections.Generic"))
            }
                    )
                );

            var webInfoGen = GetClassForWebElement(context);

            cu = cu.AddMembers(webInfoGen.ClassSyntax);

            return(cu);
        }
Exemple #10
0
        private static SyntaxNode MoveToApplication(SyntaxNode root, IEnumerable <SyntaxNode> members, Scope scope)
        {
            var appClass = root
                           .DescendantNodes()
                           .OfType <ClassDeclarationSyntax>()
                           .Where(@class => @class.Identifier.ToString() == "application")
                           .FirstOrDefault();

            if (appClass == null)
            {
                appClass = CSharp.ClassDeclaration("application");
            }

            return(CSharp.CompilationUnit()
                   .WithMembers(CSharp.List(new[] {
                (MemberDeclarationSyntax)appClass
                .WithMembers(CSharp.List(members))
            })));
        }
Exemple #11
0
        private static SyntaxNode MoveToMain(SyntaxNode root, IEnumerable <SyntaxNode> statements, Scope scope)
        {
            var appClass = root
                           .DescendantNodes()
                           .OfType <ClassDeclarationSyntax>()
                           .Where(@class => @class.Identifier.ToString() == "application")
                           .FirstOrDefault();

            if (appClass == null)
            {
                appClass = CSharp.ClassDeclaration("application");
            }

            return(CSharp.CompilationUnit()
                   .WithMembers(CSharp.List(new MemberDeclarationSyntax[] {
                appClass.AddMembers(
                    CSharp.MethodDeclaration(CSharp.ParseTypeName("int"), "main")
                    .WithModifiers(CSharp.TokenList(CSharp.Token(SyntaxKind.PrivateKeyword)))
                    .WithBody(CSharp.Block()
                              .WithStatements(CSharp.List(statements
                                                          .Union(new [] { CSharp.ParseStatement("return 0;") })))))
            })));
        }
        public string ToFullString()
        {
            var unit = SF.CompilationUnit();

            if (_options.IsJsonSerializable)
            {
                unit = unit.AddUsings(SF.UsingDirective(SF.IdentifierName("Newtonsoft.Json")));
            }

            CSharpSyntaxNode rootNode;

            if (!string.IsNullOrEmpty(_options.Namespace))
            {
                rootNode = unit.AddMembers(
                    SF.NamespaceDeclaration(SF.IdentifierName(_options.Namespace))
                    .AddMembers(_rootNode));
            }
            else
            {
                rootNode = unit.AddMembers(_rootNode);
            }

            return(Formatter.Format(rootNode, MSBuildWorkspace.Create()).ToFullString());
        }
Exemple #13
0
        void Save(string packageOutputRoot, ISymbolMap symbols, Assembly assembly, string tarballFileName, string jsiiFileName)
        {
            if (assembly.Docs != null)
            {
                // TODO: Use Microsoft.Extensions.Logging instead of Console.Error.
                Console.Error.WriteLine("Warning: Ignoring documentation comment on assembly ${assembly.Name}. Assembly-level documentation comments are not supported for .NET");
            }

            SaveProjectFile();
            SaveAssemblyInfo(assembly.Name, assembly.Version, tarballFileName);

            foreach (Type type in assembly.Types?.Values ?? Enumerable.Empty <Type>())
            {
                SaveType(type);
            }

            void SaveProjectFile()
            {
                XElement project =
                    new XElement("Project",
                                 new XAttribute("Sdk", "Microsoft.NET.Sdk"),
                                 new XElement("PropertyGroup",
                                              new XElement("TargetFramework", "netstandard2.0"),
                                              new XElement("GeneratePackageOnBuild", true),
                                              new XElement("Authors", _authors),
                                              new XElement("Company", _company),
                                              new XElement("PackageVersion", assembly.Version)
                                              ),
                                 new XElement("ItemGroup",
                                              new XElement("EmbeddedResource",
                                                           new XAttribute("Include", tarballFileName)
                                                           )
                                              ),
                                 new XElement("ItemGroup",
                                              new XElement("PackageReference",
                                                           new XAttribute("Include", "Amazon.JSII.Runtime"),
                                                           new XAttribute("Version", JsiiVersion.Version)
                                                           ),
                                              GetDependencies()
                                              .Distinct()
                                              .Select(d => new { Package = symbols.GetAssemblyName(d.Key), Version = d.Value.Version })
                                              .Select(d =>
                                                      new XElement("PackageReference",
                                                                   new XAttribute("Include", d.Package),
                                                                   new XAttribute("Version", d.Version)
                                                                   )
                                                      )
                                              )
                                 );

                if (!_fileSystem.Directory.Exists(packageOutputRoot))
                {
                    _fileSystem.Directory.CreateDirectory(packageOutputRoot);
                }

                // Save to StringBuilder instead of directly to path, so that we can
                // redirect the output through the filesystem shim. Project files are
                // small, so this shouldn't be a memory hog.
                StringBuilder     builder  = new StringBuilder();
                XmlWriterSettings settings = new XmlWriterSettings
                {
                    // Visual Studio omits the XML declaration when creating project files, so we do too.
                    OmitXmlDeclaration = true,
                    // Visual Studio indents project files (they are often edited by hand), so we do too.
                    Indent = true,
                };

                using (XmlWriter writer = XmlWriter.Create(builder, settings))
                {
                    project.Save(writer);
                }

                string csProjPath = Path.Combine(packageOutputRoot, $"{assembly.GetNativeName()}.csproj");

                _fileSystem.File.WriteAllText(csProjPath, builder.ToString());

                IEnumerable <KeyValuePair <string, PackageVersion> > GetDependencies()
                {
                    foreach (KeyValuePair <string, PackageVersion> dependency in GetDependenciesCore(assembly))
                    {
                        yield return(dependency);
                    }

                    IEnumerable <KeyValuePair <string, PackageVersion> > GetDependenciesCore(DependencyRoot root)
                    {
                        if (root.Dependencies == null)
                        {
                            yield break;
                        }
                        foreach (var kvp in root.Dependencies)
                        {
                            yield return(kvp);

                            foreach (KeyValuePair <string, PackageVersion> dependency in GetDependenciesCore(kvp.Value))
                            {
                                yield return(dependency);
                            }
                        }
                    }
                }
            }

            void SaveAssemblyInfo(string name, string version, string tarball)
            {
                SyntaxTree assemblyInfo = SF.SyntaxTree(
                    SF.CompilationUnit(
                        SF.List <ExternAliasDirectiveSyntax>(),
                        SF.List(new[] {
                    SF.UsingDirective(SF.ParseName("Amazon.JSII.Runtime.Deputy"))
                }),
                        SF.List(new[] {
                    SF.AttributeList(
                        SF.AttributeTargetSpecifier(
                            SF.Identifier("assembly"),
                            SF.Token(SyntaxKind.ColonToken)
                            ),
                        SF.SeparatedList(new[] {
                        SF.Attribute(
                            SF.ParseName("JsiiAssembly"),
                            SF.ParseAttributeArgumentList($"({SF.Literal(name)}, {SF.Literal(version)}, {SF.Literal(tarball)})")
                            )
                    })
                        )
                }),
                        SF.List <MemberDeclarationSyntax>()
                        ).NormalizeWhitespace(elasticTrivia: true)
                    );

                string assemblyInfoPath = Path.Combine(packageOutputRoot, "AssemblyInfo.cs");

                _fileSystem.File.WriteAllText(assemblyInfoPath, assemblyInfo.ToString());
            }

            void SaveType(Type type)
            {
                string packageName = Path.GetFileName(packageOutputRoot);
                string @namespace  = symbols.GetNamespace(type);

                if (@namespace.StartsWith(packageName))
                {
                    @namespace = @namespace.Substring(packageName.Length).TrimStart('.');
                }

                string directory = Path.Combine(packageOutputRoot, Path.Combine(@namespace.Split('.')));

                switch (type.Kind)
                {
                case TypeKind.Class:
                    SaveTypeFile($"{symbols.GetName(type)}.cs", new ClassGenerator(assembly.Name, (ClassType)type, symbols).CreateSyntaxTree());
                    return;

                case TypeKind.Enum:
                    SaveTypeFile($"{symbols.GetName(type)}.cs", new EnumGenerator(assembly.Name, (EnumType)type, symbols).CreateSyntaxTree());
                    return;

                case TypeKind.Interface:
                    InterfaceType interfaceType = (InterfaceType)type;

                    SaveTypeFile($"{symbols.GetName(interfaceType)}.cs", new InterfaceGenerator(assembly.Name, interfaceType, symbols).CreateSyntaxTree());
                    SaveTypeFile($"{symbols.GetInterfaceProxyName(interfaceType)}.cs", new InterfaceProxyGenerator(assembly.Name, interfaceType, symbols).CreateSyntaxTree());

                    if (interfaceType.IsDataType == true)
                    {
                        SaveTypeFile($"{symbols.GetInterfaceDefaultName(interfaceType)}.cs", new InterfaceDefaultGenerator(assembly.Name, interfaceType, symbols).CreateSyntaxTree());
                    }

                    return;

                default:
                    throw new ArgumentException($"Unkown type kind: {type.Kind}", nameof(type));
                }

                void SaveTypeFile(string filename, SyntaxTree syntaxTree)
                {
                    if (!_fileSystem.Directory.Exists(directory))
                    {
                        _fileSystem.Directory.CreateDirectory(directory);
                    }

                    _fileSystem.File.WriteAllText(
                        Path.Combine(directory, filename),
                        syntaxTree.ToString()
                        );
                }
            }
        }
        void Save(string packageOutputRoot, ISymbolMap symbols, Assembly assembly, string tarballFileName, string jsiiFileName)
        {
            if (assembly.Docs != null)
            {
                // TODO: Use Microsoft.Extensions.Logging instead of Console.Error.
                Console.Error.WriteLine($"Warning: Ignoring documentation comment on assembly {assembly.Name}. Assembly-level documentation comments are not supported for .NET");
            }

            SaveProjectFile();
            SaveAssemblyInfo(assembly.Name, assembly.Version, tarballFileName);
            SaveDependencyAnchorFile();

            foreach (Type type in assembly.Types?.Values ?? Enumerable.Empty <Type>())
            {
                SaveType(type);
            }

            void SaveProjectFile()
            {
                XElement project =
                    new XElement("Project",
                                 new XAttribute("Sdk", "Microsoft.NET.Sdk"),
                                 new XElement("PropertyGroup", assembly.GetMsBuildProperties()),
                                 new XElement("ItemGroup",
                                              new XElement("EmbeddedResource",
                                                           new XAttribute("Include", tarballFileName)
                                                           )
                                              ),
                                 new XElement("ItemGroup",
                                              new XElement("PackageReference",
                                                           new XAttribute("Include", "Amazon.JSII.Runtime"),
                                                           new XAttribute("Version", JsiiVersion.Version)
                                                           ),
                                              GetDependencies()
                                              .Distinct()
                                              .Select(d => new { Package = symbols.GetAssemblyName(d.Key), Version = d.Value.GetDecoratedVersion() })
                                              .Select(d =>
                                                      new XElement("PackageReference",
                                                                   new XAttribute("Include", d.Package),
                                                                   new XAttribute("Version", d.Version)
                                                                   )
                                                      )
                                              )
                                 );

                if (!_fileSystem.Directory.Exists(packageOutputRoot))
                {
                    _fileSystem.Directory.CreateDirectory(packageOutputRoot);
                }

                // Save to StringBuilder instead of directly to path, so that we can
                // redirect the output through the filesystem shim. Project files are
                // small, so this shouldn't be a memory hog.
                StringBuilder     builder  = new StringBuilder();
                XmlWriterSettings settings = new XmlWriterSettings
                {
                    // Visual Studio omits the XML declaration when creating project files, so we do too.
                    OmitXmlDeclaration = true,
                    // Visual Studio indents project files (they are often edited by hand), so we do too.
                    Indent = true,
                };

                using (XmlWriter writer = XmlWriter.Create(builder, settings))
                {
                    project.Save(writer);
                }

                string csProjPath = Path.Combine(packageOutputRoot, $"{assembly.GetNativePackageId()}.csproj");

                _fileSystem.File.WriteAllText(csProjPath, builder.ToString());

                IEnumerable <KeyValuePair <string, PackageVersion> > GetDependencies()
                {
                    foreach (KeyValuePair <string, PackageVersion> dependency in GetDependenciesCore(assembly))
                    {
                        yield return(dependency);
                    }

                    IEnumerable <KeyValuePair <string, PackageVersion> > GetDependenciesCore(DependencyRoot root)
                    {
                        if (root.Dependencies == null)
                        {
                            yield break;
                        }
                        foreach (var kvp in root.Dependencies)
                        {
                            yield return(kvp);

                            foreach (KeyValuePair <string, PackageVersion> dependency in GetDependenciesCore(kvp.Value))
                            {
                                yield return(dependency);
                            }
                        }
                    }
                }
            }

            void SaveDependencyAnchorFile()
            {
                string anchorNamespace = $"{assembly.GetNativeNamespace()}.Internal.DependencyResolution";
                var    syntaxTree      = SF.SyntaxTree(
                    SF.CompilationUnit(
                        SF.List <ExternAliasDirectiveSyntax>(),
                        SF.List <UsingDirectiveSyntax>(),
                        SF.List <AttributeListSyntax>(),
                        SF.List <MemberDeclarationSyntax>(new[] {
                    SF.NamespaceDeclaration(
                        SF.IdentifierName(anchorNamespace),
                        SF.List <ExternAliasDirectiveSyntax>(),
                        SF.List <UsingDirectiveSyntax>(),
                        SF.List(new MemberDeclarationSyntax[] { GenerateDependencyAnchor() })
                        )
                })
                        ).NormalizeWhitespace(elasticTrivia: true)
                    );

                string directory = GetNamespaceDirectory(packageOutputRoot, @anchorNamespace);

                SaveSyntaxTree(directory, "Anchor.cs", syntaxTree);

                ClassDeclarationSyntax GenerateDependencyAnchor()
                {
                    return(SF.ClassDeclaration(
                               SF.List <AttributeListSyntax>(),
                               SF.TokenList(SF.Token(SyntaxKind.PublicKeyword)),
                               SF.Identifier("Anchor"),
                               null,
                               null,
                               SF.List <TypeParameterConstraintClauseSyntax>(),
                               SF.List(new MemberDeclarationSyntax[] {
                        SF.ConstructorDeclaration(
                            SF.List <AttributeListSyntax>(),
                            SF.TokenList(SF.Token(SyntaxKind.PublicKeyword)),
                            SF.Identifier("Anchor"),
                            SF.ParameterList(SF.SeparatedList <ParameterSyntax>()),
                            null,
                            SF.Block(SF.List(GenerateAnchorReferences())),
                            null
                            )
                    })
                               ));

                    IEnumerable <StatementSyntax> GenerateAnchorReferences()
                    {
                        return(assembly.Dependencies?.Keys
                               .Select(k => assembly.GetNativeNamespace(k))
                               .Select(n => $"{n}.Internal.DependencyResolution.Anchor")
                               .Select(t => SF.ExpressionStatement(SF.ObjectCreationExpression(
                                                                       SF.Token(SyntaxKind.NewKeyword),
                                                                       SF.ParseTypeName(t),
                                                                       SF.ArgumentList(SF.SeparatedList <ArgumentSyntax>()),
                                                                       null
                                                                       ))) ?? Enumerable.Empty <StatementSyntax>());
                    }
                }
            }

            void SaveAssemblyInfo(string name, string version, string tarball)
            {
                SyntaxTree assemblyInfo = SF.SyntaxTree(
                    SF.CompilationUnit(
                        SF.List <ExternAliasDirectiveSyntax>(),
                        SF.List(new[] {
                    SF.UsingDirective(SF.ParseName("Amazon.JSII.Runtime.Deputy"))
                }),
                        SF.List(new[] {
                    SF.AttributeList(
                        SF.AttributeTargetSpecifier(
                            SF.Identifier("assembly"),
                            SF.Token(SyntaxKind.ColonToken)
                            ),
                        SF.SeparatedList(new[] {
                        SF.Attribute(
                            SF.ParseName("JsiiAssembly"),
                            SF.ParseAttributeArgumentList($"({SF.Literal(name)}, {SF.Literal(version)}, {SF.Literal(tarball)})")
                            )
                    })
                        )
                }),
                        SF.List <MemberDeclarationSyntax>()
                        ).NormalizeWhitespace(elasticTrivia: true)
                    );

                string assemblyInfoPath = Path.Combine(packageOutputRoot, "AssemblyInfo.cs");

                _fileSystem.File.WriteAllText(assemblyInfoPath, assemblyInfo.ToString());
            }

            void SaveType(Type type)
            {
                string @namespace = symbols.GetNamespace(type);
                string directory  = GetNamespaceDirectory(packageOutputRoot, @namespace);

                switch (type.Kind)
                {
                case TypeKind.Class:
                {
                    var classType = (ClassType)type;

                    if (classType.IsAbstract)
                    {
                        SaveTypeFile($"{symbols.GetAbstractClassProxyName(classType)}.cs",
                                     new AbstractClassProxyGenerator(assembly.Name, classType, symbols).CreateSyntaxTree());
                    }

                    SaveTypeFile($"{symbols.GetName(type)}.cs",
                                 new ClassGenerator(assembly.Name, classType, symbols).CreateSyntaxTree());
                    return;
                }

                case TypeKind.Enum:
                {
                    SaveTypeFile($"{symbols.GetName(type)}.cs",
                                 new EnumGenerator(assembly.Name, (EnumType)type, symbols).CreateSyntaxTree());
                    return;
                }

                case TypeKind.Interface:
                {
                    InterfaceType interfaceType = (InterfaceType)type;

                    SaveTypeFile($"{symbols.GetName(interfaceType)}.cs",
                                 new InterfaceGenerator(assembly.Name, interfaceType, symbols).CreateSyntaxTree());
                    SaveTypeFile($"{symbols.GetInterfaceProxyName(interfaceType)}.cs",
                                 new InterfaceProxyGenerator(assembly.Name, interfaceType, symbols).CreateSyntaxTree());

                    if (interfaceType.IsDataType)
                    {
                        SaveTypeFile($"{symbols.GetInterfaceDefaultName(interfaceType)}.cs",
                                     new InterfaceDefaultGenerator(assembly.Name, interfaceType, symbols)
                                     .CreateSyntaxTree());
                    }

                    return;
                }

                default:
                {
                    throw new ArgumentException($"Unkown type kind: {type.Kind}", nameof(type));
                }
                }

                void SaveTypeFile(string filename, SyntaxTree syntaxTree)
                {
                    SaveSyntaxTree(directory, filename, syntaxTree);
                }
            }

            void SaveSyntaxTree(string directory, string filename, SyntaxTree syntaxTree)
            {
                if (!_fileSystem.Directory.Exists(directory))
                {
                    _fileSystem.Directory.CreateDirectory(directory);
                }

                _fileSystem.File.WriteAllText(
                    Path.Combine(directory, filename),
                    syntaxTree.ToString()
                    );
            }
        }
Exemple #15
0
        public static (FixedPointType, SyntaxTree) Generate2x2Type(FixedPointType fType)
        {
            // string dimsName = shape.Select(a => a.ToString()).Aggregate((a, b) => a + "x" + b); // this would be for general tensors...
            string dimsName = string.Format("2x2");
            string typeName = string.Format("mat{0}_{1}", dimsName, fType.name);

            var usingStrings = new List <string> {
                "System",
                "System.Runtime.CompilerServices",
                "System.Runtime.InteropServices",
                "UnityEngine",
                "Unity.Mathematics",
                "Ramjet.Mathematics.FixedPoint",
            };

            var usings = new SyntaxList <UsingDirectiveSyntax>(
                from s in usingStrings select SF.UsingDirective(SF.ParseName(s)));

            var unit = SF.CompilationUnit().WithUsings(usings);

            var nameSpace = SF.NamespaceDeclaration(SF.ParseName("Ramjet.Mathematics.LinearAlgebra"));

            var type = SF.StructDeclaration(typeName)
                       .AddModifiers(SF.Token(SK.PublicKeyword))
                       .WithAttributeLists(Utils.GenerateStructLayoutAttributes());

            var fields = new List <MemberDeclarationSyntax>();

            var rowTypeName      = $@"vec2_{fType.name}";
            var rowTypeSizeBytes = (fType.wordLength * 2) / 8;

            int fieldOffset = 0;

            for (int i = 0; i < 2; i++)
            {
                var row = SF.ParseMemberDeclaration($@"[FieldOffset({fieldOffset})] public {fType.name} c{i};");
                fields.Add(row);
                fieldOffset += rowTypeSizeBytes;
            }

            type = type.AddMembers(fields.ToArray());

            // var zero = SF.ParseMemberDeclaration($@"public static readonly {typeName} Zero = {typeName}.FromInt(0);");

            // var constructorArgs = fields.Select((coeff, index) => $@"{fType.name} {CoefficientNames[index]}").Aggregate((a, b) => a + ", " + b);
            // var constructorAssignments = fields.Select((coeff, index) => $@"this.{CoefficientNames[index]} = {CoefficientNames[index]}").Aggregate((a, b) => a + ";\n" + b) + ";";

            // var constructor = SF.ParseMemberDeclaration($@"
            //     [MethodImpl(MethodImplOptions.AggressiveInlining)]
            //     public {typeName}({constructorArgs}) {{
            //         {constructorAssignments}
            //     }}");

            // type = type.AddMembers(
            //     constructor);

            // var fromIntArgs = fields.Select((coeff, index) => $@"int {CoefficientNames[index]}").Aggregate((a, b) => a + ", " + b);
            // var fromIntAssignments = fields.Select((coeff, index) => $@"{fType.name}.FromInt({CoefficientNames[index]})").Aggregate((a, b) => a + ",\n" + b);
            // var fromInt = SF.ParseMemberDeclaration($@"
            //     [MethodImpl(MethodImplOptions.AggressiveInlining)]
            //     public static {typeName} FromInt({fromIntArgs}) {{
            //         return new {typeName}(
            //             {fromIntAssignments}
            //         );
            //     }}");

            // var fromFloatArgs = fields.Select((coeff, index) => $@"float {CoefficientNames[index]}").Aggregate((a, b) => a + ", " + b);
            // var fromFloatAssignments = fields.Select((coeff, index) => $@"{fType.name}.FromFloat({CoefficientNames[index]})").Aggregate((a, b) => a + ",\n" + b);
            // var fromFloat = SF.ParseMemberDeclaration($@"
            //     [MethodImpl(MethodImplOptions.AggressiveInlining)]
            //     public static {typeName} FromFloat({fromFloatArgs}) {{
            //         return new {typeName}(
            //             {fromFloatAssignments}
            //         );
            //     }}");

            // var fromDoubleArgs = fields.Select((coeff, index) => $@"double {CoefficientNames[index]}").Aggregate((a, b) => a + ", " + b);
            // var fromDoubleAssignments = fields.Select((coeff, index) => $@"{fType.name}.FromDouble({CoefficientNames[index]})").Aggregate((a, b) => a + ",\n" + b);
            // var fromDouble = SF.ParseMemberDeclaration($@"
            //     [MethodImpl(MethodImplOptions.AggressiveInlining)]
            //     public static {typeName} FromFloat({fromDoubleArgs}) {{
            //         return new {typeName}(
            //             {fromDoubleAssignments}
            //         );
            //     }}");

            // type = type.AddMembers(
            //     fromInt,
            //     fromFloat,
            //     fromDouble
            // );

            // var opAddInstructions = fields.Select((coeff, index) => $@"lhs.{CoefficientNames[index]} + rhs.{CoefficientNames[index]}")
            //     .Aggregate((a, b) => a + ", \n" + b);
            // var opAdd = SF.ParseMemberDeclaration($@"
            //    [MethodImpl(MethodImplOptions.AggressiveInlining)]
            //     public static {typeName} operator +({typeName} lhs, {typeName} rhs) {{
            //         return new {typeName}(
            //             {opAddInstructions}
            //         );
            //     }}");

            // var opSubInstructions = fields.Select((coeff, index) => $@"lhs.{CoefficientNames[index]} - rhs.{CoefficientNames[index]}")
            //     .Aggregate((a, b) => a + ", \n" + b);
            // var opSub = SF.ParseMemberDeclaration($@"
            //    [MethodImpl(MethodImplOptions.AggressiveInlining)]
            //     public static {typeName} operator -({typeName} lhs, {typeName} rhs) {{
            //         return new {typeName}(
            //             {opSubInstructions}
            //         );
            //     }}");

            // var opMulScalarRightInstructions = fields.Select((coeff, index) => $@"lhs.{CoefficientNames[index]} * rhs")
            //     .Aggregate((a, b) => a + ", \n" + b);
            // var opMulScalarRight = SF.ParseMemberDeclaration($@"
            //    [MethodImpl(MethodImplOptions.AggressiveInlining)]
            //     public static {typeName} operator *({typeName} lhs, {fType.name} rhs) {{
            //         return new {typeName}(
            //             {opMulScalarRightInstructions}
            //         );
            //     }}");

            // var opDivScalarRightInstructions = fields.Select((coeff, index) => $@"lhs.{CoefficientNames[index]} / rhs")
            //     .Aggregate((a, b) => a + ", \n" + b);
            // var opDivScalarRight = SF.ParseMemberDeclaration($@"
            //    [MethodImpl(MethodImplOptions.AggressiveInlining)]
            //     public static {typeName} operator /({typeName} lhs, {fType.name} rhs) {{
            //         return new {typeName}(
            //             {opDivScalarRightInstructions}
            //         );
            //     }}");

            // type = type.AddMembers(
            //     opAdd,
            //     opSub,
            //     opMulScalarRight,
            //     opDivScalarRight);


            // /* Equality */

            // var eqInstructions = fields.Select((coeff, index) => $@"this.{CoefficientNames[index]} == rhs.{CoefficientNames[index]}")
            //     .Aggregate((a, b) => a + " &&\n" + b);
            // var equals = SF.ParseMemberDeclaration($@"
            //     [MethodImpl(MethodImplOptions.AggressiveInlining)]
            //     public bool Equals({typeName} rhs) {{
            //         return {eqInstructions};
            //     }}");

            // var equalsObj = SF.ParseMemberDeclaration($@"
            //     [MethodImpl(MethodImplOptions.AggressiveInlining)]
            //     public override bool Equals(object o) {{
            //         if (!(o is {typeName})) {{
            //             return false;
            //         }}
            //         return Equals(({typeName})o);
            //     }}");

            // var opEq = SF.ParseMemberDeclaration($@"
            //     public static bool operator ==({typeName} lhs, {typeName} rhs) {{
            //         return lhs.Equals(rhs);
            //     }}");

            // var opNEq = SF.ParseMemberDeclaration($@"
            //     public static bool operator !=({typeName} lhs, {typeName} rhs) {{
            //         return !lhs.Equals(rhs);
            //     }}");

            // type = type.AddMembers(
            //     equals,
            //     equalsObj,
            //     opEq,
            //     opNEq);

            // // Other

            // /*
            // GetHashCode

            // Todo: None of these make particular sense for each type yet...
            // */
            // var getHashCodeInstructions = fields.Select((coeff, index) => $@"this.{CoefficientNames[index]}.v")
            //    .Aggregate((a, b) => a + " ^\n" + b);
            // var getHashCode = SF.ParseMemberDeclaration($@"
            //     [MethodImpl(MethodImplOptions.AggressiveInlining)]
            //     public override int GetHashCode() {{
            //         return (int)({getHashCodeInstructions});
            //     }}");

            // var toStringReplaceList = fields.Select((coeff, index) => $@"{{{index}:0.000}}")
            //    .Aggregate((a, b) => a + ", " + b);
            // var toStringCoeffs = fields.Select((coeff, index) => $@"{fType.name}.ToFloat(this.{CoefficientNames[index]})")
            //    .Aggregate((a, b) => a + ", " + b);
            // var toString = SF.ParseMemberDeclaration($@"
            //     [MethodImpl(MethodImplOptions.AggressiveInlining)]
            //     public override string ToString() {{
            //         return string.Format(""{typeName}({toStringReplaceList})"", {toStringCoeffs});
            //     }}");

            // var toStringFormat = SF.ParseMemberDeclaration($@"
            //     [MethodImpl(MethodImplOptions.AggressiveInlining)]
            //     public string ToString(string format, IFormatProvider formatProvider) {{
            //         return ToString();
            //     }}");

            // type = type.AddMembers(
            //     getHashCode,
            //     toString,
            //     toStringFormat);

            nameSpace = nameSpace.AddMembers(type);
            unit      = unit.AddMembers(nameSpace);

            return(fType, CSharpSyntaxTree.Create(unit));
        }
Exemple #16
0
        public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context)
        {
            var root = await context.Document.GetSyntaxRootAsync(context.CancellationToken).ConfigureAwait(false);

            // TODO: Replace the following code with your own analysis, generating a CodeAction for each fix to suggest
            var diagnostic = context.Diagnostics.First();

            if (diagnostic.Id == StacksAnalyzer.CommandsEndWithCommand.Id)
            {
                var diagnosticSpan = diagnostic.Location.SourceSpan;

                // Find the type declaration identified by the diagnostic.
                var declaration = root.FindToken(diagnosticSpan.Start).Parent.AncestorsAndSelf().OfType <TypeDeclarationSyntax>().First();

                // Register a code action that will invoke the fix.
                context.RegisterCodeFix(
                    CodeAction.Create(
                        title: "Append 'Command'",
                        createChangedSolution: c => this.AppendCommandText(context.Document, "Command", declaration, c),
                        equivalenceKey: "Append 'Command'"),
                    diagnostic);
            }
            else if (diagnostic.Id == StacksAnalyzer.EventsEndWithEvents.Id)
            {
                var diagnosticSpan = diagnostic.Location.SourceSpan;

                // Find the type declaration identified by the diagnostic.
                var declaration = root.FindToken(diagnosticSpan.Start).Parent.AncestorsAndSelf().OfType <TypeDeclarationSyntax>().First();

                // Register a code action that will invoke the fix.
                context.RegisterCodeFix(
                    CodeAction.Create(
                        title: "Append 'Event'",
                        createChangedSolution: c => this.AppendCommandText(context.Document, "Event", declaration, c),
                        equivalenceKey: "Append 'Event'"),
                    diagnostic);
            }
            else if (diagnostic.Id == StacksAnalyzer.MessagePropertiesAreImmutable.Id)
            {
                var diagnosticSpan = diagnostic.Location.SourceSpan;

                var property = root.FindNode(diagnosticSpan) as PropertyDeclarationSyntax;

                // Register a code action that will invoke the fix.
                context.RegisterCodeFix(
                    CodeAction.Create(
                        title: "Remove setter",
                        createChangedDocument: async c =>
                {
                    var previousWhiteSpacesToken = SF.Token(property.GetLeadingTrivia(), SyntaxKind.StringLiteralToken, SyntaxTriviaList.Empty);

                    var target = property.WithModifiers(SF.TokenList(previousWhiteSpacesToken, SF.Token(SyntaxKind.PublicKeyword)))
                                 .WithAccessorList(SF.AccessorList(SF.List(new[]
                    {
                        SF.AccessorDeclaration(SyntaxKind.GetAccessorDeclaration)
                        .WithSemicolonToken(SF.Token(SyntaxKind.SemicolonToken))
                    })));

                    var updated = await context.Document.GetSyntaxRootAsync(c);
                    return(context.Document.WithSyntaxRoot(updated.ReplaceNode(property, new[] { target })));
                },
                        equivalenceKey: "Remove setter"),
                    diagnostic);

                context.RegisterCodeFix(
                    CodeAction.Create(
                        title: "Make setter private",
                        createChangedDocument: async c =>
                {
                    var previousWhiteSpacesToken = SF.Token(property.GetLeadingTrivia(), SyntaxKind.StringLiteralToken, SyntaxTriviaList.Empty);

                    var target = property.WithModifiers(SF.TokenList(previousWhiteSpacesToken, SF.Token(SyntaxKind.PublicKeyword)))
                                 .WithAccessorList(SF.AccessorList(SF.List(new[]
                    {
                        SF.AccessorDeclaration(SyntaxKind.GetAccessorDeclaration)
                        .WithSemicolonToken(SF.Token(SyntaxKind.SemicolonToken)),
                        SF.AccessorDeclaration(SyntaxKind.SetAccessorDeclaration)
                        .WithModifiers(SF.TokenList(SF.Token(SyntaxKind.PrivateKeyword)))
                        .WithSemicolonToken(SF.Token(SyntaxKind.SemicolonToken))
                    })));

                    var updated = await context.Document.GetSyntaxRootAsync(c);
                    return(context.Document.WithSyntaxRoot(updated.ReplaceNode(property, new[] { target })));
                },
                        equivalenceKey: "Make setter private"),
                    diagnostic);
            }
            else if (diagnostic.Id == StacksAnalyzer.UseCaseShouldHaveRules.Id)
            {
                var diagnosticSpan = diagnostic.Location.SourceSpan;

                var property = root.FindNode(diagnosticSpan) as ClassDeclarationSyntax;

                context.RegisterCodeFix(
                    CodeAction.Create(
                        title: "Create business rule",
                        createChangedDocument: async c =>
                {
                    //property.Identifier.ValueText;

                    var cu = SF.CompilationUnit().AddUsings(
                        SF.UsingDirective(SF.IdentifierName("System")),
                        SF.UsingDirective(SF.IdentifierName("Slalom.Stacks.Messaging.Validation")));


                    NamespaceDeclarationSyntax namespaceDeclarationSyntax = null;
                    if (!SyntaxNodeHelper.TryGetParentSyntax(property, out namespaceDeclarationSyntax))
                    {
                    }

                    var ns = SF.NamespaceDeclaration(namespaceDeclarationSyntax.Name);

                    var comp    = await context.Document.Project.GetCompilationAsync();
                    string name = property.Identifier.Value + "_rule";
                    var command = ((IdentifierNameSyntax)((GenericNameSyntax)property.BaseList.Types[0].Type).TypeArgumentList.Arguments[0]).Identifier.ValueText;
                    //if (comp.GetSymbolsWithName(x => x == name) != null)
                    //{
                    //    int i = 1;
                    //    var current = name + i;
                    //    while (comp.GetSymbolsWithName(x => x == current) != null)
                    //    {
                    //        i++;
                    //    }
                    //}

                    var cl = SF.ClassDeclaration(name)
                             .WithModifiers(SF.TokenList(SF.Token(SyntaxKind.PublicKeyword)))
                             .AddBaseListTypes(SF.SimpleBaseType(SF.ParseTypeName("BusinessRule<" + command + ">")));
                    ns = ns.AddMembers(cl);
                    cu = cu.AddMembers(ns);

                    SyntaxNode formattedNode = Formatter.Format(cu, context.Document.Project.Solution.Workspace);
                    StringBuilder sb         = new StringBuilder();
                    using (StringWriter writer = new StringWriter(sb))
                    {
                        formattedNode.WriteTo(writer);
                    }

                    return(context.Document.Project.AddDocument(name + ".cs", sb.ToString(), namespaceDeclarationSyntax.Name.ToString().Split('.').Skip(1).Concat(new[] { "Rules" })));
                },
                        equivalenceKey: "Create business rule"),
                    diagnostic);
            }
        }
        /// <summary>
        /// Generates a syntax tree for the provided assemblies.
        /// </summary>
        /// <param name="targetAssembly">The assemblies used for accessiblity checks, or <see langword="null"/> during runtime code generation.</param>
        /// <param name="assemblies">The assemblies to generate code for.</param>
        /// <returns>The generated syntax tree.</returns>
        private GeneratedSyntax GenerateCode(Assembly targetAssembly, List <Assembly> assemblies)
        {
            var features = new FeatureDescriptions();
            var members  = new List <MemberDeclarationSyntax>();

            // Expand the list of included assemblies and types.
            var knownAssemblies =
                new Dictionary <Assembly, KnownAssemblyAttribute>(
                    assemblies.ToDictionary(k => k, k => default(KnownAssemblyAttribute)));

            foreach (var attribute in assemblies.SelectMany(asm => asm.GetCustomAttributes <KnownAssemblyAttribute>()))
            {
                knownAssemblies[attribute.Assembly] = attribute;
            }

            if (logger.IsEnabled(LogLevel.Information))
            {
                logger.Info($"Generating code for assemblies: {string.Join(", ", knownAssemblies.Keys.Select(a => a.FullName))}");
            }

            // Get types from assemblies which reference Orleans and are not generated assemblies.
            var grainClasses    = new HashSet <Type>();
            var grainInterfaces = new HashSet <Type>();

            foreach (var pair in knownAssemblies)
            {
                var assembly = pair.Key;
                var treatTypesAsSerializable = pair.Value?.TreatTypesAsSerializable ?? false;
                foreach (var type in TypeUtils.GetDefinedTypes(assembly, this.logger))
                {
                    if (treatTypesAsSerializable || type.IsSerializable || TypeHasKnownBase(type))
                    {
                        string logContext = null;
                        if (logger.IsEnabled(LogLevel.Trace))
                        {
                            if (treatTypesAsSerializable)
                            {
                                logContext = $"known assembly {assembly.GetName().Name} where 'TreatTypesAsSerializable' = true";
                            }
                            else if (type.IsSerializable)
                            {
                                logContext = $"known assembly {assembly.GetName().Name} where type is [Serializable]";
                            }
                            else if (type.IsSerializable)
                            {
                                logContext = $"known assembly {assembly.GetName().Name} where type has known base type.";
                            }
                        }

                        serializableTypes.RecordType(type, targetAssembly, logContext);
                    }

                    // Include grain interfaces and classes.
                    var isGrainInterface = GrainInterfaceUtils.IsGrainInterface(type);
                    var isGrainClass     = TypeUtils.IsConcreteGrainClass(type);
                    if (isGrainInterface || isGrainClass)
                    {
                        // If code generation is being performed at runtime, the interface must be accessible to the generated code.
                        if (!TypeUtilities.IsAccessibleFromAssembly(type, targetAssembly))
                        {
                            if (this.logger.IsEnabled(LogLevel.Debug))
                            {
                                this.logger.Debug("Skipping inaccessible grain type, {0}", type.GetParseableName());
                            }

                            continue;
                        }

                        // Attempt to generate serializers for grain state classes, i.e, T in Grain<T>.
                        var baseType = type.BaseType;
                        if (baseType != null && baseType.IsConstructedGenericType)
                        {
                            foreach (var arg in baseType.GetGenericArguments())
                            {
                                string logContext = null;
                                if (logger.IsEnabled(LogLevel.Trace))
                                {
                                    logContext = "generic base type of " + type.GetLogFormat();
                                }
                                this.serializableTypes.RecordType(arg, targetAssembly, logContext);
                            }
                        }

                        // Skip classes generated by this generator.
                        if (IsOrleansGeneratedCode(type))
                        {
                            if (this.logger.IsEnabled(LogLevel.Debug))
                            {
                                this.logger.Debug("Skipping generated grain type, {0}", type.GetParseableName());
                            }

                            continue;
                        }

                        if (this.knownGrainTypes.Contains(type))
                        {
                            if (this.logger.IsEnabled(LogLevel.Debug))
                            {
                                this.logger.Debug("Skipping grain type {0} since it already has generated code.", type.GetParseableName());
                            }

                            continue;
                        }

                        if (isGrainClass)
                        {
                            if (this.logger.IsEnabled(LogLevel.Information))
                            {
                                this.logger.Info("Found grain implementation class: {0}", type.GetParseableName());
                            }

                            grainClasses.Add(type);
                        }

                        if (isGrainInterface)
                        {
                            if (this.logger.IsEnabled(LogLevel.Information))
                            {
                                this.logger.Info("Found grain interface: {0}", type.GetParseableName());
                            }

                            GrainInterfaceUtils.ValidateInterfaceRules(type);

                            grainInterfaces.Add(type);
                        }
                    }
                }
            }

            // Group the types by namespace and generate the required code in each namespace.
            foreach (var groupedGrainInterfaces in grainInterfaces.GroupBy(_ => CodeGeneratorCommon.GetGeneratedNamespace(_)))
            {
                var namespaceName    = groupedGrainInterfaces.Key;
                var namespaceMembers = new List <MemberDeclarationSyntax>();
                foreach (var grainInterface in groupedGrainInterfaces)
                {
                    var referenceTypeName = GrainReferenceGenerator.GetGeneratedClassName(grainInterface);
                    var invokerTypeName   = GrainMethodInvokerGenerator.GetGeneratedClassName(grainInterface);
                    namespaceMembers.Add(
                        GrainReferenceGenerator.GenerateClass(
                            grainInterface,
                            referenceTypeName,
                            encounteredType =>
                    {
                        string logContext = null;
                        if (logger.IsEnabled(LogLevel.Trace))
                        {
                            logContext = "used by grain type " + grainInterface.GetLogFormat();
                        }
                        this.serializableTypes.RecordType(encounteredType, targetAssembly, logContext);
                    }));
                    namespaceMembers.Add(GrainMethodInvokerGenerator.GenerateClass(grainInterface, invokerTypeName));
                    var genericTypeSuffix = GetGenericTypeSuffix(grainInterface.GetGenericArguments().Length);
                    features.GrainInterfaces.Add(
                        new GrainInterfaceDescription
                    {
                        Interface   = grainInterface.GetTypeSyntax(includeGenericParameters: false),
                        Reference   = SF.ParseTypeName(namespaceName + '.' + referenceTypeName + genericTypeSuffix),
                        Invoker     = SF.ParseTypeName(namespaceName + '.' + invokerTypeName + genericTypeSuffix),
                        InterfaceId = GrainInterfaceUtils.GetGrainInterfaceId(grainInterface)
                    });
                }

                members.Add(CreateNamespace(namespaceName, namespaceMembers));
            }

            foreach (var type in grainClasses)
            {
                features.GrainClasses.Add(
                    new GrainClassDescription
                {
                    ClassType = type.GetTypeSyntax(includeGenericParameters: false)
                });
            }

            // Generate serializers into their own namespace.
            var serializerNamespace = this.GenerateSerializers(targetAssembly, features);

            members.Add(serializerNamespace);

            // Add serialization metadata for the types which were encountered.
            this.AddSerializationTypes(features.Serializers, targetAssembly, knownAssemblies.Keys.ToList());

            foreach (var attribute in knownAssemblies.Keys.SelectMany(asm => asm.GetCustomAttributes <ConsiderForCodeGenerationAttribute>()))
            {
                this.serializableTypes.RecordType(attribute.Type, targetAssembly, "[ConsiderForCodeGeneration]");
                if (attribute.ThrowOnFailure && !this.serializableTypes.IsTypeRecorded(attribute.Type) && !this.serializableTypes.IsTypeIgnored(attribute.Type))
                {
                    throw new CodeGenerationException(
                              $"Found {attribute.GetType().Name} for type {attribute.Type.GetParseableName()}, but code" +
                              " could not be generated. Ensure that the type is accessible.");
                }
            }

            // Generate metadata directives for all of the relevant types.
            var(attributeDeclarations, memberDeclarations) = FeaturePopulatorGenerator.GenerateSyntax(targetAssembly, features);
            members.AddRange(memberDeclarations);

            var compilationUnit = SF.CompilationUnit().AddAttributeLists(attributeDeclarations.ToArray()).AddMembers(members.ToArray());

            return(new GeneratedSyntax
            {
                SourceAssemblies = knownAssemblies.Keys.ToList(),
                Syntax = compilationUnit
            });
        }
Exemple #18
0
        public static byte[] CreateControllerCode(IService service)
        {
            var @file      = SF.CompilationUnit();
            var @namespace = SF.NamespaceDeclaration(SF.ParseName("MBase.ServiceHost.Controllers")).NormalizeWhitespace();

            @file = @file
                    .AddUsings(SF.UsingDirective(SF.IdentifierName("System")));
            @file = @file
                    .AddUsings(SF.UsingDirective(SF.IdentifierName("Microsoft.AspNetCore.Mvc")));
            @file = @file
                    .AddUsings(SF.UsingDirective(SF.IdentifierName("System.Threading.Tasks")));

            @file = @file.AddUsings(SF.UsingDirective(SF.IdentifierName(service.GetType().Namespace)));
            @file = @file.AddUsings(SF.UsingDirective(SF.IdentifierName(service.GetType().Namespace + ".Models")));

            foreach (var item in service.Commands.Where(m => typeof(ICommand).IsAssignableFrom(m.GetType())))
            {
                @file = @file.AddUsings(SF.UsingDirective(SF.IdentifierName(item.GetType().Namespace)));
            }



            var classDeclaration = SF.ClassDeclaration(service.GetType().Name.ToString() + "Controller")
                                   .AddModifiers(SF.Token(SyntaxKind.PublicKeyword))
                                   .AddBaseListTypes(SF.SimpleBaseType(SF.ParseTypeName("ControllerBase")))
                                   .WithAttributeLists(
                SF.List(
                    new AttributeListSyntax[] {
                SF.AttributeList(
                    SF.SingletonSeparatedList(
                        SF.Attribute(SF.IdentifierName("Route"))
                        .WithArgumentList(
                            SF.AttributeArgumentList(
                                SF.SingletonSeparatedList(
                                    SF.AttributeArgument(
                                        SF.LiteralExpression(SyntaxKind.StringLiteralExpression, SF.Literal($"api/[controller]")))))))),
                SF.AttributeList(
                    SF.SingletonSeparatedList(
                        SF.Attribute(SF.IdentifierName("ApiController"))))
            }));

            List <MemberDeclarationSyntax> controllerMembers = new List <MemberDeclarationSyntax>();

            controllerMembers.Add(
                SF.FieldDeclaration(
                    SF.VariableDeclaration(
                        SF.ParseTypeName(service.GetType().Name))
                    .AddVariables(SF.VariableDeclarator("_service")))
                .AddModifiers(SF.Token(SyntaxKind.PrivateKeyword)));

            controllerMembers.Add(
                SF.ConstructorDeclaration(service.GetType().Name.ToString() + "Controller")
                .WithParameterList(
                    SF.ParameterList(
                        SF.SingletonSeparatedList(
                            SF.Parameter(
                                SF.Identifier("service"))
                            .WithType(
                                SF.IdentifierName("IService")))

                        ))
                .AddModifiers(SF.Token(SyntaxKind.PublicKeyword))
                .WithBody(SF.Block(SF.ParseStatement($"this._service = ({service.GetType().Name})service;"))));

            foreach (var item in service.Commands.Where(m => typeof(ICommand).IsAssignableFrom(m.GetType())))
            {
                var syntax = @$ "

            var response = await CommandHelper.ExecuteMethod<{item.Name}>(new {item.Name}(),new Request<{item.Name}>(request, new MessageEnvelope()));