diff --git a/src/CloudNimble.DotNetDocs.Mintlify/MintlifyRenderer.cs b/src/CloudNimble.DotNetDocs.Mintlify/MintlifyRenderer.cs
index 431e563..8b6902f 100644
--- a/src/CloudNimble.DotNetDocs.Mintlify/MintlifyRenderer.cs
+++ b/src/CloudNimble.DotNetDocs.Mintlify/MintlifyRenderer.cs
@@ -76,7 +76,7 @@ public async Task RenderAsync(DocAssembly model)
ArgumentNullException.ThrowIfNull(model);
var apiOutputPath = Path.Combine(Context.DocumentationRootPath, Context.ApiReferencePath);
- Console.WriteLine($"📝 Rendering documentation to: {apiOutputPath}");
+ // Console.WriteLine($"📝 Rendering documentation to: {apiOutputPath}");
// Initialize DocsJsonManager if enabled (only on first call)
DocsJsonConfig? docsConfig = null;
@@ -1501,7 +1501,7 @@ private async Task GenerateNamespacePlaceholdersAsync(DocNamespace ns, string co
var namespacePath = Context.GetNamespaceFolderPath(ns.Name ?? "global");
var namespaceDir = Path.Combine(conceptualPath, namespacePath);
- Console.WriteLine($"📝 Generating namespace placeholders for: {ns.Name} at {namespaceDir}");
+ // Console.WriteLine($"📝 Generating namespace placeholders for: {ns.Name} at {namespaceDir}");
Directory.CreateDirectory(namespaceDir);
// Generate individual placeholder files
diff --git a/src/CloudNimble.DotNetDocs.Sdk.Tasks/CloudNimble.DotNetDocs.Sdk.Tasks.csproj b/src/CloudNimble.DotNetDocs.Sdk.Tasks/CloudNimble.DotNetDocs.Sdk.Tasks.csproj
deleted file mode 100644
index 72ebe93..0000000
--- a/src/CloudNimble.DotNetDocs.Sdk.Tasks/CloudNimble.DotNetDocs.Sdk.Tasks.csproj
+++ /dev/null
@@ -1,54 +0,0 @@
-
-
-
-
- net10.0;net9.0;net8.0;net472
- false
- MSBuild tasks for CloudNimble.DotNetDocs.Sdk
-
-
- false
- false
-
-
- $(NoWarn);CS2008;NU1701
-
-
- true
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/src/CloudNimble.DotNetDocs.Sdk.Tasks/DiscoverDocumentedProjectsTask.cs b/src/CloudNimble.DotNetDocs.Sdk.Tasks/DiscoverDocumentedProjectsTask.cs
deleted file mode 100644
index db8326e..0000000
--- a/src/CloudNimble.DotNetDocs.Sdk.Tasks/DiscoverDocumentedProjectsTask.cs
+++ /dev/null
@@ -1,302 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Linq;
-using CloudNimble.EasyAF.Core;
-using Microsoft.Build.Evaluation;
-using Microsoft.Build.Framework;
-using Microsoft.Build.Utilities;
-
-namespace CloudNimble.DotNetDocs.Sdk.Tasks
-{
-
- ///
- /// MSBuild task that discovers which projects in a solution should be documented based on their MSBuild properties.
- ///
- public class DiscoverDocumentedProjectsTask : Task
- {
-
- #region Fields
-
- internal Dictionary _propertiesToEvaluate = new()
- {
- { "IsTestProject", false }, // Exclude test projects
- { "IsPackable", true }, // Include only packable projects (default is true)
- { "ExcludeFromDocumentation", false } // Exclude projects explicitly marked to be excluded
- };
-
- #endregion
-
- #region Properties
-
- ///
- /// Gets or sets the solution directory to search for projects.
- ///
- [Required]
- public string SolutionDir { get; set; } = string.Empty;
-
- ///
- /// Gets or sets the configuration to use when evaluating projects.
- ///
- public string Configuration { get; set; } = "Release";
-
- ///
- /// Gets or sets the target framework to use when evaluating projects.
- ///
- public string TargetFramework { get; set; } = "net8.0";
-
- ///
- /// Gets or sets the exclude patterns for projects that should not be documented.
- ///
- public string[]? ExcludePatterns { get; set; }
-
- ///
- /// Gets or sets the discovered projects that should be documented.
- ///
- [Output]
- public ITaskItem[] DocumentedProjects { get; set; } = [];
-
- #endregion
-
- #region Public Methods
-
- ///
- /// Executes the task to discover documented projects.
- ///
- /// true if the task executed successfully; otherwise, false.
- public override bool Execute()
- {
- try
- {
- Log.LogMessage(MessageImportance.High, $"🔍 Discovering documented projects in {SolutionDir}...");
-
- var documentedProjects = new List();
-
- // Search for all .NET project file types and filter out excluded patterns
- var projectExtensions = new[] { "*.csproj", "*.vbproj", "*.fsproj" };
- var projectFiles = projectExtensions
- .SelectMany(ext => Directory.GetFiles(SolutionDir, ext, SearchOption.AllDirectories))
- .Where(file => ExcludePatterns is null || !ExcludePatterns.Any(pattern =>
- Path.GetFileNameWithoutExtension(file).Contains(pattern.Replace("*", ""), StringComparison.OrdinalIgnoreCase)))
- .ToArray();
-
- var projectCollection = new ProjectCollection();
-
- // Set up global properties for evaluation
- var globalProperties = new Dictionary
- {
- { "Configuration", Configuration }
- };
-
- foreach (var projectFile in projectFiles)
- {
- var projectName = Path.GetFileNameWithoutExtension(projectFile);
-
- try
- {
- // Create an evaluated project to get computed property values
- var project = new Project(projectFile, globalProperties, null, projectCollection);
-
- try
- {
-
- bool shouldSkip = false;
- foreach (var prop in _propertiesToEvaluate)
- {
- var propValue = project.GetPropertyValue(prop.Key);
- if (string.Equals(propValue, "true", StringComparison.OrdinalIgnoreCase) != prop.Value)
- {
- Log.LogMessage(MessageImportance.Low, $" ⏭️ Skipping project {projectName} due to property {prop.Key}={propValue}");
- shouldSkip = true;
- break;
- }
- }
- if (shouldSkip)
- {
- continue; // Skip to next project
- }
-
- // This is a project we should document
- var item = new TaskItem(projectFile);
-
- // Set metadata from the evaluated project
- var assemblyName = project.GetPropertyValue("AssemblyName");
- if (string.IsNullOrEmpty(assemblyName))
- {
- assemblyName = projectName;
- }
-
- var targetFramework = project.GetPropertyValue("TargetFramework");
- if (string.IsNullOrEmpty(targetFramework))
- {
- // For multi-targeted projects, use TargetFrameworks and pick the first one
- var targetFrameworks = project.GetPropertyValue("TargetFrameworks");
- if (!string.IsNullOrEmpty(targetFrameworks))
- {
- targetFramework = targetFrameworks.Split(';')[0].Trim();
- }
- else
- {
- targetFramework = TargetFramework; // Use default
- }
- }
-
- item.SetMetadata("AssemblyName", assemblyName);
- item.SetMetadata("OutputPath", $"bin\\{Configuration}");
- item.SetMetadata("TargetFramework", targetFramework);
- item.SetMetadata("TargetPath", $"bin\\{Configuration}\\{targetFramework}\\{assemblyName}.dll");
-
- documentedProjects.Add(item);
- Log.LogMessage(MessageImportance.High, $" ✅ Found packable project: {projectName}");
- }
- finally
- {
- // Always unload the project to free resources
- projectCollection.UnloadProject(project);
- }
- }
- catch (Exception ex)
- {
- Log.LogWarning($"Could not evaluate project {projectFile}: {ex.Message}");
- }
- }
-
- // Clean up the project collection
- projectCollection.UnloadAllProjects();
-
- DocumentedProjects = [.. documentedProjects];
- Log.LogMessage(MessageImportance.High, $"📊 Found {DocumentedProjects.Length} documented projects");
-
- return true;
- }
- catch (Exception ex)
- {
- Log.LogError($"Failed to discover documented projects: {ex.Message}");
- return false;
- }
- }
-
- #endregion
-
- #region Internal Methods
-
- ///
- /// Discovers project files in the specified directory.
- ///
- /// The solution directory to search.
- /// Patterns to exclude from discovery.
- /// Array of discovered project file paths.
- internal string[] DiscoverProjectFiles(string solutionDir, string[]? excludePatterns)
- {
- Ensure.ArgumentNotNullOrWhiteSpace(solutionDir, nameof(solutionDir));
-
- var projectExtensions = new[] { "*.csproj", "*.vbproj", "*.fsproj" };
- return projectExtensions
- .SelectMany(ext => Directory.GetFiles(solutionDir, ext, SearchOption.AllDirectories))
- .Where(file => ShouldIncludeProject(file, excludePatterns))
- .ToArray();
- }
-
- ///
- /// Determines if a project file should be included based on exclude patterns.
- ///
- /// The project file path.
- /// Patterns to exclude.
- /// true if the project should be included; otherwise, false.
- internal bool ShouldIncludeProject(string projectFilePath, string[]? excludePatterns)
- {
- Ensure.ArgumentNotNullOrWhiteSpace(projectFilePath, nameof(projectFilePath));
-
- if (excludePatterns is null || excludePatterns.Length == 0)
- {
- return true;
- }
-
- var fileName = Path.GetFileNameWithoutExtension(projectFilePath);
- return !excludePatterns.Any(pattern =>
- fileName.Contains(pattern.Replace("*", ""), StringComparison.OrdinalIgnoreCase));
- }
-
- ///
- /// Evaluates if a project should be documented based on its properties.
- ///
- /// The MSBuild project to evaluate.
- /// true if the project should be documented; otherwise, false.
- internal bool ShouldDocumentProject(Project project)
- {
- Ensure.ArgumentNotNull(project, nameof(project));
-
- foreach (var prop in _propertiesToEvaluate)
- {
- var propValue = project.GetPropertyValue(prop.Key);
- if (string.Equals(propValue, "true", StringComparison.OrdinalIgnoreCase) != prop.Value)
- {
- return false;
- }
- }
-
- return true;
- }
-
- ///
- /// Creates a task item with metadata for a documented project.
- ///
- /// The MSBuild project.
- /// The project file path.
- /// A task item with appropriate metadata.
- internal ITaskItem CreateProjectTaskItem(Project project, string projectFilePath)
- {
- Ensure.ArgumentNotNull(project, nameof(project));
- Ensure.ArgumentNotNullOrWhiteSpace(projectFilePath, nameof(projectFilePath));
-
- var projectName = Path.GetFileNameWithoutExtension(projectFilePath);
- var item = new TaskItem(projectFilePath);
-
- // Set metadata from the evaluated project
- var assemblyName = project.GetPropertyValue("AssemblyName");
- if (string.IsNullOrEmpty(assemblyName))
- {
- assemblyName = projectName;
- }
-
- var targetFramework = GetProjectTargetFramework(project);
-
- item.SetMetadata("AssemblyName", assemblyName);
- item.SetMetadata("OutputPath", $"bin\\{Configuration}");
- item.SetMetadata("TargetFramework", targetFramework);
- item.SetMetadata("TargetPath", $"bin\\{Configuration}\\{targetFramework}\\{assemblyName}.dll");
-
- return item;
- }
-
- ///
- /// Gets the target framework for a project, handling both single and multi-targeted projects.
- ///
- /// The MSBuild project.
- /// The target framework string.
- internal string GetProjectTargetFramework(Project project)
- {
- Ensure.ArgumentNotNull(project, nameof(project));
-
- var targetFramework = project.GetPropertyValue("TargetFramework");
- if (!string.IsNullOrEmpty(targetFramework))
- {
- return targetFramework;
- }
-
- // For multi-targeted projects, use TargetFrameworks and pick the first one
- var targetFrameworks = project.GetPropertyValue("TargetFrameworks");
- if (!string.IsNullOrEmpty(targetFrameworks))
- {
- return targetFrameworks.Split(';')[0].Trim();
- }
-
- // Use default
- return TargetFramework;
- }
-
- #endregion
-
- }
-
-}
\ No newline at end of file
diff --git a/src/CloudNimble.DotNetDocs.Sdk/CloudNimble.DotNetDocs.Sdk.csproj b/src/CloudNimble.DotNetDocs.Sdk/CloudNimble.DotNetDocs.Sdk.csproj
index 2a6f12c..0c2b8ab 100644
--- a/src/CloudNimble.DotNetDocs.Sdk/CloudNimble.DotNetDocs.Sdk.csproj
+++ b/src/CloudNimble.DotNetDocs.Sdk/CloudNimble.DotNetDocs.Sdk.csproj
@@ -1,8 +1,8 @@
-
+
- netstandard2.0
+ net8.0;net472
false
The MSBuild SDK for documentation projects (.docsproj) that provides a clean way to include documentation in .NET solutions.
@@ -10,6 +10,8 @@
true
MSBuildSdk
true
+ true
+ false
$(NoWarn);NU5128;CS2008;NU1701;NU5100
@@ -19,65 +21,55 @@
true
+ $(TargetsForTfmSpecificContentInPackage);AddPerTFMDocsTasksToPackage
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+ <_TargetsForReferenceOutputs>ReferenceCopyLocalPathsOutputGroup;BuiltProjectOutputGroup
+
+
+
+
+
+
-
+
+
-
-
-
-
@@ -102,19 +94,4 @@
-
-
-
-
- $(PkgMicrosoft_Build_NoTargets)\Sdk
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/src/CloudNimble.DotNetDocs.Sdk.Tasks/GenerateDocumentationTask.cs b/src/CloudNimble.DotNetDocs.Sdk/GenerateDocumentationTask.cs
similarity index 97%
rename from src/CloudNimble.DotNetDocs.Sdk.Tasks/GenerateDocumentationTask.cs
rename to src/CloudNimble.DotNetDocs.Sdk/GenerateDocumentationTask.cs
index df40733..2e89ab5 100644
--- a/src/CloudNimble.DotNetDocs.Sdk.Tasks/GenerateDocumentationTask.cs
+++ b/src/CloudNimble.DotNetDocs.Sdk/GenerateDocumentationTask.cs
@@ -295,16 +295,6 @@ public override bool Execute()
generatedFiles.AddRange(yamlFiles);
}
- // Log statistics
- Log.LogMessage(MessageImportance.High, "📊 Documentation Statistics:");
- Log.LogMessage(MessageImportance.High, $" 📄 Documentation type: {DocumentationType}");
- Log.LogMessage(MessageImportance.High, $" 📦 Assemblies processed: {assemblyPairs.Count}");
-
- if (generatedFiles.Count > 0)
- {
- Log.LogMessage(MessageImportance.High, $" 📝 Files generated: {generatedFiles.Distinct().Count()}");
- }
-
// Return generated files as output
GeneratedFiles = [.. generatedFiles.Distinct().Select(f => new TaskItem(f))];
@@ -497,7 +487,7 @@ internal NavigationConfig ParseNavigationConfig(XElement navigationElement)
///
/// The group XML element.
/// A GroupConfig instance, or null if parsing fails.
- internal GroupConfig? ParseGroupConfig(XElement groupElement)
+ public GroupConfig? ParseGroupConfig(XElement groupElement)
{
var groupName = groupElement.Attribute("Name")?.Value;
if (string.IsNullOrWhiteSpace(groupName))
@@ -551,7 +541,7 @@ internal NavigationConfig ParseNavigationConfig(XElement navigationElement)
///
/// The integrations XML element.
/// An IntegrationsConfig instance.
- internal IntegrationsConfig ParseIntegrationsConfig(XElement integrationsElement)
+ public IntegrationsConfig ParseIntegrationsConfig(XElement integrationsElement)
{
var config = new IntegrationsConfig();
@@ -706,7 +696,7 @@ internal IntegrationsConfig ParseIntegrationsConfig(XElement integrationsElement
///
/// The styling XML element.
/// A StylingConfig instance.
- internal StylingConfig ParseStylingConfig(XElement stylingElement)
+ public StylingConfig ParseStylingConfig(XElement stylingElement)
{
var config = new StylingConfig();
@@ -732,7 +722,7 @@ internal StylingConfig ParseStylingConfig(XElement stylingElement)
///
/// The appearance XML element.
/// An AppearanceConfig instance.
- internal AppearanceConfig ParseAppearanceConfig(XElement appearanceElement)
+ public AppearanceConfig ParseAppearanceConfig(XElement appearanceElement)
{
var config = new AppearanceConfig();
diff --git a/src/CloudNimble.DotNetDocs.Sdk/Sdk/Sdk.props b/src/CloudNimble.DotNetDocs.Sdk/Sdk/Sdk.props
index eef732a..f5b0e49 100644
--- a/src/CloudNimble.DotNetDocs.Sdk/Sdk/Sdk.props
+++ b/src/CloudNimble.DotNetDocs.Sdk/Sdk/Sdk.props
@@ -6,7 +6,6 @@
Enables documentation files to be included in Visual Studio solutions
without compilation overhead or bin/obj folder creation.
============================================================================ -->
-
true
@@ -16,9 +15,6 @@
{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
-
- true
-
net8.0
@@ -73,23 +69,7 @@
$(BaseIntermediateOutputPath)
-
-
-
-
-
-
-
-
- <_NoTargetsFallbackPath>$(UserProfile)\.nuget\packages\microsoft.build.notargets\3.7.0\Sdk\Sdk.props
-
- <_NoTargetsFallbackPath Condition="!Exists('$(_NoTargetsFallbackPath)')">$(NuGetPackageRoot)microsoft.build.notargets\3.7.0\Sdk\Sdk.props
-
-
-
-
+
diff --git a/src/CloudNimble.DotNetDocs.Sdk/Sdk/Sdk.targets b/src/CloudNimble.DotNetDocs.Sdk/Sdk/Sdk.targets
index f39be88..8b40b65 100644
--- a/src/CloudNimble.DotNetDocs.Sdk/Sdk/Sdk.targets
+++ b/src/CloudNimble.DotNetDocs.Sdk/Sdk/Sdk.targets
@@ -6,23 +6,7 @@
Includes validation, generation, and integration targets.
============================================================================ -->
-
-
-
-
-
-
-
-
- <_NoTargetsTargetsFallbackPath>$(UserProfile)\.nuget\packages\microsoft.build.notargets\3.7.0\Sdk\Sdk.targets
-
- <_NoTargetsTargetsFallbackPath Condition="!Exists('$(_NoTargetsTargetsFallbackPath)')">$(NuGetPackageRoot)microsoft.build.notargets\3.7.0\Sdk\Sdk.targets
-
-
-
-
+
@@ -31,88 +15,91 @@
<_DotNetDocsTaskFramework Condition="'$(MSBuildRuntimeType)' == 'Full'">net472
<_DotNetDocsTaskFramework Condition="'$(_DotNetDocsTaskFramework)' == ''">net8.0
-
- <_DotNetDocsTasksFolder>$(MSBuildThisFileDirectory)..\tasks\$(_DotNetDocsTaskFramework)
- <_DotNetDocsTasksAssembly>$(_DotNetDocsTasksFolder)\CloudNimble.DotNetDocs.Sdk.Tasks.dll
+
+ <_DotNetDocsTasksFolder Condition="'$(_DotNetDocsTasksFolder)' == ''">$(MSBuildThisFileDirectory)..\tasks\
+ <_DotNetDocsTasksAssembly >$(_DotNetDocsTasksFolder)$(_DotNetDocsTaskFramework)\CloudNimble.DotNetDocs.Sdk.dll
+
+ AssignDocumentationProjectReferences;$(PrepareProjectReferencesDependsOn)
-
-
-
-
-
+ AssemblyFile="$(_DotNetDocsTasksAssembly)"/>
+
+
+
-
-
+
+ <_AllProjectsInRoot Include="$(IncludePatterns)" Exclude="@(ExcludePatterns)"/>
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+
- <_ProjectNames Include="@(DocumentedProjects->'%(Filename)')" />
+
-
-
+
+ DependsOnTargets="DiscoverDocumentedProjects;ResolveProjectReferences">
-
-
+
+
-
-
-
-
-
$(MSBuildProjectDirectory)
$(NamespaceMode)
-
-
-
-
-
-
+
+
+
+
-
-
-
@@ -189,12 +177,10 @@
-
+
-
-
@@ -205,10 +191,8 @@
-
-
diff --git a/src/CloudNimble.DotNetDocs.Sdk/readme.md b/src/CloudNimble.DotNetDocs.Sdk/readme.md
index 737ea74..15834fb 100644
--- a/src/CloudNimble.DotNetDocs.Sdk/readme.md
+++ b/src/CloudNimble.DotNetDocs.Sdk/readme.md
@@ -93,8 +93,6 @@ The SDK automatically detects your documentation type based on configuration fil
true
- true
- true
```
@@ -130,8 +128,6 @@ This is particularly useful when you want to:
| `GenerateMintlifyDocs` | Generate Mintlify documentation (requires EasyAF.Tools) |
| `LintMarkdown` | Lint markdown files for issues |
| `PreviewDocumentation` | Start local preview server |
-| `ValidateLinks` | Check for broken links |
-| `GeneratePdf` | Generate PDF output |
| `DeployDocumentation` | Deploy to hosting platform |
### DotNetDocs Integration
diff --git a/src/CloudNimble.DotNetDocs.Sdk/work-plan.md b/src/CloudNimble.DotNetDocs.Sdk/work-plan.md
new file mode 100644
index 0000000..4eacccb
--- /dev/null
+++ b/src/CloudNimble.DotNetDocs.Sdk/work-plan.md
@@ -0,0 +1,14 @@
+* Improve current SDK implementation
+ * improve discovery Task/logic
+ * don't do eval in DiscoverDocumentedProjectsTask x
+ * instead use Target calls x
+ * ensure that referenced projects are built before documentation generation x
+ * incrementality
+ * add a placeholder for multi-tfm handling
+ * improve sdk packaging x
+ * use nuget's per-tfm capabilities to do the current Task packaging x
+ * remove need for separate project x
+ * ensure deps are bundled per-TFM as well for correct loading x
+ * remove use of pinned-per-tfm extensions deps - newer versions are back-compatible x
+ * improve local use of custom SDK
+ * add explicit Imports to local samples for Sdk.props and Sdk.targets to remove need to build entire package and manage nuget package versions
diff --git a/src/CloudNimble.DotNetDocs.Tests.Sdk.Tasks/CloudNimble.DotNetDocs.Tests.Sdk.Tasks.csproj b/src/CloudNimble.DotNetDocs.Tests.Sdk.Tasks/CloudNimble.DotNetDocs.Tests.Sdk.Tasks.csproj
index 3aef87b..0a68e46 100644
--- a/src/CloudNimble.DotNetDocs.Tests.Sdk.Tasks/CloudNimble.DotNetDocs.Tests.Sdk.Tasks.csproj
+++ b/src/CloudNimble.DotNetDocs.Tests.Sdk.Tasks/CloudNimble.DotNetDocs.Tests.Sdk.Tasks.csproj
@@ -14,8 +14,9 @@
-
+
+
diff --git a/src/CloudNimble.DotNetDocs.Tests.Sdk.Tasks/DiscoverDocumentedProjectsTaskTests.cs b/src/CloudNimble.DotNetDocs.Tests.Sdk.Tasks/DiscoverDocumentedProjectsTaskTests.cs
deleted file mode 100644
index de8a1f5..0000000
--- a/src/CloudNimble.DotNetDocs.Tests.Sdk.Tasks/DiscoverDocumentedProjectsTaskTests.cs
+++ /dev/null
@@ -1,302 +0,0 @@
-using System;
-using System.IO;
-using CloudNimble.DotNetDocs.Sdk.Tasks;
-using CloudNimble.DotNetDocs.Tests.Shared;
-using FluentAssertions;
-using Microsoft.VisualStudio.TestTools.UnitTesting;
-
-namespace CloudNimble.DotNetDocs.Tests.Sdk.Tasks
-{
-
- ///
- /// Tests for the DiscoverDocumentedProjectsTask class, focusing on project discovery and filtering logic.
- ///
- [TestClass]
- public class DiscoverDocumentedProjectsTaskTests : DotNetDocsTestBase
- {
-
- #region Fields
-
- private DiscoverDocumentedProjectsTask _task = null!;
- private string _tempDirectory = null!;
-
- #endregion
-
- #region Test Lifecycle
-
- [TestInitialize]
- public void TestInitialize()
- {
- TestSetup();
- _task = new DiscoverDocumentedProjectsTask();
-
- // Set up a minimal build engine to avoid logging errors
- var buildEngine = new TestBuildEngine();
- _task.BuildEngine = buildEngine;
-
- // Create a temporary directory for test files
- _tempDirectory = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
- Directory.CreateDirectory(_tempDirectory);
- }
-
- [TestCleanup]
- public void TestCleanup()
- {
- // Clean up temporary files
- if (Directory.Exists(_tempDirectory))
- {
- Directory.Delete(_tempDirectory, true);
- }
-
- TestTearDown();
- }
-
- #endregion
-
- #region Project Discovery Tests
-
- ///
- /// Tests that DiscoverProjectFiles finds all project types.
- ///
- [TestMethod]
- public void DiscoverProjectFiles_WithValidDirectory_FindsAllProjectTypes()
- {
- // Create test project files
- File.WriteAllText(Path.Combine(_tempDirectory, "Test1.csproj"), "");
- File.WriteAllText(Path.Combine(_tempDirectory, "Test2.vbproj"), "");
- File.WriteAllText(Path.Combine(_tempDirectory, "Test3.fsproj"), "");
- File.WriteAllText(Path.Combine(_tempDirectory, "NotProject.txt"), "text file");
-
- var result = _task.DiscoverProjectFiles(_tempDirectory, null);
-
- result.Should().HaveCount(3);
- result.Should().Contain(p => p.EndsWith("Test1.csproj"));
- result.Should().Contain(p => p.EndsWith("Test2.vbproj"));
- result.Should().Contain(p => p.EndsWith("Test3.fsproj"));
- }
-
- ///
- /// Tests that DiscoverProjectFiles excludes projects based on patterns.
- ///
- [TestMethod]
- public void DiscoverProjectFiles_WithExcludePatterns_ExcludesMatchingProjects()
- {
- // Create test project files
- File.WriteAllText(Path.Combine(_tempDirectory, "MyProject.csproj"), "");
- File.WriteAllText(Path.Combine(_tempDirectory, "MyProject.Tests.csproj"), "");
- File.WriteAllText(Path.Combine(_tempDirectory, "MyProject.IntegrationTests.csproj"), "");
-
- var excludePatterns = new[] { "Tests", "IntegrationTests" };
- var result = _task.DiscoverProjectFiles(_tempDirectory, excludePatterns);
-
- result.Should().HaveCount(1);
- result.Should().Contain(p => p.EndsWith("MyProject.csproj"));
- }
-
- ///
- /// Tests that DiscoverProjectFiles finds projects in subdirectories.
- ///
- [TestMethod]
- public void DiscoverProjectFiles_WithSubdirectories_FindsProjectsRecursively()
- {
- // Create subdirectory and project
- var subDir = Path.Combine(_tempDirectory, "SubFolder");
- Directory.CreateDirectory(subDir);
- File.WriteAllText(Path.Combine(subDir, "SubProject.csproj"), "");
- File.WriteAllText(Path.Combine(_tempDirectory, "RootProject.csproj"), "");
-
- var result = _task.DiscoverProjectFiles(_tempDirectory, null);
-
- result.Should().HaveCount(2);
- result.Should().Contain(p => p.EndsWith("RootProject.csproj"));
- result.Should().Contain(p => p.EndsWith("SubProject.csproj"));
- }
-
- #endregion
-
- #region Project Filtering Tests
-
- ///
- /// Tests that ShouldIncludeProject returns true when no exclude patterns are provided.
- ///
- [TestMethod]
- public void ShouldIncludeProject_WithNoExcludePatterns_ReturnsTrue()
- {
- var projectPath = Path.Combine(_tempDirectory, "TestProject.csproj");
-
- var result = _task.ShouldIncludeProject(projectPath, null);
-
- result.Should().BeTrue();
- }
-
- ///
- /// Tests that ShouldIncludeProject returns true when project doesn't match exclude patterns.
- ///
- [TestMethod]
- public void ShouldIncludeProject_WithNonMatchingPatterns_ReturnsTrue()
- {
- var projectPath = Path.Combine(_tempDirectory, "MyProject.csproj");
- var excludePatterns = new[] { "Tests", "Samples" };
-
- var result = _task.ShouldIncludeProject(projectPath, excludePatterns);
-
- result.Should().BeTrue();
- }
-
- ///
- /// Tests that ShouldIncludeProject returns false when project matches exclude patterns.
- ///
- [TestMethod]
- public void ShouldIncludeProject_WithMatchingPattern_ReturnsFalse()
- {
- var projectPath = Path.Combine(_tempDirectory, "MyProject.Tests.csproj");
- var excludePatterns = new[] { "Tests", "Samples" };
-
- var result = _task.ShouldIncludeProject(projectPath, excludePatterns);
-
- result.Should().BeFalse();
- }
-
- ///
- /// Tests that ShouldIncludeProject matching is case insensitive.
- ///
- [TestMethod]
- public void ShouldIncludeProject_WithCaseInsensitiveMatch_ReturnsFalse()
- {
- var projectPath = Path.Combine(_tempDirectory, "MyProject.TESTS.csproj");
- var excludePatterns = new[] { "tests" };
-
- var result = _task.ShouldIncludeProject(projectPath, excludePatterns);
-
- result.Should().BeFalse();
- }
-
- ///
- /// Tests that ShouldIncludeProject handles wildcard patterns correctly.
- ///
- [TestMethod]
- public void ShouldIncludeProject_WithWildcardPattern_HandlesCorrectly()
- {
- var projectPath = Path.Combine(_tempDirectory, "MyProject.Tests.csproj");
- var excludePatterns = new[] { "*Tests*" };
-
- var result = _task.ShouldIncludeProject(projectPath, excludePatterns);
-
- result.Should().BeFalse();
- }
-
- #endregion
-
- #region Properties Tests
-
- ///
- /// Tests that _propertiesToEvaluate contains the expected properties and values.
- ///
- [TestMethod]
- public void PropertiesToEvaluate_ContainsExpectedProperties()
- {
- _task._propertiesToEvaluate.Should().ContainKey("IsTestProject")
- .WhoseValue.Should().BeFalse();
- _task._propertiesToEvaluate.Should().ContainKey("IsPackable")
- .WhoseValue.Should().BeTrue();
- _task._propertiesToEvaluate.Should().ContainKey("ExcludeFromDocumentation")
- .WhoseValue.Should().BeFalse();
- }
-
- ///
- /// Tests that properties can be modified for testing scenarios.
- ///
- [TestMethod]
- public void PropertiesToEvaluate_CanBeModified()
- {
- _task._propertiesToEvaluate["IsTestProject"] = true;
- _task._propertiesToEvaluate.Should().ContainKey("IsTestProject")
- .WhoseValue.Should().BeTrue();
- }
-
- #endregion
-
- #region Task Property Tests
-
- ///
- /// Tests that task properties have correct default values.
- ///
- [TestMethod]
- public void TaskProperties_HaveCorrectDefaults()
- {
- _task.Configuration.Should().Be("Release");
- _task.TargetFramework.Should().Be("net8.0");
- _task.DocumentedProjects.Should().BeEmpty();
- }
-
- ///
- /// Tests that task properties can be set.
- ///
- [TestMethod]
- public void TaskProperties_CanBeSet()
- {
- _task.SolutionDir = "C:\\TestSolution";
- _task.Configuration = "Debug";
- _task.TargetFramework = "net9.0";
- _task.ExcludePatterns = new[] { "Tests" };
-
- _task.SolutionDir.Should().Be("C:\\TestSolution");
- _task.Configuration.Should().Be("Debug");
- _task.TargetFramework.Should().Be("net9.0");
- _task.ExcludePatterns.Should().ContainSingle("Tests");
- }
-
- #endregion
-
- #region Argument Validation Tests
-
- ///
- /// Tests that DiscoverProjectFiles throws ArgumentException for null or whitespace solution directory.
- ///
- [TestMethod]
- public void DiscoverProjectFiles_WithNullSolutionDir_ThrowsArgumentException()
- {
- var action = () => _task.DiscoverProjectFiles(null!, null);
-
- action.Should().Throw();
- }
-
- ///
- /// Tests that DiscoverProjectFiles throws ArgumentException for whitespace solution directory.
- ///
- [TestMethod]
- public void DiscoverProjectFiles_WithWhitespaceSolutionDir_ThrowsArgumentException()
- {
- var action = () => _task.DiscoverProjectFiles(" ", null);
-
- action.Should().Throw();
- }
-
- ///
- /// Tests that ShouldIncludeProject throws ArgumentException for null or whitespace project file path.
- ///
- [TestMethod]
- public void ShouldIncludeProject_WithNullProjectPath_ThrowsArgumentException()
- {
- var action = () => _task.ShouldIncludeProject(null!, null);
-
- action.Should().Throw();
- }
-
- ///
- /// Tests that ShouldIncludeProject throws ArgumentException for whitespace project file path.
- ///
- [TestMethod]
- public void ShouldIncludeProject_WithWhitespaceProjectPath_ThrowsArgumentException()
- {
- var action = () => _task.ShouldIncludeProject(" ", null);
-
- action.Should().Throw();
- }
-
- #endregion
-
-
- }
-
-}
\ No newline at end of file
diff --git a/test/MultiAssembly.ByAssembly.docsproj b/test/MultiAssembly.ByAssembly.docsproj
index 260f745..ecb48f6 100644
--- a/test/MultiAssembly.ByAssembly.docsproj
+++ b/test/MultiAssembly.ByAssembly.docsproj
@@ -1,11 +1,15 @@
-
+
+
$(MSBuildProjectDirectory)\byassembly-docs\
+ true
Mintlify
Folder
ByAssembly
+ *.docsproj;**.docsproj
+ ../src/**/*.csproj
@@ -34,4 +38,10 @@
+
+ <_DotNetDocsTasksFolder>$(MSBuildThisFileDirectory)..\src\CloudNimble.DotNetDocs.Sdk\bin\Debug\
+
+
+
+
\ No newline at end of file