Ejemplo n.º 1
0
        /// <summary>
        /// Loads the <paramref name="registry"/> and Purges Generated Code given
        /// <paramref name="serviceManager"/>.
        /// </summary>
        /// <param name="serviceManager"></param>
        /// <param name="registry"></param>
        private void LoadAndPurgeGeneratedCode(CodeGenerationServiceManager serviceManager
                                               , out OrToolsSatGeneratedSyntaxTreeRegistry registry)
        {
            if (DebugMessagesSwitch)
            {
                Writer.WriteLine("Loading and purging registry.");
            }

            /* Should not need to re-load any ServiceManager Registries,
             * since this is done inherently by the SM itself. */
            registry = serviceManager.Registry;

            if (!registry.Any())
            {
                if (DebugMessagesSwitch)
                {
                    Writer.WriteLine("There are no Registry entries.");
                }

                return;
            }

            // Work around output or reference parameters.
            var local            = registry;
            var outputDirectory  = local.OutputDirectory;
            var anUpdateOccurred = local.GoogleOrToolsVersion < GoogleOrToolsVersion;

            // Purge All if any of them are missing.
            bool ShouldPurgeRegistry(GeneratedSyntaxTreeDescriptor descriptor)
            {
                /* Easy Purge to make by Version first, followed closely by whether
                 * any previously registered files have themselves disappeared. */

                bool WhetherSomeFilesAreMissing()
                {
                    var someFilesAreMissing = descriptor.GeneratedAssetKeys
                                              .Select(y => Path.Combine(outputDirectory, y.RenderGeneratedFileName()))
                                              .Any(filePath => !File.Exists(filePath));

                    return(someFilesAreMissing);
                }

                var should = anUpdateOccurred || WhetherSomeFilesAreMissing();

                if (DebugMessagesSwitch)
                {
                    Writer.WriteLine($"Should{(should ? " " : " not ")}purge generated code.");
                }

                return(should);
            }

            registry.PurgeWhere(ShouldPurgeRegistry);
        }
        public void Generates_When_Google_OrTools_Version_Updates()
        {
            VerifySingleCodeGenerationPass(out var registry);

            // TODO: TBD: could almost inject some code into a generic handler...
            void VerifyRegistryAndUpdate()
            {
                Version Parse(string s) => Version.Parse(s);

                // We need an instance of the Service Manager for what we are about to do here.
                var serviceManager = new CodeGenerationServiceManager(registry.OutputDirectory, RegistryFileName);

                // The Version will surely have updated from '0.0.0' ... Remember, we also want it in Three Parts.
                serviceManager.Registry.GoogleOrToolsVersion = Parse("0.0.0");
                serviceManager.TrySave();
            }

            VerifyRegistryAndUpdate();

            VerifySingleCodeGenerationPass(out var secondRegistry);

            VerifyDifferentRegistries(registry, secondRegistry);
        }
Ejemplo n.º 3
0
        // ReSharper disable once MemberCanBeMadeStatic.Local
        private int?GenerateCode()
        {
            void EnsureDirectoryExists(string path)
            {
                if (Directory.Exists(path))
                {
                    return;
                }

                Directory.CreateDirectory(path);
            }

            try
            {
                string outputDirectory           = OutputDirectoryVar;
                string generatedCodeRegistryFile = GeneratedCodeRegistryFileVar;

                EnsureDirectoryExists(outputDirectory);

                if (DebugMessagesSwitch)
                {
                    Writer.WriteLine($"Output Directory is '{outputDirectory}', registry file name is '{generatedCodeRegistryFile}'.");
                }

                var serviceManager = new CodeGenerationServiceManager(outputDirectory, generatedCodeRegistryFile);

                LoadAndPurgeGeneratedCode(serviceManager, out var registry);

                Registry = registry;

                registry.AssumesTrue(x => ReferenceEquals(x, serviceManager.Registry));

                // ReSharper disable once RedundantEmptyObjectOrCollectionInitializer
                var service = new SatParameterCodeGeneratorService {
                };

                var descriptor = service.Descriptor;

                service.CodeGenerationVisitor.Visit(descriptor);

                var compilationUnits = service.CodeGenerationVisitor.CompilationUnits;

                if (DebugMessagesSwitch)
                {
                    Writer.WriteLine(
                        $"There are {compilationUnits.Count} potential new compilation units as compared"
                        + $" to {registry.SelectMany(x => x.GeneratedAssetKeys).Count()} old ones."
                        );
                }

                // TODO: TBD: this is what we are really talking about...
                // TODO: TBD: we need to find an exact match, otherwise, we reject the current set and regenerate...
                // TODO: TBD: no need to go ad-hoc compiling any previously generated code... that is entirely unnecessary.
                var renderedCompilationUnits = compilationUnits.ToDictionary(
                    x => x.Key
                    , x => x.Value.NormalizeWhitespace().ToFullString()
                    );

                if (TryEvaluateCompilationUnits(registry, renderedCompilationUnits))
                {
                    if (DebugMessagesSwitch)
                    {
                        Writer.WriteLine(
                            "Evaluation complete, there are"
                            + $" {renderedCompilationUnits.Count} rendered compilation units."
                            );
                    }

                    var generatedDescriptor = GeneratedSyntaxTreeDescriptor.Create();

                    foreach (var(key, renderedCompilationUnit) in renderedCompilationUnits)
                    {
                        var filePath = Path.Combine(outputDirectory, key.RenderGeneratedFileName());

                        using (var fs = File.Open(filePath, FileMode.CreateNew, FileAccess.Write, FileShare.Read))
                        {
                            using (var sw = new StreamWriter(fs))
                            {
                                sw.WriteLine(renderedCompilationUnit);
                            }
                        }

                        generatedDescriptor.GeneratedAssetKeys.Add(key);
                    }

                    registry.Add(generatedDescriptor);

                    if (DebugMessagesSwitch)
                    {
                        Writer.WriteLine(
                            "Service Manager Registry instance"
                            + $" is{(ReferenceEquals(serviceManager.Registry, registry) ? " " : " not ")}the same."
                            );
                    }

                    if (DebugMessagesSwitch)
                    {
                        // TODO: TBD: do we need exposure of the SM Registry?
                        Writer.WriteLine(
                            $"There are {generatedDescriptor.GeneratedAssetKeys.Count} generated items and"
                            + $" {serviceManager.Registry.SelectMany(x => x.GeneratedAssetKeys).Count()} total entries to save."
                            );
                    }

                    serviceManager.TrySave();
                }
            }
            catch (Exception ex)
            {
                ReportException(ex);
                return(ErrorGeneratingCode);
            }

            return(null);
        }