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