mirror of https://github.com/mono/CppSharp.git
20 changed files with 896 additions and 11 deletions
@ -0,0 +1,16 @@
@@ -0,0 +1,16 @@
|
||||
namespace CppSharp.AST |
||||
{ |
||||
public enum StatementClass |
||||
{ |
||||
Any, |
||||
DeclarationReference, |
||||
ConstructorReference |
||||
} |
||||
|
||||
public abstract class Statement |
||||
{ |
||||
public StatementClass Class { get; set; } |
||||
public Declaration Declaration { get; set; } |
||||
public string String { get; set; } |
||||
} |
||||
} |
@ -0,0 +1,173 @@
@@ -0,0 +1,173 @@
|
||||
using System.Collections.Generic; |
||||
using System.Globalization; |
||||
using System.Linq; |
||||
using System.Text.RegularExpressions; |
||||
using CppSharp.AST; |
||||
using CppSharp.AST.Extensions; |
||||
using CppSharp.Generators.CLI; |
||||
using CppSharp.Generators.CSharp; |
||||
using CppSharp.Types; |
||||
using Type = CppSharp.AST.Type; |
||||
|
||||
namespace CppSharp.Passes |
||||
{ |
||||
public class HandleDefaultParamValuesPass : TranslationUnitPass |
||||
{ |
||||
private static readonly Regex regexFunctionParams = new Regex(@"\((.+)\)", RegexOptions.Compiled); |
||||
private static readonly Regex regexDoubleColon = new Regex(@"\w+::", RegexOptions.Compiled); |
||||
private static readonly Regex regexName = new Regex(@"(\w+)", RegexOptions.Compiled); |
||||
|
||||
public override bool VisitFunctionDecl(Function function) |
||||
{ |
||||
bool result = base.VisitFunctionDecl(function); |
||||
|
||||
var overloadIndices = new List<int>(function.Parameters.Count); |
||||
foreach (var parameter in function.Parameters.Where(p => p.DefaultArgument != null)) |
||||
{ |
||||
Type desugared = parameter.Type.Desugar(); |
||||
|
||||
if (CheckForDefaultPointer(desugared, parameter)) |
||||
continue; |
||||
|
||||
bool? defaultConstruct = CheckForDefaultConstruct(desugared, parameter); |
||||
if (defaultConstruct == null || |
||||
(!Driver.Options.MarshalCharAsManagedChar && |
||||
parameter.Type.Desugar().IsPrimitiveType(PrimitiveType.UChar))) |
||||
{ |
||||
overloadIndices.Add(function.Parameters.IndexOf(parameter)); |
||||
continue; |
||||
} |
||||
if (defaultConstruct == true) |
||||
continue; |
||||
|
||||
if (CheckForEnumValue(parameter, desugared)) |
||||
continue; |
||||
|
||||
CheckForULongValue(parameter, desugared); |
||||
} |
||||
|
||||
GenerateOverloads(function, overloadIndices); |
||||
|
||||
return result; |
||||
} |
||||
|
||||
private static bool CheckForDefaultPointer(Type desugared, Parameter parameter) |
||||
{ |
||||
if (desugared.IsPointer()) |
||||
{ |
||||
parameter.DefaultArgument.String = "null"; |
||||
return true; |
||||
} |
||||
return false; |
||||
} |
||||
|
||||
private bool? CheckForDefaultConstruct(Type desugared, Parameter parameter) |
||||
{ |
||||
Method ctor = parameter.DefaultArgument.Declaration as Method; |
||||
if (ctor == null || !ctor.IsConstructor) |
||||
return false; |
||||
|
||||
Type type; |
||||
desugared.IsPointerTo(out type); |
||||
type = type ?? desugared; |
||||
Class decl; |
||||
if (!type.TryGetClass(out decl)) |
||||
return false; |
||||
TypeMap typeMap; |
||||
|
||||
if (Driver.TypeDatabase.FindTypeMap(decl, type, out typeMap)) |
||||
{ |
||||
string mappedTo; |
||||
if (Driver.Options.IsCSharpGenerator) |
||||
{ |
||||
var typePrinterContext = new CSharpTypePrinterContext |
||||
{ |
||||
CSharpKind = CSharpTypePrinterContextKind.Managed, |
||||
Type = type |
||||
}; |
||||
mappedTo = typeMap.CSharpSignature(typePrinterContext); |
||||
} |
||||
else |
||||
{ |
||||
var typePrinterContext = new CLITypePrinterContext |
||||
{ |
||||
Type = type |
||||
}; |
||||
mappedTo = typeMap.CLISignature(typePrinterContext); |
||||
} |
||||
if (mappedTo == "string" && ctor.Parameters.Count == 0) |
||||
{ |
||||
parameter.DefaultArgument.String = "\"\""; |
||||
return true; |
||||
} |
||||
} |
||||
|
||||
parameter.DefaultArgument.String = string.Format("new {0}", parameter.DefaultArgument.String); |
||||
if (ctor.Parameters.Count > 0 && ctor.Parameters[0].OriginalName == "_0") |
||||
parameter.DefaultArgument.String = parameter.DefaultArgument.String.Replace("(0)", "()"); |
||||
|
||||
return decl.IsValueType ? true : (bool?) null; |
||||
} |
||||
|
||||
private static bool CheckForEnumValue(Parameter parameter, Type desugared) |
||||
{ |
||||
var enumItem = parameter.DefaultArgument.Declaration as Enumeration.Item; |
||||
if (enumItem != null) |
||||
{ |
||||
parameter.DefaultArgument.String = string.Format("{0}{1}.{2}.{3}", |
||||
desugared.IsPrimitiveType() ? "(int) " : string.Empty, |
||||
enumItem.Namespace.Namespace.Name, enumItem.Namespace.Name, enumItem.Name); |
||||
return true; |
||||
} |
||||
|
||||
var call = parameter.DefaultArgument.Declaration as Method; |
||||
if (call != null && call.IsConstructor) |
||||
{ |
||||
string @params = |
||||
regexFunctionParams.Match(parameter.DefaultArgument.String).Groups[1].Value; |
||||
if (@params.Contains("::")) |
||||
parameter.DefaultArgument.String = regexDoubleColon.Replace(@params, desugared + "."); |
||||
else |
||||
parameter.DefaultArgument.String = regexName.Replace(@params, desugared + ".$1"); |
||||
return true; |
||||
} |
||||
return false; |
||||
} |
||||
|
||||
private static void CheckForULongValue(Parameter parameter, Type desugared) |
||||
{ |
||||
ulong value; |
||||
string @default = parameter.DefaultArgument.String; |
||||
// HACK: .NET's Parse/TryParse have a bug preventing them from parsing UL-suffixed ulongs
|
||||
if (desugared.IsPrimitiveType() && @default.EndsWith("UL")) |
||||
@default = @default.Substring(0, @default.Length - 2); |
||||
if (ulong.TryParse(@default, out value)) |
||||
parameter.DefaultArgument.String = value.ToString(CultureInfo.InvariantCulture); |
||||
} |
||||
|
||||
private static void GenerateOverloads(Function function, List<int> overloadIndices) |
||||
{ |
||||
foreach (var overloadIndex in overloadIndices) |
||||
{ |
||||
var method = function as Method; |
||||
Function overload = method != null ? new Method(method) : new Function(function); |
||||
overload.SynthKind = FunctionSynthKind.DefaultValueOverload; |
||||
overload.Parameters[overloadIndex].GenerationKind = GenerationKind.None; |
||||
|
||||
var indices = overloadIndices.Where(i => i != overloadIndex).ToList(); |
||||
if (indices.Any()) |
||||
for (int i = 0; i <= indices.Last(); i++) |
||||
if (i != overloadIndex) |
||||
overload.Parameters[i].DefaultArgument = null; |
||||
|
||||
if (method != null) |
||||
((Class) function.Namespace).Methods.Add((Method) overload); |
||||
else |
||||
function.Namespace.Functions.Add(overload); |
||||
|
||||
for (int i = 0; i <= overloadIndex; i++) |
||||
function.Parameters[i].DefaultArgument = null; |
||||
} |
||||
} |
||||
} |
||||
} |
Loading…
Reference in new issue