Intellisense and documentation together

Topics: Extensibility, General Discussion, General Questions
Oct 8, 2007 at 1:09 PM
Needless to say DocProject is a serious concept for software documentation. I am about to use it for my work. This is though my first time documenting anything, so here are my questions:

  • Is there any possibility to use xml comments from a DocSite for VS (Visual Studio 2005) Intellisense. That is instead of writing the <summary>above a class (in a .cs source file) - write it in the DocSite API Topic Manager. Then how should I cause VS Intellisense to search there? By the way, I haven't been able to see <include> of external XML files in the Intellisesne either.

  • How can I document method parameters in DocSite - via the API Topic Manager - should I add <param> to the DocProject config file for any types?

I hope you understand my direction - I want to document my work once, in a single place and still be able to use VS Intellisense. And I would prefer this place to be the DocSite Comments folder, rather than inline comments in .cs source files. (to keep them cleaner)

Thanks in advance,
Albert

ps Just out of curiosity -- how does the .net system class library work. Do they have a short version for Intellisense and a long one for the msdn documentation? And if so - is the short version inlined in the source files?
Oct 8, 2007 at 2:47 PM
Hi Albert,

Thanks for the feedback.


Is there any possibility to use xml comments from a DocSite for VS (Visual Studio 2005) Intellisense. That is instead of writing the <summary>above a class (in a .cs source file) - write it in the DocSite API Topic Manager. Then how should I cause VS Intellisense to search there?

That's a very good question. The answer is yes, it's possible to use the XML documentation generated by the API Topic Management Dialog in IntelliSense.

The XML files generated by the dialog are valid XML documentation files that can be read by IntelliSense. You just need them copied to the bin directory of each source project after they have been generated.

You can either copy the files manually, create a post-build event for the project or use your project's Build Process Component to copy the files. The latter approach is useful if DocProject merges the dialog's XML documentation with your source code documentation. You can find the merged files in the buildhelp\assembler\Comments\ folder after each build and you can add code to your project's Build Process Component to have it automatically copy them to your source projects' bin directories so they'll be picked up by IntelliSense. However, if you're not authoring comments then the merged documents will be identical to the documents in the Help\Comments folder, but if you or someone else would like me to submit a code snippet that can automatically copy the merged documentation back to each source project using the Build Process Component, please let me know and I will.

Do you think you'd want the option in DocProject to have it automatically copy the merged XML documentation files to the output directories of each corresponding project reference after a build?


By the way, I haven't been able to see <include> of external XML files in the Intellisesne either.

That has always bugged me too, which is why I used to use <include> for remarks and examples only, but now I just use DocProject instead :) I'm not sure if it's been fixed in VS 2008 either, but I hope that it is.


How can I document method parameters in DocSite - via the API Topic Manager - should I add <param> to the DocProject config file for any types?

If you want to use the designer then you have to add the <param> tag to DocProject's config file, as you suggested. Although, if you feel comfortable writing help in Visual Studio's XML editor then you could always just edit the files in the Comments folder directly.

I have already added a work item for making the list context-sensitive, with type-specific editors as well: Api Topic Mgmt: Extend Xml Summary Items List.


ps Just out of curiosity -- how does the .net system class library work. Do they have a short version for Intellisense and a long one for the msdn documentation? And if so - is the short version inlined in the source files?

You can find some of the Framework's XML documentation files in %windir%\Microsoft.NET\Framework\{version}. If you open up one, such as System.Data.xml, you'll find that there are no <example> or <remarks> elements.

If you want to create IntelliSense-only docs then I suggest using your project's Build Process Component to extract the <summary>, <param> and <returns> tags from the documentation. You may be able to use the CommentsManager Class and the CommentsDocument Class to make things easier.

Thanks,
Dave
Oct 8, 2007 at 4:41 PM
Hi Dave,

Thanks a lot for your prompt reply - it's really of great help.

I'll try the things you suggest and post back the answers to the couple of questions you ask (about auto copy xml files to project bins). I think I should implement some logic for distributing those files. That is, I'll use the DocSite to generate XML comments for more than 1 project participating in 1 solution. So the logic should divide the xml files by the project name or something like that... If you have a snippet for that - this would help

thanks,
Albert
Oct 8, 2007 at 8:47 PM
Hi Albert,

The Help\Comments folder contains one XML documentation file per project and one project.xml file, which contains the project and namespaces documentation only. So it's just a matter of iterating over the project's sources and copying the corresponding Help\Comments\{project}.xml file, if one exists, to the source's output folder.

The code that you need to add to your build process component's BuildCompleted method follows. Note that you'll have to add a reference to the DaveSexton.DocProject.Sandcastle.dll assembly, which you can find in the DocProject's bin folder, commonly at C:\Program Files\Dave Sexton\DocProject\bin. (The %DocProjectBuildPath% environment variable points to this directory as well.)

public override void BuildCompleted(BuildContext context)
{
  TraceLine();
  TraceLine("Exporting XML documentation files...");
 
  SandcastleBuildEngine engine = (SandcastleBuildEngine) context.Engine;
  SandcastleSettings settings = engine.Settings;
 
  string commentsPath = System.IO.Path.Combine(settings.BuildAssemblerWorkingDirectory, "Comments");
 
  foreach (string source in GetSources(engine))
  {
    string name = System.IO.Path.GetFileNameWithoutExtension(source) + ".xml";
    string commentsFile = System.IO.Path.Combine(commentsPath, name);
    string target = System.IO.Path.Combine(System.IO.Path.GetDirectoryName(source), name);
 
    try
    {
      System.IO.File.Copy(commentsFile, target, true);		// overwrite
 
      TraceLine("Exported \"{0}\" to \"{1}\"", commentsFile, target);
    }
    // the source file may not exist
    catch (System.IO.DirectoryNotFoundException) { }
    catch (System.IO.FileNotFoundException) { }
  }
 
  TraceLine("Done.");
  TraceLine();
  TraceLine("Total Time Elapsed: {0}", DateTime.Now - buildStart);
}
You'll also need to add the following GetSources method to the class.

Notice that I've commented out the code that uses the IDocProject.Sources property and hard-coded a few yield return statements instead. That is because the property uses a C# iterator, which generates a state machine at compile time that is not serializable and does not derive from MarshalByRefObject. But the BPC is running in a different AppDomain, which requires the state machine to be marshaled. Running the commented code will always cause an exception to be thrown when the Sources property is read.

For now, you'll have to hard-code the paths to the source projects as I've done in the example below, but I'll look into the problem and see if I can fix it for a later release. The goal is to be able to use only the commented code.

private IEnumerable<string> GetSources(SandcastleBuildEngine engine)
{
  string root = engine.Project.Directory;
 
  yield return System.IO.Path.Combine(root, @"..\TestLib\bin\Debug\TestLib.dll");
  yield return System.IO.Path.Combine(root, @"..\AI\bin\Debug\AI.dll");
 
  /* Return the output files of each project reference: 
   * 
  foreach (ISourceProject source in engine.Project.Sources)
  {
    IProjectOutput output = source.Output;
 
    if (output.OutputIsAssembly)
      yield return output.OutputFileName;
  }
  */
}
- Dave
Oct 9, 2007 at 11:15 AM
Hi Dave,

I need to ask for your help again, although this is not a DocProject issue.

I am not able to see (summary or any other) comments from a xml file created by DocProject in IntelliSense.

Here is what I've tried:

  1. I have a ClassLibrary project Pr1. I have some inline comments in it as well as I have added some summary via the API Topic Management Dialog (In the DocSite - both DocSite and Pr1 are in one solution).
  2. I have copied the Pr1.xml file generated by DocSite to Pr1/bin/debug directory - I am unable to see the comments from the DocSite xml, but just the inline from the Pr1 .cs files. The Pr1 project is set to generate xml comment output file.
  3. I opened another classlibrary project Pr2 in the same solution. I haven't configured it to output xml comment file. I have added no inline comments. Then I added several summary comments via the DocProject API Topic Management Dialog (In the DocSite). Copied the file Pr2.xml to the Pr2/bin/debug directory - no luck again. I see no comment at all.
  4. I've tried referencing the Pr1.dll from the Pr2 (both as project refference and only dll). In both cases I can't see comments from the DocSite xml file. I've even excluded Pr1 from the solution - no luck again

Is there something obvious I am missing? I checked several sources on the net - obviously people are able to do it, at list when referencing projects as dll's.

Is it possible to see IntelliSense from a xml file in bin, if I have a single project - that is, for classes and methods within the same project I am working on?

Thanks in advance,
Albert
Oct 9, 2007 at 12:19 PM
Hi Albert,


1. I have a ClassLibrary project Pr1. I have some inline comments in it as well as I have added some summary via the API Topic Management Dialog (In the DocSite - both DocSite and Pr1 are in one solution).
2. I have copied the Pr1.xml file generated by DocSite to Pr1/bin/debug directory - I am unable to see the comments from the DocSite xml, but just the inline from the Pr1 .cs files. The Pr1 project is set to generate xml comment output file.

I was able to reproduce this. I think this is a bug along the same lines as with the <include> tag, which is that IntelliSense only works from the source code for active projects in the current solution.


3. I opened another classlibrary project Pr2 in the same solution. I haven't configured it to output xml comment file. I have added no inline comments. Then I added several summary comments via the DocProject API Topic Management Dialog (In the DocSite). Copied the file Pr2.xml to the Pr2/bin/debug directory - no luck again. I see no comment at all.

That's expected. I think it's the same problem as the first.


4. I've tried referencing the Pr1.dll from the Pr2 (both as project refference and only dll). In both cases I can't see comments from the DocSite xml file. I've even excluded Pr1 from the solution - no luck again

This I can't reproduce. Using an assembly reference, even to another project in the same solution, seems to pick up the XMl documentation file next to the assembly. Although, you may want to try restarting VS if it doesn't (in my test I didn't even have to restart VS - I just changed the project reference to an assembly reference and it picked up the documentation in the XML file automatically).

Check that DocProject's output appears to be the same as the compiler's output (i.e., check the <assembly> and <member> tags for consistency). If you find any problems with DocProject's output please let me know. If you're not sure, then post the files here or email them to me and I'll check them out.

It's unfortunate that this doesn't work for active projects using project references. I'll do some research and see if this can be remedied with a setting, although I doubt it.

- Dave
Oct 9, 2007 at 5:24 PM
Hi Dave,

thanks for you reply,

That's how I currently see the picture:

Due to bugs or strange behavior in the host environment - that is VS2005, I'll have to downgrade to using inline comments at least for summary and method params. I can still add remarks, examples, exceptions, etc via the DocProject designer (In addition to custom topics of course).

That's such a pity. I'll still have some hope left for the answer from your research.

Again I want to stress on the fact that DocProject is the best concept (that serves my needs) I've found up to now. And I've searched a lot - for weeks. The trouble is in the host - if one wants to use the combination of documentation and IntelliSense.
And honestly I am pessimistic about next VS version fixing those irritating bugs (or changing their concept).

So I think I'll get started documenting - the people I do this for are getting nervous.

Regards,
Albert

ps - maybe the time has come for another environment, say Eclipse or so...
Oct 9, 2007 at 6:46 PM
Edited Oct 9, 2007 at 6:47 PM
Hi Albert,

Those issues can be irritating :|

I scanned the web for information about redirecting IntelliSense to look in the bin directory for active projects, but I've come up with nothing. But that doesn't mean it's not possible. Perhaps some registry manipulation or something could do the trick. Maybe you could submit this feedback to Microsoft at https://connect.microsoft.com/VisualStudio and get some info for us? ;)


Again I want to stress on the fact that DocProject is the best concept (that serves my needs) I've found up to now.

Thank you. I appreciate it :)

Have you actually tried to build and run the new DocSite template yet? I haven't received any feedback on the new format and features so I'm curious to know what you think.

Thanks,
Dave
Oct 10, 2007 at 2:40 PM
Hi everyone,

This is just an update about the bug that caused an exception when attempting to read the engine.Project.Sources property in my example above (the commented code). The bug has been fixed for the next release of DocProject. The example also incorrectly used output.OutputFileName when it should have been, output.OutputFile, but that has nothing to do with the bug that I fixed.

I've also enabled delegates, including anonymous methods, to be passed to the BuildContext.Invoke method from within a build process component by using the inherited Invoke methods instead (these new methods substitute a delegate with a delegate that can be marshaled correctly to the default AppDomain).

There are also new methods on the BuildProcessComponent class: AddBuildStep, InsertBuildStep, InsertBeforeBuildStep and InsertAfterBuildStep. These new methods allow authors to add dynamic build steps without having to create classes that implement IBuildStep. Here's an example:

public override void BuildStarting(BuildContext context)
{
  // Uncomment the following line to break into the debugger: 
  // System.Diagnostics.Debugger.Break();
 
  buildStart = DateTime.Now;
 
  InsertBeforeBuildStep("Build Assembler {sandcastle.help1x.config}", 
    "My Step", false, false, false, delegate(BuildContext stepContext)
  {
    stepContext.TraceLine("Hello from my dynamic build step!");
  });
}
The output is:

...
Step 8 of 14: My Step
Hello from my dynamic build step!
 
Step 8 Time Elapsed: 00:00:00.0170000
 
Step 9 of 14: Build Assembler {sandcastle.help1x.config}
...
I may blog about these updates as well.

- Dave