Esempio n. 1
0
        /// <summary>
        /// Write mixed-mode (partial) classes.
        /// </summary>
        /// <param name="project">The current project.</param>
        /// <param name="profile">The profile to write mixed-mode classes for.</param>
        /// <param name="folder">The folder to store the generated classes in.</param>
        public static void WriteMixedModeClasses(this Project project, Profile profile, string folder, BindState task)
        {
            // public abstract class MixedModeClass : IMixedModeClass
            // {
            // }
            foreach (var @class in project.Classes)
            {
                if ((@class.NativeApis.Values.Sum
                         (x => x.Functions.Count) + @class.Functions.Count + @class.Constants.Count) == 0)
                {
                    Console.WriteLine($"Warning: No functions or constants, writing of class \"{@class.ClassName}\" " +
                                      $"skipped...");
                    continue;
                }

                if (project.IsRoot)
                {
                    var allFunctions = @class.NativeApis.SelectMany
                                           (x => x.Value.Functions)
                                       .RemoveDuplicates()
                                       .ToArray();
                    var sw = new StreamWriter(Path.Combine(folder, $"{@class.ClassName}.gen.cs"))
                    {
                        NewLine = "\n"
                    };
                    StreamWriter?swOverloads = null;
                    sw.Write(task.LicenseText());
                    sw.WriteCoreUsings();
                    sw.WriteLine();
                    sw.WriteLine("#pragma warning disable 1591");
                    sw.WriteLine();
                    sw.WriteLine($"namespace {task.Task.Namespace}{project.Namespace}");
                    sw.WriteLine("{");
                    sw.Write($"    public unsafe partial class {@class.ClassName}");
                    if (allFunctions.Any())
                    {
                        sw.WriteLine(" : NativeAPI");
                    }
                    else
                    {
                        sw.WriteLine();
                    }

                    sw.WriteLine("    {");
                    foreach (var constant in @class.Constants)
                    {
                        sw.WriteLine($"        [NativeName(\"Type\", \"{constant.Type.OriginalName}\")]");
                        sw.WriteLine($"        [NativeName(\"Name\", \"{constant.NativeName}\")]");
                        sw.WriteLine
                        (
                            $"        public const {constant.Type} {constant.Name} = " +
                            $"unchecked(({constant.Type}) {constant.Value});"
                        );
                    }

                    sw.WriteLine();
                    foreach (var function in allFunctions)
                    {
                        AddInjectionAttributes(function, task);

                        if (!string.IsNullOrWhiteSpace(function.PreprocessorConditions))
                        {
                            sw.WriteLine($"#if {function.PreprocessorConditions}");
                        }

                        using (var sr = new StringReader(function.Doc))
                        {
                            string line;
                            while ((line = sr.ReadLine()) != null)
                            {
                                sw.WriteLine($"        {line}");
                            }
                        }

                        foreach (var attr in function.Attributes)
                        {
                            sw.WriteLine($"        [{attr.Name}({string.Join(", ", attr.Arguments)})]");
                        }


                        if (function.Convention != CallingConvention.Cdecl)
                        {
                            sw.WriteLine
                            (
                                $"        [NativeApi(EntryPoint = \"{function.NativeName}\", " +
                                $"Convention = CallingConvention.{function.Convention})]"
                            );
                        }
                        else
                        {
                            sw.WriteLine($"        [NativeApi(EntryPoint = \"{function.NativeName}\")]");
                        }

                        using (var sr = new StringReader(function.ToString(null, true, true)))
                        {
                            string line;
                            while ((line = sr.ReadLine()) != null)
                            {
                                sw.WriteLine($"        {line}");
                            }
                        }

                        if (!string.IsNullOrWhiteSpace(function.PreprocessorConditions))
                        {
                            sw.WriteLine("#endif");
                        }

                        sw.WriteLine();
                    }

                    foreach (var overload in Overloader.GetOverloads(allFunctions, profile.Projects["Core"], task.Task.OverloaderExclusions))
                    {
                        var sw2u = overload.Signature.Kind == SignatureKind.PotentiallyConflictingOverload
                            ? swOverloads ??= CreateOverloadsFile(folder, @class.ClassName, false)
                            : sw;
                        if (!string.IsNullOrWhiteSpace(overload.Base.PreprocessorConditions))
                        {
                            sw2u.WriteLine($"#if {overload.Base.PreprocessorConditions}");
                        }

                        if (sw2u == swOverloads)
                        {
                            overload.Signature.Parameters.Insert
                            (
                                0,
                                new Parameter
                            {
                                Name = "thisApi",
                                Type = new Common.Functions.Type {
                                    Name = @class.ClassName, IsThis = true
                                }
                            }
                            );
                        }

                        using (var sr = new StringReader(overload.Signature.Doc))
                        {
                            string line;
                            while ((line = sr.ReadLine()) != null)
                            {
                                sw2u.WriteLine($"        {line}");
                            }
                        }

                        foreach (var attr in overload.Signature.Attributes)
                        {
                            sw2u.WriteLine($"        [{attr.Name}({string.Join(", ", attr.Arguments)})]");
                        }

                        sw2u.WriteLine($"        public {overload.Signature.ToString(overload.IsUnsafe, @static: sw2u == swOverloads).TrimEnd(';')}");
                        sw2u.WriteLine("        {");
                        foreach (var line in overload.Body)
                        {
                            sw2u.WriteLine($"            {line}");
                        }

                        sw2u.WriteLine("        }");

                        if (!string.IsNullOrWhiteSpace(overload.Base.PreprocessorConditions))
                        {
                            sw2u.WriteLine($"#endif");
                        }

                        sw2u.WriteLine();
                    }

                    if (allFunctions.Any())
                    {
                        sw.WriteLine();
                        sw.WriteLine($"        public {@class.ClassName}(INativeContext ctx)");
                        sw.WriteLine("            : base(ctx)");
                        sw.WriteLine("        {");
                        sw.WriteLine("        }");
                    }

                    sw.WriteLine("    }");
                    sw.WriteLine("}");
                    sw.WriteLine();
                    FinishOverloadsFile(swOverloads);
                    sw.Flush();
                    sw.Dispose();
                    if (!File.Exists(Path.Combine(folder, $"{@class.ClassName}.cs")) && allFunctions.Any())
                    {
                        sw = new StreamWriter(Path.Combine(folder, $"{@class.ClassName}.cs"))
                        {
                            NewLine = "\n"
                        };
                        sw.WriteCoreUsings();
                        sw.WriteLine("using static Silk.NET.Core.Attributes.ExtensionAttribute;");
                        sw.WriteLine();
                        sw.WriteLine("#pragma warning disable 1591");
                        sw.WriteLine();
                        sw.WriteLine($"namespace {task.Task.Namespace}{project.Namespace}");
                        sw.WriteLine("{");
                        sw.WriteLine($"    public partial class {@class.ClassName}");
                        sw.WriteLine("    {");
                        sw.WriteLine($"        public static {@class.ClassName} GetApi()");
                        sw.WriteLine("        {");
                        if (!(task.Task.NameContainer is null))
                        {
                            sw.WriteLine
                            (
                                $"             return new(CreateDefaultContext" +
                                $"(new {task.Task.NameContainer.ClassName}().GetLibraryName()));"
                            );
                        }
                        else
                        {
                            sw.WriteLine("             throw new NotImplementedException();");
                        }
                        sw.WriteLine("        }");
                        sw.WriteLine();
                        sw.WriteLine("        public bool TryGetExtension<T>(out T ext)");
                        sw.WriteLine($"            where T:NativeExtension<{@class.ClassName}>");
                        sw.WriteLine("        {");
                        sw.WriteLine("             ext = IsExtensionPresent(GetExtensionAttribute(typeof(T)).Name)");
                        sw.WriteLine("                 ? (T) Activator.CreateInstance(typeof(T), Context)");
                        sw.WriteLine("                 : null;");
                        sw.WriteLine("             return ext is not null;");
                        sw.WriteLine("        }");
                        sw.WriteLine();
                        sw.WriteLine("        public override bool IsExtensionPresent(string extension)");
                        sw.WriteLine("        {");
                        sw.WriteLine("            throw new NotImplementedException();");
                        sw.WriteLine("        }");
                        sw.WriteLine("    }");
                        sw.WriteLine("}");
                        sw.WriteLine();
                        sw.Flush();
                        sw.Dispose();
                    }

                    if (!(task.Task.NameContainer is null))
                    {
                        project.WriteNameContainer
                            (profile, Path.Combine(folder, $"{task.Task.NameContainer.ClassName}.cs"), task);
                    }
                }
Esempio n. 2
0
        public static void WriteMixedModeClasses(this Project project, Profile profile, string folder)
        {
            // public abstract class MixedModeClass : IMixedModeClass
            // {
            // }
            if (project.IsRoot)
            {
                var sw = new StreamWriter(Path.Combine(folder, profile.ClassName + ".gen.cs"));
                sw.Write(LicenseText.Value);
                sw.WriteLine("using System;");
                sw.WriteLine("using System.Runtime.InteropServices;");
                sw.WriteLine("using System.Text;");
                sw.WriteLine("using Silk.NET.Core.Native;");
                sw.WriteLine("using Silk.NET.Core.Loader;");
                sw.WriteLine("using AdvancedDLSupport;");
                sw.WriteLine();
                sw.WriteLine("namespace " + profile.Namespace + project.Namespace);
                sw.WriteLine("{");
                sw.WriteLine($"    public abstract partial class {profile.ClassName} : NativeAPI, I{profile.ClassName}");
                sw.WriteLine("    {");
                var allFunctions = project.Interfaces.SelectMany(x => x.Value.Functions).RemoveDuplicates();
                foreach (var function in allFunctions)
                {
                    sw.WriteLine("        /// <inheritdoc />");
                    using (var sr = new StringReader(function.ToString()))
                    {
                        string line;
                        var    flPrefix = "public abstract ";
                        while ((line = sr.ReadLine()) != null)
                        {
                            sw.WriteLine($"        {flPrefix}{line}");
                            flPrefix = string.Empty;
                        }
                    }
                    sw.WriteLine();
                }

                foreach (var overload in Overloader.GetOverloads(project))
                {
                    using (var sr = new StringReader(overload.Signature.Doc))
                    {
                        string line;
                        while ((line = sr.ReadLine()) != null)
                        {
                            sw.WriteLine("        " + line);
                        }
                    }

                    foreach (var attr in overload.Signature.Attributes)
                    {
                        sw.WriteLine("        [" + attr.Name + "(" + string.Join(", ", attr.Arguments) + ")]");
                    }

                    sw.WriteLine("        public " + overload.Signature.ToString(overload.Unsafe).TrimEnd(';'));
                    sw.WriteLine("        {");
                    using (var sr = new StringReader(overload.CodeBlock))
                    {
                        string line;
                        while ((line = sr.ReadLine()) != null)
                        {
                            sw.WriteLine($"            {line}");
                        }
                    }
                    sw.WriteLine("        }");
                    sw.WriteLine();
                }

                sw.WriteLine
                (
                    "        public override SearchPathContainer SearchPaths { get; } = new "
                    + profile.Names.ClassName + "();"
                );
                sw.WriteLine();
                sw.WriteLine($"        public {profile.ClassName}(string path, ImplementationOptions opts)");
                sw.WriteLine("            : base(path, opts)");
                sw.WriteLine("        {");
                sw.WriteLine("        }");
                if (profile.SymbolLoaderName != null)
                {
                    sw.WriteLine();
                    sw.WriteLine($"        static {profile.ClassName}()");
                    sw.WriteLine("        {");
                    sw.WriteLine($"            LibraryLoader.CreateBuilder<{profile.ClassName}>({profile.SymbolLoaderName});");
                    sw.WriteLine("        }");
                }
                sw.WriteLine("    }");
                sw.WriteLine("}");
                sw.WriteLine();
                sw.Flush();
                sw.Dispose();
                if (!File.Exists(Path.Combine(folder, profile.ClassName + ".cs")))
                {
                    sw = new StreamWriter(Path.Combine(folder, profile.ClassName + ".cs"));
                    sw.WriteLine("using System;");
                    sw.WriteLine("using Silk.NET.Core.Loader;");
                    sw.WriteLine("using Silk.NET.Core.Native;");
                    sw.WriteLine();
                    sw.WriteLine("namespace " + profile.Namespace + project.Namespace);
                    sw.WriteLine("{");
                    sw.WriteLine("    public partial class " + profile.ClassName);
                    sw.WriteLine("    {");
                    sw.WriteLine("        public static " + profile.ClassName + " GetApi()");
                    sw.WriteLine("        {");
                    sw.WriteLine($"             return LibraryLoader<{profile.ClassName}>.Load(new {profile.Names.ClassName}());");
                    sw.WriteLine("        }");
                    sw.WriteLine();
                    sw.WriteLine("        public bool TryGetExtension<T>(out T ext)");
                    sw.WriteLine("            where T:NativeExtension<" + profile.ClassName + ">");
                    sw.WriteLine("        {");
                    sw.WriteLine($"             ext = LibraryLoader<{profile.ClassName}>.Load<T>(this);");
                    sw.WriteLine("             return ext != null;");
                    sw.WriteLine("        }");
                    sw.WriteLine();
                    sw.WriteLine("        public override bool IsExtensionPresent(string extension)");
                    sw.WriteLine("        {");
                    sw.WriteLine("            throw new NotImplementedException();");
                    sw.WriteLine("        }");
                    sw.WriteLine("    }");
                    sw.WriteLine("}");
                    sw.WriteLine();
                    sw.Flush();
                    sw.Dispose();
                }

                project.WriteNameContainer(profile, Path.Combine(folder, profile.Names.ClassName + ".cs"));
            }
            else
            {
                foreach (var(key, i) in project.Interfaces)
                {
                    var name = key.Substring(1);
                    var sw   = new StreamWriter(Path.Combine(folder, name + ".gen.cs"));
                    sw.Write(LicenseText.Value);
                    sw.WriteLine("using System;");
                    sw.WriteLine("using System.Runtime.InteropServices;");
                    sw.WriteLine("using System.Text;");
                    sw.WriteLine("using " + profile.Projects["Core"].GetNamespace(profile) + ";");
                    sw.WriteLine("using Silk.NET.Core.Loader;");
                    sw.WriteLine("using Silk.NET.Core.Native;");
                    sw.WriteLine("using AdvancedDLSupport;");
                    sw.WriteLine();
                    sw.WriteLine("namespace " + profile.ExtensionsNamespace + project.Namespace);
                    sw.WriteLine("{");
                    sw.WriteLine($"    public abstract partial class {name} : NativeExtension<{profile.ClassName}>, I{name}");
                    sw.WriteLine("    {");
                    foreach (var function in i.Functions)
                    {
                        sw.WriteLine("        /// <inheritdoc />");
                        using (var sr = new StringReader(function.ToString()))
                        {
                            string line;
                            var    flPrefix = "public abstract ";
                            while ((line = sr.ReadLine()) != null)
                            {
                                sw.WriteLine($"        {flPrefix}{line}");
                                flPrefix = string.Empty;
                            }
                        }
                        sw.WriteLine();
                    }

                    foreach (var overload in Overloader.GetOverloads(i))
                    {
                        using (var sr = new StringReader(overload.Signature.Doc))
                        {
                            string line;
                            while ((line = sr.ReadLine()) != null)
                            {
                                sw.WriteLine("        " + line);
                            }
                        }

                        foreach (var attr in overload.Signature.Attributes)
                        {
                            sw.WriteLine("        [" + attr.Name + "(" + string.Join(", ", attr.Arguments) + ")]");
                        }

                        sw.WriteLine("        public " + overload.Signature.ToString(overload.Unsafe).TrimEnd(';'));
                        sw.WriteLine("        {");
                        using (var sr = new StringReader(overload.CodeBlock))
                        {
                            string line;
                            while ((line = sr.ReadLine()) != null)
                            {
                                sw.WriteLine($"            {line}");
                            }
                        }
                        sw.WriteLine("        }");
                        sw.WriteLine();
                    }

                    sw.WriteLine($"        public {name}(string path, ImplementationOptions opts)");
                    sw.WriteLine("            : base(path, opts)");
                    sw.WriteLine("        {");
                    sw.WriteLine("        }");
                    sw.WriteLine("    }");
                    sw.WriteLine("}");
                    sw.WriteLine();
                    sw.Flush();
                }
            }
        }