/// <summary>
        /// Generates the documentation for the artifacts represented by this
        /// manifest, starting at the namespace(s) in the assembly and working
        /// down through the type hierarchy. Types that exist in the deferable
        /// namespaces will be processed later in generation, when the awssdk.core
        /// assembly is processed.
        /// </summary>
        /// <param name="deferrableTypes">
        /// Collection for types in service assemblies that we want to defer processing
        /// on until we process awssdk.core.
        /// </param>
        /// <param name="tocWriter">
        /// Toc generation handler to which each processed namespace is registered
        /// </param>
        public void Generate(DeferredTypesProvider deferrableTypes, TOCWriter tocWriter)
        {
            Trace.WriteLine($"\tgenerating from {Options.Platform}/{Path.GetFileName(AssemblyPath)}");

            // load the assembly and ndoc dataset for the service we're about to generate; assuming
            // they contain no deferrable types we'll release them when done
            var discardAssemblyOnExit = true;

            foreach (var platform in AllPlatforms)
            {
                NDocUtilities.LoadDocumentation(AssemblyName, ServiceName, platform, Options);
            }

            var namespaceNames = ManifestAssemblyContext.SdkAssembly.GetNamespaces();

            var frameworkVersion = FrameworkVersion.FromPlatformFolder(Options.Platform);
            var processed        = 0;

            foreach (var namespaceName in namespaceNames)
            {
                // when processing awssdk.core, we don't get handed a collection to hold
                // deferrable types
                if (deferrableTypes != null)
                {
                    if (deferrableTypes.Namespaces.Contains(namespaceName))
                    {
                        var types = ManifestAssemblyContext.SdkAssembly.GetTypesForNamespace(namespaceName);
                        if (types.Any())
                        {
                            Trace.WriteLine($"\t\tdeferring processing of types in namespace {namespaceName} for {Path.GetFileName(AssemblyPath)}");
                            deferrableTypes.AddTypes(types);
                            discardAssemblyOnExit = false;
                        }

                        continue;
                    }
                }

                WriteNamespace(frameworkVersion, namespaceName);
                tocWriter.BuildNamespaceToc(namespaceName, ManifestAssemblyContext.SdkAssembly);

                Trace.WriteLine($"\t\t{namespaceName} processed ({++processed} of {namespaceNames.Count()})");
            }

            if (discardAssemblyOnExit)
            {
                // release artifact roots for future GC collections to operate on
                foreach (var platform in AllPlatforms)
                {
                    NDocUtilities.UnloadDocumentation(ServiceName, platform);
                }

                ManifestAssemblyContext.Dispose();
                ManifestAssemblyContext = null;
            }
        }
Пример #2
0
        /// <summary>
        /// Runs the doc generator to produce or update a consistent documentation
        /// set for the SDK.
        /// </summary>
        /// <param name="options"></param>
        /// <returns>0 on successful completion</returns>
        public int Execute(GeneratorOptions options)
        {
            // this is just to record the run duration, so we can monitor and optimize
            // build-time perf
            _startTimeTicks = DateTime.Now.Ticks;

            Options = options;

            Trace.Listeners.Add(new ConditionalConsoleTraceListener(Options.Verbose));

            if (Options.TestMode)
            {
                SetOptionsForTestMode();
            }

            if (string.IsNullOrEmpty(Options.SDKAssembliesRoot))
            {
                Info("ERROR: SDKAssembliesRoot option not set");
                return(-1);
            }

            if (Options.Verbose)
            {
                Info("Starting generation with options:");
                Info("...TestMode: {0}", Options.TestMode);
                Info("...Clean: {0}", Options.Clean);
                Info("...WriteStaticContent: {0}", Options.WriteStaticContent);
                Info("...WaitOnExit: {0}", Options.WaitOnExit);
                Info("");
                Info("...SDKAssembliesRoot: {0}", Options.SDKAssembliesRoot);
                Info("...OutputFolder: {0}", Options.OutputFolder);
                Info("...Platform: {0}", Options.Platform);
                Info("...Services: {0}", string.Join(",", Options.Services));
                Info("...CodeSamplesRootFolder: {0}", Options.CodeSamplesRootFolder);
                Info("");
            }

            if (options.Clean)
            {
                FileUtilties.CleanFolder(options.OutputFolder, true);
            }

            if (!Directory.Exists(options.OutputFolder))
            {
                Directory.CreateDirectory(options.OutputFolder);
            }

            // use the sdk root and primary platform to determine the set of
            // service manifests to process
            var manifests = ConstructGenerationManifests();

            TOCWriter = new TOCWriter(options);

            GenerationManifest    coreManifest  = null;
            DeferredTypesProvider deferredTypes = new DeferredTypesProvider(null);

            foreach (var m in manifests)
            {
                if (m.ServiceName.Equals("Core", StringComparison.InvariantCultureIgnoreCase))
                {
                    coreManifest = m;
                    continue;
                }

                m.Generate(deferredTypes, TOCWriter);
            }

            // now all service assemblies are processed, handle core plus any types in those assemblies that
            // we elected to defer until we processed core.
            coreManifest.ManifestAssemblyContext.SdkAssembly.DeferredTypesProvider = deferredTypes;
            coreManifest.Generate(null, TOCWriter);

            Info("Generating table of contents entries...");
            TOCWriter.Write();

            CopyVersionInfoManifest();

            if (options.WriteStaticContent)
            {
                Info("Generating/copying static content:");
                Info("...creating landing page");
                var lpWriter = new LandingPageWriter(options);
                lpWriter.Write();

                Info("...copying static resources");
                var sourceLocation = Directory.GetParent(typeof(SdkDocGenerator).Assembly.Location).FullName;
                FileUtilties.FolderCopy(Path.Combine(sourceLocation, "output-files"), options.OutputFolder, true);
            }

            // Write out all the redirect rules for doc cross-linking.
            using (Stream stream = File.Open(Path.Combine(options.OutputFolder, SDKDocRedirectWriter.RedirectFileName), FileMode.Create))
            {
                SDKDocRedirectWriter.Write(stream);
            }

            return(0);
        }