/// <summary> /// Runs this instance. /// </summary> public void Run(Config config) { if (AssemblyManager == null) throw new InvalidOperationException("AssemblyManager must be set"); if (ModelBuilder == null) throw new InvalidOperationException("ModelBuilder must be set"); // Setup the PageId function ModelBuilder.PageIdFunction = PageIdFunction; var assemblySources = AssemblyManager.Load(config); // Process all assemblies foreach (var assemblySource in assemblySources) { ModelBuilder.LoadFrom(assemblySource, Registry); } Namespaces.AddRange(Registry.Namespaces); Namespaces.Sort((from, to) => string.CompareOrdinal(@from.Name, to.Name)); foreach (var @namespace in Namespaces) { ProcessDescendants(@namespace.Types); } foreach (var @namespace in Namespaces) { @namespace.Types.Sort((from, to) => string.CompareOrdinal(@from.Name, to.Name)); FlattenHierarchy(@namespace.Types); } }
/// <summary> /// Loads all assembly sources/xml doc and references /// </summary> public List<NAssemblySource> Load(Config config) { var configPath = Path.GetDirectoryName(Path.GetFullPath(config.FilePath)); configPath = configPath ?? Environment.CurrentDirectory; // Load all sources foreach (var group in config.Groups) { group.MergeGroup = group.MergeGroup ?? "default"; foreach (var source in group.Sources) { // Setup full path if (!string.IsNullOrEmpty(source.AssemblyPath)) source.AssemblyPath = Path.Combine(configPath, source.AssemblyPath); if (!string.IsNullOrEmpty(source.DocumentationPath)) source.DocumentationPath = Path.Combine(configPath, source.DocumentationPath); Load(group, source); } } var finalSources = new List<NAssemblySource>(); // Check that all source assemblies have valid Xml associated with it foreach (var assemblySource in AssemblySources.Where(node => node.Assembly != null)) { int countXmlDocFound = 0; NDocumentApi docFound = null; string assemblyName = ((AssemblyDefinition) assemblySource.Assembly).Name.Name; var docSources = new List<NAssemblySource>(); if (assemblySource.Document != null) docSources.Add(assemblySource); docSources.AddRange( AssemblySources.Where(node => node.Assembly == null) ); foreach (var doc in docSources) { var node = doc.Document.Document.SelectSingleNode("/doc/assembly/name"); if (assemblyName == node.InnerText.Trim()) { docFound = doc.Document; countXmlDocFound++; } } if (countXmlDocFound == 0) Logger.Fatal("Unable to find documentation for assembly [{0}]", assemblyName); else if (countXmlDocFound > 1) Logger.Fatal("Cannot load from multiple ([{0}]) documentation sources for assembly [{1}]", countXmlDocFound, assemblyName); assemblySource.Document = docFound; finalSources.Add(assemblySource); } return finalSources; }
/// <summary> /// Runs this instance. /// </summary> public void Run(Config config) { if (AssemblyManager == null) throw new InvalidOperationException("AssemblyManager must be set"); if (ModelBuilder == null) throw new InvalidOperationException("ModelBuilder must be set"); // Setup the PageId function ModelBuilder.PageIdFunction = PageIdFunction; var assemblySources = AssemblyManager.Load(config); // Add exclude list to ModelBuilder ModelBuilder.ExcludeList.Clear(); foreach (var excludeItem in config.ExcludeList) { if (!string.IsNullOrWhiteSpace(excludeItem)) { ModelBuilder.ExcludeList.Add(excludeItem); } } // Process all assemblies foreach (var assemblySource in assemblySources) { ModelBuilder.LoadFrom(assemblySource, Registry); } Namespaces.AddRange(Registry.Namespaces); Namespaces.Sort((from, to) => string.CompareOrdinal(@from.Name, to.Name)); foreach (var @namespace in Namespaces) { ProcessDescendants(@namespace.Types); } foreach (var @namespace in Namespaces) { @namespace.Types.Sort((from, to) => string.CompareOrdinal(@from.Name, to.Name)); FlattenHierarchy(@namespace.Types); } // Link extension method to the corresponding classes ModelBuilder.ProcessExtensionMethods(); // inherit documentation ModelBuilder.ProcessInheritedDoc(); }
/// <summary> /// Initialize this instance from the specified config. /// </summary> /// <param name="config">The config.</param> public void Init(Config config) { var exePath = Path.GetDirectoryName(typeof(Config).Assembly.Location); // Locate global styles var dirInfo = new DirectoryInfo(exePath); if (dirInfo.Name.ToLower() == "debug" || dirInfo.Name.ToLower() == "release") AddPath(Path.Combine(exePath, "..\\..\\" + DefaultStyleDirectoryName)); else if (dirInfo.Name.ToLower() == "bin") AddPath(Path.Combine(exePath, "..\\" + DefaultStyleDirectoryName)); // Add Style directory from sharpdoc executable path AddPath(Path.Combine(exePath, DefaultStyleDirectoryName)); // Add from current directory AddPath(Path.Combine(Environment.CurrentDirectory, DefaultStyleDirectoryName)); // Add from current path of config if (!string.IsNullOrEmpty(config.FilePath)) AddPath(Path.Combine(Path.GetDirectoryName(config.FilePath), DefaultStyleDirectoryName)); // Add path declared from config file AddPath(config.StyleDirectories); }
/// <summary> /// Initializes a new instance of the <see cref="SharpDocApp"/> class. /// </summary> public SharpDocApp() { Config = new Config(); StyleManager = new StyleManager(); }
/// <summary> /// Build topics for Assemblies, Namespaces and Types in order to use them in the TOC /// </summary> public void Run(Config config, Func<IModelReference, string> pageIdFunction) { RootTopic = config.RootTopic; // Load an existing root topic if (RootTopic != null) { RootTopic.ForEachTopic( topic => { topic.PageId = pageIdFunction(topic); // Check that PageId is a valid filename if (!Utility.IsValidFilename(topic.PageId)) Logger.Error("Invalid PageId [{0}] for topic [{1}]. Fileid must contain valid filename chars", topic.PageId, this); }); } NTopic topicLibrary = null; // If there are any assemblies, we have to generate class library topics if (Namespaces.Count >= 0) { // Find if a ClassLibrary topic is referenced in the config topic topicLibrary = (RootTopic != null) ? RootTopic.FindTopicById(NTopic.ClassLibraryTopicId) : null; if (topicLibrary == null) { // If no class library topic found, create a new one topicLibrary = NTopic.DefaultClassLibraryTopic; if (RootTopic == null) RootTopic = topicLibrary; else RootTopic.SubTopics.Add(topicLibrary); } ClassLibraryTopic = topicLibrary; } if (RootTopic == null) { Logger.Fatal("No root topic assigned/ no topic for class library "); return; } // Calculate starting index for class library based on index from topics int index = 0; var indices = new HashSet<int>(); var topicToReindex = new List<NTopic>(); RootTopic.ForEachTopic( topic => { if (indices.Contains(topic.Index)) { // Silently reassign an index, as index is no longer important //Logger.Warning("Index [{0}] for Topic [{1}] is already used. Need to reassign a new index.", topic.Index, topic.Name); topicToReindex.Add(topic); } else { indices.Add(topic.Index); index = Math.Max(index, topic.Index); } }); index++; foreach (var topicToIndex in topicToReindex) { topicToIndex.Index = index++; } foreach (var @namespace in Namespaces) { // Affect new Index based on previous topics @namespace.Index = index++; var namespaceTopic = new NTopic(@namespace) { Name = @namespace.Name + " Namespace", AttachedClassNode = @namespace }; @namespace.TopicLink = namespaceTopic; topicLibrary.SubTopics.Add(namespaceTopic); @namespace.SeeAlsos.Add(new NSeeAlso(topicLibrary)); foreach (var type in @namespace.Types) { // Affect new Index based on previous topics type.Index = index++; var typeTopic = new NTopic(type) { Name = type.Name + " " + type.Category, AttachedClassNode = type}; type.TopicLink = typeTopic; namespaceTopic.SubTopics.Add(typeTopic); type.SeeAlsos.Add(new NSeeAlso(topicLibrary)); // We don't process fields for enums if (!(type is NEnum)) { foreach (var member in type.Members) { var memberTopic = new NTopic(member) { Name = member.Name, AttachedClassNode = type }; member.TopicLink = memberTopic; typeTopic.SubTopics.Add(memberTopic); // Affect new Index based on previous topics member.Index = index++; member.SeeAlsos.Add(new NSeeAlso(topicLibrary)); } } } } SearchTopic = NTopic.DefaultSearchResultsTopic; SearchTopic.Index = index++; // Add SearchTopic to the root topic RootTopic.SubTopics.Add(SearchTopic); // Associate each topic with its parent RootTopic.BuildParents(); // Register root topics and all sub topics (excluding class library topics) Registry.Register(RootTopic); }