private static void CreateObjectMethodGraphs(GenesisContext genesis, TypeInfo cls, ObjectGraph obj) { var events = new List <string>(); foreach (var m in cls.GetMethods(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly)) { if (m.Name.StartsWith("get_") || m.Name.StartsWith("set_")) { continue; //already did property accessors } if (m.Name.StartsWith("add_") || m.Name.StartsWith("remove_")) { var name = m.Name.Split('_')[1]; //just get the event Name if (!events.Contains(name)) { events.Add(name); } } Debug.WriteLine($@"Method:{(_nullableRegex.IsMatch(m.Name) ? _nullableRegex.Match(m.Name).Value : m.Name)}"); var methodGraph = new MethodGraph { Name = _nullableRegex.IsMatch(m.Name) ? _nullableRegex.Match(m.Name).Value : m.Name, MethodVisibility = MethodVisibilities.Public, ReturnDataType = m.ReturnType, ReturnTypeFormattedName = m.ReturnType.GetFormattedName(), HasGenericParams = m.ContainsGenericParameters, IsGeneric = m.IsGenericMethod, FormattedGenericArguments = m.GetGenericArguments().ToFormattedNames(), }; foreach (var par in m.GetParameters().OrderBy(o => o.Position)) { var mp = new ParameterGraph { DataType = par.ParameterType, DataTypeFormattedName = par.ParameterType.GetFormattedName(), DisplayName = par.ParameterType.GetDisplayName(), Name = par.Name, IsOut = par.IsOut, IsIn = par.IsIn, IsOptional = par.IsOptional, Position = par.Position, IsGeneric = par.ParameterType.IsGenericType, IsGenericMethodParameter = par.ParameterType.IsGenericMethodParameter, GenericArgumentFormattedTypeNames = par.ParameterType.GetGenericArguments().ToFormattedNames(), }; methodGraph.Parameters.Add(mp); } obj.Methods.Add(methodGraph); Text.GrayLine( $"\tMethod: {m.Name}, Return: {methodGraph.ReturnTypeFormattedName}, Visibility: {(m.IsPublic ? "public" : m.IsPrivate ? "private" : "protected")}"); } genesis.Objects.Add(obj); }
public override async Task <IGenesisExecutionResult> Execute(GenesisContext genesis, string[] args) { Text.WhiteLine($"Downloading from [{Config.Address}]"); //https://swagger.io/docs/specification/basic-structure/ var gen = await OpenApiDocument.FromUrlAsync(Config.Address); gen.GenerateOperationIds(); var usings = new[] { "System", "System.Text", "System.Collections", "System.Collections.Generic", "System.Threading.Tasks", "System.Linq", "System.Net.Http", "System.ComponentModel.DataAnnotations", "Newtonsoft.Json", }; var settings = new CSharpClientGeneratorSettings { GenerateDtoTypes = true, AdditionalContractNamespaceUsages = usings, AdditionalNamespaceUsages = usings }; settings.CodeGeneratorSettings.InlineNamedAny = true; settings.CSharpGeneratorSettings.Namespace = Config.OutputNamespace; settings.CSharpGeneratorSettings.ClassStyle = CSharpClassStyle.Inpc; var generator = new NSwag.CodeGeneration.OperationNameGenerators.MultipleClientsFromFirstTagAndPathSegmentsOperationNameGenerator(); var csgen = new CSharpClientGenerator(gen, settings); csgen.Settings.GenerateOptionalParameters = true; csgen.Settings.GenerateResponseClasses = true; csgen.Settings.SerializeTypeInformation = true; csgen.Settings.OperationNameGenerator = generator; Text.White($"Processing contents... "); var code = csgen.GenerateFile(ClientGeneratorOutputType.Full); Text.GreenLine("OK"); var trustedAssembliesPaths = ((string)AppContext.GetData("TRUSTED_PLATFORM_ASSEMBLIES")).Split(Path.PathSeparator); var neededLibs = new [] { "mscorlib", "netstandard", "System.Core", "System.Runtime", "System.IO", "System.ObjectModel", "System.Linq", "System.Net.Http", "System.Collections", "System.CodeDom.Compiler", "System.ComponentModel", "System.ComponentModel.Annotations", "System.Net.Primitives", "System.Runtime.Serialization", "System.Runtime.Serialization.Primitives", "System.Runtime.Extensions", "System.Private.Uri", "System.CodeDom", "System.Composition.AttributedModel", "System.Composition.Convention", "System.Composition.Runtime", "System.Diagnostics.Tools", "Microsoft.CodeAnalysis.CSharp", "NJsonSchema", "Newtonsoft.Json", }; Text.WhiteLine($"Determining dependencies"); var refs = trustedAssembliesPaths .Where(p => neededLibs.Contains(Path.GetFileNameWithoutExtension(p))) .Select(p => MetadataReference.CreateFromFile(p)) .ToList(); refs.Add(MetadataReference.CreateFromFile(typeof(object).GetTypeInfo().Assembly.Location)); var options = new CSharpParseOptions(LanguageVersion.CSharp8, DocumentationMode.Parse, SourceCodeKind.Regular); Text.WhiteLine("Defining entry point"); var rdr = new StringReader(code); var lines = new StringBuilder(); var i = 0; string line; while ((line = await rdr.ReadLineAsync()) != null) { lines.AppendLine(line); if (i == 26) //lol lame { lines.AppendLine(ENTRY_POINT); } i++; } code = lines.ToString(); File.WriteAllText(@"C:\Temp\GeneratedCode.cs", code); Text.WhiteLine("Creating Syntax Tree"); var syntax = CSharpSyntaxTree.ParseText(code, options: options); Text.WhiteLine("Preprocessing"); var comp = CSharpCompilation.Create("swag-gen-temp.dll", new[] { syntax }, refs.ToArray()); await using var stream = new MemoryStream(); Text.White("Creating temporary objects... "); var result = comp.Emit(stream); Text.GreenLine("OK"); if (!result.Success) { Text.RedLine("Unable to build temp library"); var failures = result.Diagnostics.Where(diagnostic => diagnostic.IsWarningAsError || diagnostic.Severity == DiagnosticSeverity.Error); foreach (var diagnostic in failures) { Text.RedLine($@"\t{diagnostic.Id}: {diagnostic.GetMessage()}"); } return(new InputGenesisExecutionResult { Success = false, Message = "Errors occurred" }); } stream.Seek(0, SeekOrigin.Begin); var tmpAss = AssemblyLoadContext.Default.LoadFromStream(stream); // loop classes foreach (var c in tmpAss.GetTypes().Where(w => w.IsClass)) { Text.GrayLine($"Class: {c.Name}"); var obj = new ObjectGraph { Name = c.Name, Namespace = Config.OutputNamespace, GraphType = GraphTypes.Object, }; foreach (var p in c.GetProperties().Where(w => w.MemberType == MemberTypes.Property)) { if (!p.CanWrite || !p.GetSetMethod(/*nonPublic*/ true).IsPublic) { continue; //for now; } var pg = new PropertyGraph { Name = p.Name, SourceType = p.PropertyType.Name, IsKeyProperty = p.Name.EndsWith("Id", StringComparison.CurrentCultureIgnoreCase), //NOTE: cheesy Accesibility = (p.CanWrite && p.GetSetMethod(/*nonPublic*/ true).IsPublic) ? "public" : "protected" }; obj.Properties.Add(pg); Text.GrayLine($"\tProperty: {c.Name}"); } foreach (var m in c.GetMethods(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly)) { var meth = new MethodGraph { Name = m.Name.Replace("get_", string.Empty), MethodVisibility = MethodVisibilities.Public, ReturnDataType = m.ReturnType, HasGenericParams = m.ContainsGenericParameters, IsGeneric = m.IsGenericMethod, }; foreach (var par in m.GetParameters().Where(w => w.IsIn).OrderBy(o => o.Position)) { var mp = new ParameterGraph { DataType = par.ParameterType, Name = par.Name, IsOut = par.IsOut, IsOptional = par.IsOptional, Position = par.Position }; meth.Parameters.Add(mp); Text.GrayLine($"\tMethod: {c.Name}"); } } genesis.Objects.Add(obj); } Text.SuccessGraffiti(); return(await base.Execute(genesis, args)); //TODO: fix the whole IGenesisExecutionResult "stuff" }