Example #1
0
        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);
        }
Example #2
0
    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();
        }
    }
Example #3
0
    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);
        }
    }
Example #4
0
        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);
        }
Example #5
0
    /*
     * 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();
    }
Example #6
0
    /*
     * 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();
    }
Example #7
0
    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();
        }
    }
Example #8
0
    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);
            }
        }
    }
Example #10
0
    /*
     * 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();
    }
Example #11
0
    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);
            }
        }
    }
Example #12
0
    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);
            }
        }
    }
Example #13
0
    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);
            }
        }
    }
Example #14
0
 private GenerateResults GetGeneratedMethods(bool hasEvents) =>
 MethodsGenerator.Generate(this.BaseType,
                           this.Namespaces, this.NameGenerator, this.InformationBuilder,
                           this.IsMake, this.HandleRefOutMethod, hasEvents);