public static string CreateMultipleComplexTypesClassInstance(MethodDeclarationSyntax wcfClientMethod, string serviceComplexTypeParamName, IEnumerable <MethodDeclarationSyntax> wcfServiceMethods) { // handle if method has two or more (i.e. "multiple") complex types parameters var wcfServiceMethod = MethodsGenerator.FindWcfServiceMethod(wcfClientMethod, wcfServiceMethods); var wcfServiceParameters = wcfServiceMethod .ParameterList .Parameters; var multipleComplexParameters = MultipleComplexTypesGenerator.FindMultipleComplexTypesOrOutKeyword(wcfServiceParameters); // get the param names and use as anonymous class property names var properties = multipleComplexParameters.Any() ? multipleComplexParameters .Select(parameter => { var name = parameter.Identifier.ToFullString(); return(name); }) .Aggregate((name1, name2) => $"{name1},{name2}") : ""; // create anonymous class instance with complex type properties var hasComplexTypeProperties = !string.IsNullOrEmpty(properties); var classInstance = hasComplexTypeProperties ? $@"var {serviceComplexTypeParamName} = new {{{properties}}};" : ""; return(classInstance); }
private void GenerateInternalImplementationMethods() { for (short i = 1; i <= data.Smoke->numClasses; i++) { Smoke.Class *klass = data.Smoke->classes + i; if (klass->external) { continue; } CodeTypeDeclaration type = data.SmokeTypeMap[(IntPtr)klass]; CodeTypeDeclaration implType; if (!data.InternalTypeMap.TryGetValue(type, out implType)) { continue; } MethodsGenerator methgen = new MethodsGenerator(data, translator, implType, klass); methgen.InternalImplementation = true; foreach (KeyValuePair <Smoke.ModuleIndex, string> pair in Util.GetAbstractMethods(data.Smoke, i)) { methgen.GenerateMethod(pair.Key.smoke, pair.Key.index, pair.Value); } methgen.GenerateProperties(); } }
private void GenerateInheritedMethods(Smoke.Class *klass, MethodsGenerator methgen, AttributeGenerator attrgen, List <Smoke.ModuleIndex> alreadyImplemented) { // Contains inherited methods that have to be implemented by the current class. // We use our custom comparer, so we don't end up with the same method multiple times. IDictionary <Smoke.ModuleIndex, string> implementMethods = new Dictionary <Smoke.ModuleIndex, string>(SmokeMethodEqualityComparer.DefaultEqualityComparer); bool firstParent = true; for (short *parent = data.Smoke->inheritanceList + klass->parents; *parent > 0; parent++) { if (firstParent) { // we're only interested in parents implemented as interfaces firstParent = false; continue; } // collect all methods (+ inherited ones) and add them to the implementMethods Dictionary data.Smoke->FindAllMethods(*parent, implementMethods, true); } foreach (KeyValuePair <Smoke.ModuleIndex, string> pair in implementMethods) { Smoke.Method *meth = pair.Key.smoke->methods + pair.Key.index; Smoke.Class * ifaceKlass = pair.Key.smoke->classes + meth->classId; if ((meth->flags & (ushort)Smoke.MethodFlags.mf_enum) > 0 || (meth->flags & (ushort)Smoke.MethodFlags.mf_ctor) > 0 || (meth->flags & (ushort)Smoke.MethodFlags.mf_copyctor) > 0 || (meth->flags & (ushort)Smoke.MethodFlags.mf_dtor) > 0 || (meth->flags & (ushort)Smoke.MethodFlags.mf_static) > 0 || (meth->flags & (ushort)Smoke.MethodFlags.mf_internal) > 0) { // no need to check for properties here - QObjects don't support multiple inheritance anyway continue; } if (alreadyImplemented.Contains(pair.Key, SmokeMethodEqualityComparer.DefaultEqualityComparer)) { continue; } if ((meth->flags & (ushort)Smoke.MethodFlags.mf_attribute) > 0) { attrgen.ScheduleAttributeAccessor(pair.Key.smoke, meth); continue; } CodeTypeReference type = translator.CppToCSharp(ByteArrayManager.GetString(ifaceKlass->className)); methgen.GenerateMethod(pair.Key.smoke, meth, pair.Value, type); } }
public static string CreateInterfaceParameterNameMappings(MethodDeclarationSyntax wcfClientMethod, IEnumerable <MethodDeclarationSyntax> wcfServiceMethods) { // sometimes interface methods' parameter names don't match names belonging to derived classes // therefore, find and map them var wcfServiceMethod = MethodsGenerator.FindWcfServiceMethod(wcfClientMethod, wcfServiceMethods); var mappings = BuildParameterMappings(wcfClientMethod, wcfServiceMethod); var mappingsCode = mappings.Any() ? mappings .Select(map => $"var {map.serviceParameterName} = {map.clientParameterName};") .Aggregate((map1, map2) => $"{map1}\n\r{map2}") : ""; return(mappingsCode); }
/* * Adds the methods to the classes created by Run() */ private void GenerateMethods() { short currentClassId = 0; Smoke.Class * klass = (Smoke.Class *)IntPtr.Zero; MethodsGenerator methgen = null; AttributeGenerator attrgen = null; CodeTypeDeclaration type = null; List <Smoke.ModuleIndex> alreadyImplemented = new List <Smoke.ModuleIndex>(); this.FillEnums(); for (short i = 1; i < data.Smoke->numMethodMaps; i++) { Smoke.MethodMap *map = data.Smoke->methodMaps + i; if (currentClassId != map->classId) { // we encountered a new class if (attrgen != null) { // generate inherited methods this.GenerateInheritedMethods(klass, methgen, attrgen, alreadyImplemented); // generate all scheduled attributes attrgen.Run(); if (PostMembersHooks != null) { PostMembersHooks(data.Smoke, klass, type); } methgen.GenerateProperties(); } currentClassId = map->classId; klass = data.Smoke->classes + currentClassId; type = data.SmokeTypeMap[(IntPtr)klass]; alreadyImplemented.Clear(); attrgen = new AttributeGenerator(data, translator, type); methgen = new MethodsGenerator(data, translator, type, klass); } string mungedName = ByteArrayManager.GetString(data.Smoke->methodNames[map->name]); if (map->method > 0) { Smoke.Method *meth = data.Smoke->methods + map->method; if ((meth->flags & (ushort)Smoke.MethodFlags.mf_enum) > 0) { continue; } if ((meth->flags & (ushort)Smoke.MethodFlags.mf_property) > 0 && // non-virtual properties are excluded (meth->flags & (ushort)Smoke.MethodFlags.mf_virtual) == 0 && (meth->flags & (ushort)Smoke.MethodFlags.mf_purevirtual) == 0) { continue; } if ((meth->flags & (ushort)Smoke.MethodFlags.mf_attribute) > 0) { attrgen.ScheduleAttributeAccessor(meth); continue; } methgen.GenerateMethod(map->method, mungedName); alreadyImplemented.Add(new Smoke.ModuleIndex(data.Smoke, map->method)); } else if (map->method < 0) { for (short *overload = data.Smoke->ambiguousMethodList + (-map->method); *overload > 0; overload++) { Smoke.Method *meth = data.Smoke->methods + *overload; if ((meth->flags & (ushort)Smoke.MethodFlags.mf_enum) > 0) { continue; } if ((meth->flags & (ushort)Smoke.MethodFlags.mf_property) > 0 && // non-virtual properties are excluded (meth->flags & (ushort)Smoke.MethodFlags.mf_virtual) == 0 && (meth->flags & (ushort)Smoke.MethodFlags.mf_purevirtual) == 0) { continue; } if ((meth->flags & (ushort)Smoke.MethodFlags.mf_attribute) > 0) { attrgen.ScheduleAttributeAccessor(meth); continue; } // if the methods differ only by constness, we will generate special code bool nextDiffersByConst = false; if (*(overload + 1) > 0) { if (SmokeMethodEqualityComparer.EqualExceptConstness(meth, data.Smoke->methods + *(overload + 1))) { nextDiffersByConst = true; } } methgen.GenerateMethod(*overload, mungedName); alreadyImplemented.Add(new Smoke.ModuleIndex(data.Smoke, *overload)); if (nextDiffersByConst) { overload++; } } } } // Generate the last scheduled attributes attrgen.Run(); // Generate remaining inherited methods this.GenerateInheritedMethods(klass, methgen, attrgen, alreadyImplemented); if (PostMembersHooks != null) { PostMembersHooks(data.Smoke, klass, type); } methgen.GenerateProperties(); AddMissingOperators(); }
/* * Adds the methods to the classes created by Run() */ private void GenerateMethods() { short currentClassId = 0; Smoke.Class* klass = (Smoke.Class*) IntPtr.Zero; MethodsGenerator methgen = null; AttributeGenerator attrgen = null; CodeTypeDeclaration type = null; List<Smoke.ModuleIndex> alreadyImplemented = new List<Smoke.ModuleIndex>(); this.FillEnums(); for (short i = 1; i < data.Smoke->numMethodMaps; i++) { Smoke.MethodMap* map = data.Smoke->methodMaps + i; if (currentClassId != map->classId) { // we encountered a new class if (attrgen != null) { // generate inherited methods this.GenerateInheritedMethods(klass, methgen, attrgen, alreadyImplemented); // generate all scheduled attributes attrgen.Run(); if (PostMembersHooks != null) { PostMembersHooks(data.Smoke, klass, type); } methgen.GenerateProperties(); } currentClassId = map->classId; klass = data.Smoke->classes + currentClassId; type = data.SmokeTypeMap[(IntPtr) klass]; alreadyImplemented.Clear(); attrgen = new AttributeGenerator(data, translator, type); methgen = new MethodsGenerator(data, translator, type, klass); } string mungedName = ByteArrayManager.GetString(data.Smoke->methodNames[map->name]); if (map->method > 0) { Smoke.Method* meth = data.Smoke->methods + map->method; if ((meth->flags & (ushort) Smoke.MethodFlags.mf_enum) > 0) { continue; } if ((meth->flags & (ushort) Smoke.MethodFlags.mf_property) > 0 // non-virtual properties are excluded && (meth->flags & (ushort) Smoke.MethodFlags.mf_virtual) == 0 && (meth->flags & (ushort) Smoke.MethodFlags.mf_purevirtual) == 0) { continue; } if ((meth->flags & (ushort) Smoke.MethodFlags.mf_attribute) > 0) { attrgen.ScheduleAttributeAccessor(meth); continue; } methgen.GenerateMethod(map->method, mungedName); alreadyImplemented.Add(new Smoke.ModuleIndex(data.Smoke, map->method)); } else if (map->method < 0) { for (short* overload = data.Smoke->ambiguousMethodList + (-map->method); *overload > 0; overload++) { Smoke.Method* meth = data.Smoke->methods + *overload; if ((meth->flags & (ushort) Smoke.MethodFlags.mf_enum) > 0) { continue; } if ((meth->flags & (ushort) Smoke.MethodFlags.mf_property) > 0 // non-virtual properties are excluded && (meth->flags & (ushort) Smoke.MethodFlags.mf_virtual) == 0 && (meth->flags & (ushort) Smoke.MethodFlags.mf_purevirtual) == 0) { continue; } if ((meth->flags & (ushort) Smoke.MethodFlags.mf_attribute) > 0) { attrgen.ScheduleAttributeAccessor(meth); continue; } // if the methods differ only by constness, we will generate special code bool nextDiffersByConst = false; if (*(overload + 1) > 0) { if (SmokeMethodEqualityComparer.EqualExceptConstness(meth, data.Smoke->methods + *(overload + 1))) nextDiffersByConst = true; } methgen.GenerateMethod(*overload, mungedName); alreadyImplemented.Add(new Smoke.ModuleIndex(data.Smoke, *overload)); if (nextDiffersByConst) overload++; } } } // Generate the last scheduled attributes attrgen.Run(); // Generate remaining inherited methods this.GenerateInheritedMethods(klass, methgen, attrgen, alreadyImplemented); if (PostMembersHooks != null) { PostMembersHooks(data.Smoke, klass, type); } methgen.GenerateProperties(); AddMissingOperators(); }
private void GenerateInternalImplementationMethods() { for (short i = 1; i <= data.Smoke->numClasses; i++) { Smoke.Class* klass = data.Smoke->classes + i; if (klass->external) { continue; } CodeTypeDeclaration type = data.SmokeTypeMap[(IntPtr) klass]; CodeTypeDeclaration implType; if (!data.InternalTypeMap.TryGetValue(type, out implType)) { continue; } MethodsGenerator methgen = new MethodsGenerator(data, translator, implType, klass); methgen.InternalImplementation = true; foreach (KeyValuePair<Smoke.ModuleIndex, string> pair in Util.GetAbstractMethods(data.Smoke, i)) { methgen.GenerateMethod(pair.Key.smoke, pair.Key.index, pair.Value); } methgen.GenerateProperties(); } }
private void GenerateInheritedMethods(Smoke.Class* klass, MethodsGenerator methgen, AttributeGenerator attrgen, List<Smoke.ModuleIndex> alreadyImplemented) { // Contains inherited methods that have to be implemented by the current class. // We use our custom comparer, so we don't end up with the same method multiple times. IDictionary<Smoke.ModuleIndex, string> implementMethods = new Dictionary<Smoke.ModuleIndex, string>(SmokeMethodEqualityComparer.DefaultEqualityComparer); bool firstParent = true; for (short* parent = data.Smoke->inheritanceList + klass->parents; *parent > 0; parent++) { if (firstParent) { // we're only interested in parents implemented as interfaces firstParent = false; continue; } // collect all methods (+ inherited ones) and add them to the implementMethods Dictionary data.Smoke->FindAllMethods(*parent, implementMethods, true); } foreach (KeyValuePair<Smoke.ModuleIndex, string> pair in implementMethods) { Smoke.Method* meth = pair.Key.smoke->methods + pair.Key.index; Smoke.Class* ifaceKlass = pair.Key.smoke->classes + meth->classId; if ((meth->flags & (ushort) Smoke.MethodFlags.mf_enum) > 0 || (meth->flags & (ushort) Smoke.MethodFlags.mf_ctor) > 0 || (meth->flags & (ushort) Smoke.MethodFlags.mf_copyctor) > 0 || (meth->flags & (ushort) Smoke.MethodFlags.mf_dtor) > 0 || (meth->flags & (ushort) Smoke.MethodFlags.mf_static) > 0 || (meth->flags & (ushort) Smoke.MethodFlags.mf_internal) > 0) { // no need to check for properties here - QObjects don't support multiple inheritance anyway continue; } if (alreadyImplemented.Contains(pair.Key, SmokeMethodEqualityComparer.DefaultEqualityComparer)) { continue; } if ((meth->flags & (ushort) Smoke.MethodFlags.mf_attribute) > 0) { attrgen.ScheduleAttributeAccessor(pair.Key.smoke, meth); continue; } CodeTypeReference type = translator.CppToCSharp(ByteArrayManager.GetString(ifaceKlass->className)); methgen.GenerateMethod(pair.Key.smoke, meth, pair.Value, type); } }
public void Run() { HashSet<short> interfaceClasses = GetClassList(); // Make the interfaces known first, otherwise Translator won't work correctly. foreach (short idx in interfaceClasses) { Smoke.Class* klass = data.Smoke->classes + idx; string className = ByteArrayManager.GetString(klass->className); int colon = className.LastIndexOf("::", StringComparison.Ordinal); string prefix = (colon != -1) ? className.Substring(0, colon) : string.Empty; string name = (colon != -1) ? className.Substring(colon + 2) : className; CodeTypeDeclaration ifaceDecl = new CodeTypeDeclaration('I' + name); ifaceDecl.IsInterface = true; CodeAttributeDeclaration attr = new CodeAttributeDeclaration("SmokeClass", new CodeAttributeArgument( new CodePrimitiveExpression(className))); ifaceDecl.CustomAttributes.Add(attr); data.GetTypeCollection(prefix).Add(ifaceDecl); data.InterfaceTypeMap[className] = ifaceDecl; } // Now generate the methods. foreach (short idx in interfaceClasses) { Smoke.Class* klass = data.Smoke->classes + idx; string className = ByteArrayManager.GetString(klass->className); CodeTypeDeclaration ifaceDecl = data.InterfaceTypeMap[className]; short* parent = data.Smoke->inheritanceList + klass->parents; while (*parent > 0) { ifaceDecl.BaseTypes.Add(translator.CppToCSharp(data.Smoke->classes + *parent, ifaceDecl)); parent++; } MethodsGenerator mg = new MethodsGenerator(data, translator, ifaceDecl, klass); AttributeGenerator ag = new AttributeGenerator(data, translator, ifaceDecl); List<IntPtr> methods = new List<IntPtr>(); ///TODO: replace this algorithm, it's highly inefficient for (short i = 0; i <= data.Smoke->numMethods && data.Smoke->methods[i].classId <= idx; i++) { Smoke.Method* meth = data.Smoke->methods + i; if (meth->classId != idx) continue; string methName = ByteArrayManager.GetString(data.Smoke->methodNames[meth->name]); // we don't want anything except protected, const or empty flags if ((meth->flags & (ushort) Smoke.MethodFlags.mf_enum) > 0 || (meth->flags & (ushort) Smoke.MethodFlags.mf_ctor) > 0 || (meth->flags & (ushort) Smoke.MethodFlags.mf_copyctor) > 0 || (meth->flags & (ushort) Smoke.MethodFlags.mf_dtor) > 0 || (meth->flags & (ushort) Smoke.MethodFlags.mf_static) > 0 || (meth->flags & (ushort) Smoke.MethodFlags.mf_internal) > 0 || (meth->flags & (ushort) Smoke.MethodFlags.mf_protected) > 0 || methName.StartsWith("operator")) { continue; } if ((meth->flags & (ushort) Smoke.MethodFlags.mf_attribute) > 0) { ag.ScheduleAttributeAccessor(meth); continue; } methods.Add((IntPtr) meth); } methods.Sort(CompareSmokeMethods); foreach (Smoke.Method* method in methods) { CodeMemberMethod cmm = mg.GenerateBasicMethodDefinition(data.Smoke, method); if (cmm != null && !ifaceDecl.HasMethod(cmm)) { ifaceDecl.Members.Add(cmm); } } mg.GenerateProperties(); foreach (CodeMemberProperty prop in ag.GenerateBasicAttributeDefinitions()) { ifaceDecl.Members.Add(prop); } } }
/* * Adds the methods to the classes created by Run() */ private void GenerateMethods(IList<IntPtr> excludedMethods) { List<Smoke.ModuleIndex> alreadyImplemented = new List<Smoke.ModuleIndex>(); this.FillEnums(); Dictionary<short, List<Smoke.MethodMap>> dictionary = new Dictionary<short, List<Smoke.MethodMap>>(); List<short> classes = new List<short>(); for (short i = 1; i < data.Smoke->numMethodMaps; i++) { Smoke.MethodMap* map = data.Smoke->methodMaps + i; if (!dictionary.ContainsKey(map->classId)) { dictionary.Add(map->classId, new List<Smoke.MethodMap>()); } dictionary[map->classId].Add(*map); if (!classes.Contains(map->classId)) { classes.Add(map->classId); } } foreach (KeyValuePair<short, List<Smoke.MethodMap>> pair in dictionary.OrderBy(k => { int chainLength = 0; Smoke.Class* klass = data.Smoke->classes + k.Key; short* parent = data.Smoke->inheritanceList + klass->parents; while (*parent > 0) { ++chainLength; klass = data.Smoke->classes + *parent; parent = data.Smoke->inheritanceList + klass->parents; } return chainLength; })) { Smoke.Class* klass = data.Smoke->classes + pair.Key; CodeTypeDeclaration type = data.SmokeTypeMap[(IntPtr) klass]; alreadyImplemented.Clear(); AttributeGenerator attrgen = new AttributeGenerator(data, translator, type); MethodsGenerator methgen = new MethodsGenerator(data, translator, type, klass); foreach (Smoke.MethodMap map in pair.Value) { string mungedName = ByteArrayManager.GetString(data.Smoke->methodNames[map.name]); if (map.method > 0) { Smoke.Method* meth = data.Smoke->methods + map.method; if (excludedMethods.Contains((IntPtr) meth) || (meth->flags & (ushort) Smoke.MethodFlags.mf_enum) > 0) { continue; } if ((meth->flags & (ushort) Smoke.MethodFlags.mf_property) > 0 // non-virtual properties are excluded && (meth->flags & (ushort) Smoke.MethodFlags.mf_virtual) == 0 && (meth->flags & (ushort) Smoke.MethodFlags.mf_purevirtual) == 0) { continue; } if ((meth->flags & (ushort) Smoke.MethodFlags.mf_attribute) > 0) { attrgen.ScheduleAttributeAccessor(meth); continue; } methgen.GenerateMethod(map.method, mungedName); alreadyImplemented.Add(new Smoke.ModuleIndex(data.Smoke, map.method)); } else if (map.method < 0) { for (short* overload = data.Smoke->ambiguousMethodList + (-map.method); *overload > 0; overload++) { Smoke.Method* meth = data.Smoke->methods + *overload; if (excludedMethods.Contains((IntPtr) meth) || (meth->flags & (ushort) Smoke.MethodFlags.mf_enum) > 0) { continue; } if ((meth->flags & (ushort) Smoke.MethodFlags.mf_property) > 0 // non-virtual properties are excluded && (meth->flags & (ushort) Smoke.MethodFlags.mf_virtual) == 0 && (meth->flags & (ushort) Smoke.MethodFlags.mf_purevirtual) == 0) { continue; } if ((meth->flags & (ushort) Smoke.MethodFlags.mf_attribute) > 0) { attrgen.ScheduleAttributeAccessor(meth); continue; } // if the methods differ only by constness, we will generate special code bool nextDiffersByConst = false; if (*(overload + 1) > 0) { if (SmokeMethodEqualityComparer.EqualExceptConstness(meth, data.Smoke->methods + *(overload + 1))) nextDiffersByConst = true; } methgen.GenerateMethod(*overload, mungedName); alreadyImplemented.Add(new Smoke.ModuleIndex(data.Smoke, *overload)); if (nextDiffersByConst) overload++; } } } // generate inherited methods this.GenerateInheritedMethods(klass, methgen, attrgen, alreadyImplemented); // generate all scheduled attributes attrgen.Run(); methgen.GenerateProperties(); } foreach (short @class in classes) { Smoke.Class* klass = data.Smoke->classes + @class; CodeTypeDeclaration type = data.SmokeTypeMap[(IntPtr) klass]; if (PostMembersHooks != null) { PostMembersHooks(this.data.Smoke, klass, type); } } AddMissingOperators(); }
public void Run() { HashSet <short> interfaceClasses = GetClassList(); // Make the interfaces known first, otherwise Translator won't work correctly. foreach (short idx in interfaceClasses) { Smoke.Class *klass = data.Smoke->classes + idx; string className = ByteArrayManager.GetString(klass->className); int colon = className.LastIndexOf("::", StringComparison.Ordinal); string prefix = (colon != -1) ? className.Substring(0, colon) : string.Empty; string name = (colon != -1) ? className.Substring(colon + 2) : className; CodeTypeDeclaration ifaceDecl = new CodeTypeDeclaration('I' + name); ifaceDecl.IsInterface = true; CodeAttributeDeclaration attr = new CodeAttributeDeclaration("SmokeClass", new CodeAttributeArgument( new CodePrimitiveExpression(className))); ifaceDecl.CustomAttributes.Add(attr); data.GetTypeCollection(prefix).Add(ifaceDecl); data.InterfaceTypeMap[className] = ifaceDecl; } // Now generate the methods. foreach (short idx in interfaceClasses) { Smoke.Class * klass = data.Smoke->classes + idx; string className = ByteArrayManager.GetString(klass->className); CodeTypeDeclaration ifaceDecl = data.InterfaceTypeMap[className]; short *parent = data.Smoke->inheritanceList + klass->parents; while (*parent > 0) { ifaceDecl.BaseTypes.Add(translator.CppToCSharp(data.Smoke->classes + *parent)); parent++; } MethodsGenerator mg = new MethodsGenerator(data, translator, ifaceDecl, klass); AttributeGenerator ag = new AttributeGenerator(data, translator, ifaceDecl); List <IntPtr> methods = new List <IntPtr>(); ///TODO: replace this algorithm, it's highly inefficient for (short i = 0; i <= data.Smoke->numMethods && data.Smoke->methods[i].classId <= idx; i++) { Smoke.Method *meth = data.Smoke->methods + i; if (meth->classId != idx) { continue; } string methName = ByteArrayManager.GetString(data.Smoke->methodNames[meth->name]); // we don't want anything except protected, const or empty flags if ((meth->flags & (ushort)Smoke.MethodFlags.mf_enum) > 0 || (meth->flags & (ushort)Smoke.MethodFlags.mf_ctor) > 0 || (meth->flags & (ushort)Smoke.MethodFlags.mf_copyctor) > 0 || (meth->flags & (ushort)Smoke.MethodFlags.mf_dtor) > 0 || (meth->flags & (ushort)Smoke.MethodFlags.mf_static) > 0 || (meth->flags & (ushort)Smoke.MethodFlags.mf_internal) > 0 || (meth->flags & (ushort)Smoke.MethodFlags.mf_protected) > 0 || methName.StartsWith("operator")) { continue; } if ((meth->flags & (ushort)Smoke.MethodFlags.mf_attribute) > 0) { ag.ScheduleAttributeAccessor(meth); continue; } methods.Add((IntPtr)meth); } methods.Sort(CompareSmokeMethods); foreach (Smoke.Method *method in methods) { CodeMemberMethod cmm = mg.GenerateBasicMethodDefinition(data.Smoke, method); if (cmm != null && !ifaceDecl.HasMethod(cmm)) { ifaceDecl.Members.Add(cmm); } } mg.GenerateProperties(); foreach (CodeMemberProperty prop in ag.GenerateBasicAttributeDefinitions()) { ifaceDecl.Members.Add(prop); } } }
public void Run() { for (short classId = 1; classId <= data.Smoke->numClasses; classId++) { Smoke.Class *klass = data.Smoke->classes + classId; if (klass->external) { continue; } List <Property> props = new List <Property>(); if (!GetProperties(data.Smoke, classId, (name, originalType, typeName, writable, isEnum) => props.Add(new Property(name, originalType, typeName, writable, isEnum)))) { continue; } CodeTypeDeclaration type = data.SmokeTypeMap[(IntPtr)klass]; string className = ByteArrayManager.GetString(klass->className); foreach (Property prop in props) { CodeMemberProperty cmp = new CodeMemberProperty(); try { bool isRef; short id = data.Smoke->IDType(prop.Type); if (id > 0) { cmp.Type = translator.CppToCSharp(data.Smoke->types + id, out isRef); } else { if (!prop.Type.Contains("::")) { id = data.Smoke->IDType(className + "::" + prop.Type); if (id > 0) { cmp.Type = translator.CppToCSharp(data.Smoke->types + id, out isRef); } else { cmp.Type = translator.CppToCSharp(prop.Type, out isRef); } } cmp.Type = translator.CppToCSharp(prop.Type, out isRef); } } catch (NotSupportedException) { Debug.Print(" |--Won't wrap Property {0}::{1}", className, prop.Name); continue; } if (documentation.ContainsKey(type)) { IList <string> docs = documentation[type]; for (int i = 0; i < docs.Count; i++) { Match match = Regex.Match(docs[i], prop.Name + " : (const )?" + prop.OriginalType + @"\n(?<docs>This.*?)\nAccess functions:", RegexOptions.Singleline); if (match.Success) { Util.FormatComment(match.Groups["docs"].Value, cmp, i > 0); break; } } } cmp.Name = prop.Name; // capitalize the first letter StringBuilder builder = new StringBuilder(cmp.Name); builder[0] = char.ToUpper(builder[0]); string capitalized = builder.ToString(); // If the new name clashes with a name of a type declaration, keep the lower-case name (or even make the name lower-case). var typesWithSameName = from member in data.GetAccessibleMembers(data.Smoke->classes + classId) where (member.Type == MemberTypes.NestedType || member.Type == MemberTypes.Method) && member.Name == capitalized select member; if (typesWithSameName.Any()) { Debug.Print( " |--Conflicting names: property/(type or method): {0} in class {1} - keeping original property name", capitalized, className); if (capitalized == cmp.Name) { builder[0] = char.ToLower(builder[0]); cmp.Name = builder.ToString(); // lower case the property if necessary } } else { cmp.Name = capitalized; } cmp.HasGet = true; cmp.HasSet = prop.IsWritable; cmp.Attributes = MemberAttributes.Public | MemberAttributes.New | MemberAttributes.Final; cmp.CustomAttributes.Add(new CodeAttributeDeclaration("Q_PROPERTY", new CodeAttributeArgument( new CodePrimitiveExpression(prop.OriginalType)), new CodeAttributeArgument( new CodePrimitiveExpression(prop.Name)))); // ===== get-method ===== short getterMapId = FindQPropertyGetAccessorMethodMapId(classId, prop, capitalized); if (getterMapId == 0) { Debug.Print(" |--Missing 'get' method for property {0}::{1} - using QObject.Property()", className, prop.Name); cmp.GetStatements.Add(new CodeMethodReturnStatement(new CodeCastExpression(cmp.Type, new CodeMethodInvokeExpression( new CodeThisReferenceExpression(), "Property", new CodePrimitiveExpression(prop.Name))))); } else { Smoke.MethodMap *map = data.Smoke->methodMaps + getterMapId; short getterId = map->method; if (getterId < 0) { // simply choose the first (i.e. non-const) version if there are alternatives getterId = data.Smoke->ambiguousMethodList[-getterId]; } Smoke.Method *getter = data.Smoke->methods + getterId; if (getter->classId != classId) { // The actual get method is defined in a parent class - don't create a property for it. continue; } if ((getter->flags & (uint)Smoke.MethodFlags.mf_virtual) == 0 && (getter->flags & (uint)Smoke.MethodFlags.mf_purevirtual) == 0) { cmp.GetStatements.Add(new CodeMethodReturnStatement(new CodeCastExpression(cmp.Type, new CodeMethodInvokeExpression( SmokeSupport.interceptor_Invoke, new CodePrimitiveExpression( ByteArrayManager.GetString( data.Smoke->methodNames[getter->name ])), new CodePrimitiveExpression( data.Smoke->GetMethodSignature(getter)), new CodeTypeOfExpression(cmp.Type), new CodePrimitiveExpression(false))))); } else { cmp.HasGet = false; if (!cmp.HasSet) { // the get accessor is virtual and there's no set accessor => continue continue; } } } // ===== set-method ===== if (!prop.IsWritable) { // not writable? => continue type.Members.Add(cmp); continue; } char mungedSuffix; short setterMethId = FindQPropertySetAccessorMethodId(classId, prop, capitalized, out mungedSuffix); if (setterMethId == 0) { Debug.Print(" |--Missing 'set' method for property {0}::{1} - using QObject.SetProperty()", className, prop.Name); cmp.SetStatements.Add(new CodeExpressionStatement( new CodeMethodInvokeExpression(new CodeThisReferenceExpression(), "SetProperty", new CodePrimitiveExpression(prop.Name), new CodeArgumentReferenceExpression("value")))); } else { Smoke.Method *setter = data.Smoke->methods + setterMethId; if (setter->classId != classId) { // defined in parent class, continue type.Members.Add(cmp); continue; } string setterName = ByteArrayManager.GetString(data.Smoke->methodNames[setter->name]); if (!cmp.HasGet) { // so the 'get' method is virtual - generating a property for only the 'set' method is a bad idea MethodsGenerator mg = new MethodsGenerator(data, translator, type, klass); mg.GenerateMethod(setterMethId, setterName + mungedSuffix); continue; } cmp.SetStatements.Add(new CodeExpressionStatement( new CodeMethodInvokeExpression(SmokeSupport.interceptor_Invoke, new CodePrimitiveExpression(setterName + mungedSuffix), new CodePrimitiveExpression( this.data.Smoke->GetMethodSignature(setterMethId)), new CodeTypeOfExpression(typeof(void)), new CodePrimitiveExpression(false), new CodeTypeOfExpression(cmp.Type), new CodeArgumentReferenceExpression("value")))); } type.Members.Add(cmp); } } }
public void Run() { for (short classId = 1; classId <= data.Smoke->numClasses; classId++) { Smoke.Class* klass = data.Smoke->classes + classId; if (klass->external) continue; List<Property> props = new List<Property>(); if (!GetProperties(data.Smoke, classId, (name, originalType, typeName, writable, isEnum) => props.Add(new Property(name, originalType, typeName, writable, isEnum)))) { continue; } CodeTypeDeclaration type = data.SmokeTypeMap[(IntPtr) klass]; string className = ByteArrayManager.GetString(klass->className); foreach (Property prop in props) { CodeMemberProperty cmp = new CodeMemberProperty(); try { bool isRef; short id = data.Smoke->IDType(prop.Type); if (id > 0) { cmp.Type = translator.CppToCSharp(data.Smoke->types + id, out isRef); } else { if (!prop.Type.Contains("::")) { id = data.Smoke->IDType(className + "::" + prop.Type); if (id > 0) { cmp.Type = translator.CppToCSharp(data.Smoke->types + id, out isRef); } else { cmp.Type = translator.CppToCSharp(prop.Type, out isRef); } } cmp.Type = translator.CppToCSharp(prop.Type, out isRef); } } catch (NotSupportedException) { Debug.Print(" |--Won't wrap Property {0}::{1}", className, prop.Name); continue; } if (documentation.ContainsKey(type)) { IList<string> docs = documentation[type]; for (int i = 0; i < docs.Count; i++) { Match match = Regex.Match(docs[i], prop.Name + " : (const )?" + prop.OriginalType + @"\n(?<docs>This.*?)\nAccess functions:", RegexOptions.Singleline); if (match.Success) { Util.FormatComment(match.Groups["docs"].Value, cmp, i > 0); break; } } } cmp.Name = prop.Name; // capitalize the first letter StringBuilder builder = new StringBuilder(cmp.Name); builder[0] = char.ToUpper(builder[0]); string capitalized = builder.ToString(); // If the new name clashes with a name of a type declaration, keep the lower-case name (or even make the name lower-case). var typesWithSameName = from member in data.GetAccessibleMembers(data.Smoke->classes + classId) where (member.Type == MemberTypes.NestedType || member.Type == MemberTypes.Method) && member.Name == capitalized select member; if (typesWithSameName.Any()) { Debug.Print( " |--Conflicting names: property/(type or method): {0} in class {1} - keeping original property name", capitalized, className); if (capitalized == cmp.Name) { builder[0] = char.ToLower(builder[0]); cmp.Name = builder.ToString(); // lower case the property if necessary } } else { cmp.Name = capitalized; } cmp.HasGet = true; cmp.HasSet = prop.IsWritable; cmp.Attributes = MemberAttributes.Public | MemberAttributes.New | MemberAttributes.Final; cmp.CustomAttributes.Add(new CodeAttributeDeclaration("Q_PROPERTY", new CodeAttributeArgument( new CodePrimitiveExpression(prop.OriginalType)), new CodeAttributeArgument( new CodePrimitiveExpression(prop.Name)))); // ===== get-method ===== short getterMapId = FindQPropertyGetAccessorMethodMapId(classId, prop, capitalized); if (getterMapId == 0) { Debug.Print(" |--Missing 'get' method for property {0}::{1} - using QObject.Property()", className, prop.Name); cmp.GetStatements.Add(new CodeMethodReturnStatement(new CodeCastExpression(cmp.Type, new CodeMethodInvokeExpression( new CodeThisReferenceExpression(), "Property", new CodePrimitiveExpression(prop.Name))))); } else { Smoke.MethodMap* map = data.Smoke->methodMaps + getterMapId; short getterId = map->method; if (getterId < 0) { // simply choose the first (i.e. non-const) version if there are alternatives getterId = data.Smoke->ambiguousMethodList[-getterId]; } Smoke.Method* getter = data.Smoke->methods + getterId; if (getter->classId != classId) { // The actual get method is defined in a parent class - don't create a property for it. continue; } if ((getter->flags & (uint) Smoke.MethodFlags.mf_virtual) == 0 && (getter->flags & (uint) Smoke.MethodFlags.mf_purevirtual) == 0) { cmp.GetStatements.Add(new CodeMethodReturnStatement(new CodeCastExpression(cmp.Type, new CodeMethodInvokeExpression( SmokeSupport.interceptor_Invoke, new CodePrimitiveExpression( ByteArrayManager.GetString( data.Smoke->methodNames[getter->name ])), new CodePrimitiveExpression( data.Smoke->GetMethodSignature(getter)), new CodeTypeOfExpression(cmp.Type), new CodePrimitiveExpression(false))))); } else { cmp.HasGet = false; if (!cmp.HasSet) { // the get accessor is virtual and there's no set accessor => continue continue; } } } // ===== set-method ===== if (!prop.IsWritable) { // not writable? => continue type.Members.Add(cmp); continue; } char mungedSuffix; short setterMethId = FindQPropertySetAccessorMethodId(classId, prop, capitalized, out mungedSuffix); if (setterMethId == 0) { Debug.Print(" |--Missing 'set' method for property {0}::{1} - using QObject.SetProperty()", className, prop.Name); cmp.SetStatements.Add(new CodeExpressionStatement( new CodeMethodInvokeExpression(new CodeThisReferenceExpression(), "SetProperty", new CodePrimitiveExpression(prop.Name), new CodeArgumentReferenceExpression("value")))); } else { Smoke.Method* setter = data.Smoke->methods + setterMethId; if (setter->classId != classId) { // defined in parent class, continue type.Members.Add(cmp); continue; } string setterName = ByteArrayManager.GetString(data.Smoke->methodNames[setter->name]); if (!cmp.HasGet) { // so the 'get' method is virtual - generating a property for only the 'set' method is a bad idea MethodsGenerator mg = new MethodsGenerator(data, translator, type, klass); mg.GenerateMethod(setterMethId, setterName + mungedSuffix); continue; } cmp.SetStatements.Add(new CodeExpressionStatement( new CodeMethodInvokeExpression(SmokeSupport.interceptor_Invoke, new CodePrimitiveExpression(setterName + mungedSuffix), new CodePrimitiveExpression( this.data.Smoke->GetMethodSignature(setterMethId)), new CodeTypeOfExpression(typeof(void)), new CodePrimitiveExpression(false), new CodeTypeOfExpression(cmp.Type), new CodeArgumentReferenceExpression("value")))); } type.Members.Add(cmp); } } }
private GenerateResults GetGeneratedMethods(bool hasEvents) => MethodsGenerator.Generate(this.BaseType, this.Namespaces, this.NameGenerator, this.InformationBuilder, this.IsMake, this.HandleRefOutMethod, hasEvents);