Skip to content

Commit c439dd1

Browse files
committed
Improve XML documentation loading and support for additional Spectre.Console packages
1 parent c83f95c commit c439dd1

4 files changed

Lines changed: 58 additions & 27 deletions

File tree

Spectre.Docs.slnx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
<File Path=".github/workflows/publish-to-gh-pages.yml" />
1010
<File Path=".gitignore" />
1111
<File Path="README.md" />
12-
<File Path="Remove-TagsFromMarkdown.ps1" />
1312
</Folder>
1413
<Project Path="Spectre.Docs.Examples/Spectre.Docs.Examples.csproj" />
1514
<Project Path="Spectre.Docs/Spectre.Docs.csproj" />

Spectre.Docs/Components/Reference/WidgetApiReference.razor

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
@using System.Reflection
2-
@using Spectre.Console
32
@using Spectre.Docs.Services
43
@inject XmlDocumentationService XmlDocs
54

@@ -245,13 +244,17 @@
245244
return;
246245
}
247246

248-
// Get the type from Spectre.Console assembly
249-
var assembly = typeof(AnsiConsole).Assembly;
250-
var type = assembly.GetType(TypeName);
247+
// Get the type from Spectre assemblies
248+
Type? type = null;
249+
foreach (var assembly in XmlDocumentationService.Assemblies)
250+
{
251+
type = assembly.GetType(TypeName);
252+
if (type != null) break;
253+
}
251254

252255
if (type == null)
253256
{
254-
_error = $"Type '{TypeName}' not found in Spectre.Console assembly";
257+
_error = $"Type '{TypeName}' not found in Spectre assemblies";
255258
return;
256259
}
257260

@@ -364,8 +367,8 @@
364367

365368
private void LoadExtensionMethods(Type type)
366369
{
367-
var assembly = typeof(AnsiConsole).Assembly;
368-
var extensionMethods = assembly.GetTypes()
370+
var extensionMethods = XmlDocumentationService.Assemblies
371+
.SelectMany(GetLoadableTypes)
369372
.Where(t => t.IsSealed && !t.IsGenericType && !t.IsNested)
370373
.SelectMany(t => t.GetMethods(BindingFlags.Static | BindingFlags.Public))
371374
.Where(m => m.IsDefined(typeof(System.Runtime.CompilerServices.ExtensionAttribute), false))
@@ -404,6 +407,18 @@
404407
}
405408
}
406409

410+
private static IEnumerable<Type> GetLoadableTypes(Assembly assembly)
411+
{
412+
try
413+
{
414+
return assembly.GetTypes();
415+
}
416+
catch (ReflectionTypeLoadException ex)
417+
{
418+
return ex.Types.Where(t => t != null)!;
419+
}
420+
}
421+
407422
private string GetFriendlyTypeName(Type type)
408423
{
409424
if (type == typeof(void)) return "void";

Spectre.Docs/Services/XmlDocumentationService.cs

Lines changed: 33 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,19 @@ namespace Spectre.Docs.Services;
55

66
public class XmlDocumentationService
77
{
8+
private static readonly (string PackageName, string XmlFileName, Type MarkerType)[] _packages =
9+
[
10+
("spectre.console", "Spectre.Console.xml", typeof(Console.AnsiConsole)),
11+
("spectre.console.json", "Spectre.Console.Json.xml", typeof(Console.Json.JsonText)),
12+
("spectre.console.imagesharp", "Spectre.Console.ImageSharp.xml", typeof(Console.CanvasImage)),
13+
("spectre.console.cli", "Spectre.Console.Cli.xml", typeof(Console.Cli.CommandApp))
14+
];
15+
16+
public static IReadOnlyList<Assembly> Assemblies { get; } = _packages
17+
.Select(p => p.MarkerType.Assembly)
18+
.Distinct()
19+
.ToArray();
20+
821
private readonly Dictionary<string, XmlDocumentation> _documentation = new();
922
private bool _isLoaded;
1023

@@ -15,7 +28,7 @@ public XmlDocumentationService()
1528

1629
public XmlDocumentation? GetDocumentation(string memberName)
1730
{
18-
return _documentation.TryGetValue(memberName, out var doc) ? doc : null;
31+
return _documentation.GetValueOrDefault(memberName);
1932
}
2033

2134
public XmlDocumentation? GetDocumentation(Type type)
@@ -46,28 +59,29 @@ private void LoadDocumentation()
4659
{
4760
if (_isLoaded) return;
4861

49-
try
62+
foreach (var (packageName, xmlFileName, markerType) in _packages)
5063
{
51-
var xmlPath = FindXmlDocumentationPath();
52-
if (xmlPath == null || !File.Exists(xmlPath))
64+
try
5365
{
54-
// XML documentation file not found - service will return null for all lookups
55-
return;
66+
var xmlPath = FindXmlDocumentationPath(packageName, xmlFileName, markerType);
67+
if (xmlPath != null && File.Exists(xmlPath))
68+
{
69+
ParseXmlDocumentation(xmlPath);
70+
}
71+
}
72+
catch (Exception)
73+
{
74+
// Error loading XML documentation for this package - continue with next
5675
}
57-
58-
ParseXmlDocumentation(xmlPath);
59-
_isLoaded = true;
60-
}
61-
catch (Exception)
62-
{
63-
// Error loading XML documentation - service will return null for all lookups
6476
}
77+
78+
_isLoaded = true;
6579
}
6680

67-
private string? FindXmlDocumentationPath()
81+
private string? FindXmlDocumentationPath(string packageName, string xmlFileName, Type markerType)
6882
{
6983
// Strategy 1: Check assembly location (works when XML is copied to output)
70-
var assembly = typeof(Spectre.Console.AnsiConsole).Assembly;
84+
var assembly = markerType.Assembly;
7185
var assemblyPath = assembly.Location;
7286

7387
if (!string.IsNullOrEmpty(assemblyPath))
@@ -80,7 +94,7 @@ private void LoadDocumentation()
8094
}
8195

8296
// Strategy 2: Search NuGet global packages folder
83-
var nugetPath = FindInNuGetCache();
97+
var nugetPath = FindInNuGetCache(packageName, xmlFileName);
8498
if (nugetPath != null && File.Exists(nugetPath))
8599
{
86100
return nugetPath;
@@ -89,11 +103,11 @@ private void LoadDocumentation()
89103
return null;
90104
}
91105

92-
private string? FindInNuGetCache()
106+
private string? FindInNuGetCache(string packageName, string xmlFileName)
93107
{
94108
// Get NuGet global packages folder (cross-platform)
95109
var userProfile = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile);
96-
var nugetFolder = Path.Combine(userProfile, ".nuget", "packages", "spectre.console");
110+
var nugetFolder = Path.Combine(userProfile, ".nuget", "packages", packageName);
97111

98112
if (!Directory.Exists(nugetFolder))
99113
{
@@ -122,7 +136,7 @@ private void LoadDocumentation()
122136

123137
foreach (var tfmDir in tfmDirs)
124138
{
125-
var xmlPath = Path.Combine(tfmDir, "Spectre.Console.xml");
139+
var xmlPath = Path.Combine(tfmDir, xmlFileName);
126140
if (File.Exists(xmlPath))
127141
{
128142
return xmlPath;

Spectre.Docs/Spectre.Docs.csproj

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,5 +20,8 @@
2020
<PackageReference Include="MyLittleContentEngine.UI" Version="0.0.0-alpha.0.228" />
2121
<PackageReference Include="SixLabors.ImageSharp" Version="3.1.12" />
2222
<PackageReference Include="Spectre.Console" Version="0.54.1-alpha.0.7" />
23+
<PackageReference Include="Spectre.Console.Cli" Version="1.0.0-alpha.0.11" />
24+
<PackageReference Include="Spectre.Console.ImageSharp" Version="0.54.1-alpha.0.7" />
25+
<PackageReference Include="Spectre.Console.Json" Version="0.54.1-alpha.0.7" />
2326
</ItemGroup>
2427
</Project>

0 commit comments

Comments
 (0)