mirror of https://github.com/mono/CppSharp.git
4 changed files with 146 additions and 215 deletions
@ -1,146 +0,0 @@
@@ -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 @@
@@ -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 @@
@@ -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