/// <summary> /// Represents a single service, supported on one or more platforms, that we will be /// generating documentation for. /// </summary> /// <param name="assemblyPath"> /// The full path and filename of the assembly. The .Net platform for the assembly /// is assumed to be the name of the folder containing the assembly. The name of the /// service will be inferred from the name pattern of the assembly. /// </param> /// <param name="outputFolderRoot"> /// The root output folder that the artifacts should be placed in. A further subfolder /// representing the service (or 'core' if the assembly is the runtime) is added. /// </param> /// <param name="allPlatforms">The set of platform subfolders to use to discover ndoc tables</param> /// <param name="options">The user options governing doc generation</param> /// <param name="useAppDomain"></param> public GenerationManifest(string assemblyPath, string outputFolderRoot, IEnumerable <string> allPlatforms, GeneratorOptions options, bool useAppDomain) { AssemblyPath = Path.GetFullPath(assemblyPath); var assemblyName = Path.GetFileNameWithoutExtension(AssemblyPath); ServiceName = assemblyName.StartsWith(AWSAssemblyNamePrefix + ".", StringComparison.OrdinalIgnoreCase) ? assemblyName.Substring(AWSAssemblyNamePrefix.Length + 1) : assemblyName; Options = options; AssemblyWrapper = CreateAssemblyWrapper(AssemblyPath, useAppDomain); OutputFolder = Path.GetFullPath(outputFolderRoot); foreach (var platform in allPlatforms) { NDocUtilities.LoadDocumentation(assemblyName, ServiceName, platform, options); } if (Options.Verbose) { Trace.WriteLine("\tConstructed GenerationManifest:"); Trace.WriteLine(String.Format("\t...AssemblyPath: {0}", AssemblyPath)); Trace.WriteLine(String.Format("\t...ServiceName: {0}", ServiceName)); Trace.WriteLine(String.Format("\t...OutputFolder: {0}", OutputFolder)); } }
/// <summary> /// Returns the discovered NDoc table for a given platform, if it existed. If platform /// is not specified, we attempt to return the NDoc for the primary platform specified /// in the generator options. /// </summary> /// <param name="platform"></param> /// <returns></returns> public IDictionary <string, XElement> NDocForPlatform(string platform = null) { if (string.IsNullOrEmpty(platform)) { platform = Options.Platform; } return(NDocUtilities.GetDocumentationInstance(ServiceName, platform)); }
/// <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> /// /// </summary> /// <param name="filePath"></param> /// <returns></returns> private IDictionary <string, XElement> CreateNDocTable(string filePath) { var dict = new Dictionary <string, XElement>(); var document = NDocUtilities.LoadAssemblyDocumentationWithSamples(filePath, Options.CodeSamplesRootFolder, ServiceName); NDocUtilities.PreprocessCodeBlocksToPreTags(Options, document); foreach (var element in document.XPathSelectElements("//members/member")) { var xattribute = element.Attributes().FirstOrDefault(x => x.Name.LocalName == "name"); if (xattribute == null) { continue; } dict[xattribute.Value] = element; } return(dict); }
public ManifestAssemblyWrapper(string serviceName, string platform, string assemblyPath, bool useNewAppDomain) { var docId = NDocUtilities.GenerateDocId(serviceName, platform); if (useNewAppDomain) { Domain = AppDomain.CreateDomain(assemblyPath); var inst = Domain.CreateInstance(this.GetType().Assembly.FullName, typeof(AssemblyWrapper).FullName, true, BindingFlags.CreateInstance | BindingFlags.Public | BindingFlags.Instance, null, new object[] { docId }, null, null); SdkAssembly = (AssemblyWrapper)inst.Unwrap(); SdkAssembly.LoadAssembly(assemblyPath); } else { SdkAssembly = new AssemblyWrapper(docId); SdkAssembly.LoadAssembly(assemblyPath); } }
/// <summary> /// /// </summary> /// <param name="filePath"></param> /// <param name="useAppDomain"></param> /// <returns></returns> private AssemblyWrapper CreateAssemblyWrapper(string filePath, bool useAppDomain) { var docId = NDocUtilities.GenerateDocId(ServiceName, Options.Platform); if (useAppDomain) { var domain = AppDomain.CreateDomain(filePath); var inst = domain.CreateInstance(this.GetType().Assembly.FullName, typeof(AssemblyWrapper).FullName, true, BindingFlags.CreateInstance | BindingFlags.Public | BindingFlags.Instance, null, new object[] { docId }, null, null); var wrapper = (AssemblyWrapper)inst.Unwrap(); wrapper.LoadAssembly(filePath); return(wrapper); } else { var wrapper = new AssemblyWrapper(docId); wrapper.LoadAssembly(filePath); return(wrapper); } }