XML Doc Comment Conventions for cref Members

Topics: User Forum
Dec 24, 2009 at 6:21 PM
Edited Dec 24, 2009 at 8:01 PM

I am not sure if this is an SHFB question--it depends on whether this turns out to be user error or not :-). Given the code fragment shown, what is the proper way to specify cref members that are not simple types? I found an SHFB faq entry indicating to use curly braces for generic types but I have not found there nor anywhere else how to specify other non-simple types, as in the string array shown below. What I have shown here does not work:

/// <summary>
/// Creates a single phrase used in an SQL <c>where</c> clause;
/// see more at <see cref="M:GetPhrase(string,List{string})"/>
/// </summary>
public string GetPhrase(string fieldName, params string[] value) { ... }

/// <summary>
/// Creates a single phrase used in an SQL <c>where</c> clause;
/// see more at <see cref="M:GetPhrase(string,string[])"/>
/// </summary>
public string GetPhrase(string fieldName, List<string> value) { ... }

The SandCastle log file, interestingly, reports that the curly braces for the generic type does not work and that the "string[]" notation does not work.

  Warn: ResolveReferenceLinksComponent2: Unknown reference link target 'M:GetPhrase(string,string[])'.
  Warn: ResolveReferenceLinksComponent2: Invalid reference link target 'M:GetPhrase(string,string[])'.
  Warn: ResolveReferenceLinksComponent2: Unknown reference link target 'M:GetPhrase(string,List{string})'.
  Warn: ResolveReferenceLinksComponent2: Invalid reference link target 'M:GetPhrase(string,List{string})'.


So on the final help file web page I have the undesired result:
"Creates a single phrase used in an SQL where clause; see more at [M:GetPhrase(string,string[])]".

Am I using incorrect doc-comment notation or is there something else missing? Thanks!

UPDATE TWO HOURS LATER:
I believe I tracked down the root cause: The specification of the method parameters in the cref examples above are both correct--it is the specification of the method itself that caused the documentation failure. The presence of the "M:" caused SandCastle to fail; once I removed the "M:" then the hyperlink was correctly generated.

But this issue is not quite that simple! With the "M:" present, Visual Studio compiled the project with neither error nor warning. That is what led me astray in the first place. So SandCastle and Visual Studio act differently towards that "M:". Once I realized this I looked for other places where links were not generated and they all were fixed by removing the "M:" (or "P:" in some cases).

Note, however, that I did find some uses of "M:" where it does work correctly in SandCastle. I did not do extensive testing but it looks like the "M:" works when the cref specifies a fully qualified namespace on the method name (rather than letting the system figure out the path from a using directive).

If you see anything wrong in my description or know other idiosyncracies, please add your knowledge here!
Coordinator
Dec 24, 2009 at 7:50 PM
Edited Dec 24, 2009 at 7:54 PM

For generics, you always have to use the generic typeparam name(s) (i.e. List{T}, Dictionary{TKey, TValue}).  I don't think the compiler lets you specify concrete type names in the cref value.  However, if you include a prefix on the cref value such as "M:", it assumes you've given it a fully qualified name and it won't validate it and will pass it through as is even if it is incorrect.  That's the problem on the string[] method reference.  Since you included the "M:", the compiler didn't bother adding the full type name.  In such cases, you must add the fully qualified name so that it can be matched when building the help file.  In this case, you can remove the prefix and let the compiler fully qualify the name.  Once you do that, you should find that the string[] method reference is matched correctly.  You can do the same on the List{T} version since with the proper typeparam name, it will fully qualify it for you too.  For the most part, you can look at the method's signature in the XML comments file to get an idea of how to enter the parameter values in in the cref value.  The main difference is that you don't need to use the fully qualified .NET type names (i.e. you can use "int" instead of "System.Int32").  The exceptions are generic types which need the curly braces and typeparam names rather than how they are generated in the comments file which is some sort of encoded format using a numeric value to indicate the number of generic parameters.

Eric

 

Dec 26, 2009 at 12:54 AM

Looks like my subsequent edit "crossed in the mail" with your post, Eric -- nice to confirm I came to the correct conclusions :-)