예제 #1
0
        protected CppModule ParseCpp(ConfigFile config)
        {
            var loaded = ConfigFile.Load(config, new string[0], Logger);

            loaded.GetFilesWithIncludesAndExtensionHeaders(out var configsWithIncludes,
                                                           out var configsWithExtensionHeaders);

            var cppHeaderGenerator = new CppHeaderGenerator(Logger, TestDirectory.FullName);

            var updated = cppHeaderGenerator
                          .GenerateCppHeaders(loaded, configsWithIncludes, configsWithExtensionHeaders)
                          .UpdatedConfigs;

            var castXml = GetCastXml(loaded);

            var macro = new MacroManager(castXml);
            var extensionGenerator = new CppExtensionHeaderGenerator();

            var skeleton = loaded.CreateSkeletonModule();

            macro.Parse(Path.Combine(TestDirectory.FullName, loaded.HeaderFileName), skeleton);

            extensionGenerator.GenerateExtensionHeaders(
                loaded, TestDirectory.FullName, skeleton, configsWithExtensionHeaders, updated
                );

            var parser = new CppParser(Logger, loaded)
            {
                OutputPath = TestDirectory.FullName
            };

            using var xmlReader = castXml.Process(parser.RootConfigHeaderFileName);

            return(parser.Run(skeleton, xmlReader));
        }
예제 #2
0
        protected CppModule ParseCpp(ConfigFile config, string[] additionalArguments = null)
        {
            var loaded = ConfigFile.Load(config, new string[0], Logger);

            loaded.GetFilesWithIncludesAndExtensionHeaders(out var configsWithIncludes,
                                                           out var filesWithExtensionHeaders);

            var cppHeaderGenerator = new CppHeaderGenerator(Logger, TestDirectory.FullName);

            var updated = cppHeaderGenerator.GenerateCppHeaders(loaded, configsWithIncludes, filesWithExtensionHeaders)
                          .UpdatedConfigs;

            var castXml = GetCastXml(loaded, additionalArguments);

            var extensionGenerator = new CppExtensionHeaderGenerator(new MacroManager(castXml));

            var skeleton = extensionGenerator.GenerateExtensionHeaders(loaded, TestDirectory.FullName, filesWithExtensionHeaders, updated);

            var parser = new CppParser(Logger, loaded)
            {
                OutputPath = TestDirectory.FullName
            };

            using var xmlReader = castXml.Process(parser.RootConfigHeaderFileName);

            return(parser.Run(skeleton, xmlReader));
        }
예제 #3
0
        protected CppModule ParseCpp(ConfigFile config, string[] additionalArguments = null)
        {
            var loaded = ConfigFile.Load(config, new string[0], Logger);

            var(filesWithIncludes, filesWithExtensionHeaders) = loaded.GetFilesWithIncludesAndExtensionHeaders();

            var configsWithIncludes = new HashSet <ConfigFile>();

            foreach (var cfg in loaded.ConfigFilesLoaded)
            {
                if (filesWithIncludes.Contains(cfg.Id))
                {
                    configsWithIncludes.Add(cfg);
                }
            }

            var cppHeaderGenerator = new CppHeaderGenerator(Logger, true, TestDirectory.FullName);

            var(updated, _) = cppHeaderGenerator.GenerateCppHeaders(loaded, configsWithIncludes, filesWithExtensionHeaders);

            var castXml = GetCastXml(loaded);

            var extensionGenerator = new CppExtensionHeaderGenerator(new MacroManager(castXml));

            var skeleton = extensionGenerator.GenerateExtensionHeaders(loaded, TestDirectory.FullName, filesWithExtensionHeaders, updated);

            var parser = new CppParser(Logger, castXml)
            {
                OutputPath = TestDirectory.FullName
            };

            parser.Initialize(loaded);

            return(parser.Run(skeleton));
        }
예제 #4
0
        private HashSet <ConfigFile> GenerateHeaders(IReadOnlyCollection <ConfigFile> configsWithIncludes, ConfigFile consumerConfig)
        {
            var headerGenerator = new CppHeaderGenerator(Logger, true, IntermediateOutputPath);

            var(cppHeadersUpdated, prolog) = headerGenerator.GenerateCppHeaders(Config, configsWithIncludes);

            consumerConfig.IncludeProlog.Add(prolog);
            return(cppHeadersUpdated);
        }
예제 #5
0
        protected override bool Execute(ConfigFile config)
        {
            var cppHeaderGenerator = new CppHeaderGenerator(
                SharpGenLogger,
                ForceParsing,
                OutputPath);

            var configsWithHeaders = new HashSet <ConfigFile>();

            foreach (var cfg in config.ConfigFilesLoaded)
            {
                if (HeaderFiles.Any(item => item.GetMetadata("ConfigId") == cfg.Id))
                {
                    configsWithHeaders.Add(cfg);
                }
            }

            var configsWithExtensions = new HashSet <string>();

            foreach (var file in ExtensionHeaders)
            {
                configsWithExtensions.Add(file.GetMetadata("ConfigId"));
            }

            var(updatedConfigs, prolog) = cppHeaderGenerator.GenerateCppHeaders(config, configsWithHeaders, configsWithExtensions);

            var consumerConfig = new ConfigFile
            {
                Id            = "CppConsumerConfig",
                IncludeProlog =
                {
                    prolog
                }
            };

            consumerConfig.Write(CppConsumerConfigCache.ItemSpec);

            var updatedConfigFiles = new List <ITaskItem>();

            foreach (var cfg in configsWithHeaders)
            {
                if (updatedConfigs.Contains(cfg) && cfg.AbsoluteFilePath != null)
                {
                    var item = new TaskItem(cfg.AbsoluteFilePath);
                    item.SetMetadata("Id", cfg.Id);
                    updatedConfigFiles.Add(item);
                }
            }

            UpdatedConfigs = updatedConfigFiles.ToArray();

            return(!SharpGenLogger.HasErrors);
        }
예제 #6
0
        private bool Execute(ConfigFile config)
        {
            config.GetFilesWithIncludesAndExtensionHeaders(
                out var configsWithHeaders,
                out var configsWithExtensionHeaders
                );

            var cppHeaderGenerator = new CppHeaderGenerator(SharpGenLogger, OutputPath);

            var cppHeaderGenerationResult = cppHeaderGenerator.GenerateCppHeaders(config, configsWithHeaders, configsWithExtensionHeaders);

            if (SharpGenLogger.HasErrors)
            {
                return(false);
            }

            var resolver = new IncludeDirectoryResolver(SharpGenLogger);

            resolver.Configure(config);

            var castXml = new CastXmlRunner(SharpGenLogger, resolver, CastXmlExecutable.ItemSpec, CastXmlArguments)
            {
                OutputPath = OutputPath
            };

            var macroManager = new MacroManager(castXml);

            var cppExtensionGenerator = new CppExtensionHeaderGenerator();

            var module = config.CreateSkeletonModule();

            macroManager.Parse(Path.Combine(OutputPath, config.HeaderFileName), module);

            cppExtensionGenerator.GenerateExtensionHeaders(
                config, OutputPath, module, configsWithExtensionHeaders, cppHeaderGenerationResult.UpdatedConfigs
                );

            GenerateInputsCache(
                macroManager.IncludedFiles
                .Concat(config.ConfigFilesLoaded.Select(x => x.AbsoluteFilePath))
                .Concat(configsWithExtensionHeaders.Select(x => Path.Combine(OutputPath, x.ExtensionFileName)))
                .Select(s => Utilities.FixFilePath(s, Utilities.EmptyFilePathBehavior.Ignore))
                .Where(x => x != null)
                .Distinct()
                );

            if (SharpGenLogger.HasErrors)
            {
                return(false);
            }

            // Run the parser
            var parser = new CppParser(SharpGenLogger, config)
            {
                OutputPath = OutputPath
            };

            if (SharpGenLogger.HasErrors)
            {
                return(false);
            }

            CppModule group;

            using (var xmlReader = castXml.Process(parser.RootConfigHeaderFileName))
            {
                // Run the C++ parser
                group = parser.Run(module, xmlReader);
            }

            if (SharpGenLogger.HasErrors)
            {
                return(false);
            }

            config.ExpandDynamicVariables(SharpGenLogger, group);

            var docLinker    = new DocumentationLinker();
            var typeRegistry = new TypeRegistry(SharpGenLogger, docLinker);
            var namingRules  = new NamingRulesManager();

            var globalNamespace = new GlobalNamespaceProvider();

            foreach (var nameOverride in GlobalNamespaceOverrides)
            {
                var wellKnownName = nameOverride.ItemSpec;
                var overridenName = nameOverride.GetMetadata("Override");

                if (string.IsNullOrEmpty(overridenName))
                {
                    continue;
                }

                if (Enum.TryParse(wellKnownName, out WellKnownName name))
                {
                    globalNamespace.OverrideName(name, overridenName);
                }
                else
                {
                    SharpGenLogger.Warning(
                        LoggingCodes.InvalidGlobalNamespaceOverride,
                        "Invalid override of \"{0}\": unknown class name, ignoring the override.",
                        wellKnownName
                        );
                }
            }

            // Run the main mapping process
            var transformer = new TransformManager(
                globalNamespace,
                namingRules,
                SharpGenLogger,
                typeRegistry,
                docLinker,
                new ConstantManager(namingRules, docLinker)
                );

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

            var consumerConfig = new ConfigFile
            {
                Id            = ConsumerBindMappingConfigId,
                IncludeProlog = { cppHeaderGenerationResult.Prologue },
                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
            }
                    )
                );

            GenerateConfigForConsumers(consumerConfig);

            if (SharpGenLogger.HasErrors)
            {
                return(false);
            }

            var documentationCacheItemSpec = DocumentationCache.ItemSpec;

            Utilities.RequireAbsolutePath(documentationCacheItemSpec, nameof(DocumentationCache));

            var cache = File.Exists(documentationCacheItemSpec)
                            ? DocItemCache.Read(documentationCacheItemSpec)
                            : new DocItemCache();

            DocumentationLogger docLogger = new(SharpGenLogger) { MaxLevel = LogLevel.Warning };
            var docContext = new Lazy <DocumentationContext>(() => new DocumentationContext(docLogger));

            ExtensibilityDriver.Instance.DocumentModule(SharpGenLogger, cache, solution, docContext).Wait();

            if (docContext.IsValueCreated)
            {
                Regex[] silencePatterns    = null;
                var     docLogLevelDefault = DocumentationFailuresAsErrors ? LogLevel.Error : LogLevel.Warning;

                foreach (var queryFailure in docContext.Value.Failures)
                {
                    if (silencePatterns == null)
                    {
                        silencePatterns = new Regex[SilenceMissingDocumentationErrorIdentifierPatterns.Length];
                        for (var i = 0; i < silencePatterns.Length; i++)
                        {
                            silencePatterns[i] = new Regex(
                                SilenceMissingDocumentationErrorIdentifierPatterns[i].ItemSpec,
                                RegexOptions.CultureInvariant
                                );
                        }
                    }

                    if (silencePatterns.Length != 0)
                    {
                        bool SilencePredicate(Regex x) => x.Match(queryFailure.Query).Success;

                        if (silencePatterns.Any(SilencePredicate))
                        {
                            continue;
                        }
                    }

                    var providerName = queryFailure.FailedProviderName ?? "<null>";

                    var docLogLevel = queryFailure.TreatProviderFailuresAsErrors
                                          ? docLogLevelDefault
                                          : docLogLevelDefault > LogLevel.Warning
                                              ? LogLevel.Warning
                                              : docLogLevelDefault;

                    if (queryFailure.Exceptions == null || queryFailure.Exceptions.Count <= 1)
                    {
                        SharpGenLogger.LogRawMessage(
                            docLogLevel,
                            LoggingCodes.DocumentationProviderInternalError,
                            "Documentation provider [{0}] query for \"{1}\" failed.",
                            queryFailure.Exceptions?.FirstOrDefault(),
                            providerName,
                            queryFailure.Query
                            );
                    }
                    else
                    {
                        var exceptionsCount = queryFailure.Exceptions.Count;
                        for (var index = 0; index < exceptionsCount; index++)
                        {
                            var exception = queryFailure.Exceptions[index];

                            SharpGenLogger.LogRawMessage(
                                docLogLevel,
                                LoggingCodes.DocumentationProviderInternalError,
                                "Documentation provider [{0}] query for \"{1}\" failed ({2}/{3}).",
                                exception,
                                providerName,
                                queryFailure.Query,
                                index + 1,
                                exceptionsCount
                                );
                        }
                    }
                }
            }

            cache.WriteIfDirty(documentationCacheItemSpec);

            if (SharpGenLogger.HasErrors)
            {
                return(false);
            }

            var documentationFiles = new Dictionary <string, XmlDocument>();

            foreach (var file in ExternalDocumentation)
            {
                using var stream = File.OpenRead(file.ItemSpec);

                var xml = new XmlDocument();
                xml.Load(stream);
                documentationFiles.Add(file.ItemSpec, xml);
            }

            PlatformDetectionType platformMask = 0;

            foreach (var platform in Platforms)
            {
                if (!Enum.TryParse <PlatformDetectionType>(platform.ItemSpec, out var parsedPlatform))
                {
                    SharpGenLogger.Warning(
                        LoggingCodes.InvalidPlatformDetectionType,
                        "The platform type {0} is an unknown platform to SharpGenTools. Falling back to Any platform detection.",
                        platform
                        );
                    platformMask = PlatformDetectionType.Any;
                }
                else
                {
                    platformMask |= parsedPlatform;
                }
            }

            if (platformMask == 0)
            {
                platformMask = PlatformDetectionType.Any;
            }

            if (SharpGenLogger.HasErrors)
            {
                return(false);
            }

            var generator = new RoslynGenerator(
                SharpGenLogger,
                globalNamespace,
                docLinker,
                new ExternalDocCommentsReader(documentationFiles),
                new GeneratorConfig
            {
                Platforms = platformMask
            }
                );

            generator.Run(solution, GeneratedCodeFolder);

            return(!SharpGenLogger.HasErrors);
        }