Wraps the generation information required to emit documentation for a service, which may have assemblies in all or some of the platforms subfolders.
Esempio n. 1
0
        /// <summary>
        /// Enumerates the assembly, folder and platform settings in the options
        /// to construct a per-service manifest that we will then process. Our preferred
        /// documentation source is for the 'net45' platform but if a subfolder does
        /// not exist under the root for this platform, we'll generate using the
        /// assemblies in the first subfolder we find.
        /// </summary>
        /// <remarks>
        /// Currently we only construct manifests for the assemblies we find in the
        /// preferred or first platform subfolder. Distinct assemblies that exist
        /// outside this folder do not get included.
        /// </remarks>
        /// <returns>Collections of service manifests to process</returns>
        private IList <GenerationManifest> ConstructGenerationManifests()
        {
            var platformSubfolders = Directory.GetDirectories(Options.SDKAssembliesRoot, "*", SearchOption.TopDirectoryOnly);
            var availablePlatforms = platformSubfolders.Select(Path.GetFileName).ToList();

            if (!availablePlatforms.Any(ap => ap.Equals(Options.Platform, StringComparison.OrdinalIgnoreCase)))
            {
                Info("Warning: selected platform '{0}' is not available, switching to '{1}' for assembly discovery.",
                     Options.Platform,
                     availablePlatforms[0]);
                Options.Platform = availablePlatforms[0];
            }

            var manifests = new List <GenerationManifest>();

            // discover the matching service/core assemblies in the selected platform folder and
            // construct a processing manifest for each
            var assemblySourcePath = Path.Combine(Options.SDKAssembliesRoot, Options.Platform);

            if (Options.Verbose)
            {
                Info("Discovering assemblies in {0}", assemblySourcePath);
            }

            foreach (var service in Options.Services)
            {
                var namePattern = $"{GenerationManifest.AWSAssemblyNamePrefix}.{service}.dll";
                var assemblies  = Directory.GetFiles(assemblySourcePath, namePattern);
                foreach (var assembly in assemblies)
                {
                    if (_assembliesToSkip.Any(toSkip => assembly.Contains(toSkip)))
                    {
                        continue;
                    }
                    // keep items as the root for content, but a further subfolder of the root namespace
                    // will be added for the artifacts
                    var artifactManifest = new GenerationManifest(assembly, Options.ComputedContentFolder, availablePlatforms, Options, true);
                    manifests.Add(artifactManifest);
                }
            }

            return(manifests);
        }
Esempio n. 2
0
        public void GetHelpURL(FrameworkVersion version, out string url, out string target)
        {
            target = "";
            url    = null;

            if (IsSystemNamespace)
            {
                // msdn urls for generic collections are not predictable, so
                // we elect to output as simple text
                if (!this.IsGenericType)
                {
                    target = "target=_new";
                    url    = string.Format(NDocUtilities.MSDN_TYPE_URL_PATTERN, this.GetDisplayName(true).ToLower());
                }
            }
            else if (IsAmazonNamespace)
            {
                // don't know if reference is to a type in folder for namespace of declaring type we're
                // processing, or in another namespace (folder), so jump to output root on the link
                url = string.Format("../{0}/{1}",
                                    GenerationManifest.OutputSubFolderFromNamespace(this.Namespace),
                                    FilenameGenerator.GenerateFilename(this));
            }
        }
Esempio n. 3
0
        /// <summary>
        /// Enumerates the assembly, folder and platform settings in the options
        /// to construct a per-service manifest that we will then process. Our preferred
        /// documentation source is for the 'net45' platform but if a subfolder does
        /// not exist under the root for this platform, we'll generate using the
        /// assemblies in the first subfolder we find.
        /// </summary>
        /// <remarks>
        /// Currently we only construct manifests for the assemblies we find in the
        /// preferred or first platform subfolder. Distinct assemblies that exist
        /// outside this folder do not get included.
        /// </remarks>
        /// <returns>Collections of service manifests to process</returns>
        private IList<GenerationManifest> ConstructGenerationManifests()
        {
            var platformSubfolders = Directory.GetDirectories(Options.SDKAssembliesRoot, "*", SearchOption.TopDirectoryOnly);
            var availablePlatforms = platformSubfolders.Select(Path.GetFileName).ToList();

            if (!availablePlatforms.Any(ap => ap.Equals(Options.Platform, StringComparison.OrdinalIgnoreCase)))
            {
                Info("Warning: selected platform '{0}' is not available, switching to '{1}' for assembly discovery.", 
                                  Options.Platform,
                                  availablePlatforms[0]);
                Options.Platform = availablePlatforms[0];
            }

            var manifests = new List<GenerationManifest>();

            // discover the matching service/core assemblies in the selected platform folder and
            // construct a processing manifest for each
            var assemblySourcePath = Path.Combine(Options.SDKAssembliesRoot, Options.Platform);
            if (Options.Verbose)
                Info("Discovering assemblies in {0}", assemblySourcePath);

            foreach (var service in Options.Services)
            {
                var namePattern = string.Format("{0}.{1}.dll", GenerationManifest.AWSAssemblyNamePrefix, service);
                var assemblies = Directory.GetFiles(assemblySourcePath, namePattern);
                foreach (var a in assemblies)
                {
                    // keep items as the root for content, but a further subfolder of the root namespace
                    // will be added for the artifacts
                    var artifactManifest = new GenerationManifest(a, Options.ComputedContentFolder, availablePlatforms, Options, true);
                    manifests.Add(artifactManifest);
                }
            }

            return manifests;
        }
Esempio n. 4
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);
        }
Esempio n. 5
0
        public string CreateReferenceHtml(bool fullTypeName)
        {
            string html;
            var    nameOrFullName = fullTypeName ? (this.FullName ?? this.Name) : this.Name;

            if (this.IsGenericParameter)
            {
                html = this.JustName;
            }
            else if (this.IsGenericType)
            {
                var fixedName = nameOrFullName.Substring(0, nameOrFullName.IndexOf('`'));
                using (var writer = new StringWriter())
                {
                    writer.Write("<a");

                    string url;
                    if (this.IsAmazonNamespace)
                    {
                        url = $"../{GenerationManifest.OutputSubFolderFromNamespace(this.Namespace)}/{FilenameGenerator.GenerateFilename(this)}";
                    }
                    else if (this.IsSystemNamespace)
                    {
                        writer.Write(" target=_new");

                        var fixedMsdnName = this.Name.Replace('`', '-');
                        url = $"https://docs.microsoft.com/en-us/dotnet/api/{this.Namespace}.{fixedMsdnName}";
                    }
                    else
                    {
                        throw new ApplicationException($"Type {this.FullName} is not a System or Amazon type, no idea how to handle its help URL");
                    }

                    writer.Write(" href=\"{0}\"", url);
                    writer.Write(">");

                    writer.Write(fixedName);
                    writer.Write("</a>");

                    writer.Write("&lt;");
                    var typeArguments = this.GenericTypeArguments();
                    for (int i = 0; i < typeArguments.Count; i++)
                    {
                        if (i != 0)
                        {
                            writer.Write(", ");
                        }
                        var typeArgument = typeArguments[i];
                        var argumentHtml = typeArgument.CreateReferenceHtml(fullTypeName);
                        writer.Write(argumentHtml);
                    }
                    writer.Write("&gt;");

                    html = writer.ToString();
                }
            }
            else if (this.IsArray)
            {
                var elementType     = this.GetElementType();
                var elementTypeHtml = elementType.CreateReferenceHtml(fullTypeName);
                html = $"{elementTypeHtml}[]";
            }
            else
            {
                string url, label, target;
                if (this.IsAmazonNamespace)
                {
                    url    = $"../{GenerationManifest.OutputSubFolderFromNamespace(this.Namespace)}/{FilenameGenerator.GenerateFilename(this)}";
                    label  = nameOrFullName;
                    target = string.Empty;
                }
                else if (this.IsSystemNamespace)
                {
                    url    = string.Format(NDocUtilities.MSDN_TYPE_URL_PATTERN, this.GetDisplayName(true).ToLower());
                    target = " target=_new";
                    label  = nameOrFullName;
                }
                else
                {
                    throw new ApplicationException($"Type {this.FullName} is not a System or Amazon type, no idea how to handle its help URL");
                }

                html = $"<a{target} href=\"{url}\">{label}</a>";
            }

            return(html);
        }
Esempio n. 6
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();

            // We want to aggregate all types(such as AmazonS3Config) under Amazon namespace before generating docs for Core.
            // Currently, the doc generator will stomp over files with conflicting namespaces across dll.  If we encounter manifest
            // for Core, stash all its types and process it last.
            List <string> namespacesToIgnore =
                new List <string> {
                "Amazon",
                "Amazon.Util",
                "Amazon.Runtime",
                "Amazon.Runtime.SharedInterfaces"
            };
            GenerationManifest  coreManifest           = null;
            PartialTypeProvider additionalTypeProvider = new PartialTypeProvider(null);

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

                m.Generate(namespacesToIgnore);

                foreach (var namespaceName in namespacesToIgnore)
                {
                    additionalTypeProvider.ProcessTypes(m.AssemblyWrapper.GetTypesForNamespace(namespaceName));
                }
            }
            coreManifest.AssemblyWrapper.SetSecondaryTypeProvider(additionalTypeProvider);
            coreManifest.Generate(null);

            // finish up by outputting/updating the TOC and emitting the static doc framework content if requested
            // we try and generate the toc based on the .Net 4.5 platform by preference, falling back as necessary
            GenerateTableOfContents(manifests);

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