From 06aba88fbbe7b2a891e6bf58f9d8e3e2bcd5b8a6 Mon Sep 17 00:00:00 2001 From: marcos henrich Date: Tue, 30 Jul 2013 10:22:04 +0100 Subject: [PATCH] Modified GetterSetterToPropertyPass more complex properties are supported. Now even if we only have a getter or a setter a property is created. Trying to convert multiple setter with same name and different types is an issue, so we check before creating a setter for a matching getter or the non existence of more setters. --- .../Passes/GetterSetterToPropertyPass.cs | 102 +++++++++++++----- 1 file changed, 75 insertions(+), 27 deletions(-) diff --git a/src/Generator/Passes/GetterSetterToPropertyPass.cs b/src/Generator/Passes/GetterSetterToPropertyPass.cs index 6fa6e2a3..a3c26349 100644 --- a/src/Generator/Passes/GetterSetterToPropertyPass.cs +++ b/src/Generator/Passes/GetterSetterToPropertyPass.cs @@ -1,4 +1,6 @@ using System; +using System.Diagnostics; +using System.Linq; using CppSharp.AST; namespace CppSharp.Passes @@ -44,51 +46,97 @@ namespace CppSharp.Passes 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) { - //var expansions = method.PreprocessedEntities.OfType(); - //if (expansions.Any(e => e.Text.Contains("ACCESSOR"))) - // System.Diagnostics.Debugger.Break(); + if (AlreadyVisited(method)) + return false; - if (!IsGetter(method)) + if (ASTUtils.CheckIgnoreMethod(null, method)) return false; var @class = method.Namespace as Class; - foreach (var classMethod in @class.Methods) + + if (@class == null || @class.IsIncomplete) + return false; + + if (IsGetter(method)) { - if (!IsSetter(classMethod)) - continue; + var name = method.Name.Substring("get".Length); + var prop = GetOrCreateProperty(@class, name, method.ReturnType); + prop.GetMethod = method; - if (classMethod.Parameters[0].Type.Equals(method.ReturnType.Type)) - continue; + // Do not generate the original method now that we know it is a getter. + method.IsGenerated = false; - var getName = method.Name.Substring("get".Length); - var setName = classMethod.Name.Substring("set".Length); + Driver.Diagnostics.EmitMessage(DiagnosticId.PropertySynthetized, + "Getter created: {0}::{1}", @class.Name, name); - if (getName != setName) - continue; + return false; + } - // We found a compatible pair of methods, create a property. - var prop = new Property - { - Name = getName, - Namespace = @class, - QualifiedType = method.ReturnType - }; + if (IsSetter(method) && IsValidSetter(method)) + { + var name = method.Name.Substring("set".Length); - // Ignore the original methods now that we have a property. - method.ExplicityIgnored = true; - classMethod.ExplicityIgnored = true; + var type = method.Parameters[0].QualifiedType; + var prop = GetOrCreateProperty(@class, name, type); + prop.SetMethod = method; - @class.Properties.Add(prop); + // Ignore the original method now that we know it is a setter. + method.IsGenerated = false; Driver.Diagnostics.EmitMessage(DiagnosticId.PropertySynthetized, - "Getter/setter property created: {0}::{1}", @class.Name, - getName); - return true; + "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; + } } }