Browse Source

Added CheckDuplicatedNamesPass that check all class members names for duplicated names. When a non function member has an already used name a number is append to its name. When a method is found with a know signature a number is append to its name. The appended number for each method overload is independently incremented, others members appended number start at the most overloaded method count which is then incremented with each non function member sharing the same name.

pull/16/head
marcos henrich 12 years ago
parent
commit
12daa4980c
  1. 2
      src/Generator/Driver.cs
  2. 146
      src/Generator/Passes/CheckAmbiguousOverloads.cs
  3. 145
      src/Generator/Passes/CheckDuplicatedNamesPass.cs
  4. 68
      src/Generator/Passes/DuplicatedNamesCheckerPass.cs

2
src/Generator/Driver.cs

@ -132,7 +132,7 @@ namespace CppSharp @@ -132,7 +132,7 @@ namespace CppSharp
Passes.CleanInvalidDeclNames();
Passes.CheckIgnoredDecls();
Passes.CheckFlagEnums();
Passes.CheckAmbiguousOverloads();
Passes.CheckDuplicateNames();
Generator.SetupPasses(Passes);
}

146
src/Generator/Passes/CheckAmbiguousOverloads.cs

@ -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);
}
}
}

145
src/Generator/Passes/CheckDuplicatedNamesPass.cs

@ -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);
}
}
}

68
src/Generator/Passes/DuplicatedNamesCheckerPass.cs

@ -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…
Cancel
Save