mirror of https://github.com/mono/CppSharp.git
c-sharpdotnetmonobindingsbridgecclangcpluspluscppsharpglueinteropparserparsingpinvokeswigsyntax-treevisitorsxamarinxamarin-bindings
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
123 lines
3.9 KiB
123 lines
3.9 KiB
using System; |
|
using System.Linq; |
|
using CppSharp.AST; |
|
|
|
namespace CppSharp.Passes |
|
{ |
|
public class CleanInvalidDeclNamesPass : TranslationUnitPass |
|
{ |
|
private int uniqueName; |
|
|
|
string CheckName(string name) |
|
{ |
|
// Generate a new name if the decl still does not have a name |
|
if (string.IsNullOrWhiteSpace(name)) |
|
return string.Format("_{0}", uniqueName++); |
|
|
|
var firstChar = name.FirstOrDefault(); |
|
|
|
// Clean up the item name if the first digit is not a valid name. |
|
if (char.IsNumber(firstChar)) |
|
return '_' + name; |
|
|
|
return name; |
|
} |
|
|
|
public override bool VisitType(AST.Type type, TypeQualifiers quals) |
|
{ |
|
return false; |
|
} |
|
|
|
public override bool VisitDeclaration(Declaration decl) |
|
{ |
|
// Do not clean up namespace names since it can mess up with the |
|
// names of anonymous or the global namespace. |
|
if (decl is Namespace) |
|
return true; |
|
|
|
// types with empty names are assumed to be private |
|
if (decl is Class && string.IsNullOrWhiteSpace(decl.Name)) |
|
{ |
|
decl.ExplicityIgnored = true; |
|
return false; |
|
} |
|
|
|
decl.Name = CheckName(decl.Name); |
|
|
|
StringHelpers.CleanupText(ref decl.DebugText); |
|
return base.VisitDeclaration(decl); |
|
} |
|
|
|
public override bool VisitClassDecl(Class @class) |
|
{ |
|
if (@class.IsDynamic) |
|
{ |
|
// HACK: entries in v-tables are not shared (as objects) with the virtual methods they represent; |
|
// this is why this pass fixes only the arg names used with real methods, |
|
// while the v-table entries could remain with empty names; |
|
// this should be fixed in the parser: it should reuse method objects |
|
foreach (var parameter in VTables.GatherVTableMethodEntries(@class).Where( |
|
entry => entry.Method != null).SelectMany(entry => entry.Method.Parameters)) |
|
{ |
|
parameter.Name = CheckName(parameter.Name); |
|
} |
|
} |
|
|
|
return base.VisitClassDecl(@class); |
|
} |
|
|
|
public override bool VisitFunctionDecl(Function function) |
|
{ |
|
uniqueName = 0; |
|
return base.VisitFunctionDecl(function); |
|
} |
|
|
|
public override bool VisitTypedefDecl(TypedefDecl typedef) |
|
{ |
|
var @class = typedef.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; |
|
|
|
return base.VisitTypedefDecl(typedef); |
|
} |
|
|
|
private static void CheckEnumName(Enumeration @enum) |
|
{ |
|
// If we still do not have a valid name, then try to guess one |
|
// based on the enum value names. |
|
|
|
if (!String.IsNullOrWhiteSpace(@enum.Name)) |
|
return; |
|
|
|
var prefix = @enum.Items.Select(item => item.Name) |
|
.ToArray().CommonPrefix(); |
|
|
|
// Try a simple heuristic to make sure we end up with a valid name. |
|
if (prefix.Length < 3) |
|
return; |
|
|
|
prefix = prefix.Trim().Trim(new char[] { '_' }); |
|
@enum.Name = prefix; |
|
} |
|
|
|
public override bool VisitEnumDecl(Enumeration @enum) |
|
{ |
|
CheckEnumName(@enum); |
|
return base.VisitEnumDecl(@enum); |
|
} |
|
|
|
public override bool VisitEnumItem(Enumeration.Item item) |
|
{ |
|
item.Name = CheckName(item.Name); |
|
return base.VisitEnumItem(item); |
|
} |
|
} |
|
} |
|
|
|
|