Jolt : Querying XML Doc Comments

XML documentation comments is a feature supported by many .NET language compilers, allowing users to inline API documentation with the corresponding API source code. When parsing the inline documentation (1), a compiler will generally output this documentation into an XML file, which may then interpreted by an external tool. The following are some examples of external tools that process XML doc comments.
  • The Visual Studio IDE interprets XML doc comment files when rendering Intellisense information for functions and types.
  • The Sandcastle project aims to transform an XML doc comment file into a format resembling MSDN-style documentation.

The structure of an XML doc comment file is specified and publicly available, however there are two main challenges in processing such a file. First, there is no consistent way to locate an XML doc comment file for a given assembly (2) as the convention for storing XML doc comment files has changed three times with the first four releases of the .NET Framework. Second, there is no .NET Framework feature that encapsualtes type and member encoding rules for each documentation node in an XML doc comment file. Consequently, users must use an XML-query language to retrieve the data and implement the encoding rules in their applications.

Table of Contents

  1. Locating Xml Doc Comments
  2. Design Scope
    1. Query Limitations
  3. Usage Examples
    1. Converting a metadata type to its XML doc comment member name
    2. Overriding the default XML doc comment search paths
    3. Querying for the documentation of a given type
    4. Querying for the documentation of given members
    5. Querying for the documentation of all methods of a type
    6. Querying for the documentation of the current type or method
    7. Implementing a custom XML doc comment read policy

Locating Xml Doc Comments

The Jolt library aims to facilitate the processing of an XML doc comment file by using types that represent metadata as a key into the file. Using such types is a natural choice as they contain all the information that is required to retrieve documentation for a type or member, and also provide easy-to-read source code when used with the Jolt library. The Jolt.XmlDocCommentReader class provides the method GetComments(), which is overloaded for each of the types that may be represented in an XML doc comment file.

Furthermore, the Jolt library uses a list of predefined paths to existing reference assembly locations. These paths contain all of the XML doc comment files for the .NET Framework versions 3.5 and earlier, for both x86 and AMD64 architectures. The current release of the Jolt library will search for an XML doc comment file (for a given System.Reflection.Assembly object) in the following ordered locations.
  • The application's current directory, as returned by System.Environment.CurrentDirectory.
  • %ProgramFiles% (x86)\Reference Assemblies\Microsoft\Framework\v3.5
  • %ProgramFiles%\Reference Assemblies\Microsoft\Framework\v3.5
  • %ProgramFiles% (x86)\Reference Assemblies\Microsoft\Framework\v3.0
  • %ProgramFiles%\Reference Assemblies\Microsoft\Framework\v3.0
  • %SystemRoot%\Microsoft.NET\Framework\v2.0.50727\cc
    • Where cc represents the two letter ISO code of the application's current culture, as returned by System.Globalization.CultureInfo.CurrentCulture.TwoLetterISOLanguageName.
  • %SystemRoot%\Microsoft.NET\Framework\v1.1.4322
  • %SystemRoot%\Microsoft.NET\Framework\v1.0.3705

In order to query an XML doc comment file, the type or member must be encoded into a string. The Jolt.Convert class perfomrs this conversion, proving the method ToXmlDocCommentMember() for each of the types represented in an XML doc comment file. This class is used directly by the Jolt.XmlDocCommentReader class, and is publicly exported for developers who wish to implement their own query system into an XML doc comment data structure.

Design Scope

The XML doc comment querying implementation of the Jolt library is designed to support the following features.
  • Location of an XML doc comments file from an instance of the System.Reflection.Assembly type.
  • Customization of the paths used to locate an XML doc comments file.
  • Retrieve the XML doc comments for a given type or type member, by using an object of the following type.
    • System.Type
    • System.Reflection.ConstructorInfo
    • System.Reflection.EventInfo
    • System.Reflection.FieldInfo
    • System.Reflection.MethodInfo
    • System.Reflection.PropertyInfo
  • Convert an object from the aforementioned type list to a string representing the key to the XML doc comment data for that type.
  • Customize the way XML doc comment files are loaded and stored in memory.

Query Limitations

The initial testing of the Jolt.Convert.ToXmlDocCommentMember() method implementation was accomplished by writing tests that verify the encoding rules as specificed in the MSDN documentation, and by using the C# compiler to generate specific examples for comparison. Consequently, some features of the XML doc comment specification were omitted from the implementation as they cannot be exercised by the C# compiler. These features are listed as follows.
  • Member keys representing an error string (i.e. <member name="!:name"/>) are not queryable.
  • Parameters of type ELEMENT_TYPE_PINNED.
  • Parameters of type ELEMENT_TYPE_CMOD_OPT.
  • Parameters of type ELEMENT_TYPE_CMOD_REQ.
  • Parameters of type ELEMENT_TYPE_GENERIC_ARRAY.
  • Parameters of type ELEMENT_TYPE_FNPTR.

The C++/CLI compiler can assist in generating some of the XML doc comment tokens in the above list. However, deficiencies in the .NET reflection API prevent general access to types that are decorated with these tokens. For an analysis on these deficiencies, please refer to "Limitations to XML Doc Comment Parsing".

Finally, since it is not possible to query for the index of the first element through reflection, all multiple dimension arrays (ELEMENT_TYPE_ARRAY) are queried as if they were zero-based. Please check your compiler documentation to see if its output is compatible with the Jolt.XmlDocCommentsReader class.

Usage Examples


The following code snippet demonstrates how to obtain an XML doc comment member name from a metadata type instance.

using Jolt;
using System.Collections.Generic;
using System.Linq;

IEnumerable<string> GetMemberNames()
{
  yield return Convert.ToXmlDocCommentMember(typeof(int));
  yield return Convert.ToXmlDocCommentMember(typeof(string).GetMethod("ToLowerInvariant"));
  yield return Convert.ToXmlDocCommentMember(typeof(List<>).GetProperty("Count"));
  
  yield return typeof(string).GetConstructors().Select<ConstructorInfo, string>(Convert.ToXmlDocCommentMember);
}


The following XML configuration file demonstrates how to override the default search paths of the XmlDocCommentReader class.

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <configSections>
    <section name="XmlDocCommentsReader" type="Jolt.XmlDocCommentReaderSettings, Jolt" />
  </configSections>

  <XmlDocCommentsReader>
    <XmlDocCommentDirectories>
      <Directory name="."/>
      <Directory name="..\..\MyDocComments"/>
      <Directory name="C:\directory\MyOtherDocComments"/>
    </XmlDocCommentDirectories>
  </XmlDocCommentsReader>
</configuration>

Programmatic overriding of search paths is also supported, as demonstrated in the following snippet.

using Jolt;

void main()
{
  string[] directoryNames = { ".", @"..\..\MyDocComments", @"C:\directory\MyOtherDocComments" };
  XmlDocCommentReaderSettings settings = new XmlDocCommentReaderSettings(directoryNames);
  
  XmlDocCommentReader reader = new XmlDocCommentReader(GetType().Assembly, settings);
}


The following snippet demonstrates how to retrieve the XML doc comments for a given type.

using System;
using Jolt;

void AppendCommentsToDocument(XDocument document)
{
  // Loads the XML doc comments from mscorlib.xml.
  XmlDocCommentReader reader = new XmlDocCommentReader(typeof(int).Assembly);
  
  document.Add(reader.GetComments(typeof(int)));
  document.Add(reader.GetComments(typeof(string)));
  document.Add(reader.GetComments(typeof(DateTime)));
}


The following snipped demonstrates how to retrieve the XML doc comments for members of various types.

using System;
using Jolt;

void AppendCommentsToDocument(XDocument document)
{
  // Loads the XML doc comments from mscorlib.xml.
  XmlDocCommentReader reader = new XmlDocCommentReader(typeof(int).Assembly);
  
  document.Add(reader.GetComments(typeof(int).GetMethod("GetType")));
  document.Add(reader.GetComments(typeof(Console).GetEvent("CancelKeyPress")));
  document.Add(reader.GetComments(typeof(DateTime).GetProperty("Now")));
}


The following snippet demonstrates how to use the System.Linq extension methods to retrieve the documentation of all methods from a given type.

using System.Linq;
using System.Reflection;
using System.Xml.Linq;
using Jolt;

void AppendCommentsToDocument(XDocument document)
{
  // Loads the XML doc comments from mscorlib.xml.
  XmlDocCommentReader reader = new XmlDocCommentReader(typeof(int).Assembly);
  
  // Append documentation for all methods of the System.String type.
  document.Add(typeof(string).GetMethods().Select<MethodInfo, XElement>(reader.GetComments));
}


The following snipped demonstrates how to retrieve the XML doc comments of the enclosing type and currently executing method or constructor.

using System.Reflection;
using System.Xml.Linq;
using Jolt;

/// <summary>This is the documentation for <see cref="MyType"/>.</summary>
public class MyType
{
  /// <summary>Initializes the fields of the class</summary>
  public MyType()
  {
    m_reader = new XmlDocCommentReader(GetType().Assembly);
    m_comments = new XDocument();

    m_comments.Add(m_reader.GetComments(GetType()));
    m_comments.Add(m_reader.GetComments(MethodBase.GetCurrentMethod() as ConstructorInfo));
  }
  
  /// <summary>Does something with an <see cref="Int32"/> value.</summary>
  /// <param name="i">The integer to do something with.</param>
  public void DoSomething(int i)
  {
    m_comments.Add(m_reader.GetComments(MethodBase.GetCurrentMethod() as MethodInfo));
  }
  
  private readonly XmlDocCommentReader m_reader;
  private readonly XDocument m_comments;
}


The following snippet demonstrates how to override the default XML doc comment loading behavior in the Jolt.XmlDocCommentReader class.

using Jolt;
using System;

public class MyXmlDocCommentReadPolicy : AbstractXDCReadPolicy, IXmlDocCommentReadPolicy
{
  public MyXmlDocCommentReadPolicy(string docCommentsFullPath)
    : base(docCommentsFullPath) { }
  
  XElement IXmlDocCommentsReadPolicy.ReadMember(string memberName)
  {
    if (!m_cache.ContainsKey(memberName))
	{
	  XElement element = FindMemberInXml(memberName, base.CreateReader());
	  m_cache.Add(memberName, element);
	}
	
	return m_cache[memberName];
  }

  // Definition of private methods and fields removed for brevity.
}

void main()
{
  // Policy is provided to type via a factory method.
  XmlDocCommentReader reader = new XmlDocCommentReader(typeof(string).Assembly, path => new MyXmlDocCommentReadPolicy(path));
}



[1] Check with your compiler implementor to verify that this feature is supported. Microsoft implements this feature in the Visual C++, C#, and Visual Basic compilers.


[2] Refer to the Jolt.NET Development Blog for an analysis on locating reference assemblies.

Last edited Dec 6, 2009 at 7:15 PM by SteveGuidi, version 8

Comments

sehe Oct 11, 2010 at 10:24 PM 
Brilliant. I think I just found what I had been looking for. Thanks, will report success later