<inheritdoc /> support?

Feb 26, 2008 at 3:22 PM
Will we ever see support for <inheritdoc/> in Sandcastle?
JavaDoc has had this for years: http://java.sun.com/j2se/1.4.2/docs/tooldocs/windows/javadoc.html#inheritingcomments.

Karl
Feb 26, 2008 at 10:16 PM
Hi Karl,

GhostDoc might do that (I haven't used it myself so I can't say for sure). Although, I agree that it might be nice as a first-class feature of Sandcastle. You should add it to the Issue Tracker.

- Dave
Feb 26, 2008 at 11:16 PM
Hi Dave,


davedev wrote:
GhostDoc might do that (I haven't used it myself so I can't say for sure).

I tried it (I saw your reference already in another post with a similar topic), but the problem is, it just copies the base documentation.
So, when you change the docs in your base class, the change won't be propagated and you have to manually re-apply the GhostDoc function for every sub-class.

Although, I agree that it might be nice as a first-class feature of Sandcastle. You should add it to the Issue Tracker.

Done. Hope you can vote for it. :-)

Karl
Feb 27, 2008 at 12:23 AM
Edited Feb 27, 2008 at 12:26 AM
Hi Karl,

Vote+=1

I wonder if it could be extended to provide more control using an XPath expression, in the same vein as <include>:

/// <inheritdoc select="summary"/>
/// <remarks>
///   <para>
///   My new remarks, including the last paragraph from the remarks in the base class: 
///   </para>
///   <inheritdoc select="remarks/para[last()]"/>
/// </remarks>
/// <inheritdoc select="example"/>
public override void MyMethod() { }
Do you think that would be useful?

- Dave

(EDIT: Added override keyword to the example ;)
Feb 27, 2008 at 2:11 AM
Hi Dave,


I wonder if it could be extended to provide more control using an XPath expression, in the same vein as <include>:

/// <inheritdoc select="summary"/>
/// <remarks>
///   <para>
///   My new remarks, including the last paragraph from the remarks in the base class: 
///   </para>
///   <inheritdoc select="remarks/para[last()]"/>
/// </remarks>
/// <inheritdoc select="example"/>
public override void MyMethod() { }
Do you think that would be useful?


Definitely. However, I would make it behave like JavaDoc (see my link in a previous message), and apply an XPath expression only where it adds extra selectivity. Like:

/// <summary><inheritdoc/>Extra stuff added.</summary>
/// <remarks>
///   <para>
///   My new remarks, including the last paragraph from the remarks in the base class: 
///   </para>
///   <inheritdoc select="para[last()]"/>
/// </remarks>
/// <example>
/// <inheritdoc/>
/// <para>Extra example: ... </para>
/// </example>
public override void MyMethod() { }

Karl
Feb 27, 2008 at 2:48 AM
Hi Karl,

I skimmed over the article before I posted but I didn't see that feature, which is why I mentioned it :) I'll have to take another look.

Anyway, I do like the idea of having the tag work in XPath's context. Then you could still use my original example on the root:

/// <inheritdoc select="summary"/>
/// <remarks><inheritdoc/>  <para>Additional remarks.</para></remarks>
/// <example>
/// <para>All code blocks from the base documentation:</para>
/// <inheritdoc select="code"/>
/// </example>
- Dave
Feb 27, 2008 at 2:06 PM
Hi Dave,


davedev wrote:
I skimmed over the article before I posted but I didn't see that feature, which is why I mentioned it :)

Probably a misunderstanding. I didn't mean that JavaDoc supported XPath, just that it supported context.

Karl
Feb 27, 2008 at 2:28 PM
Hi Karl,


Probably a misunderstanding. I didn't mean that JavaDoc supported XPath, just that it supported context.

Yep. Thanks for clearing that up.

- Dave
Editor
Feb 29, 2008 at 2:26 AM
Edited Feb 29, 2008 at 2:31 AM
I gave this some thought and have been playing around for the past couple of evenings and I've just about finished a tool that can produce inherited documentation. It's a standalone tool so it can be used by SHFB, DocProject, or any custom build script or the default ones supplied with Sandcastle. You run it after MRefBuilder and, given a configuration file containing information about the reflection file and XML comments files to use, it will produce an additional XML comments file containing all members that have an <inheritdoc /> tag with all the comments expanded. You include this extra comments file as the last one in the list for the CopyFromIndexComponent that handles the "Copy in comments" task. Since it is last, its members override any matching members found in the files that preceed it.

I've got it working for root level occurrences and just need to wrap up support for occurrences nested within other tags such as in the examples above. Documentation can be inherited from any member in the project all the way up the chain into the base framework member comments. It supports a cref attribute that lets you explicitly tell it from which member to inhert docs or it will infer it from the base type(s) based on a set of rules. It also supports a select attribute to apply a filter to the inherited documentation.

I hope to have it completed this weekend and I'll post here when its available so that people can try it out, find bugs, suggest additional features, and more or less give it a good workout to see how it handles what everyone can throw at it. I'll start a separate thread here when it's ready.

Eric
Feb 29, 2008 at 3:40 AM
Very nice, Eric. Thanks.

Just to play devil's advocate for a moment though, don't you think that this functionality is better suited in Sandcastle's XSL transformations? Having the capability sooner than later is nice, but it is after all adding yet another external tool dependency for functionality that should probably be built-in to Sandcastle.

That said, if this is all we've got then I'd still like to use it :)

- Dave
Editor
Feb 29, 2008 at 4:26 AM
Bearing in mind that I don't know how to use XSL very effectively, my thought is that given what has to happen, I doubt it could be pulled off in an XSL transformation. I did consider making a build component but that had its drawbacks. The main one being that everything is topic-based so while you could probably expand docs for the member, the inherited summaries wouldn't show up in the list pages without some additional effort.

Eric
Feb 29, 2008 at 8:50 AM
Hi Eric,

XSL could definitely accomplish this, but I guess not by itself. A bit of the MS-extensions for injecting C# script into XSL might be required to do some of the dirty work, so I'll agree that it's probably not the most elegant solution.

However, the build component stack seems to provide all of the data that's required, AFAICT. Reflection information is indexed by one component and then another pulls in XML documentation, for the current topic. A replacement component for the one generating the XML documentation index could, theoretically, also parse comments for <inheritdoc/> tags while they're being pulled in and use the reflection information that's already in memory to find and replace those tags with inherited documentation. From here the rest of the process wouldn't need to change.

All of the current topic's inheritance info is already in memory, so it's just a matter of discovering the XML documentation from other files, which could be accomplished by transforming topic IDs from the current topic's inheritance data into documentation comment member IDs that can be found in the same XML documentation files that were indexed previously. Breaching that once-per-topic boundary seems easy enough then, but I don't see any limitations that would prevent this solution from working correctly.

Would you consider taking the business logic in your tool and moving it to a custom build component that can create the XML documentation index in place of the CopyFromIndexComponent that's currently being used?

- Dave
Feb 29, 2008 at 10:14 AM
Hi Eric,

I just gave it some more thought and took an in-depth look at CopyFromIndexComponent. Since IndexedDocumentCache is internal I can see how it would be difficult to replace that component after all. Also, it doesn't make it easy to get at the reflection data and documentation comments for other members, so I see what you mean now. However, a custom component that ran after the CopyFromIndexComponent that generates the comments index could still do what I suggested, but it would have to create a second reflection index and a second XML comments index, which would take up more memory and decrease performance.

I wonder though, if the Sandcastle team were to make IndexedDocumentCache and IndexedDocument public, and then extend CopyFromIndexComponent so that it supported plug-ins kind of like how syntax generation works, then at least the current topic's comments could be processed with full access to the entire comment index and reflection index. That would also be a very flexible way to manipulate documentation comments using plug-ins. For example, I could see an <include/> plug-in being implemented, which would work much how the compilers handle it currently. Another scenario would be a comment formatter; e.g., a separate Code Block Component might not be necessary - it could be written as a plug-in for CopyFromIndexComponent. This flexibility might solve other problems as well.

- Dave
Editor
Feb 29, 2008 at 3:52 PM
I did examine CopyFromIndexComponent and, as you found, there's too much stuff implemented privately to pull it off in a build component right now. I think it's a bit more involved than just exposing the index caches as there are probably other internal implementation details to consider that may not yet be apparent without a much closer inspection (i.e. the caches are effectively read-only as they use XPathNavigator objects). The code block component is paired with the post-transform component as it injects the scripts after the HTML transformation only if needed so I still see it being separate and not a sub-component of CopyFromIndexComponent even if it were possible.

The tool I've written does effectively mimic the component in some ways in that it indexes the comments files and creates a cache. It runs fast, generates one extra comments file, and there's no extra overhead when generating the topics during the build as the processing is already in place to override duplicate member comment entries. I view <inheritdoc /> as being similar to <exclude /> which is effectively handled by adding entries to the API filter in MRefBuilder's config file. It does the job more efficiently than XSL or a build component.

Eric
Mar 1, 2008 at 12:10 AM
Hi Eric,

Well I know that it wouldn't work using the current implementation of CopyFromIndexComponent, and yes the particular implementation of XPathNavigator being used by IndexedDocument is in fact read-only. I just thought that the Sandcastle team might like to accommodate the community's needs in a subsequent release :)

I do appreciate your effort and I'll certainly try out your tool.

Though I think that a build component would be more efficient because your tool is forced to create another in-memory index but a build component could use the cached data that's already in memory during builds. Producing only one, or one hundred comments files, doesn't make the tool more efficient since a build component wouldn't have to produce any.

- Dave
Mar 1, 2008 at 3:56 AM

davedev wrote:
Just to play devil's advocate for a moment though, don't you think that this functionality is better suited in Sandcastle's XSL transformations?


I read an old post about the PostSharp documentation, and I found an XSLT they use just after they apply the VS 2005 transformation:
http://code.thinkpond.org/viewvc.cgi/cslerp2/trunk/PostSharp/Documentation/ClassRef/TransformComments.xslt?revision=1&view=markup&pathrev=23

Karl
Mar 1, 2008 at 6:58 AM
Hi Karl,

Nice find. That's pretty much what I expected it would look like, although I assumed that a bit more C# would be required - maybe that would be true for our extension idea though.

I'd still like to see this implemented in Sandcastle, if possible. As a build component though it would probably increase performance.

- Dave
Editor
Mar 1, 2008 at 7:15 PM
If the build component interface opens up, I'll reconsider it.

Eric