/// <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; } }
/// <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); }