Co-authored-by: omegaleo <5655201+omegaleo@users.noreply.github.com>
4.8 KiB
Why Rider Shows Documentation Attribute Instead of XML Documentation
The Problem
When working in the HelperLib repository, hovering over methods in Rider shows:
[Documentation("TryGetValue", "Tries to get the value...", null, "")]
public bool TryGetValue(TKey key, out TValue value)
Instead of rich IntelliSense documentation.
Root Cause: Source Code Takes Priority
How IDEs Resolve Documentation
IDEs like Rider, Visual Studio, and VS Code follow this priority order:
- Triple-slash comments (
///) in source code ← HIGHEST PRIORITY - XML documentation files (
.xml) - Decompiled/reflected information
- Raw signature
What's Happening in HelperLib
Current state:
[Documentation("TryGetValue", "Tries to get the value...")]
public bool TryGetValue(TKey key, out TValue value)
{
// No /// comments here!
}
The test project uses <ProjectReference>:
- Rider can access the source code directly
- No
///comments exist in source - Rider shows the raw source code (including the attribute)
- XML file is ignored because source is available
The Solution: Add Triple-Slash Comments
Option 1: Minimal Comments (Recommended)
Add simple /// <summary> that references the documentation:
[Documentation("TryGetValue", "Tries to get the value from the NeoDictionary for the given key.")]
/// <summary>
/// Tries to get the value from the NeoDictionary for the given key.
/// </summary>
public bool TryGetValue(TKey key, out TValue value)
Benefits:
- ✅ Rider shows documentation immediately
- ✅ Works for developers with source access
- ✅ XML generator can still augment with additional info
- ✅ Standard .NET practice
Option 2: Generated Comments (Advanced)
Create a Source Generator that reads DocumentationAttribute and generates /// <summary> comments automatically.
Benefits:
- ✅ Single source of truth (the attribute)
- ✅ No duplication
Drawbacks:
- ❌ More complex
- ❌ Requires Source Generator infrastructure
- ❌ Comments generated at compile-time (not visible in source)
Option 3: Accept Current Behavior
Keep as-is and document that developers see attributes, consumers see XML.
Benefits:
- ✅ No code changes needed
- ✅ XML documentation works perfectly for NuGet consumers
Drawbacks:
- ❌ Poor developer experience in IDE
- ❌ Makes development harder
Why This Matters
For Library Developers (Us)
Working on HelperLib with ProjectReference:
- ❌ Without
///: See raw attributes, no IntelliSense - ✅ With
///: See rich documentation in IDE
For Library Consumers
Installing HelperLib NuGet package:
- ✅ Only have DLL + XML
- ✅ Always see rich documentation
- ✅ Not affected by source code
Recommendation
Add /// <summary> comments to all public APIs.
This is standard practice in .NET libraries:
- Microsoft does this (see .NET source code)
- Popular libraries do this (Newtonsoft.Json, etc.)
- Provides best developer experience
The DocumentationAttribute can still provide additional metadata:
- Code examples
- Extended remarks
- Structured argument descriptions
The XmlDocGenerator augments the XML with this additional content.
Implementation Plan
- Add
/// <summary>to all public types and members - Keep DocumentationAttribute for extended metadata
- XmlDocGenerator augments XML with attribute data
- Best of both worlds:
- Developers see documentation in IDE
- XML files have rich content from attributes
- Consumers get full documentation
Example
Before:
[Documentation("BenchmarkUtility", "Utility class for benchmarking code execution time.")]
public class BenchmarkUtility
{
[Documentation("Start", "Starts or restarts the stopwatch for the given key.")]
public static void Start(string key)
After:
[Documentation("BenchmarkUtility", "Utility class for benchmarking code execution time.", null, @"```csharp
BenchmarkUtility.Start(""MyBenchmark"");
// Code to benchmark
BenchmarkUtility.Stop(""MyBenchmark"");
```")]
/// <summary>
/// Utility class for benchmarking code execution time.
/// </summary>
public class BenchmarkUtility
{
[Documentation("Start", "Starts or restarts the stopwatch for the given key.")]
/// <summary>
/// Starts or restarts the stopwatch for the given key.
/// </summary>
/// <param name="key">The benchmark identifier</param>
public static void Start(string key)
Result:
- ✅ Rider shows documentation immediately
- ✅ XML file has base documentation
- ✅ XmlDocGenerator adds code examples from attribute
- ✅ Perfect IDE experience for everyone
Automated Solution
Could create a tool or analyzer that:
- Reads DocumentationAttribute
- Warns if no
/// <summary>exists - Suggests adding the summary from the attribute
This enforces the pattern and maintains single source of truth.