mirror of https://github.com/mono/CppSharp.git
c-sharpdotnetmonobindingsbridgecclangcpluspluscppsharpglueinteropparserparsingpinvokeswigsyntax-treevisitorsxamarinxamarin-bindings
88 lines
3.0 KiB
88 lines
3.0 KiB
using System.Linq; |
|
using CppSharp.AST; |
|
using CppSharp.AST.Extensions; |
|
using CppSharp.Generators; |
|
|
|
namespace CppSharp.Passes |
|
{ |
|
/// <summary> |
|
/// This pass will try to hoist functions into classes so they |
|
/// work just like instance methods. |
|
/// </summary> |
|
public class FunctionToInstanceMethodPass : TranslationUnitPass |
|
{ |
|
public override bool VisitMethodDecl(Method method) |
|
{ |
|
return true; |
|
} |
|
|
|
public override bool VisitFunctionDecl(Function function) |
|
{ |
|
if (!function.IsGenerated) |
|
return false; |
|
|
|
// Check if this function can be converted. |
|
if (function.Parameters.Count == 0) |
|
return false; |
|
|
|
var classParam = function.Parameters[0]; |
|
|
|
Class @class; |
|
if (!GetClassParameter(classParam, out @class)) |
|
return false; |
|
|
|
// If we reach here, it means the first parameter is of class type. |
|
// This means we can change the function to be an instance method. |
|
|
|
// Clean up the name of the function now that it will be an instance method. |
|
if (!function.Name.StartsWith(@class.Name, System.StringComparison.Ordinal)) |
|
return false; |
|
|
|
function.Name = function.Name.Substring(@class.Name.Length); |
|
function.ExplicitlyIgnore(); |
|
|
|
// Create a new fake method so it acts as an instance method. |
|
var method = new Method |
|
{ |
|
Namespace = @class, |
|
OriginalNamespace = function.Namespace, |
|
Name = function.Name, |
|
OriginalName = function.OriginalName, |
|
Mangled = function.Mangled, |
|
Access = AccessSpecifier.Public, |
|
Kind = CXXMethodKind.Normal, |
|
ReturnType = function.ReturnType, |
|
CallingConvention = function.CallingConvention, |
|
IsVariadic = function.IsVariadic, |
|
IsInline = function.IsInline, |
|
Conversion = MethodConversionKind.FunctionToInstanceMethod, |
|
FunctionType = function.FunctionType |
|
}; |
|
|
|
method.Parameters.AddRange(function.Parameters.Select( |
|
p => new Parameter(p) { Namespace = method })); |
|
|
|
if (Options.GeneratorKind == GeneratorKind.CSharp) |
|
method.Parameters.RemoveAt(0); |
|
|
|
@class.Methods.Add(method); |
|
|
|
Diagnostics.Debug("Function converted to instance method: {0}::{1}", @class.Name, |
|
function.Name); |
|
|
|
return true; |
|
} |
|
|
|
public static bool GetClassParameter(Parameter classParam, out Class @class) |
|
{ |
|
TagType tag; |
|
if (classParam.Type.IsPointerTo(out tag)) |
|
{ |
|
@class = tag.Declaration as Class; |
|
return true; |
|
} |
|
|
|
return classParam.Type.TryGetClass(out @class); |
|
} |
|
} |
|
}
|
|
|