mirror of https://github.com/mono/CppSharp.git
4 changed files with 146 additions and 215 deletions
@ -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<string> Parameters; |
|
||||||
public Function Function; |
|
||||||
|
|
||||||
public OverloadSignature(Function function) |
|
||||||
{ |
|
||||||
Function = function; |
|
||||||
|
|
||||||
Return = function.ReturnType.ToString(); |
|
||||||
Parameters = new List<string>(); |
|
||||||
|
|
||||||
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<Function> visited; |
|
||||||
|
|
||||||
public CheckAmbiguousOverloads() |
|
||||||
{ |
|
||||||
visited = new HashSet<Function>(); |
|
||||||
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); |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
@ -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<string, int> methodSignatures; |
||||||
|
private int Count; |
||||||
|
|
||||||
|
public DeclarationName(string name) |
||||||
|
{ |
||||||
|
Name = name; |
||||||
|
methodSignatures = new Dictionary<string, int>(); |
||||||
|
} |
||||||
|
|
||||||
|
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<string, DeclarationName> names; |
||||||
|
|
||||||
|
public CheckDuplicatedNamesPass() |
||||||
|
{ |
||||||
|
names = new Dictionary<string, DeclarationName>(); |
||||||
|
} |
||||||
|
|
||||||
|
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); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -1,68 +0,0 @@ |
|||||||
using System; |
|
||||||
using System.Collections.Generic; |
|
||||||
using CppSharp.AST; |
|
||||||
|
|
||||||
namespace CppSharp.Passes |
|
||||||
{ |
|
||||||
public class DuplicatedNamesCheckerPass : TranslationUnitPass |
|
||||||
{ |
|
||||||
private readonly IDictionary<string, Declaration> names; |
|
||||||
|
|
||||||
public DuplicatedNamesCheckerPass() |
|
||||||
{ |
|
||||||
names = new Dictionary<string, Declaration>(); |
|
||||||
} |
|
||||||
|
|
||||||
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); |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
Loading…
Reference in new issue