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.
 
 
 
 
 

143 lines
4.8 KiB

using System;
using System.Linq;
using CppSharp.AST;
namespace CppSharp.Passes
{
/// <summary>
/// This pass checks for compatible combinations of getters/setters methods
/// and creates matching properties that call back into the methods.
/// </summary>
public class GetterSetterToPropertyPass : TranslationUnitPass
{
public GetterSetterToPropertyPass()
{
Options.VisitClassFields = false;
Options.VisitClassProperties = false;
Options.VisitNamespaceEnums = false;
Options.VisitNamespaceTemplates = false;
Options.VisitNamespaceTypedefs = false;
Options.VisitNamespaceEvents = false;
Options.VisitNamespaceVariables = false;
Options.VisitFunctionParameters = false;
Options.VisitTemplateArguments = false;
}
static bool IsSetter(Function method)
{
var isRetVoid = method.ReturnType.Type.IsPrimitiveType(
PrimitiveType.Void);
var isSetter = method.OriginalName.StartsWith("set",
StringComparison.InvariantCultureIgnoreCase);
return isRetVoid && isSetter && method.Parameters.Count == 1;
}
static bool IsGetter(Function method)
{
var isRetVoid = method.ReturnType.Type.IsPrimitiveType(
PrimitiveType.Void);
var isGetter = method.OriginalName.StartsWith("get",
StringComparison.InvariantCultureIgnoreCase);
return !isRetVoid && isGetter && method.Parameters.Count == 0;
}
Property GetOrCreateProperty(Class @class, string name, QualifiedType type)
{
var prop = @class.Properties.FirstOrDefault(property => property.Name == name
&& property.QualifiedType.Equals(type));
var prop2 = @class.Properties.FirstOrDefault(property => property.Name == name);
if (prop == null && prop2 != null)
Driver.Diagnostics.EmitWarning(DiagnosticId.PropertySynthetized,
"Property {0}::{1} already exist with type {2}", @class.Name, name, type.Type.ToString());
if (prop != null)
return prop;
prop = new Property
{
Name = name,
Namespace = @class,
QualifiedType = type
};
@class.Properties.Add(prop);
return prop;
}
public override bool VisitMethodDecl(Method method)
{
if (AlreadyVisited(method))
return false;
if (ASTUtils.CheckIgnoreMethod(method))
return false;
var @class = method.Namespace as Class;
if (@class == null || @class.IsIncomplete)
return false;
if (IsGetter(method))
{
var name = method.Name.Substring("get".Length);
var prop = GetOrCreateProperty(@class, name, method.ReturnType);
prop.GetMethod = method;
prop.Access = method.Access;
// Do not generate the original method now that we know it is a getter.
method.IsGenerated = false;
Driver.Diagnostics.EmitMessage(DiagnosticId.PropertySynthetized,
"Getter created: {0}::{1}", @class.Name, name);
return false;
}
if (IsSetter(method) && IsValidSetter(method))
{
var name = method.Name.Substring("set".Length);
var type = method.Parameters[0].QualifiedType;
var prop = GetOrCreateProperty(@class, name, type);
prop.SetMethod = method;
prop.Access = method.Access;
// Ignore the original method now that we know it is a setter.
method.IsGenerated = false;
Driver.Diagnostics.EmitMessage(DiagnosticId.PropertySynthetized,
"Setter created: {0}::{1}", @class.Name, name);
return false;
}
return false;
}
// Check if a matching getter exist or no other setter exists.
private bool IsValidSetter(Method method)
{
var @class = method.Namespace as Class;
var name = method.Name.Substring("set".Length);
if (method.Parameters.Count == 0)
return false;
var type = method.Parameters[0].Type;
var getter = @class.Methods.FirstOrDefault(m => m.Name == "Get" + name && m.Type.Equals(type));
var otherSetter = @class.Methods.FirstOrDefault(m => m.Name == method.Name
&& m.Parameters.Count == 1
&& !m.Parameters[0].Type.Equals(type));
return getter != null || otherSetter == null;
}
}
}