public override void VisitEnumDecl(EnumDecl decl, VisitKind visitKind) { if (visitKind != VisitKind.Enter) { return; } if (!decl.IsDefinition) { return; } string name = decl.Name; if (name == null) { return; } // check availability macros to see if the API is available on the OS and not deprecated if (!decl.IsAvailable()) { return; } var mname = Helpers.GetManagedName(name); TypeDefinition type; if (!enums.TryGetValue(mname, out type)) { Console.WriteLine("!missing-enum! {0} not bound", name); return; } else { enums.Remove(mname); } int native_size = 4; bool native = false; // FIXME: this can be simplified switch (decl.IntegerQualType.ToString()) { case "NSInteger": case "NSUInteger": case "CFIndex": case "CFOptionFlags": native_size = 8; // in managed code it's always the largest size native = true; break; case "unsigned long": case "unsigned int": case "int32_t": case "uint32_t": case "int": case "GLint": case "GLuint": case "GLenum": case "SInt32": case "UInt32": case "OptionBits": // UInt32 case "long": case "FourCharCode": break; case "int64_t": case "uint64_t": case "unsigned long long": case "CVOptionFlags": // uint64_t native_size = 8; break; case "UInt16": case "int16_t": case "uint16_t": case "short": native_size = 2; break; case "UInt8": case "int8_t": case "uint8_t": native_size = 1; break; default: throw new NotImplementedException(decl.IntegerQualType.ToString()); } // check correct [Native] decoration if (native) { if (!IsNative(type)) { Console.WriteLine("!missing-enum-native! {0}", name); } } else { if (IsNative(type)) { Console.WriteLine("!extra-enum-native! {0}", name); } } int managed_size = 4; switch (GetEnumUnderlyingType(type).Name) { case "Byte": case "SByte": managed_size = 1; break; case "Int16": case "UInt16": managed_size = 2; break; case "Int32": case "UInt32": break; case "Int64": case "UInt64": managed_size = 8; break; default: throw new NotImplementedException(); } if (native_size != managed_size) { Console.WriteLine("!wrong-enum-size! {0} managed {1} vs native {2}", name, managed_size, native_size); } }
void SymbolDecl.IVisitor.Visit(EnumDecl decl) { Fix(decl); }
public override void VisitEnumDecl(EnumDecl decl, VisitKind visitKind) { if (visitKind != VisitKind.Enter || !decl.IsCompleteDefinition || decl.QualifiedName == null) return; if (!decl.QualifiedName.StartsWith ("Urho")) { if (!decl.QualifiedName.ToLower ().Contains ("loopmode2d")) return; } //Console.WriteLine($"VisitingType: {decl.QualifiedName}"); string typeName = RemapTypeName(decl.Name); PushType(new TypeDeclaration { Name = typeName, ClassType = ClassType.Enum, Modifiers = Modifiers.Public }, StringUtil.GetTypeComments(decl)); foreach (var constantDecl in decl.Decls<EnumConstantDecl>()) { var valueName = RemapEnumName (typeName, constantDecl.Name); switch (valueName) { // LIST HERE ANY Values we want to skip case "foo": case null: continue; } var x = new EnumMemberDeclaration(); var enumValue = new EnumMemberDeclaration { Name = valueName }; if (constantDecl.InitExpr != null) { APSInt v; constantDecl.InitExpr.EvaluateAsInt (decl.AstContext, out v); var ul = v.GetLimitedValue (); PrimitiveExpression value; if ((ul & 0xffffffff) == ul) value = new PrimitiveExpression ((int)ul); else throw new NotImplementedException ($"Got a {ul} value which will not fit on an int, you must manually handle this case in the generatorg"); enumValue.Initializer = value; } currentType.Members.Add(enumValue); } }
public override void VisitEnumDecl(EnumDecl decl, VisitKind visitKind) { if (visitKind != VisitKind.Enter) { return; } if (!decl.IsDefinition) { return; } string name = decl.Name; if (name == null) { return; } // check availability macros to see if the API is available on the OS and not deprecated if (!decl.IsAvailable()) { return; } var framework = Helpers.GetFramework(decl); if (framework == null) { return; } var mname = Helpers.GetManagedName(name); // If our enum is obsoleted, then don't process it. if (obsoleted_enums.ContainsKey(mname)) { return; } if (!enums.TryGetValue(mname, out var type)) { Log.On(framework).Add($"!missing-enum! {name} not bound"); return; } else { enums.Remove(mname); } int native_size = 4; bool native = false; // FIXME: this can be simplified switch (decl.IntegerQualType.ToString()) { case "NSInteger": case "NSUInteger": case "CFIndex": case "CFOptionFlags": case "AVAudioInteger": native_size = 8; // in managed code it's always the largest size native = true; break; case "unsigned long": case "unsigned int": case "int32_t": case "uint32_t": case "int": case "GLint": case "GLuint": case "GLenum": case "SInt32": case "UInt32": case "OptionBits": // UInt32 case "long": case "FourCharCode": case "OSStatus": break; case "int64_t": case "uint64_t": case "unsigned long long": case "CVOptionFlags": // uint64_t native_size = 8; break; case "UInt16": case "int16_t": case "uint16_t": case "short": native_size = 2; break; case "UInt8": case "int8_t": case "uint8_t": native_size = 1; break; default: throw new NotImplementedException(decl.IntegerQualType.ToString()); } // check correct [Native] decoration if (native) { if (!IsNative(type)) { Log.On(framework).Add($"!missing-enum-native! {name}"); } } else { if (IsNative(type)) { Log.On(framework).Add($"!extra-enum-native! {name}"); } } int managed_size = 4; bool signed = true; switch (GetEnumUnderlyingType(type).Name) { case "Byte": signed = false; managed_size = 1; break; case "SByte": managed_size = 1; break; case "Int16": managed_size = 2; break; case "UInt16": signed = false; managed_size = 2; break; case "Int32": break; case "UInt32": signed = false; break; case "Int64": managed_size = 8; break; case "UInt64": signed = false; managed_size = 8; break; default: throw new NotImplementedException(); } var fields = type.Fields; if (signed) { managed_signed_values.Clear(); native_signed_values.Clear(); foreach (var f in fields) { // skip special `value__` if (f.IsRuntimeSpecialName && !f.IsStatic) { continue; } if (!f.IsObsolete()) { managed_signed_values [Convert.ToInt64(f.Constant)] = f; } } long n = 0; foreach (var value in decl.Values) { if ((value.InitExpr != null) && value.InitExpr.EvaluateAsInt(decl.AstContext, out var integer)) { n = integer.SExtValue; } native_signed_values [n] = value.ToString(); // assume, sequentially assigned (in case next `value.InitExpr` is null) n++; } foreach (var value in native_signed_values.Keys) { if (!managed_signed_values.ContainsKey(value)) { Log.On(framework).Add($"!missing-enum-value! {type.Name} native value {native_signed_values [value]} = {value} not bound"); } else { managed_signed_values.Remove(value); } } foreach (var value in managed_signed_values.Keys) { if ((value == 0) && IsExtraZeroValid(type.Name, managed_signed_values [0].Name)) { continue; } // value could be decorated with `[No*]` and those should not be reported if (managed_signed_values [value].IsAvailable()) { Log.On(framework).Add($"!extra-enum-value! Managed value {value} for {type.Name}.{managed_signed_values [value].Name} not found in native headers"); } } } else { managed_unsigned_values.Clear(); native_unsigned_values.Clear(); foreach (var f in fields) { // skip special `value__` if (f.IsRuntimeSpecialName && !f.IsStatic) { continue; } if (!f.IsObsolete()) { managed_unsigned_values [Convert.ToUInt64(f.Constant)] = f; } } ulong n = 0; foreach (var value in decl.Values) { if ((value.InitExpr != null) && value.InitExpr.EvaluateAsInt(decl.AstContext, out var integer)) { n = integer.ZExtValue; } native_unsigned_values [n] = value.ToString(); // assume, sequentially assigned (in case next `value.InitExpr` is null) n++; } foreach (var value in native_unsigned_values.Keys) { if (!managed_unsigned_values.ContainsKey(value)) { // only for unsigned (flags) native enums we allow all bits set on 32 bits (UInt32.MaxValue) // to be equal to all bit set on 64 bits (UInt64.MaxValue) since the MaxValue differs between // 32bits (e.g. watchOS) and 64bits (all others) platforms var log = true; if (native && (value == UInt32.MaxValue)) { log = !managed_unsigned_values.ContainsKey(UInt64.MaxValue); managed_unsigned_values.Remove(UInt64.MaxValue); } if (log) { Log.On(framework).Add($"!missing-enum-value! {type.Name} native value {native_unsigned_values [value]} = {value} not bound"); } } else { managed_unsigned_values.Remove(value); } } foreach (var value in managed_unsigned_values.Keys) { if ((value == 0) && IsExtraZeroValid(type.Name, managed_unsigned_values [0].Name)) { continue; } // value could be decorated with `[No*]` and those should not be reported if (managed_unsigned_values [value].IsAvailable()) { Log.On(framework).Add($"!extra-enum-value! Managed value {value} for {type.Name}.{managed_unsigned_values [value].Name} not found in native headers"); } } } if (native_size != managed_size) { Log.On(framework).Add($"!wrong-enum-size! {name} managed {managed_size} vs native {native_size}"); } }
static SymbolDecl[] ParseSymbolInternal(string[] tokens, ref int index) { if (CppParser.Token(tokens, ref index, "public") || CppParser.Token(tokens, ref index, "protected") || CppParser.Token(tokens, ref index, "private")) { index--; return(null); } TemplateDecl templateDecl = null; if (CppParser.Token(tokens, ref index, "template")) { templateDecl = new TemplateDecl { TypeParameters = new List <TypeParameterDecl>(), Specialization = new List <TypeDecl>(), }; CppParser.EnsureToken(tokens, ref index, "<"); if (!CppParser.Token(tokens, ref index, ">")) { while (true) { string token = null; CppParser.SkipUntilInTemplate(tokens, ref index, out token, ",", ">", "="); index -= 2; templateDecl.TypeParameters.Add(new TypeParameterDecl { Name = CppParser.EnsureId(tokens, ref index), }); index++; if (token == "=") { CppParser.SkipUntilInTemplate(tokens, ref index, out token, ",", ">"); } if (token == ">") { break; } } } } if (CppParser.Token(tokens, ref index, "friend")) { int oldIndex = index - 1; string token = null; CppParser.SkipUntil(tokens, ref index, out token, ";", "{"); if (token == ";") { return(null); } else { index = oldIndex; tokens[index] = "static"; } } if (CppParser.Token(tokens, ref index, "namespace")) { if (templateDecl != null) { throw new ArgumentException("Failed to parse."); } var decl = new NamespaceDecl(); decl.Name = CppParser.EnsureId(tokens, ref index); CppParser.EnsureToken(tokens, ref index, "{"); ParseSymbols(tokens, ref index, decl); CppParser.EnsureToken(tokens, ref index, "}"); return(new SymbolDecl[] { decl }); } else if (CppParser.Token(tokens, ref index, "using")) { if (CppParser.Token(tokens, ref index, "namespace")) { if (templateDecl != null) { throw new ArgumentException("Failed to parse."); } var decl = new UsingNamespaceDecl(); decl.Path = new List <string>(); decl.Path.Add(CppParser.EnsureId(tokens, ref index)); while (!CppParser.Token(tokens, ref index, ";")) { CppParser.EnsureToken(tokens, ref index, ":"); CppParser.EnsureToken(tokens, ref index, ":"); decl.Path.Add(CppParser.EnsureId(tokens, ref index)); } return(new SymbolDecl[] { decl }); } else { string name = null; if (CppParser.Id(tokens, ref index, out name)) { if (templateDecl != null) { if (CppParser.Token(tokens, ref index, "<")) { while (true) { templateDecl.Specialization.Add(CppTypeParser.EnsureTypeWithoutName(tokens, ref index)); if (CppParser.Token(tokens, ref index, ">")) { break; } CppParser.EnsureToken(tokens, ref index, ","); } } } if (CppParser.Token(tokens, ref index, "=")) { SymbolDecl decl = new TypedefDecl { Name = name, Type = CppTypeParser.EnsureTypeWithoutName(tokens, ref index), }; CppParser.EnsureToken(tokens, ref index, ";"); if (templateDecl != null) { templateDecl.Element = decl; decl = templateDecl; } return(new SymbolDecl[] { decl }); } } if (templateDecl != null) { throw new ArgumentException("Failed to parse."); } CppParser.SkipUntil(tokens, ref index, ";"); } } else if (CppParser.Token(tokens, ref index, "typedef")) { if (templateDecl != null) { throw new ArgumentException("Failed to parse."); } string name = null; var type = CppTypeParser.EnsureTypeWithName(tokens, ref index, out name); CppParser.EnsureToken(tokens, ref index, ";"); var decl = new TypedefDecl(); decl.Name = name; decl.Type = type; return(new SymbolDecl[] { decl }); } else if (CppParser.Token(tokens, ref index, "enum")) { if (templateDecl != null) { throw new ArgumentException("Failed to parse."); } bool enumClass = CppParser.Token(tokens, ref index, "class"); string name = CppParser.EnsureId(tokens, ref index); if (CppParser.Token(tokens, ref index, ":")) { CppTypeParser.EnsureTypeWithoutName(tokens, ref index); } if (!CppParser.Token(tokens, ref index, ";")) { CppParser.EnsureToken(tokens, ref index, "{"); var decl = new EnumDecl { Name = name, EnumClass = enumClass, Children = new List <SymbolDecl>(), }; while (true) { if (CppParser.Token(tokens, ref index, "}")) { break; } while (index < tokens.Length && tokens[index].Length >= 3 && tokens[index].StartsWith("///")) { index++; } decl.Children.Add(new EnumItemDecl { Name = CppParser.EnsureId(tokens, ref index), }); string token = null; CppParser.SkipUntil(tokens, ref index, out token, ",", "}"); if (token == "}") { break; } } if (CppParser.Id(tokens, ref index, out name)) { var varDecl = new VarDecl { Static = false, Name = name, Type = new RefTypeDecl { Name = decl.Name, }, }; CppParser.EnsureToken(tokens, ref index, ";"); return(new SymbolDecl[] { decl, varDecl }); } else { CppParser.EnsureToken(tokens, ref index, ";"); return(new SymbolDecl[] { decl }); } } } else if (CppParser.Token(tokens, ref index, "struct") || CppParser.Token(tokens, ref index, "class") || CppParser.Token(tokens, ref index, "union")) { if (CppParser.Token(tokens, ref index, "{")) { if (tokens[index - 2] == "class") { throw new ArgumentException("Failed to parse."); } var decl = new GroupedFieldDecl { Grouping = tokens[index - 2] == "struct" ? Grouping.Struct : Grouping.Union, }; ParseSymbols(tokens, ref index, decl); CppParser.EnsureToken(tokens, ref index, "}"); CppParser.EnsureToken(tokens, ref index, ";"); return(new SymbolDecl[] { decl }); } else { string name = CppParser.EnsureId(tokens, ref index); if (!CppParser.Token(tokens, ref index, ";")) { var classDecl = new ClassDecl { ClassType = tokens[index - 2] == "struct" ? ClassType.Struct : tokens[index - 2] == "class" ? ClassType.Class : ClassType.Union, BaseTypes = new List <BaseTypeDecl>(), Name = name, }; if (templateDecl != null) { if (CppParser.Token(tokens, ref index, "<")) { if (!CppParser.Token(tokens, ref index, ">")) { while (true) { int oldIndex = index; try { templateDecl.Specialization.Add(CppTypeParser.EnsureTypeWithoutName(tokens, ref index)); } catch (ArgumentException) { index = oldIndex; CppParser.SkipUntilInTemplate(tokens, ref index, ",", ">"); index--; templateDecl.Specialization.Add(new ConstantTypeDecl { Value = tokens .Skip(oldIndex) .Take(index - oldIndex) .Aggregate((a, b) => a + " " + b), }); } if (CppParser.Token(tokens, ref index, ">")) { break; } CppParser.EnsureToken(tokens, ref index, ","); } } } } CppParser.Token(tokens, ref index, "abstract"); if (CppParser.Token(tokens, ref index, ":")) { while (true) { Access access = classDecl.ClassType == ClassType.Class ? Access.Private : Access.Public; CppParser.Token(tokens, ref index, "virtual"); if (CppParser.Token(tokens, ref index, "private")) { access = Access.Private; } else if (CppParser.Token(tokens, ref index, "protected")) { access = Access.Protected; } else if (CppParser.Token(tokens, ref index, "public")) { access = Access.Public; } CppParser.Token(tokens, ref index, "virtual"); classDecl.BaseTypes.Add(new BaseTypeDecl { Access = access, Type = CppTypeParser.EnsureTypeWithoutName(tokens, ref index), }); if (!CppParser.Token(tokens, ref index, ",")) { break; } } } CppParser.EnsureToken(tokens, ref index, "{"); while (true) { if (CppParser.Token(tokens, ref index, "}")) { break; } Access access = classDecl.ClassType == ClassType.Class ? Access.Private : Access.Public; if (CppParser.Token(tokens, ref index, "private")) { access = Access.Private; CppParser.EnsureToken(tokens, ref index, ":"); } else if (CppParser.Token(tokens, ref index, "protected")) { access = Access.Protected; CppParser.EnsureToken(tokens, ref index, ":"); } else if (CppParser.Token(tokens, ref index, "public")) { access = Access.Public; CppParser.EnsureToken(tokens, ref index, ":"); } ParseSymbols(tokens, ref index, classDecl, access); } SymbolDecl decl = classDecl; if (templateDecl != null) { templateDecl.Element = decl; decl = templateDecl; } if (CppParser.Id(tokens, ref index, out name)) { var varDecl = new VarDecl { Static = false, Name = name, Type = new RefTypeDecl { Name = classDecl.Name, }, }; CppParser.EnsureToken(tokens, ref index, ";"); return(new SymbolDecl[] { decl, varDecl }); } else { CppParser.EnsureToken(tokens, ref index, ";"); return(new SymbolDecl[] { decl }); } } } } else if (!CppParser.Token(tokens, ref index, ";")) { Function function = Function.Function; { int oldIndex = index; string name = null; if (CppParser.Id(tokens, ref index, out name)) { if (CppParser.Token(tokens, ref index, "(")) { CppParser.SkipUntil(tokens, ref index, ")"); if (CppParser.Token(tokens, ref index, ";") || CppParser.Token(tokens, ref index, "=") || CppParser.Token(tokens, ref index, ":") || CppParser.Token(tokens, ref index, "{")) { function = Function.Constructor; } } index = oldIndex; } else if (CppParser.Token(tokens, ref index, "~")) { function = Function.Destructor; } } if (function == Function.Function) { Virtual virtualFunction = Virtual.Normal; CppParser.Token(tokens, ref index, "extern"); CppParser.Token(tokens, ref index, "mutable"); if (CppParser.Token(tokens, ref index, "virtual")) { virtualFunction = Virtual.Virtual; } else if (CppParser.Token(tokens, ref index, "static")) { virtualFunction = Virtual.Static; } CppParser.Token(tokens, ref index, "inline"); CppParser.Token(tokens, ref index, "__forceinline"); if (CppParser.Token(tokens, ref index, "operator")) { TypeDecl returnType = null; { int oldIndex = index; CppParser.SkipUntilInTemplate(tokens, ref index, "("); int modify = --index; tokens[modify] = "$"; index = oldIndex; returnType = CppTypeParser.EnsureTypeWithoutName(tokens, ref index); if (index != modify) { throw new ArgumentException("Failed to parse."); } tokens[modify] = "("; } var decl = new FuncDecl { Virtual = Virtual.Normal, Name = "operator", Function = function, }; TypeDecl functionType = null; Action <TypeDecl> continuation = null; CallingConvention callingConvention = CallingConvention.Default; CppTypeParser.ParseTypeContinueAfterName(tokens, ref index, ref callingConvention, out functionType, out continuation); continuation(returnType); decl.Type = functionType; if (!CppParser.Token(tokens, ref index, ";")) { CppParser.EnsureToken(tokens, ref index, "{"); CppParser.SkipUntil(tokens, ref index, "}"); } if (templateDecl != null) { templateDecl.Element = decl; return(new SymbolDecl[] { templateDecl }); } else { return(new SymbolDecl[] { decl }); } } else { string name = null; TypeDecl type = null; if (CppTypeParser.ParseType(tokens, ref index, out type, out name)) { if (name == null) { throw new ArgumentException("Failed to parse."); } if (type is FunctionTypeDecl) { if (CppParser.Token(tokens, ref index, "=")) { if (CppParser.Token(tokens, ref index, "0")) { virtualFunction = Virtual.Abstract; } else { CppParser.EnsureToken(tokens, ref index, "default", "delete"); } } var decl = new FuncDecl { Virtual = virtualFunction, Name = name, Type = type, Function = Function.Function, }; if (!CppParser.Token(tokens, ref index, ";")) { CppParser.EnsureToken(tokens, ref index, "{"); CppParser.SkipUntil(tokens, ref index, "}"); } if (templateDecl != null) { templateDecl.Element = decl; return(new SymbolDecl[] { templateDecl }); } else { return(new SymbolDecl[] { decl }); } } else { if (virtualFunction != Virtual.Normal && virtualFunction != Virtual.Static) { throw new ArgumentException("Failed to parse."); } if (CppParser.Token(tokens, ref index, "=")) { CppParser.SkipUntil(tokens, ref index, ";"); } else { CppParser.EnsureToken(tokens, ref index, ";"); } if (!(type is ClassMemberTypeDecl)) { var decl = new VarDecl { Static = virtualFunction == Virtual.Static, Name = name, Type = type, }; return(new SymbolDecl[] { decl }); } } } } } else { var decl = new FuncDecl { Virtual = Virtual.Normal, Name = (function == Function.Constructor ? "" : "~") + CppParser.EnsureId(tokens, ref index), Function = function, }; TypeDecl functionType = null; Action <TypeDecl> continuation = null; CallingConvention callingConvention = CallingConvention.Default; CppTypeParser.ParseTypeContinueAfterName(tokens, ref index, ref callingConvention, out functionType, out continuation); continuation(new RefTypeDecl { Name = "void" }); decl.Type = functionType; if (CppParser.Token(tokens, ref index, "=")) { CppParser.EnsureToken(tokens, ref index, "default", "delete"); } if (!CppParser.Token(tokens, ref index, ";")) { if (CppParser.Token(tokens, ref index, ":")) { CppParser.SkipUntil(tokens, ref index, "{"); } else { CppParser.EnsureToken(tokens, ref index, "{"); } CppParser.SkipUntil(tokens, ref index, "}"); } if (templateDecl != null) { templateDecl.Element = decl; return(new SymbolDecl[] { templateDecl }); } else { return(new SymbolDecl[] { decl }); } } } return(null); }
public static IEnumerable <string> GetTypeComments(EnumDecl decl) { return(ExtractTextComments(decl.DumpToString()).Take(1)); }
void SymbolDecl.IVisitor.Visit(EnumDecl decl) { EntryDecl(decl); }
public static IEnumerable<string> GetTypeComments(EnumDecl decl) { return ExtractTextComments(decl.DumpToString()).Take(1); }
/// <summary> /// Corresponds to CLI "extract" keyword. Converts assembly types to declarations. /// ExtractVerbOptions.ProjectPath has been introduced to add project structure info to declarations. /// </summary> public void Execute() { AssemblyCache assemblies = new AssemblyCache(); // Create list of assemblies (enrolling masks when needed) foreach (string assemblyPath in Assemblies) { string assemblyName = Path.GetFileName(assemblyPath); if (!string.IsNullOrEmpty(assemblyName)) { string assemblyDirectory = string.IsNullOrEmpty(assemblyDirectory = Path.GetDirectoryName(assemblyPath)) ? Environment.CurrentDirectory : Path.GetFullPath(assemblyDirectory); assemblies.AddFiles(Directory.EnumerateFiles(assemblyDirectory, assemblyName)); } } // When no assemblies provided, search inside working directory if (assemblies.IsEmpty) { assemblies.AddFiles(Directory.EnumerateFiles(Environment.CurrentDirectory, "*.dll")); } if (!Directory.Exists(OutputFolder)) { Directory.CreateDirectory(OutputFolder); } foreach (Assembly assembly in assemblies) { Console.Write("A> "); Console.WriteLine(assembly.Location); bool hasDocumentation = CommentNavigator.TryCreate(assembly, out CommentNavigator docNavigator); if (hasDocumentation) { Console.Write("D> "); Console.WriteLine(docNavigator.XmlLocation); } bool isProjectLocated = ProjectNavigator.TryCreate(ProjectPath, assembly, out ProjectNavigator projNavigator); if (isProjectLocated) { Console.Write("P> "); Console.WriteLine(projNavigator.Location); } List <Type> types = TypesExtractor.GetTypes(assembly, Types); foreach (Type type in types) { TypeDecl decl = DeclarationConvertor.TypeToDecl(type, docNavigator, projNavigator); string outputFolder = Path.Combine(OutputFolder, decl.Module.ModuleName.Replace('.', '\\')); Directory.CreateDirectory(outputFolder); string extension = type.IsSubclassOf(typeof(Enum)) ? "clenum" : "cltype"; string outputFile = Path.Combine(outputFolder, $"{decl.Name}.{extension}"); Console.Write(type.FullName); Console.Write(" => "); Console.WriteLine(outputFile); File.WriteAllText(outputFile, DeclarationSerializer.Serialize(decl)); } List <Type> enums = TypesExtractor.GetEnums(assembly, Types); foreach (Type type in enums) { EnumDecl decl = DeclarationConvertor.EnumToDecl(type, docNavigator, projNavigator); string outputFolder = Path.Combine(OutputFolder, decl.Module.ModuleName.Replace('.', '\\')); Directory.CreateDirectory(outputFolder); string extension = type.IsSubclassOf(typeof(Enum)) ? "clenum" : "cltype"; string outputFile = Path.Combine(outputFolder, $"{decl.Name}.{extension}"); Console.Write(type.FullName); Console.Write(" => "); Console.WriteLine(outputFile); File.WriteAllText(outputFile, DeclarationSerializer.Serialize(decl)); } } }