diff --git a/src/Generator/Driver.cs b/src/Generator/Driver.cs index c0cf56b3..809dc833 100644 --- a/src/Generator/Driver.cs +++ b/src/Generator/Driver.cs @@ -132,7 +132,7 @@ namespace CppSharp Passes.CleanInvalidDeclNames(); Passes.CheckIgnoredDecls(); Passes.CheckFlagEnums(); - Passes.CheckAmbiguousOverloads(); + Passes.CheckDuplicateNames(); Generator.SetupPasses(Passes); } diff --git a/src/Generator/Passes/CheckAmbiguousOverloads.cs b/src/Generator/Passes/CheckAmbiguousOverloads.cs deleted file mode 100644 index ae6922d5..00000000 --- a/src/Generator/Passes/CheckAmbiguousOverloads.cs +++ /dev/null @@ -1,146 +0,0 @@ -using System.Collections.Generic; -using System.Linq; -using CppSharp.AST; -using CppSharp.Generators; - -namespace CppSharp.Passes -{ - struct OverloadSignature - { - public string Return; - public List Parameters; - public Function Function; - - public OverloadSignature(Function function) - { - Function = function; - - Return = function.ReturnType.ToString(); - Parameters = new List(); - - foreach (var param in function.Parameters) - { - var paramType = param.Type.ToString(); - Parameters.Add(paramType); - } - } - - public static bool IsAmbiguous(OverloadSignature overload1, - OverloadSignature overload2, Class @class) - { - if (overload1.Function == overload2.Function) - return false; - - if (ASTUtils.CheckIgnoreFunction(@class, overload1.Function)) - return false; - - if (ASTUtils.CheckIgnoreFunction(@class, overload2.Function)) - return false; - - // TODO: Default parameters? - if (overload1.Parameters.Count != overload2.Parameters.Count) - return false; - - if (overload1.Parameters.Count == 0) - return true; - - for (var i = 0; i < overload1.Parameters.Count; i++) - { - if (overload1.Parameters[i] != overload2.Parameters[i]) - return false; - } - - return true; - } - }; - - public class CheckAmbiguousOverloads : TranslationUnitPass - { - private readonly ISet visited; - - public CheckAmbiguousOverloads() - { - visited = new HashSet(); - Options.VisitNamespaceEnums = false; - Options.VisitNamespaceTemplates = false; - Options.VisitNamespaceTypedefs = false; - Options.VisitNamespaceEvents = false; - Options.VisitNamespaceVariables = false; - - Options.VisitClassBases = false; - Options.VisitClassFields = false; - Options.VisitClassProperties = false; - } - - public override bool VisitClassDecl(Class @class) - { - visited.Clear(); - return base.VisitClassDecl(@class); - } - - public override bool VisitMethodDecl(Method method) - { - CheckOverloads(method); - return false; - } - - public override bool VisitFunctionDecl(Function function) - { - CheckOverloads(function); - return false; - } - - private bool CheckOverloads(Function function) - { - if (visited.Contains(function)) - return false; - - if (function.Ignore) - return false; - - var overloads = function.Namespace.GetFunctionOverloads(function); - var signatures = overloads.Select(fn => new OverloadSignature(fn)).ToList(); - - foreach (var sig1 in signatures) - { - visited.Add(sig1.Function); - - if (sig1.Function.Ignore) - continue; - - foreach (var sig2 in signatures) - { - if (sig2.Function.Ignore) - continue; - - var @class = function.Namespace as Class; - if (!OverloadSignature.IsAmbiguous(sig1, sig2, @class)) - continue; - - Driver.Diagnostics.EmitWarning(DiagnosticId.AmbiguousOverload, - "Overload {0} is ambiguous, renaming automatically", - sig1.Function.QualifiedOriginalName); - - RenameOverload(sig1.Function); - return false; - } - } - - return true; - } - - public void RenameOverload(Function function) - { - function.Name = function.Name + "0"; - } - } - - public static class CheckAmbiguousOverloadsExtensions - { - public static void CheckAmbiguousOverloads(this PassBuilder builder) - { - var pass = new CheckAmbiguousOverloads(); - builder.AddPass(pass); - } - } -} diff --git a/src/Generator/Passes/CheckDuplicatedNamesPass.cs b/src/Generator/Passes/CheckDuplicatedNamesPass.cs new file mode 100644 index 00000000..6453ec67 --- /dev/null +++ b/src/Generator/Passes/CheckDuplicatedNamesPass.cs @@ -0,0 +1,145 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using CppSharp.AST; + +namespace CppSharp.Passes +{ + class DeclarationName + { + private readonly string Name; + private readonly Dictionary methodSignatures; + private int Count; + + public DeclarationName(string name) + { + Name = name; + methodSignatures = new Dictionary(); + } + + public bool UpdateName(Declaration decl) + { + if (decl.Name != Name) + throw new Exception("Invalid name"); + + var method = decl as Method; + if (method != null) + { + return UpdateName(method); + } + + var count = Count++; + if (count == 0) + return false; + + decl.Name += count.ToString(CultureInfo.InvariantCulture); + return true; + } + + private bool UpdateName(Method method) + { + var @params = method.Parameters.Select(p => p.QualifiedType.ToString()); + var signature = string.Format("{0}({1})", Name,string.Join( ", ", @params)); + + if (Count == 0) + Count++; + + if (!methodSignatures.ContainsKey(signature)) + { + methodSignatures.Add(signature, 0); + return false; + } + + var methodCount = ++methodSignatures[signature]; + + if (Count < methodCount+1) + Count = methodCount+1; + + method.Name += methodCount.ToString(CultureInfo.InvariantCulture); + return true; + } + } + + public class CheckDuplicatedNamesPass : TranslationUnitPass + { + private readonly IDictionary names; + + public CheckDuplicatedNamesPass() + { + names = new Dictionary(); + } + + public override bool VisitFieldDecl(Field decl) + { + if (ASTUtils.CheckIgnoreField(null, decl)) + return false; + + if(!AlreadyVisited(decl)) + CheckDuplicate(decl); + return false; + } + + public override bool VisitProperty(Property decl) + { + if(!AlreadyVisited(decl)) + CheckDuplicate(decl); + return false; + } + + public override bool VisitMethodDecl(Method decl) + { + if (ASTUtils.CheckIgnoreMethod(null, decl)) + return false; + + if(!AlreadyVisited(decl)) + CheckDuplicate(decl); + return false; + } + + public override bool VisitClassDecl(Class @class) + { + if (AlreadyVisited(@class) || @class.IsIncomplete) + return false; + + // In order to DeclarationName works, we visit methods first. + foreach (var method in @class.Methods) + VisitMethodDecl(method); + + foreach (var field in @class.Fields) + VisitFieldDecl(field); + + foreach (var property in @class.Properties) + VisitProperty(property); + + return false; + } + + void CheckDuplicate(Declaration decl) + { + if (decl.IsDependent || decl.Ignore) + return; + + if (string.IsNullOrWhiteSpace(decl.Name)) + return; + + var fullName = decl.QualifiedName; + + // If the name is not yet on the map, then add it. + if (!names.ContainsKey(fullName)) + names.Add(fullName, new DeclarationName(decl.Name)); + + if (names[fullName].UpdateName(decl)) + Driver.Diagnostics.EmitWarning("Duplicate name {0}, renamed to {1}", fullName, decl.Name); + } + } + + public static class CheckDuplicateNamesExtensions + { + public static void CheckDuplicateNames(this PassBuilder builder) + { + var pass = new CheckDuplicatedNamesPass(); + builder.AddPass(pass); + } + } +} diff --git a/src/Generator/Passes/DuplicatedNamesCheckerPass.cs b/src/Generator/Passes/DuplicatedNamesCheckerPass.cs deleted file mode 100644 index 3424cad2..00000000 --- a/src/Generator/Passes/DuplicatedNamesCheckerPass.cs +++ /dev/null @@ -1,68 +0,0 @@ -using System; -using System.Collections.Generic; -using CppSharp.AST; - -namespace CppSharp.Passes -{ - public class DuplicatedNamesCheckerPass : TranslationUnitPass - { - private readonly IDictionary names; - - public DuplicatedNamesCheckerPass() - { - names = new Dictionary(); - } - - public override bool VisitClassDecl(Class @class) - { - if (@class.Ignore) return false; - - names.Clear(); - return base.VisitClassDecl(@class); - } - - public override bool VisitDeclaration(Declaration decl) - { - if (AlreadyVisited(decl)) - return true; - - Visited.Add(decl); - - CheckDuplicate(decl); - return base.VisitDeclaration(decl); - } - - public override bool VisitParameterDecl(Parameter parameter) - { - return true; - } - - void CheckDuplicate(Declaration decl) - { - if (string.IsNullOrWhiteSpace(decl.Name)) - return; - - Declaration duplicate; - - // If the name is not yet on the map, then add it. - if (!names.TryGetValue(decl.Name, out duplicate)) - { - names[decl.Name] = decl; - return; - } - - // Else we found a duplicate name and need to change it. - Console.WriteLine("Found a duplicate named declaration: {0}", - decl.Name); - } - } - - public static class CheckDuplicateNamesExtensions - { - public static void CheckDuplicateNames(this PassBuilder builder) - { - var pass = new DuplicatedNamesCheckerPass(); - builder.AddPass(pass); - } - } -}