Beispiel #1
0
        /// <summary>
        /// Process the specified config file.
        /// </summary>
        /// <param name="file">The file.</param>
        private void ProcessCppModuleWithConfig(CppModule cppModule, ConfigFile file)
        {
            Logger.PushLocation(file.AbsoluteFilePath);
            try
            {
                CsAssembly assembly = null;

                if (!string.IsNullOrEmpty(file.Assembly))
                {
                    assembly = assemblyManager.GetOrCreateAssembly(file.Assembly);
                }

                if (assembly != null)
                {
                    Logger.Message("Process rules for assembly [{0}] and namespace [{1}]", file.Assembly, file.Namespace);
                }

                var elementFinder = new CppElementFinder(cppModule);

                // Only attach includes when there is a bind to an assembly
                if (assembly != null)
                {
                    AttachIncludes(file);

                    ProcessExtensions(elementFinder, file);
                }

                ProcessMappings(elementFinder, file);
            }
            finally
            {
                Logger.PopLocation();
            }
        }
Beispiel #2
0
    public void PointerSizeReturnValueNotLarge()
    {
        var config = new ConfigFile
        {
            Id        = nameof(PointerSizeReturnValueNotLarge),
            Namespace = nameof(PointerSizeReturnValueNotLarge),
            Includes  =
            {
                new IncludeRule
                {
                    File      = "pointerSize.h",
                    Attach    = true,
                    Namespace = nameof(PointerSizeReturnValueNotLarge)
                }
            },
            Extension =
            {
                new DefineExtensionRule
                {
                    Struct            = "SharpGen.Runtime.PointerSize",
                    SizeOf            = 8,
                    IsNativePrimitive = true,
                }
            },
            Bindings =
            {
                new BindRule("int", "SharpGen.Runtime.PointerSize")
            }
        };

        var iface = new CppInterface("Interface");

        iface.Add(new CppMethod("method")
        {
            ReturnValue = new CppReturnValue
            {
                TypeName = "int"
            }
        });

        var include = new CppInclude("pointerSize");

        include.Add(iface);

        var module = new CppModule("SharpGenTestModule");

        module.Add(include);

        var(solution, _) = MapModel(module, config);

        Assert.Single(solution.EnumerateDescendants <CsInterface>());

        var csIface = solution.EnumerateDescendants <CsInterface>().First();

        Assert.Single(csIface.Methods);

        var method = csIface.Methods.First();

        Assert.False(method.IsReturnStructLarge);
    }
Beispiel #3
0
        public void SequentialOffsets()
        {
            var config = new Config.ConfigFile
            {
                Id        = nameof(SequentialOffsets),
                Namespace = nameof(SequentialOffsets),
                Includes  =
                {
                    new Config.IncludeRule
                    {
                        File      = "simple.h",
                        Attach    = true,
                        Namespace = nameof(SequentialOffsets)
                    }
                },
                Bindings =
                {
                    new Config.BindRule("int", "System.Int32")
                }
            };

            var cppStruct = new CppStruct
            {
                Name = "struct"
            };

            cppStruct.Add(new CppField
            {
                Name     = "field",
                TypeName = "int"
            });

            cppStruct.Add(new CppField
            {
                Name     = "field2",
                TypeName = "int",
                Offset   = 1
            });

            var cppInclude = new CppInclude
            {
                Name = "simple"
            };

            var cppModule = new CppModule();

            cppModule.Add(cppInclude);
            cppInclude.Add(cppStruct);

            var(solution, _) = MapModel(cppModule, config);

            var csStruct = solution.EnumerateDescendants().OfType <CsStruct>().First();

            var field  = csStruct.Fields.First(fld => fld.Name == "Field");
            var field2 = csStruct.Fields.First(fld => fld.Name == "Field2");

            Assert.Equal(0, field.Offset);

            Assert.Equal(4, field2.Offset);
        }
Beispiel #4
0
        private CppModule ParseCpp(CastXml castXml, CppModule group)
        {
            // Run the parser
            var parser = new CppParser(Logger, castXml)
            {
                OutputPath = IntermediateOutputPath
            };

            parser.Initialize(Config);

            if (Logger.HasErrors)
            {
                Logger.Fatal("Initializing parser failed");
            }

            // Run the parser
            group = parser.Run(group);

            if (Logger.HasErrors)
            {
                Logger.Fatal("Parsing C++ failed.");
            }
            else
            {
                Logger.Message("Parsing C++ finished");
            }

            // Print statistics
            PrintStatistics(parser);

            return(group);
        }
Beispiel #5
0
        /// <summary>
        /// Prepares a transformer from C++ to C# model.
        /// </summary>
        /// <typeparam name="TCppElement">The C++ type of data to process</typeparam>
        /// <param name="transform">The transform.</param>
        /// <param name="typeToProcess">The type to process.</param>
        private IEnumerable <TCsElement> PrepareTransform <TCppElement, TCsElement>(CppModule cppModule, ITransformPreparer <TCppElement, TCsElement> transform)
            where TCppElement : CppElement
            where TCsElement : CsBase
        {
            var csElements = new List <TCsElement>();

            // Predefine all structs, typedefs and interfaces
            foreach (var cppInclude in cppModule.Includes)
            {
                foreach (var cppItem in cppInclude.Iterate <TCppElement>())
                {
                    Logger.RunInContext(
                        cppItem.ToString(),
                        () =>
                    {
                        // If already mapped, it means that there is already a predefined mapping
                        if (typeRegistry.FindBoundType(cppItem.Name) == null)
                        {
                            var csElement = transform.Prepare(cppItem);
                            if (csElement != null)
                            {
                                csElements.Add(csElement);
                            }
                        }
                    });
                }
            }
            return(csElements);
        }
Beispiel #6
0
    public void ShortNameRuleReplacesAcronym()
    {
        var config = new ConfigFile
        {
            Id        = nameof(ShortNameRuleReplacesAcronym),
            Namespace = nameof(ShortNameRuleReplacesAcronym),
            Includes  =
            {
                new IncludeRule
                {
                    File      = "simpleStruct.h",
                    Attach    = true,
                    Namespace = nameof(ShortNameRuleReplacesAcronym)
                }
            },
            Naming =
            {
                new NamingRuleShort("DESC", "Description")
            }
        };


        var cppStruct = new CppStruct("TEST_DESC");

        var include = new CppInclude("simpleStruct");

        include.Add(cppStruct);
        var module = new CppModule("SharpGenTestModule");

        module.Add(include);

        var(solution, _) = MapModel(module, config);

        Assert.Single(solution.EnumerateDescendants <CsStruct>().Where(element => element.Name == "TestDescription"));
    }
Beispiel #7
0
        /// <summary>
        /// Run CodeGenerator
        /// </summary>
        public void Run()
        {
            log.Info("Starting code generation...");

            // Initialize the parser
            CppParser parser = new CppParser(CastXmlExecutablePath, VcToolsPath);

            parser.ForceParsing = configHasChanged || forceParsing;
            parser.Initialize(config);

            // Run the parser
            CppModule mainModule = parser.Run();

            // Run the code generation process
            NodeJSGenerator generator = new NodeJSGenerator(config, new DriverOptions(), mainModule);

            // Setup rules and process code
            generator.SetupPasses();
            generator.ProcessCode();

            // Generate wrapper code
            List <GeneratorOutput> outputs = generator.GenerateCode();

            SaveCode(outputs);
        }
Beispiel #8
0
        /// <summary>
        /// Initializes this instance with the specified C++ module and config.
        /// </summary>
        /// <param name="cppModule">The C++ module.</param>
        /// <param name="config">The root config file.</param>
        /// <returns>The module to transform after mapping rules have been applied.</returns>
        private CppModule MapModule(CppModule cppModule, IEnumerable <ConfigFile> configFiles)
        {
            var numberOfConfigFilesToParse = configFiles.Count();

            var indexFile = 0;

            // Process each config file

            foreach (var configFile in configFiles)
            {
                Logger.Progress(30 + (indexFile * 30) / numberOfConfigFilesToParse, "Processing mapping rules [{0}]", configFile.Assembly ?? configFile.Id);
                ProcessCppModuleWithConfig(cppModule, configFile);
                indexFile++;
            }

            // Strip out includes we aren't processing from transformation

            var moduleToTransform = new CppModule
            {
                Name = cppModule.Name
            };

            foreach (var include in cppModule.Includes.Where(cppInclude => _includesToProcess.Contains(cppInclude.Name)).ToArray())
            {
                moduleToTransform.Add(include);
            }

            return(moduleToTransform);
        }
Beispiel #9
0
        /// <summary>
        /// Apply documentation from an external provider. This is optional.
        /// </summary>
        /// <param name="cache">The cache of doc items.</param>
        /// <param name="group">The module to document.</param>
        private Task <CppModule> ApplyDocumentation(DocItemCache cache, CppModule group)
        {
            IDocProvider docProvider = null;

            // Try to load doc provider from an external assembly
            if (DocProviderAssemblyPath != null)
            {
                try
                {
                    var assembly = Assembly.LoadFrom(DocProviderAssemblyPath);

                    foreach (var type in assembly.GetTypes())
                    {
                        if (typeof(IDocProvider).GetTypeInfo().IsAssignableFrom(type))
                        {
                            docProvider = (IDocProvider)Activator.CreateInstance(type);
                            break;
                        }
                    }
                }
                catch (Exception)
                {
                    Logger.Warning(null, "Warning, Unable to locate/load DocProvider Assembly.");
                    Logger.Warning(null, "Warning, DocProvider was not found from assembly [{0}]", DocProviderAssemblyPath);
                }
            }

            if (docProvider == null)
            {
                return(Task.FromResult(group));
            }

            Logger.Progress(20, "Applying C++ documentation");
            return(docProvider.ApplyDocumentation(cache, group));
        }
Beispiel #10
0
        public void Simple()
        {
            var config = new Config.ConfigFile
            {
                Id        = nameof(Simple),
                Namespace = nameof(Simple),
                Assembly  = nameof(Simple),
                Includes  =
                {
                    new Config.IncludeRule
                    {
                        File      = "simple.h",
                        Attach    = true,
                        Namespace = nameof(Simple)
                    }
                },
                Bindings =
                {
                    new Config.BindRule("int", "System.Int32")
                }
            };

            var cppStruct = new CppStruct
            {
                Name = "struct"
            };

            cppStruct.Add(new CppField
            {
                Name     = "field",
                TypeName = "int"
            });

            var cppInclude = new CppInclude
            {
                Name = "simple"
            };

            var cppModule = new CppModule();

            cppModule.Add(cppInclude);
            cppInclude.Add(cppStruct);

            var(solution, _) = MapModel(cppModule, config);

            Assert.Single(solution.EnumerateDescendants().OfType <CsStruct>());

            var csStruct = solution.EnumerateDescendants().OfType <CsStruct>().First();

            Assert.Single(csStruct.Fields.Where(fld => fld.Name == "Field"));

            var field = csStruct.Fields.First(fld => fld.Name == "Field");

            Assert.IsType <CsFundamentalType>(field.PublicType);

            var fundamental = (CsFundamentalType)field.PublicType;

            Assert.Equal(typeof(int), fundamental.Type);
        }
Beispiel #11
0
        public ASTConverter(BindingContext bindingContext, ConfigMapping configurationContext, CppModule moduleContext)
        {
            this.configurationContext = configurationContext;
            this.bindingContext       = bindingContext;
            this.moduleContext        = moduleContext;

            cppElementToDeclarationMapping = new Dictionary <CppElement, Declaration>();
        }
Beispiel #12
0
        public void Simple()
        {
            var config = new ConfigFile
            {
                Id        = nameof(Simple),
                Namespace = nameof(Simple),
                Includes  =
                {
                    new IncludeRule
                    {
                        File      = "interface.h",
                        Attach    = true,
                        Namespace = nameof(Simple)
                    }
                },
                Bindings =
                {
                    new BindRule("int", "System.Int32")
                }
            };

            var iface = new CppInterface("Interface")
            {
                TotalMethodCount = 1
            };

            iface.Add(new CppMethod("method")
            {
                ReturnValue = new CppReturnValue
                {
                    TypeName = "int"
                }
            });

            var include = new CppInclude("interface");

            include.Add(iface);

            var module = new CppModule("SharpGenTestModule");

            module.Add(include);

            var(solution, _) = MapModel(module, config);

            Assert.Single(solution.EnumerateDescendants().OfType <CsInterface>());

            var csIface = solution.EnumerateDescendants().OfType <CsInterface>().First();

            Assert.Single(csIface.Methods);

            var method = csIface.Methods.First();

            Assert.Equal(0, method.Offset);

            Assert.IsType <CsFundamentalType>(method.ReturnValue.PublicType);

            Assert.Equal(TypeRegistry.Int32, method.ReturnValue.PublicType);
        }
Beispiel #13
0
        public void IntFieldMappedToBoolIsMarkedAsBoolToInt()
        {
            var structName = "BoolToInt";
            var config     = new ConfigFile
            {
                Id        = nameof(IntFieldMappedToBoolIsMarkedAsBoolToInt),
                Namespace = nameof(IntFieldMappedToBoolIsMarkedAsBoolToInt),
                Includes  =
                {
                    new IncludeRule
                    {
                        File      = "test.h",
                        Attach    = true,
                        Namespace = nameof(IntFieldMappedToBoolIsMarkedAsBoolToInt)
                    }
                },
                Bindings =
                {
                    new BindRule("int",  "System.Int32"),
                    new BindRule("bool", "System.Boolean")
                },
                Mappings =
                {
                    new MappingRule
                    {
                        Field       = $"{structName}::field",
                        MappingType = "bool",
                    },
                }
            };

            var structure = new CppStruct(structName);

            structure.Add(new CppField("field")
            {
                TypeName = "int"
            });

            var include = new CppInclude("test");

            include.Add(structure);

            var module = new CppModule("SharpGenTestModule");

            module.Add(include);

            var(solution, _) = MapModel(module, config);

            Assert.Single(solution.EnumerateDescendants().OfType <CsStruct>().Where(csStruct => csStruct.Name == structName));

            var generatedStruct = solution.EnumerateDescendants().OfType <CsStruct>().First(csStruct => csStruct.Name == structName);

            Assert.Single(generatedStruct.Fields);

            var field = generatedStruct.Fields.First();

            Assert.True(field.IsBoolToInt);
        }
Beispiel #14
0
        public void InheritingStructs()
        {
            var config = new ConfigFile
            {
                Id        = nameof(InheritingStructs),
                Namespace = nameof(InheritingStructs),
                Includes  =
                {
                    new IncludeRule
                    {
                        File      = "struct.h",
                        Attach    = true,
                        Namespace = nameof(SequentialOffsets)
                    }
                },
                Bindings =
                {
                    new BindRule("int", "System.Int32")
                }
            };

            var baseStruct = new CppStruct("base");

            baseStruct.Add(new CppField("field")
            {
                TypeName = "int"
            });

            var inheritingStruct = new CppStruct("inheriting")
            {
                Base = "base"
            };

            inheritingStruct.Add(new CppField("field2")
            {
                TypeName = "int",
                Offset   = 1
            });

            var cppInclude = new CppInclude("struct");

            var cppModule = new CppModule("SharpGenTestModule");

            cppModule.Add(cppInclude);
            cppInclude.Add(baseStruct);
            cppInclude.Add(inheritingStruct);

            var(solution, _) = MapModel(cppModule, config);

            var csStruct = solution.EnumerateDescendants().OfType <CsStruct>().First(@struct => @struct.Name == "Inheriting");

            var field  = csStruct.Fields.First(fld => fld.Name == "Field");
            var field2 = csStruct.Fields.First(fld => fld.Name == "Field2");

            Assert.Equal(0u, field.Offset);

            Assert.Equal(4u, field2.Offset);
        }
Beispiel #15
0
        public void MappingNameRuleRenamesStructMember()
        {
            var config = new Config.ConfigFile
            {
                Id        = nameof(MappingNameRuleRenamesStructMember),
                Namespace = nameof(MappingNameRuleRenamesStructMember),
                Assembly  = nameof(MappingNameRuleRenamesStructMember),
                Includes  =
                {
                    new Config.IncludeRule
                    {
                        File      = "simpleStruct.h",
                        Attach    = true,
                        Namespace = nameof(MappingNameRuleRenamesStructMember)
                    }
                },
                Bindings =
                {
                    new Config.BindRule("int", "System.Int32")
                },
                Mappings =
                {
                    new Config.MappingRule
                    {
                        Field       = "Test::field",
                        MappingName = "MyField"
                    }
                }
            };

            var cppStruct = new CppStruct
            {
                Name = "Test"
            };

            cppStruct.Add(new CppField
            {
                Name     = "field",
                TypeName = "int"
            });

            var include = new CppInclude
            {
                Name = "simpleStruct"
            };

            include.Add(cppStruct);
            var module = new CppModule();

            module.Add(include);

            var(solution, _) = MapModel(module, config);

            var csStruct = solution.EnumerateDescendants().OfType <CsStruct>().First(element => element.Name == "Test");

            Assert.Single(csStruct.Fields.Where(field => field.Name == "MyField"));
        }
Beispiel #16
0
        public void RemoveParentDoesNotRemoveAllParents()
        {
            var config = new Config.ConfigFile
            {
                Id        = nameof(RemoveParentDoesNotRemoveAllParents),
                Assembly  = nameof(RemoveParentDoesNotRemoveAllParents),
                Namespace = nameof(RemoveParentDoesNotRemoveAllParents),
                Includes  =
                {
                    new Config.IncludeRule
                    {
                        Attach    = true,
                        File      = "cppEnum.h",
                        Namespace = nameof(RemoveParentDoesNotRemoveAllParents)
                    }
                },
                Mappings =
                {
                    new Config.RemoveRule
                    {
                        Method = @"#.*ToRemove"
                    }
                }
            };

            var cppModel = new CppModule();

            var cppInclude = new CppInclude
            {
                Name = "cppEnum"
            };

            var cppIface = new CppInterface
            {
                Name = "TestInterface"
            };

            cppInclude.Add(cppIface);

            var cppMethod = new CppMethod
            {
                Name = "Method"
            };

            cppMethod.Add(new CppParameter
            {
                Name = "ParamToRemove"
            });
            cppModel.Add(cppInclude);

            var(solution, _) = MapModel(cppModel, config);

            var members = solution.EnumerateDescendants();

            Assert.NotEmpty(members.OfType <CsInterface>());
            Assert.Empty(members.OfType <CsParameter>());
        }
Beispiel #17
0
        public void DualCallbackFlowsNativeImplementation()
        {
            var config = new ConfigFile
            {
                Id        = nameof(Simple),
                Namespace = nameof(Simple),
                Includes  =
                {
                    new IncludeRule
                    {
                        File      = "interface.h",
                        Attach    = true,
                        Namespace = nameof(Simple)
                    }
                },
                Bindings =
                {
                    new BindRule("int", "System.Int32")
                },
                Mappings =
                {
                    new MappingRule
                    {
                        Interface               = "Interface",
                        IsCallbackInterface     = true,
                        IsDualCallbackInterface = true
                    }
                }
            };

            var iface = new CppInterface("Interface")
            {
                TotalMethodCount = 1
            };

            iface.Add(new CppMethod("method")
            {
                ReturnValue = new CppReturnValue
                {
                    TypeName = "int"
                }
            });

            var include = new CppInclude("interface");

            include.Add(iface);

            var module = new CppModule("SharpGenTestModule");

            module.Add(include);

            var(_, defines) = GetConsumerBindings(module, config);

            var interfaceDefine = defines.First(define => define.Interface == "Simple.Interface");

            Assert.Equal("Simple.InterfaceNative", interfaceDefine.NativeImplementation);
        }
Beispiel #18
0
        public void UnionsWithPointersGeneratesStructure()
        {
            var config = new ConfigFile
            {
                Id        = nameof(UnionsWithPointersGeneratesStructure),
                Namespace = nameof(UnionsWithPointersGeneratesStructure),
                Includes  =
                {
                    new IncludeRule
                    {
                        File      = "test.h",
                        Attach    = true,
                        Namespace = nameof(UnionsWithPointersGeneratesStructure)
                    }
                },
                Bindings =
                {
                    new BindRule("int", "System.Int32")
                }
            };


            var structure = new CppStruct("Test")
            {
                IsUnion = true
            };

            structure.Add(new CppField("pointer")
            {
                TypeName = "int",
                Pointer  = "*"
            });

            structure.Add(new CppField("scalar")
            {
                TypeName = "int"
            });

            var include = new CppInclude("test");

            include.Add(structure);

            var module = new CppModule("SharpGenTestModule");

            module.Add(include);

            var(solution, _) = MapModel(module, config);

            var csStruct = solution.EnumerateDescendants().OfType <CsStruct>().First();

            foreach (var field in csStruct.Fields)
            {
                Assert.Equal(0u, field.Offset);
            }

            Assert.False(Logger.HasErrors);
        }
Beispiel #19
0
        public void ContextRuleLimitsWhereMappingRuleExecutes()
        {
            var config = new ConfigFile
            {
                Id        = nameof(ContextRuleLimitsWhereMappingRuleExecutes),
                Namespace = nameof(ContextRuleLimitsWhereMappingRuleExecutes),
                Includes  =
                {
                    new IncludeRule
                    {
                        Attach    = true,
                        File      = "cppEnum.h",
                        Namespace = nameof(ContextRuleLimitsWhereMappingRuleExecutes)
                    },
                    new IncludeRule
                    {
                        Attach    = true,
                        File      = "secondFile.h",
                        Namespace = nameof(ContextRuleLimitsWhereMappingRuleExecutes)
                    }
                },
                Mappings =
                {
                    new Config.ContextRule("cppEnum"),
                    new MappingRule
                    {
                        Enum             = "AnotherEnum",
                        MappingNameFinal = "NewEnum"
                    },
                    new ClearContextRule()
                }
            };

            var cppModel = new CppModule("SharpGenTestModule");

            var cppInclude = new CppInclude("cppEnum");

            var cppEnum = new CppEnum("TestEnum");

            var secondInclude = new CppInclude("secondFile");

            var cppEnum2 = new CppEnum("AnotherEnum");

            cppEnum.AddEnumItem("Element1", "0");
            cppEnum.AddEnumItem("Element2", "1");
            cppInclude.Add(cppEnum);
            cppModel.Add(cppInclude);


            var(solution, _) = MapModel(cppModel, config);

            Assert.Empty(solution.EnumerateDescendants().OfType <CsEnum>().Where(csEnum => csEnum.Name == "AnotherEnum"));
        }
Beispiel #20
0
        /// <summary>
        /// Runs this instance.
        /// </summary>
        /// <returns></returns>
        public CppModule Run(CppModule groupSkeleton, string[] additionalCompilationArguments)
        {
            _group = groupSkeleton;
            Logger.Message("Config files changed.");

            const string progressMessage = "Parsing C++ headers starts, please wait...";

            StreamReader xmlReader = null;

            try
            {
                Logger.Progress(15, progressMessage);

                var configRootHeader = Path.Combine(OutputPath, _configRoot.Id + ".h");

                xmlReader = _gccxml.Process(configRootHeader, additionalCompilationArguments);
                if (xmlReader != null)
                {
                    Parse(xmlReader);
                }

                Logger.Progress(30, progressMessage);
            }
            catch (Exception ex)
            {
                Logger.Error(null, "Unexpected error", ex);
            }
            finally
            {
                xmlReader?.Dispose();

                // Write back GCCXML document on the disk
                using (var stream = File.OpenWrite(Path.Combine(OutputPath, GccXmlFileName)))
                {
                    GccXmlDoc?.Save(stream);
                }
                Logger.Message("Parsing headers is finished.");
            }


            // Track number of included macros for statistics
            foreach (var cppInclude in _group.Includes)
            {
                IncludeMacroCounts.TryGetValue(cppInclude.Name, out int count);
                foreach (var cppDefine in cppInclude.Macros)
                {
                    count++;
                }
                IncludeMacroCounts[cppInclude.Name] = count;
            }

            return(_group);
        }
        public BindingContext(ConfigMapping configurationContext, DriverOptions driverOptions, CppModule moduleContext)
            : base(driverOptions)
        {
            ConfigurationContext = configurationContext;
            ParserContext        = moduleContext;
            Options = driverOptions;

            FoundEnums = new SortedList();
            ASTConverter converter = new ASTConverter(this, configurationContext, moduleContext);

            ASTContext = converter.Convert();
        }
Beispiel #22
0
    public static void ExpandDynamicVariables(this ConfigFile config, Logger logger, CppModule module)
    {
        // Load all defines and store them in the config file to allow dynamic variable substitution
        foreach (var cppInclude in module.Includes)
        {
            foreach (var cppDefine in cppInclude.Macros)
            {
                config.DynamicVariables[cppDefine.Name] = cppDefine.Value;
            }
        }

        // Expand all variables with all dynamic variables
        config.ExpandVariables(true, logger);
    }
Beispiel #23
0
        public void Enum()
        {
            var config = new Config.ConfigFile
            {
                Id        = nameof(Enum),
                Assembly  = nameof(Enum),
                Namespace = nameof(Enum),
                Includes  =
                {
                    new Config.IncludeRule
                    {
                        Attach    = true,
                        File      = "cppEnum.h",
                        Namespace = nameof(Enum)
                    }
                },
                Mappings =
                {
                    new Config.RemoveRule
                    {
                        Enum = @".*ToRemove\d+"
                    }
                }
            };

            var cppModel = new CppModule();

            var cppInclude = new CppInclude
            {
                Name = "cppEnum"
            };

            var cppEnum = new CppEnum
            {
                Name = "TestEnum"
            };

            cppInclude.Add(cppEnum);
            cppInclude.Add(new CppEnum
            {
                Name = "EnumToRemove1"
            });
            cppModel.Add(cppInclude);

            var(solution, _) = MapModel(cppModel, config);

            var members = solution.EnumerateDescendants();

            Assert.Single(members.OfType <CsEnum>());
        }
Beispiel #24
0
        public void ExplicitValues()
        {
            var config = new Config.ConfigFile
            {
                Id        = nameof(ExplicitValues),
                Assembly  = nameof(ExplicitValues),
                Namespace = nameof(ExplicitValues),
                Includes  =
                {
                    new Config.IncludeRule
                    {
                        Attach    = true,
                        File      = "cppEnum.h",
                        Namespace = nameof(ExplicitValues)
                    }
                }
            };

            var cppModel = new CppModule();

            var cppInclude = new CppInclude
            {
                Name = "cppEnum"
            };

            var cppEnum = new CppEnum
            {
                Name = "TestEnum"
            };

            cppEnum.AddEnumItem("Element1", "10");
            cppEnum.AddEnumItem("Element2", "15");
            cppEnum.AddEnumItem("Element3", "10");
            cppInclude.Add(cppEnum);
            cppModel.Add(cppInclude);

            var(solution, _) = MapModel(cppModel, config);

            var members = solution.EnumerateDescendants();

            Assert.Single(members.OfType <CsEnum>());

            var csEnum = members.OfType <CsEnum>().First();

            Assert.Single(csEnum.EnumItems.Where(item => item.Name == "Element1" && item.Value == "10"));
            Assert.Single(csEnum.EnumItems.Where(item => item.Name == "Element2" && item.Value == "15"));
            Assert.Single(csEnum.EnumItems.Where(item => item.Name == "Element3" && item.Value == "10"));
            Assert.Equal(typeof(int), csEnum.UnderlyingType.Type);
        }
Beispiel #25
0
        private (IDocumentationLinker doc, CsSolution solution) ExecuteMappings(CppModule group, ConfigFile consumerConfig)
        {
            var docLinker       = new DocumentationLinker();
            var typeRegistry    = new TypeRegistry(Logger, docLinker);
            var namingRules     = new NamingRulesManager();
            var assemblyManager = new AssemblyManager();

            // Run the main mapping process
            var transformer = new TransformManager(
                GlobalNamespace,
                namingRules,
                Logger,
                typeRegistry,
                docLinker,
                new ConstantManager(namingRules, docLinker),
                assemblyManager)
            {
                ForceGenerator = _isAssemblyNew
            };

            var(solution, defines) = transformer.Transform(group, Config, IntermediateOutputPath);

            consumerConfig.Extension = new List <ExtensionBaseRule>(defines);

            var(bindings, generatedDefines) = transformer.GenerateTypeBindingsForConsumers();

            consumerConfig.Bindings.AddRange(bindings);
            consumerConfig.Extension.AddRange(generatedDefines);
            consumerConfig.Mappings.AddRange(
                docLinker.GetAllDocLinks().Select(
                    link => new MappingRule
            {
                DocItem          = link.cppName,
                MappingNameFinal = link.cSharpName
            }));


            if (Logger.HasErrors)
            {
                Logger.Fatal("Executing mapping rules failed");
            }

            PrintStatistics(assemblyManager);

            DumpRenames(transformer);

            return(docLinker, solution);
        }
Beispiel #26
0
        public void Simple()
        {
            var config = new ConfigFile
            {
                Id        = nameof(Simple),
                Namespace = nameof(Simple),
                Includes  =
                {
                    new IncludeRule
                    {
                        File      = "simple.h",
                        Attach    = true,
                        Namespace = nameof(Simple)
                    }
                },
                Bindings =
                {
                    new BindRule("int", "System.Int32")
                }
            };

            var cppStruct = new CppStruct("struct");

            cppStruct.Add(new CppField("field")
            {
                TypeName = "int"
            });

            var cppInclude = new CppInclude("simple");

            var cppModule = new CppModule("SharpGenTestModule");

            cppModule.Add(cppInclude);
            cppInclude.Add(cppStruct);

            var(solution, _) = MapModel(cppModule, config);

            Assert.Single(solution.EnumerateDescendants().OfType <CsStruct>());

            var csStruct = solution.EnumerateDescendants().OfType <CsStruct>().First();

            Assert.Single(csStruct.Fields.Where(fld => fld.Name == "Field"));

            var field = csStruct.Fields.First(fld => fld.Name == "Field");

            Assert.IsType <CsFundamentalType>(field.PublicType);
            Assert.Equal(TypeRegistry.Int32, field.PublicType);
        }
Beispiel #27
0
    public void MappingNameRuleRenamesStruct()
    {
        var config = new ConfigFile
        {
            Id        = nameof(MappingNameRuleRenamesStruct),
            Namespace = nameof(MappingNameRuleRenamesStruct),
            Includes  =
            {
                new IncludeRule
                {
                    File      = "simpleStruct.h",
                    Attach    = true,
                    Namespace = nameof(MappingNameRuleRenamesStruct)
                }
            },
            Bindings =
            {
                new BindRule("int", "System.Int32")
            },
            Mappings =
            {
                new MappingRule
                {
                    Struct      = "Test",
                    MappingName = "MyStruct"
                }
            }
        };

        var cppStruct = new CppStruct("Test");

        cppStruct.Add(new CppField("field")
        {
            TypeName = "int"
        });

        var include = new CppInclude("simpleStruct");

        include.Add(cppStruct);
        var module = new CppModule("SharpGenTestModule");

        module.Add(include);

        var(solution, _) = MapModel(module, config);

        Assert.Single(solution.EnumerateDescendants <CsStruct>().Where(element => element.Name == "MyStruct"));
    }
Beispiel #28
0
        /// <summary>
        /// Runs this instance.
        /// </summary>
        /// <returns></returns>
        public CppModule Run()
        {
            // If config is updated, we need to run the
            if (masterConfigHasChanged)
            {
                log.Info("Config files changed.");


                StreamReader xmlReader = null;
                try
                {
                    xmlReader = castXML.Process(masterHeaderFile);
                    if (xmlReader != null)
                    {
                        Parse(xmlReader);
                    }

                    // Save back the C++ parsed includes
                    masterCppModule.Write(MasterModuleFileName);
                }
                catch (Exception ex)
                {
                    log.Error("Unexpected error", ex);
                }
                finally
                {
                    if (xmlReader != null)
                    {
                        xmlReader.Close();
                    }

                    // Write back GCCXML document on the disk
                    if (CastXmlDoc != null)
                    {
                        CastXmlDoc.Save(CastXmlFileName);
                    }

                    log.Info("Parsing headers is finished.");
                }
            }
            else
            {
                masterCppModule = CppModule.Read(MasterModuleFileName);
            }

            return(masterCppModule);
        }
Beispiel #29
0
    public static CppModule CreateSkeletonModule(this ConfigFile config)
    {
        var module = new CppModule(config.Id);

        foreach (var includeRule in config.ConfigFilesLoaded.SelectMany(cfg => cfg.Includes))
        {
            var cppInclude = module.FindInclude(includeRule.Id);
            if (cppInclude != null)
            {
                continue;
            }

            module.Add(new CppInclude(includeRule.Id));
        }

        return(module);
    }
Beispiel #30
0
        /// <summary>
        /// Runs this instance.
        /// </summary>
        /// <returns></returns>
        public CppModule Run(CppModule groupSkeleton, StreamReader xmlReader)
        {
            _group = groupSkeleton;
            Logger.Message("Config files changed.");

            const string progressMessage = "Parsing C++ headers starts, please wait...";

            try
            {
                Logger.Progress(15, progressMessage);

                if (xmlReader != null)
                {
                    Parse(xmlReader);
                }

                Logger.Progress(30, progressMessage);
            }
            catch (Exception ex)
            {
                Logger.Error(null, "Unexpected error", ex);
            }
            finally
            {
                // Write back GCCXML document on the disk
                using (var stream = File.OpenWrite(GccXmlFileName))
                {
                    GccXmlDoc?.Save(stream);
                }

                Logger.Message("Parsing headers is finished.");
            }


            // Track number of included macros for statistics
            foreach (var cppInclude in _group.Includes)
            {
                IncludeMacroCounts.TryGetValue(cppInclude.Name, out var count);
                count += cppInclude.Macros.Count();
                IncludeMacroCounts[cppInclude.Name] = count;
            }

            return(_group);
        }