public static CodeTypeDeclaration Sort(this CodeTypeDeclaration original) { if (original.IsEnum) { return(original); } var sorted = new CodeTypeDeclaration(original.Name) { Attributes = original.Attributes, CustomAttributes = original.CustomAttributes, IsClass = original.IsClass, IsEnum = original.IsEnum, IsInterface = original.IsInterface, IsPartial = original.IsPartial, IsStruct = original.IsStruct, LinePragma = original.LinePragma, Name = original.Name, TypeAttributes = original.TypeAttributes, }; sorted.BaseTypes.AddRange(original.BaseTypes); sorted.Comments.AddRange(original.Comments); sorted.EndDirectives.AddRange(original.EndDirectives); sorted.StartDirectives.AddRange(original.StartDirectives); sorted.TypeParameters.AddRange(original.TypeParameters); foreach (var key in original.UserData.Keys) { sorted.UserData[key] = original.UserData[key]; } var emptyParamList = new List <CodeParameterDeclarationExpression>(); var sortedMembers = original.Members.OfType <CodeTypeMember>() .OrderBy(m => m.Attributes.HasFlag(MemberAttributes.Static)) .ThenBy(m => m.GetType().Name, StringComparer.Ordinal) .ThenBy(m => CodeNormalizer.NormalizeMethodName(m.Name), StringComparer.Ordinal) .ThenBy(m => m is CodeMemberMethod method ? method.TypeParameters.Count : 0) .ThenBy(m => m is CodeMemberMethod method ? method.Parameters.Count : 0) .ThenBy(m => m is CodeMemberMethod method ? method.Parameters.OfType <CodeParameterDeclarationExpression>().ToList() : emptyParamList, new ParamListComparer()); foreach (var member in sortedMembers) { sorted.Members.Add(member); } return(sorted); }
// TODO: Assembly references? // TODO: Better handle namespaces - using statements? - requires non-qualified type names static string CreatePublicApiForAssembly(AssemblyDefinition assembly, Func <TypeDefinition, bool> shouldIncludeType, bool shouldIncludeAssemblyAttributes, string[] whitelistedNamespacePrefixes, AttributeFilter attributeFilter) { using (var provider = new CSharpCodeProvider()) { var compileUnit = new CodeCompileUnit(); if (shouldIncludeAssemblyAttributes && assembly.HasCustomAttributes) { PopulateCustomAttributes(assembly, compileUnit.AssemblyCustomAttributes, attributeFilter); } var publicTypes = assembly.Modules.SelectMany(m => m.GetTypes()) .Where(t => !t.IsNested && ShouldIncludeType(t) && shouldIncludeType(t)) .OrderBy(t => t.FullName, StringComparer.Ordinal); foreach (var publicType in publicTypes) { var @namespace = compileUnit.Namespaces.Cast <CodeNamespace>() .FirstOrDefault(n => n.Name == publicType.Namespace); if (@namespace == null) { @namespace = new CodeNamespace(publicType.Namespace); compileUnit.Namespaces.Add(@namespace); } using (NullableContext.Push(publicType)) { var typeDeclaration = CreateTypeDeclaration(publicType, whitelistedNamespacePrefixes, attributeFilter); @namespace.Types.Add(typeDeclaration); } } using (var writer = new StringWriter()) { var cgo = new CodeGeneratorOptions { BracingStyle = "C", BlankLinesBetweenMembers = false, VerbatimOrder = false, IndentString = " " }; provider.GenerateCodeFromCompileUnit(compileUnit, writer, cgo); return(CodeNormalizer.NormalizeGeneratedCode(writer)); } } }