diff --git a/src/Generator/Passes/CleanInvalidDeclNamesPass.cs b/src/Generator/Passes/CleanInvalidDeclNamesPass.cs new file mode 100644 index 00000000..96c99f58 --- /dev/null +++ b/src/Generator/Passes/CleanInvalidDeclNamesPass.cs @@ -0,0 +1,134 @@ +using System.Collections.Generic; +using System.Linq; +using Cxxi.Types; + +namespace Cxxi.Passes +{ + public class CleanInvalidDeclNamesPass : TranslationUnitPass + { + private int uniqueName; + private TypeRefsVisitor typeRefs; + + public CleanInvalidDeclNamesPass() + { + typeRefs = new TypeRefsVisitor(); + } + + public override bool ProcessUnit(TranslationUnit unit) + { + if (unit.ExplicityIgnored) + return false; + + if (unit.IsSystemHeader) + return false; + + typeRefs = new TypeRefsVisitor(); + ProcessNamespace(unit); + unit.ForwardReferences = typeRefs.ForwardReferences.ToList(); + + return true; + } + + private void ProcessNamespace(Namespace @namespace) + { + ProcessDeclarations(@namespace.Enums); + ProcessFunctions(@namespace.Functions); + ProcessClasses(@namespace.Classes); + ProcessTypedefs(@namespace, @namespace.Typedefs); + + foreach (var inner in @namespace.Namespaces) + ProcessNamespace(inner); + } + + public override bool ProcessDeclaration(Declaration decl) + { + decl.Visit(typeRefs); + + // Generate a new name if the decl still does not have a name + if (string.IsNullOrWhiteSpace(decl.Name)) + decl.Name = string.Format("_{0}", uniqueName++); + + StringHelpers.CleanupText(ref decl.DebugText); + return true; + } + + private void ProcessDeclarations(IEnumerable decls) + where T : Declaration + { + foreach (T decl in decls) + ProcessDeclaration(decl); + } + + private void ProcessClasses(List classes) + { + ProcessDeclarations(classes); + + foreach (var @class in classes) + { + ProcessFields(@class.Fields); + ProcessMethods(@class.Methods); + } + } + + private void ProcessFields(List fields) + { + ProcessDeclarations(fields); + + foreach (var field in fields) + ProcessField(field); + } + + private void ProcessMethods(List methods) + { + ProcessDeclarations(methods); + + foreach (var method in methods) + ProcessFunction(method); + } + + private void ProcessFunctions(List functions) + { + ProcessDeclarations(functions); + + foreach (var function in functions) + ProcessFunction(function); + } + + public override bool ProcessFunction(Function function) + { + foreach (var param in function.Parameters) + ProcessDeclaration(param); + + return true; + } + + private void ProcessTypedefs(Namespace @namespace, List typedefs) + { + ProcessDeclarations(typedefs); + + foreach (var typedef in typedefs) + { + var @class = @namespace.FindClass(typedef.Name); + + // Clang will walk the typedef'd tag decl and the typedef decl, + // so we ignore the class and process just the typedef. + + if (@class != null) + typedef.ExplicityIgnored = true; + + if (typedef.Type == null) + typedef.ExplicityIgnored = true; + } + } + } + + public static class CleanInvalidDeclNamesExtensions + { + public static void CleanInvalidDeclNames(this PassBuilder builder) + { + var pass = new CleanInvalidDeclNamesPass(); + builder.AddPass(pass); + } + } +} +