Tools and libraries to glue C/C++ APIs to high-level languages
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.
 
 
 
 
 

191 lines
6.2 KiB

using System.Collections.Generic;
using System.Linq;
using System.Text;
using CppSharp.AST;
using CppSharp.Generators.CLI;
using CppSharp.Generators.CSharp;
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++);
// Clean up the item name if the first digit is not a valid name.
if (char.IsNumber(name[0]))
return '_' + name;
// TODO: Fix this to not need per-generator code.
var units = new List<TranslationUnit> { new TranslationUnit() };
if (Options.IsCLIGenerator)
return new CLIHeaders(Context, units).SafeIdentifier(name);
return new CSharpSources(Context, units).SafeIdentifier(name);
}
public override bool VisitDeclaration(Declaration decl)
{
if (!base.VisitDeclaration(decl))
return false;
// 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.Name = decl.Namespace.Name == "_" ? "__" : "_";
decl.ExplicitlyIgnore();
return true;
}
var function = decl as Function;
var method = function as Method;
if ((function == null || !function.IsOperator) && !(decl is Enumeration) &&
(method == null || method.Kind == CXXMethodKind.Normal))
decl.Name = CheckName(decl.Name);
StringHelpers.CleanupText(ref decl.DebugText);
return true;
}
public override bool VisitParameterDecl(Parameter parameter)
{
return VisitDeclaration(parameter);
}
public override bool VisitClassDecl(Class @class)
{
var currentUniqueName = uniqueName;
uniqueName = 0;
base.VisitClassDecl(@class);
uniqueName = currentUniqueName;
if (!@class.IsDependent)
foreach (var field in @class.Layout.Fields.Where(f => string.IsNullOrEmpty(f.Name)))
field.Name = @class.Name == "_" ? "__" : "_";
if (@class is ClassTemplateSpecialization &&
!(from c in @class.Namespace.Classes
where c.Name == @class.Name && !(@class is ClassTemplateSpecialization) &&
c != ((ClassTemplateSpecialization) @class).TemplatedDecl.TemplatedClass
select c).Any())
return true;
if (@class.Namespace.Classes.Any(d => d != @class && d.Name == @class.Name))
{
StringBuilder str = new StringBuilder();
str.Append(@class.Name);
do
{
str.Append('_');
} while (@class.Classes.Any(d => d != @class && d.Name == str.ToString()));
@class.Name = str.ToString();
}
return true;
}
public override bool VisitFunctionDecl(Function function)
{
var currentUniqueName = uniqueName;
uniqueName = 0;
var ret = base.VisitFunctionDecl(function);
uniqueName = currentUniqueName;
return ret;
}
public override bool VisitEvent(Event @event)
{
var currentUniqueName = uniqueName;
uniqueName = 0;
var ret = base.VisitEvent(@event);
uniqueName = currentUniqueName;
return ret;
}
public override bool VisitFunctionType(FunctionType type,
TypeQualifiers quals)
{
var currentUniqueName = this.uniqueName;
this.uniqueName = 0;
var ret = base.VisitFunctionType(type, quals);
this.uniqueName = currentUniqueName;
return ret;
}
private 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)
{
@enum.Name = CheckName(@enum.Name);
return;
}
var prefixBuilder = new StringBuilder(prefix);
prefixBuilder.TrimUnderscores();
while (@enum.Namespace.Enums.Any(e => e != @enum &&
e.Name == prefixBuilder.ToString()))
prefixBuilder.Append('_');
@enum.Name = prefixBuilder.ToString();
}
public override bool VisitEnumDecl(Enumeration @enum)
{
if (!base.VisitEnumDecl(@enum))
return false;
CheckEnumName(@enum);
return true;
}
public override bool VisitEnumItemDecl(Enumeration.Item item)
{
if (!base.VisitEnumItemDecl(item))
return false;
item.Name = CheckName(item.Name);
return true;
}
public override bool VisitFieldDecl(Field field)
{
if (!base.VisitFieldDecl(field))
return false;
if (field.Class.Fields.Count(c => c.Name.Equals(field.Name)) > 1)
{
StringBuilder str = new StringBuilder();
str.Append(field.Name);
do
{
str.Append('_');
} while (field.Class.Fields.Any(c => c.Name.Equals(str.ToString())));
field.Name = str.ToString();
}
return true;
}
}
}