WIP: Generate XML documentation from DocumentationAttribute for IDE IntelliSense #12

Closed
Copilot wants to merge 24 commits from copilot/enhance-documentation-tooltip into main
2 changed files with 164 additions and 11 deletions
Showing only changes of commit 2c19eb730e - Show all commits
+25 -11
View File
@@ -277,16 +277,11 @@ static string GetTypeName(Type type)
static void AddOrUpdateMember(XElement membersElement, string memberName, object attribute, Type docAttrType)
{
// Extract attribute values using reflection
var titleProp = docAttrType.GetField("Title");
var descProp = docAttrType.GetField("Description");
var argsProp = docAttrType.GetField("Args");
var exampleProp = docAttrType.GetField("CodeExample");
var title = titleProp?.GetValue(attribute) as string ?? "";
var description = descProp?.GetValue(attribute) as string ?? "";
var args = argsProp?.GetValue(attribute) as string[] ?? Array.Empty<string>();
var codeExample = exampleProp?.GetValue(attribute) as string ?? "";
// Extract attribute values using reflection - check both fields and properties
var title = GetMemberValue<string>(docAttrType, attribute, "Title") ?? "";
var description = GetMemberValue<string>(docAttrType, attribute, "Description") ?? "";
var args = GetMemberValue<string[]>(docAttrType, attribute, "Args") ?? Array.Empty<string>();
var codeExample = GetMemberValue<string>(docAttrType, attribute, "CodeExample") ?? "";
// Find or create the member element
var existingMember = membersElement.Elements("member")
@@ -314,7 +309,7 @@ static void AddOrUpdateMember(XElement membersElement, string memberName, object
}
// Add parameter descriptions as remarks
if (args != null && args.Length > 0)
if (args.Length > 0)
{
var remarksContent = new StringBuilder();
remarksContent.AppendLine();
@@ -332,3 +327,22 @@ static void AddOrUpdateMember(XElement membersElement, string memberName, object
memberElement.Add(new XElement("example", new XCData(codeExample)));
}
}
static T? GetMemberValue<T>(Type type, object instance, string memberName) where T : class
{
// Try as field first
var field = type.GetField(memberName);
if (field != null)
{
return field.GetValue(instance) as T;
}
// Try as property
var property = type.GetProperty(memberName);
if (property != null)
{
return property.GetValue(instance) as T;
}
return null;
}
@@ -0,0 +1,139 @@
# OmegaLeo.HelperLib.XmlDocGenerator
A tool that automatically generates XML documentation from `DocumentationAttribute` custom attributes, making them visible in IDE tooltips.
## What Problem Does This Solve?
The `DocumentationAttribute` is a custom attribute that allows you to document classes, methods, and properties with rich information including descriptions, parameters, and code examples. However, custom attributes don't automatically appear in IDE hover tooltips.
This tool solves that problem by:
1. Reading the compiled assemblies after build
2. Extracting information from `DocumentationAttribute` instances
3. Generating/augmenting the XML documentation file with this information
4. Making the documentation visible in IDEs like Visual Studio and JetBrains Rider
## How It Works
The tool is automatically run as a post-build step in projects that include the MSBuild target. It:
1. **Loads the assembly** with proper dependency resolution
2. **Finds all types** with `DocumentationAttribute`
3. **Extracts documentation** information (Title, Description, Args, CodeExample)
4. **Generates XML** in the standard .NET XML documentation format:
- `<summary>` - from Description
- `<remarks>` - from Args (parameters)
- `<example>` - from CodeExample
## Usage
### In Your Code
Use the `DocumentationAttribute` as usual:
```csharp
[Documentation(
"MyMethod",
"This method does something important.",
new string[] { "param1: The first parameter.", "param2: The second parameter." },
@"```csharp
MyMethod(param1, param2);
```"
)]
public void MyMethod(string param1, int param2)
{
// Method implementation
}
```
### Build Integration
The tool is automatically integrated into the build process for projects that include the MSBuild target. No manual action is required.
When you build your project, you'll see a message like:
```
[DocumentationAttribute] Augmenting XML documentation for YourProject from DocumentationAttribute
```
### Viewing in IDE
Once built, hover over any method, class, or property with a `DocumentationAttribute` in your IDE:
- **Visual Studio**: Hover tooltip will show the documentation
- **JetBrains Rider**: Quick Documentation (Ctrl+Q / F1) will show the documentation
- **VS Code**: IntelliSense will show the documentation
## Configuration
The tool runs automatically after the Build target with these settings:
```xml
<Target Name="GenerateXmlDocFromAttributes" AfterTargets="Build">
<PropertyGroup>
<XmlDocGenExe>$(MSBuildThisFileDirectory)../OmegaLeo.HelperLib.XmlDocGenerator/bin/$(Configuration)/net8.0/OmegaLeo.HelperLib.XmlDocGenerator.dll</XmlDocGenExe>
<TargetAssembly>$(TargetDir)$(TargetFileName)</TargetAssembly>
<TargetXmlDoc>$(TargetDir)$(TargetName).xml</TargetXmlDoc>
</PropertyGroup>
<Exec Command="dotnet &quot;$(XmlDocGenExe)&quot; &quot;$(TargetAssembly)&quot; &quot;$(TargetXmlDoc)&quot;"
Condition="Exists('$(XmlDocGenExe)') And Exists('$(TargetAssembly)')"
IgnoreExitCode="true"
ContinueOnError="true" />
</Target>
```
## Requirements
- .NET 8.0 SDK (for building the tool)
- Projects must have `GenerateDocumentationFile` enabled (optional but recommended for best results)
## Troubleshooting
### Tool not running
- Ensure the XmlDocGenerator project is built first: `dotnet build OmegaLeo.HelperLib.XmlDocGenerator/OmegaLeo.HelperLib.XmlDocGenerator.csproj`
- Check that the path in the MSBuild target is correct relative to your project
### Documentation not showing in IDE
- Ensure the XML file is generated in the output directory
- For consumed packages, ensure the XML file is included in the package
- Restart your IDE if it doesn't pick up changes
### Assembly loading errors
- The tool uses `AssemblyLoadContext` to load assemblies and their dependencies
- Dependencies must be present in the same directory as the target assembly
## Examples
### Before (Custom Attribute Only)
```csharp
[Documentation("Calculate", "Calculates something", new[] { "x: First number", "y: Second number" })]
public int Calculate(int x, int y) => x + y;
```
**IDE shows**: No documentation (custom attributes don't appear in tooltips)
### After (With XML Doc Generator)
The same code now generates:
```xml
<member name="M:MyNamespace.MyClass.Calculate(System.Int32,System.Int32)">
<summary>Calculates something</summary>
<remarks>
Parameters:
- x: First number
- y: Second number
</remarks>
</member>
```
**IDE shows**: Full documentation with description and parameter information!
## Technical Details
- **Language**: C# (.NET 8.0)
- **Dependencies**: `System.Reflection.Metadata`
- **XML Format**: Standard .NET XML documentation format
- **Assembly Loading**: Uses `AssemblyLoadContext` for isolated loading
- **Performance**: Runs only during build, no runtime overhead
## Contributing
To modify the XML generation logic, see `Program.cs` in the XmlDocGenerator project.