Start Page

G h o s t D o c v2022.1

Welcome to GhostDoc v2022.1 Help

Getting Started

  • How do I get started?
    This QuickStart will guide you to a quick demo of GhostDoc's features.
  • Where can I read more about the basic ideas?
    The Introduction will tell you more about what GhostDoc is (and what it is not).
  • What features are included with different editions of GhostDoc?
    Please see the GhostDoc Edition Comparison - Community, Pro and Enterprise page.

About v2019 Release

Version v2019.1 adds compatibility with Visual Studio 2019.

For more detailed information about this and previous releases, see Release Notes.

Visual Studio support

Please note:

  • Version v2022.1 is compatible with VS2010, 2012, 2013, VS2015, 2017 and 2019.

Supported Languages

GhostDoc supports the following programming languages:

  • C#
  • Visual Basic
  • C++/CLI (managed only)
  • JavaScript

Contact

We have a GhostDoc discussion forum where you can post questions, bug reports and feature requests. If you want to contact the SubMain team, you can email us at support@submain.com.

See Also

  • GhostDoc Edition Comparison - Community, Pro and Enterprise
  • GhostDoc Tutorials and Resources
Don't remove the image, it is required for help compilation (the image and this text are hidden in the help file)
Copyright © 2003-2021 SubMain


Quickstart

G h o s t D o c v2022.1

Getting Started

To Get an Overview of GhostDoc's Features

New - the Getting Started with GhostDoc tutorial is now available online.

  • Download the GhostDoc Demo Project from the SubMain web site.
  • Extract the content of the ZIP file into a folder.
  • Open Demo.csproj (for C#) or Demo.vbproj (for VB) in Visual Studio
  • Inside Visual Studio, open the Demo.cs file (or Demo.vb respectively) and try the "Document this" command on properties and methods. You can access the "Document This" command either by selecting Tools -> GhostDoc (or GhostDoc Pro) -> Document This, or by using the default hotkey combination of Ctrl-Shift-D.
  • To try out the features in version 4.5, take a look at the files NewIn4.5.cs (or NewIn4.5.vb respectively) that contain some code to demonstrate the most popular uses of GhostDoc.


Introduction

G h o s t D o c v2022.1

Introduction to GhostDoc

Background

The XML documentation comments of .NET are very useful in many ways: Visual Studio shows their content in several places (for example, in tooltips in the code editor and in the object browser). Also, some tools (e.g. NDoc or Microsoft's documentation tool SandCastle) can automatically generate help files for you based on the content of the XML Comments. So overall, writing XML documentation comments sounds like a pretty good idea. Unfortunately it often consists of a lot of routine, boring work that simply has to be done.

Some things are especially tiresome to document, e.g. implementations of interfaces or overrides of base class members. Often documentation already exists but has to be copied manually over and over again. And then there are fairly obvious language elements like constructors (with a typical summary of "Initializes a new instance of the <see cref="Foobar" /> class."), or properties (remember how often you write "Gets or sets ...", or even worse "Gets or sets a value indicating whether..."?).

If you feel that you spend too much time on writing "bread-and-butter" texts, and too little time on finally adding that bit of really valuable extra info, GhostDoc is for you.

What does GhostDoc do?

GhostDoc installs a new command ("Document this") into the Visual Studio code editor context menu. When editing a source file, you simply navigate the cursor into the language element you want to document (or in front of it, on the same text line), and call the "Document this" command by either pressing a hotkey or using the context menu. GhostDoc will insert an XML documentation comment, much like typing "///" in front of a language element. But there’s a major difference: for specific language elements like methods and properties, GhostDoc attempts to generate large parts of the actual documentation for you. (Where it can’t - for instance with other language elements such as enums and their values - an empty summary will be generated).

If a class member is an interface implementation or override of a base class member, GhostDoc will use the existing documentation, regardless of where the interface or base class comes from. So basically what this means is that you can re-use tons of documentation that Microsoft wrote. Just remember the last time you implemented IEnumerable and thought about how to comment the GetEnumerator() method.

In those cases where no existing documentation can be used, GhostDoc attempts to analyze the code element name. Under certain conditions (we'll get to that later) GhostDoc actually does a very good job. Sometimes, the results may not be completely accurate or don’t make sense, but correcting the mistakes/problems in the generated documentation will still take less time than writing the whole comment from scratch.

But how can a tool with virtually no understanding of the English language generate often pretty accurate documentation? Well, the basic idea is pretty simple: GhostDoc assumes that your code follows Microsoft's Design Guidelines for Class Library Developers. In particular, and most importantly:

  • you are using PascalCasing or camelCasing to write identifier names consisting of multiple words
  • your method names usually start with a verb
  • you do not use abbreviations in identifier names

If you follow these rules (e.g. write "ClearCache()" instead of "Clrcch()") and choose more or less self-documenting identifier names, you give GhostDoc the best chance to produce a good result. GhostDoc will split the identifier names into words, tweak and/or shuffle the words a little and produce a comment that, while not always being perfect, gives you a head start on the way to good documentation.

As already mentioned, GhostDoc does not really understand English identifier names. Nevertheless, it attempts to apply certain rules to improve the quality of the generated comments:

  • Handling of verbs. GhostDoc assumes the first word of a method name is a verb. It will add trailing letters as needed to the verb, so Add becomes Adds, Do becomes Does, and Specify becomes Specifies.
  • "Of the" reordering. When GhostDoc finds a trigger word like "width", "height", or "name", etc., it reorders the string elements and inserts "of the". So, the comment for ColumnWidth becomes Width of the column, ChangePanelHeight method comment becomes Changes the height of the panel, and so on. You can add your own keywords to the trigger word list.
  • Certain specific prefix words are given special handling when the "of the" reordering applied. Words such as "maximum", "Minimum" and "new" all fall into this category. In these cases, the comment is reordered so that MaximumColumnWidth becomes "Maximum width of the column" instead of "Width of the maximum column". Again, you can add your own keywords to the trigger word list.
  • Automatic detection of acronyms. Acronyms that consist solely of consonants (e.g. Html, Gui, or Ansi) are automatically changed to all upper case. Html becomes HTML, Gui becomes GUI, Ansi becomes ANSI. You can override this behaviour by editing the list of acronyms.
  • Words that shouldn't be prefixed by "the". Uses a list of words where the word should not be headed by "the". For example, AddItem becomes Adds the item, but BuildFromScratch becomes Builds from scratch, and not Builds from the scratch.

Here's an example of what GhostDoc is able to do: If you have a method "DetermineInputCacheSize", GhostDoc is able to create the summary "Determines the size of the input cache.". If you want to see more examples, take a look at the demo project as described in the QuickStart document.

As the quality of the comment depends on the quality of the identifier name, using GhostDoc for a longer period of time actually teaches the writing of consistent and self-documenting identifier names, which is definitely a nice added bonus.

What doesn't GhostDoc do?

GhostDoc can't work miracles, and the way it generates documentation may not always work well with your personal style. In particular, if you are not following the Microsoft Guidelines, you will most likely run into problems.

When GhostDoc is able to re-use documentation from interfaces and base class members, it simply copies the comments over. It does not check whether the comment still applies, which, for example, becomes obvious when you document an override of the ToString method of System.Object. The generated summary is "Returns a System.String that represents the current System.Object." (<see> tags omitted for clarity), where it should read "Returns a System.String that represents the current MyNamespace.MyClass.". A developer quickly figures out that in this case System.Object has to be replaced, but a tool like GhostDoc cannot (at least not without an extensive code analysis).

The free version of GhostDoc is a fully functioning tool for creating XML comments, allowing you to create the comments one at a time. Ghost Doc Free may be all you need for your comment creation tasks. However, the Pro version does offer several very useful enhancements, which are listed below.

What is GhostDoc Pro?

GhostDoc Pro is an enhanced version of the product that gives you complete control over your XML Comment content and layout as well as automates XML Comment generation via batch actions.

The Pro version has all features of GhostDoc and adds:

  • T4 based XML Comment templates - total control over your XML documentation content and style
  • Document Type/File - generate XML comments for the entire type/class/file
  • Build a complete help file with a single click
  • Spell Check – an intelligent code spell checker that can check spelling for a file, a project, or even a complete solution
  • Documentation Quality hints in Visual Studio editor
  • Documentation Management assistance - find auto-generated comments, edit or remove the bulk created docs; identify and fix comments that are missing, out of sync or can be copied from base class; mark generated XML comments as auto-generated and "to be edited"
  • Select from multiple Help documentation themes.

See Also

  • GhostDoc Edition Comparison - Community, Pro and Enterprise


GhostDoc Documentation

G h o s t D o c v2022.1

GhostDoc Edition Comparison - Community, Pro and Enterprise

This page moved online, please see GhostDoc Edition Comparison - Community, Pro and Enterprise


What's New in this Release

G h o s t D o c v2022.1

Release Notes

Version 2022.1.21330 2021-11-26 (v2022 release)

  • Added: Support of VS2022 - the new 64-bit development environment from Microsoft
  • Added: Support for External XML Comments Files - external file is an alternative to placing documentation comments directly in your source code file
  • Added: <include /> tag to reference XML Comment in external file
  • Added: External XML Comment can be edited using Comment Editor while in the source code file
  • Added: New Move/Merge XML Comment to/from external file menus and commands
  • Added: New Move file XML Docs/Merge from XML Docs menus and commands to move all file XML Comments to or from an external file
  • Added: Generated comments statistics data for performance dashboard
  • Added: Support for high DPI resolutions in all GhostDoc dialog windows
  • Added: Support for file scoped namespaces in C#
  • Changed: Only VSIX setup now available for VS2017-VS2022, significantly reducing the download size
  • Changed: VS2013-VS2015 compatible add-on is only included with GhostDoc Enterprise
  • Changed: The Real-time Preview feature is now Off by default
  • Fixed: Issue parsing verbatim interpolation string
  • Fixed: Issue with the <returns /> tag when documenting async methods using Roslyn parser
  • Fixed: Preview Comment toolwindow backcolor now matches the theme selected in Visual Studio

Version 2021.2.21290 2021-10-17 (Maintenance release)

  • Added: Added .md to the list of spell checker supported extensions
  • Changed: No longer add inherited documentation for a member that has the new keyword
  • Fixed: Comment Editor - the Autogenerate button works correctly for VB code
  • Fixed: No longer add <inheritdoc /> for constructors
  • Fixed: Parsing issue with the creating anonymous object syntax in C# 9 "new(...)"
  • Fixed: Issue when using preprocess directives inside the <example /> tag
  • Fixed: Under certain scenarios, duplicate exceptions were added when Document This with existing comment
  • Fixed: Resolved issue when setting user TEMP folder as the destination to build the help documentation
  • Fixed: Resolved issue cleaning up target folder in Generate Help Documentation

Version 2021.2.21150 2021-05-30 (Maintenance release)

  • Added: New UseCurlyForGenerics solution property to switch between curly braces ({}) and "&lt;/&gt;" for generics
  • Added: New ClassicLookCHM solution property to switch between classic and modern icon sets in generated CHM docs
  • Fixed: Web themes would not switch under certain circumstances
  • Fixed: Issue when generating help preview and help docs with a note tag specified of a specific type
  • Fixed: Generated summary starts with a lower case character for async methods

Version 2021.2.21090 2021-03-31 (Minor feature release)

  • Added: Support for C# 9 syntax - Records, Nullable reference types, Init Only Setters, Extending partial methods, Pattern-matching changes (except Variable definitions and definite assignment), Top-level statements, Lambda discard parameters, Static anonymous functions, Attributes on local functions, Native-sized integers, Unconstrained type parameter annotations
  • Added: MSI setup is showing clear instructions to use the VSIX installer for VS2019 instead of the MSI/EXE
  • Added: Preview toolwindow supports dark theme
  • Added: Support the <inheritdoc /> tag at the class level
  • Added: cref attribute support in the <inheritdoc /> tag
  • Added: Visual Editor - show a warning when Esc pressed with unsaved edits in the example and note dialogs
  • Added: Memory optimization - the new DisableUndoAndSaveDocumentProject reduces VS memory use by saving all modified files when performing Document Project batch action
  • Added: Display a progress dialog when documenting a C++ type/file
  • Fixed: Now adding <param> and <typeparam> tags from the base member when use <inheritdoc /> tag
  • Fixed: Issue documenting a member with identical <exception> tags producing a duplicate cref record
  • Fixed: Issue with the <example> tags that includes <code> blocks with comments inside
  • Fixed: FlatDark.theme now shows vertical scrollbar
  • Fixed: C++ reference (ampersand) is now escaped in the generated XML Comment

Version 2021.1.20350 2020-12-05 (v2021 release)

  • Added: Dark Theme for help documentation
  • Added: Support for TypeScript language and TypeScript projects
    • Currently supported in
      • Document This
      • Re-document This
      • Document Type
      • Document File
      • Document Project
    • Not supported yet in
      • Document File Header
      • Document Checked Out Files
      • Exclude This from Documentation
      • Visual Comment Editor
      • Generate Help Documentation
      • Preview Comment
      • Documentation Maintenance
  • Added: Backup error-recovery compliant parsing engine that improves the quality of comment template generation in Document This/Type/File/Project, Comment Preview and Build Help Documentation
  • Added: Display subscription information in the About window
  • Changed: No longer distributing the legacy frame-based themes with GhostDoc - will be available for download at our support site
  • Fixed: Issue with TOC in web-based help docs with more than one namespace in it
  • Fixed: Resolved Solution Options -> General options being overwritten by the Settings Override values

Version 2020.2.20300 2020-10-26 (Minor feature release)

  • Added: Options -> Comment Editor - "Do not cache Comment Editor window" option to resolve issues rendering the Comment Editor
  • Added: Command line utility new parameter /msBuildFolder to set the location of the correct version of MS Build
  • Added: A backup code parser when the primary fails parse latest syntax changes
  • Added: Build help documentation now includes a warning when a source file can't be parsed correctly
  • Fixed: Command line utility loading references correctly for the .NET Core projects
  • Fixed: Issue with the command line utility not finding Microsoft.Build.dll
  • Fixed: Comment Editor - no longer removes \n after the comment
  • Fixed: Comment Editor - resolved freezing with the <see> and <seealso> tags
  • Fixed: Addressed the issue with auto-generated documentation not picking up documentation from the interface in some cases
  • Fixed: Parsing errors with the interpolation expressions
  • Fixed: Improved C# parser for default interface implementations, !null-forgiving operator and underscore number separator

Version 2020.2.20230 2020-08-20 (Maintenance release)

  • Fixed: Unhandled exception when building web help docs using a frameless theme
  • Fixed: Insert button is no longer disabled when inserting the <see> tag in the Comment Editor
  • Fixed: CSS style for section headings in CHM help
  • Fixed: Removed the unwanted leading whitespace when an XML comment is authored in the Comment Editor
  • Fixed: Correctly generating help docs for multiple property definitions in VB

Version 2020.2.20200 2020-07-20 (Minor feature release)

  • Added: New $(blankLine) macro to insert an empty XML Comment line with the leading /// (''')
  • Added: Now settings Export/Import and Rule Library Save/Load also save/load the rule enabled/disabled state
  • Added: Improved and optimized web help TOC generation in non-frame themes
  • Fixed: Comment Editor will no longer show up when the Re-Document action is selected
  • Fixed: Visual Editor not displaying correctly in the Comment editor under certain circumstances
  • Fixed: Unhandled exception in Community edition when using the Auto-generate option in the Comment Editor
  • Fixed: Build Help Docs failing when run on a non-english system locale
  • Fixed: Issue in Community edition when GhostDoc does retain existing <returns> tag for "void" methods
  • Fixed: Memory leak after using the Comment Editor
  • Fixed: Parsing issues related to the latest C# syntactical enhancements including "pattern match", "foreach" enhancements, "??=" operator, "ref struct", "await using" and "out var"

Version 2020.1.20070 2020-03-10 (v2020 release)

  • Added: New and improved syntax editor for Rule Template editor and Visual Editor
  • Added: Rule Template editor - easier template customization with improved Intellisense, added Quick Info (on mouse over), Completion List (Ctrl+Space), and Parameter Info
  • Added: Visual Editor - added Re-Document action
  • Added: Visual Editor - key combination Ctrl+Enter now saves and close the window
  • Added: Visual Editor - <see> and <seealso> authoring supported in the Visual Editor
  • Added: Support for <kbd> tag in GhostDoc themes, preview, help documentation, and Visual Editor
  • Added: New 'Document Checked Out Files' menu action
  • Added: Documentation Maintenance - now allow analysis on Solution/Project level for 'Missing Documentation', 'Auto-generated Documentation', 'Synchronize with member signature'
  • Added: Documentation Maintenance - improved responsiveness and performance when running the maintenance analysis on a large number of files or projects.
  • Added: (EE) New x64 command line utility allows producing help documentation for very large solutions
  • Added: Now can document local functions
  • Added: Improved summary/return value/param summary for async methods
  • Added: Arguments property to the Attribute class in T4 rule templates
  • Added: Added GroupSimilarExceptions option to group/ungroup exceptions in Constructor, Indexer, Event, Method, and Property rule templates
  • Fixed: Improved performance when typing /// in the Visual Studio code editor
  • Fixed: Spell Checker - improved spelling popup colors when using the dark theme in VS2019
  • Fixed: Visual Editor - Alt+Enter in the editable field no longer opens the web page properties dialog
  • Fixed: Visual Editor - resolved indent/unindent issues
  • Fixed: Visual Editor - fixed issue related to inserting <see>/<seealso> tag in a Note
  • Fixed: .xaml files are now ignored by the Document Project batch action
  • Fixed: C# parser now handles correctly the static keyword in local function
  • Fixed: Improved C# parser to handle some cases of the nullable reference types
  • Fixed: Fixed async local function declarations in C# parser
  • Fixed: Null-forgiving operator in C# parser
  • Fixed: Issue with the VB interpolated strings format syntax

Version 2019.3.19260 2019-09-17 (Maintenance release)

  • Added: Rule Template editor now includes Search dialog
  • Added: Help & Support\Show Extension Path menu opens the extension folder
  • Added: Help & Support\Show Settings Path menu opens the Settings folder
  • Added: Modified Constructor, Indexer, Event, Method, Property T4 templates to add "GroupSimilarExceptions" option to group (or not) exceptions when generating XML Comment
  • Fixed: Issue rendering tool windows in VS2019
  • Fixed: Tags TODO/<autogenerate /> no longer added when updating existing comment
  • Fixed: Issue when re-documenting Class after <seealso> is removed
  • Fixed: Issue documenting in VS2013 when VS2015 is installed
  • Fixed: Batch actions (Document Type, Document File) now skip methogs that have <exclude /> or <inheritdoc /> in XML comment
  • Fixed: Issue adding method parameter multiple times when re-documenting a VB property
  • Fixed: Issue with the comment previews when parentheses added to the property or field in a <see> link

Version 2019.2.19200 2019-07-19 (minor feature release)

  • Added: Support for C# 8 syntax
  • Fixed: Resolved inconsistency of rendering cref between Preview and generated docs
  • Fixed: Issue of attempting to document a .html file while using the Document Project command
  • Fixed: Incorrectly documenting an interface property when the signature is extended in the implementation
  • Fixed: Incorrectly documenting an Async method with Task return type that should be considered as void

Version 2019.1.19150 2019-05-30 (Maintenance release)

  • Added: TempFolderPath setting (%TEMP% by default) to the solution config/global - changing the setting moves the temp folder when GhostDoc builds help documentation
  • Fixed: Enterprise edition registration command line tool failed to register correctly under certain circumstances
  • Fixed: Parsing issue related to Tuples in the C# syntax
  • Fixed: Issue in the older iFrame themes in MS Edge on high zoom ratios
  • Fixed: Issue with image padding in MS Help Viewer
  • Fixed: Issue with image path macro in Visual Editor
  • Fixed: Issue with image path in MS Help Viewer
  • Fixed: Issue in the Community edition resulting in Macros custom text not added in Visual Editor
  • Fixed: Issue in the Community edition - Enter key in Custom text textbox in Marcos options closing the Options dialog
  • Fixed: Issue loading configuration define constants in .NET Core project
  • Fixed: Error when invoking IntelliSense in the rule T4 template editor in VS2019
  • Fixed: Issue with Document This in VS2012
  • Fixed: Spelling error when documenting method with name Max
  • Fixed: Overriding Global settings within the Solution properties

Version 2019.1.19100 2019-04-10 (v2019 Release)

  • Added: Support for Visual Studio 2019
  • Added: Options -> Solution -> Settings Override - New feature allowing to override any global setting at the solution level and introduce new custom solution settings that can be used in the rule templates
  • Fixed: Issue with adding notes in the Visual Editor
  • Fixed: Issue of Get/set property overriding base XML comment
  • Fixed: Issue resulting in duplicating header XML comment
  • Fixed: Improved the Options -> Dictionaries -> "^To(?-<pattern->.*)"
  • Fixed: Community edition property "Last word triggers an 'of the' reordering" rule where "Flag: Use value tag template?" flag wasn't working
  • Fixed: Incorrect exception summary with interpolated string as a message
  • Fixed: Parsing issue related to async local functions

Version 2018.2.19030 2019-01-30 (minor feature release)

  • Added: Visual Studio integration - migrated to Async support with background load enabled. This minimizes the GhostDoc load on Visual Studio startup.
  • Added:<inheritdoc /> tag - added Options -> Solution Options -> General -> "Use <inheritdoc /> tag for inherited comments" setting. When checked, GhostDoc will insert the <inheritdoc /> tag instead of copying the base member documentation. Note: When using the <inheritdoc /> remember it is a custom tag and you must use GhostDoc to generate help documentation and VS Intellisense files.
  • Added:<inheritdoc /> tag - modified Properties, Methods, Indexer, Event and Constructor T4 templates to insert the <inheritdoc /> tag instead of copying the base member documentation - when UseInheritdocTag setting is True.
  • Added: Encryptions within GhostDoc are now FIPS compliant.
  • Added: Abbreviations dictionary now allows abbreviations with an empty value. This enables skipping abbreviations and word parts like prefix, suffix etc.
  • Added: New XML Comment template is generated when Visual Editor opens using Ctrl-Shift-D for the member that does not have XML Comment.
  • Fixed: Improved license related error messages for clarity in Registration and Cmd utilities.
  • Fixed: Fixed parser issues in the particular Async use scenarios
  • Fixed: Issue when re-assigning shortcut to DocumentThis.
  • Fixed: Issue no scrollbar appearing in Visual Editor on high resolutions and high DPI fonts.
  • Fixed: Issue the Visual Editor inserting extra <p> tag
  • Fixed: Resolved tab indentation problem after using Autogenerate in Visual Editor.
  • Fixed: Visual Editor no longer adds extra indentation in the <code> section
  • Fixed: Visual Editor - adding Notes was not working correctly
  • Fixed: Issue with Options -> Dictionaries -> "^To(?<pattern>.*)" pattern being "greedy"
  • Fixed: Issue in GhostDoc Community with property "Last word triggers an 'of the' reordering" and "Flag: Use value tag template?"

Version 2018.1.18330 2018-11-26 (maintenance release)

  • Added: Solution Ignore List patterns now apply to folders/path as well
  • Added: Visual Editor improvement - when add a new section (e.g. <remarks>) the focus is set inside the new tag edit field
  • Fixed: Improved performance loading solutions with node_modules by ignoring these
  • Fixed: Occasional progress indicator ("Loading...") after closing Visual Editor
  • Fixed: Issue in C++ code when using Document This with Visual Editor enabled
  • Fixed: Issue of Visual Editor ignoring the "Keep single line under X characters" option value

Version 2018.1.18320 2018-11-16 (maintenance update)

  • Fixed: Improved GhostDoc Community edition performance

Version 2018.1.18310 2018-11-06 (maintenance update)

  • Fixed: Improved performance and usability of the Visual Editor dialog

Version 2018.1.18300 2018-10-27 (maintenance release)

  • Fixed: Resolved the issue of the Visual Editor not opening in GhostDoc Community in some cases
  • Fixed: No longer duplicating <summary> when runnning the Document Project command
  • Fixed: Issue with Visual Editor not rendering <see> or <seealso> tags correctly
  • Fixed: Updated the To{pattern} and New{pattern} entries in Options -> Dictionaries -> Summary Override - these now won't look for the pattern in the middle of the name
  • Fixed: Added "inheritdoc" into built-in dictionary - it will no longer be flagged as a misspelling
  • Fixed: Issue when adding <example> tag with a "title" attribute in Visual Editor
  • Fixed: Web documentation Classic scheme now generates correct table of content
  • Fixed: Long delays when documenting classes without a namespace (JavaScript)
  • Fixed: Issue with Document File Header command not executing for some users
  • Fixed: Issue in Visual Editor not refreshing after switching between tabs in under certain circumstances

Version 2018.1.18250 2018-09-07 (v2018 Release)

  • Added: New documentation output format - VS IntelliSense file
  • Added: Submit Bug Bounty Report menu item
  • Added: Support for regular expression support in Dictionaries - Summary Override - enables for flexible summary generation
  • Added: Support for documenting Visual Basic event parameters
  • Added: "Document This" in the Peek Definition (Alt-F12) window
  • Added: Attributes collection to the T4.Context
  • Added: Documenting test methods and classes based on the attributes
  • Added: "Obsolete" note in the generated help documentation, preview and Visual Editor for deprecated methods (marked with the Obsolete attribute)
  • Added: Revised support/help/feedback menu structure
  • Added: Support for <ddue:linkTarget> in the *.tokens files which enables using "target="_blank"" type of links in conceptual content
  • Added: Display documentation generation progress while populating reflection.xml file - the process does not look like it "hung" on large projects
  • Added: Log error message when file declared in MediaContent.xml does not exist
  • Changed: We retired the MS Help 2 documentation output format and replaced with it the VS IntelliSense format
  • Changed: Build Help Documentation window "Clean Up" button now shows a warning when the folder to be cleaned up is a System folder
  • Changed: Replaced the "No APIs found..." message with an improved message
  • Changed: Revised Build Help File to include "protected internal" when either "Protected" or "Internal" scope is selected
  • Fixed: Resolved VS2017 Update 15.8 compatibility issue - the VS freezing when comparing two versions of a source code file
  • Fixed: Context.HasExistingTagText and Context.GetInheritedTagText are now working with custom tags
  • Fixed: Issue when parsing string interpolation
  • Fixed: Issue with spell checker in string interpolation expressions
  • Fixed: Problem documenting with a custom rule for a constructor when the caret is set on an empty line inside constructor body
  • Fixed: Tab key now navigates between cells in Options -> Acronyms
  • Fixed: Issue with Document Project generating namespace comments when Namespace Template is unchecked in GhostDoc Options -> Rules
  • Fixed: Spelling Report toolwindow lock up
  • Fixed: Modified the File Header template to use the current file name (when renamed)

Version 2018.1.18150 2018-05-30 (Release Candidate)

  • Added: Visual Editor is now included with the free/community version of GhostDoc as well
  • Added: Introduced the Bug Bounty program - earn a license for helping us discover and fix bugs. Learn more
  • Added: The base web help documentation themes are now frameless. Original frame-based themes still shipped under new names
  • Added: Added search button in all help documentation themes
  • Added: Now prompt with guidance info when web help documentation search feature not on a server
  • Added: GhostDoc Community edition now requires a one-time free Community License activation after 30 days of use. Learn more
  • Added: Support for C# 7.2 and VB 2017 syntax
  • Changed: GhostDoc EULA has been split into Commercial License and Community License
  • Changed: Made changes to Community edition and license terms to clarify the personal use and eligibility. Learn more
  • Changed: Modified class summary template to include the "Implements" details when the class implements an interface
  • Fixed: Issue in GhostDoc Enterprise not building help documentation from command line in some cases
  • Fixed: Issue in GhostDoc Enterprise when building help file with conceptual content
  • Fixed: Issues for users with EN-NL code page in Windows
  • Fixed: "Badly formed XML comment" issue when inserting a table in the Visual Editor

Version 2018.0.18070 2018-03-09 (compatibility release)

  • Fixed: Resolved VS2017 Update 15.6 compatibility issue - the "Visual Studio still loading the project." message

Version 2018.0.18045 2018-02-14 (Beta 3 refresh)

Fixed the issues reported after the initial Beta 3 release.

  • Fixed: Code Contracts XML Comment sections are now rendering in the Visual Editor and help documentation.
  • Fixed: Visual Editor improvements
    • Resolved the "Badly formed XML comment" error when regular comments are included with the <code> block in XML Comment.
    • Now properly format the line breaks forced with Shift + Enter.

Version 2018.0.18030 2018-01-30 (Beta 3 release)

    In the Beta 3, we are continuing to build out the Visual Editor features as well as improvements and fixes.

  • Added: Document Project feature - now can generate XML Comment templates for a whole project
  • Added: Support for the <inheritdoc> tag - for type members only in the XML Comments as well as the generated help documentation. This allows using the tag instead of copying the documentation from base members and synchronizing the changes.
  • Added: Visual Editor improvements
    • New command - Add Table
    • New command - Remove Table
    • New command - Add Note
    • New command - Remove Note
    • Now the tags not recognized by the Visual Editor are added back to the XML Comment when saving the edits
    • Now render the Code Contract section preview
    • A number of improvements that impact proper XML comment generation
  • Added: /cleanup switch for the command line tool - when used will delete all files and folders in the output directory before creating help documentation.
  • Added: Support for Code Contracts when generating help documentation
  • Added: Added Options -> General -> 'Keep solution properties file in the .vs folder' allowing to hide the solution properties file (<solution path>.GhostDoc.xml) in the solution's .vs folder.
  • Added: Now GhostDoc solution settings file will reload when modified externally or within another instance of Visual Studio
  • Changed: The Cleanup checkbox in the Build Help Documentation dialog has been changed to a button. Now the folder must be cleaned up manually - this is to prevent accidental file loss when the output folder picked at an incorrect location.
  • Changed: Default toolbar icon is now Build Help Documentation where previously was Comment Preview
  • Fixed: Issue with the command line tool when loading .NET Core projects in MSBuild v15.1
  • Fixed: The Enable Spell Checking command now turns on/off only the real-time spell checking

Version 2018.0.220 2017-08-08 (Beta 2 release)

    Version note: we are changing the way we do the versioning for our products to keep it straightforward and simple. The new upcoming major GhostDoc version is to be v2018.x instead of the v6 we initially announced. Going forward we will have major versions by the year of the release.

    In the Beta 2, we are continuing to build out the Visual Editor features as well as improvements and fixes.

  • Added: New menu item and command - Open Comment Editor - with shortcut Ctrl-Shift-E to open Visual Editor for XML Comment
  • Added: Visual Editor improvements
    • New command - Insert Image
    • New command - Add Hyperlink
    • New command - Remove Hyperlink
    • Editors for the <code> blocks with encoding for the relevant XML elements to preserve well-formed XML Comment.
    • New option to replace <p> to <para>
    • New option to keep single line if the text is less than N characters (default: 200 characters)
    • New option to replace hard space (&nbsp;) with a regular space when the hard spaces are added by the Visual Editor
    • Resolved the issue breaking formatting of the XML Comment by adding leading tabs when using Visual Editor
    • Visual Editor is no longer showing security messages ("enable active content") when pasting from the Clipboard
    • When opening the Visual Editor now focus is in the Summary section
  • Added: New menu item and VS command - Document File Header - allows to generate/update the file header without having to re-document the file
  • Added: Progress indication for the Document File/Type batch actions with large number of the members to be documented
  • Added: Now .cshtml and .vbhtml file extensions are enabled for spell checking
  • Fixed: Improved performance of the Document File/Type batch actions
  • Fixed: Issue of missing readonly VB properties without get/set blocks when generating help documentation
  • Fixed: Issue related to the PathTooLongException when building help file - these now are attempted to get resolved automatically, and when fails GhostDoc shows a warning message
  • Fixed: No longer show Exception when previewing an empty member comment

Version 5.5.17181 2017-06-29 (v6 Beta 1 release)

    First public Beta if the new v6.x - our apologies for a bit of mess in versioning here

  • Added: Introduced Visual Editing for XML Comments

Version 5.6.17190 2017-07-09 (maintenance release)

    This update is highly recommended for VS2017 users.

  • Fixed: Improved support of VS2017 .NET Core projects
  • Fixed: Resolved the "Environment Integration error - Current file is not part of the project" error on VS2017 .NET Core projects
  • Fixed: Addressed issue of the realtime Spell Checker not highlighting misspellings when using MSI setup
  • Fixed: Resolved issue of the Documentation Quality Hints not rendering when using MSI setup
  • Added: Introduced support for "target" and "alt" attributes within the <see href="">, <seealso href=""> tags
  • Added: Enable Spell Checker and Show Documentation Hints in Editor are now Off when using the VS2017 VSIX setup
  • Fixed: Synced the use of lower and proper casing web-based help docs that used to cause errors when hosted on a UNIX server
  • Fixed: Issue calculating max file path when generating web-based help documentation
  • Fixed: JavaScript source files are not recognized by GhostDoc in VS2017
  • Fixed: Issue with comment inheritance in C++
  • Fixed: Suggestions when spell checking "Doesnt"
  • Fixed: Duplicates of the selected projects in .sln.GhostDoc.xml file
  • Fixed: Spell checker not taking IgnoreFiles into account in some cases

Version 5.5.17070 2017-03-11 (minor feature release)

  • Added: Support for VS2017 RTM
  • Added: GhostDoc is now also available as VSIX for VS2017
  • Fixed: Documentation Hints no longer visible in the Debug mode
  • Fixed: Issue wrapping lines within the <value></value> tag
  • Added: In the Offline Activation Preview - the fields are now auto-selected on focus/click for easy copying
  • Fixed: No longer adding extra line when re-documenting header in VB
  • Fixed: No longer appending generated XML comments to the existing comment when using auto-generated properties in VB

Version 5.4.16325 2016-11-20 (maintenance release)

  • Added: VS2017 RC integration
  • Added: New menu items - Getting Started Tutorial and Tutorials and Resources
  • Added: (Pro) (Ent) Edit buttons in Options - Solution Ignore List and Options - Spelling Ignore List
  • Added: (Pro) (Ent) Test button in Options - Solution Ignore List
  • Added: (Ent) Now GhostDoc shows error message when Conceptual Content path is invalid in the solution configuration file
  • Fixed: PathTooLongException exception when generating preview/build help file for C++ projects
  • Fixed: (Ent) Updated ClassLibrary1.zip, moved all conceptual content files inside the project in GhostDoc Enterprise\Samples\Conceptual Content\
  • Fixed: Issues documenting ReadOnly auto-properties in VB
  • Fixed: Issue re-documenting a type at the top of source code file in VB
  • Fixed: Issue with generating preview of the <seealso> tag for generics in VB

Version 5.3.16260 2016-09-16 (maintenance release)

  • Added: Full support for string interpolation in C# and VB parsers
  • Added: Support for "arrow functions" in JavaScript parser
  • Fixed: "File is not part of a solution" issue when loading projects
  • Added: (Pro) (Ent) IsAbstract property to CurrentCodeElement in the T4 templates
  • Changed: Improved exception documentation - now the type name in a nameof() parameter is added as part of the generated documentation template
  • Fixed: (Ent) Issue when using <section> along with <code> elements in an .aml file

Version 5.2.16200 2016-07-18 (minor feature release)

  • Added: Support for Visual Studio 2015 Update 3
  • Fixed: Now correctly loading the latest ASP.NET Core projects
  • Added: GhostDoc now treats underscore as a delimiter to improve summary generation for underscore delimited identifiers
  • Added: "Use Modern URLs" Help Configuration option for declarative help documentation file naming - namespace-classname-membername.htm
  • Added: Option to turn on/off Documentation Hints during setup
  • Added: (Pro) (Ent)Comment Preview is now rendered using the FlatGray theme
  • Changed: No longer creating the solution settings .ghostdoc.xml file if none of the default settings have been changed for the solution
  • Fixed: Issue when using the /// and ''' shortcuts at the end of file
  • Fixed: Issue when renaming a project within the Solution Folder
  • Fixed: (Ent) Incorrect cref linking when building help documentation from command line
  • Fixed: Exception text is now rendered correctly when the exception argument is a string interpolated string
  • Fixed: Issue using with Global namespace in VB.NET
  • Fixed: Custom property rules not working
  • Fixed: Help Configuration not saved when cancel out of the Build Help File
  • Fixed: Issue with Command Line utility failing when the output folder does not exist. The folder is now created when generating the help docs
  • Fixed: Problem with GhostDoc incorrectly identifying user path as a network location
  • Fixed: Help Configuration issue when Output Path points at a network location
  • Fixed: CSHTML files are no longer included as the Documentation Maintenance supported source file type
  • Changed: Renamed Browse button to Change in GhostDoc Options -> General -> User folder path
  • Fixed: Issue when handling expression body methods

Version 5.1.16036 2016-02-05 (maintenance release)

This update is highly recommended for Visual Studio 2015 users.

  • Added: Added property IsConst to CodeElement enabling proper identification for constants in the rule T4 template
  • Added: Comment Preview - both Refresh and Synchronize now work in GhostDoc Community
  • Added: Added a mutex to prevent GhostDoc setting file corruption when multiple instances of Visual Studio open/close simultaneously
  • Added: When time limited license expires, now showing appropriate message "The license code has expired on {date}."
  • Fixed: Resolved minor styling/formatting issues with the new Help documentation themes
  • Fixed: Expression bodied function followed by function with documentation no longer breaks the documenting function
  • Fixed: When using v4 license, GhostDoc won't anymore erroneously confirm the registration
  • Fixed: Resolved PathTooLongException when loading ASP.NET 5.0/ASP.NET Code 1.0 solution/project
  • Fixed: Issues with Visual Studio when documenting inside the Peek Definition window
  • Fixed: In the generated help documentation for the <example> tag no longer inserting extra blank line for VB sample code

Version 5.0.15325 2015-11-21 (feature release)

The free version of GhostDoc has been re-branded as GhostDoc Community Edition and adds general improvements, limited generation of CHM help documentation as well as the means to find auto-generated comments.

Both Pro and Enterprise editions of GhostDoc in version 5 introduce Documentation Quality hints in Visual Studio editor; Documentation Management assistance - find auto-generated comments, edit or remove the bulk created docs; identify and fix comments that are missing, out of sync or can be copied from base class; mark generated XML comments as auto-generated and "to be edited". The v5 also includes multiple Help documentation themes and layouts to choose from.

List of changes:

  • Added: Support for C# 6.0 and VB 14 syntax
  • Added: Documentation Quality hints in Visual Studio editor
  • Added: Documentation Maintenance - Find auto-generated comments - edit or remove the bulk created docs
  • Added: Documentation Maintenance - Identify and fix comments that are missing, out of sync or can be copied from base class
  • Added: (Pro) Help Configuration options for comments marked auto-generated or "to be edited" - Include/Ignore/Highlight
  • Added: (Pro) Theme support for generated help documentation
  • Added: (Pro) New help documentation themes - Flat Gray (default) and Flat Main. The old help doc view preserved as Classic theme. Web theme preview - Flat Gray and Flat Main
  • Added: (Pro) Help Configuration option to select help documentation theme
  • Added: (Pro) Help Configuration option to clean up the output directory before generating new help documentation
  • Added: (Pro) Options -> Rules dialog now allows to turn specific templates On or Off instead of blanking them out. Works with Document Type and Document File commands
  • Added: 'Exlcude This from Documentation' menu item - adds <exclude /> tag to the member
  • Changed: (Pro) Namespace Template is now turned Off by default
  • Added: Performance - new option - Options -> General -> "Show only Missing Comments hints for large files" - intended to improve GhostDoc editor hints performance when editing large source files. When On GhostDoc will not be analyzing in real-time for auto-generated comments and base class comments.
  • Added: Performance - Solution option "Search for inherited comments only within the project" - When turned On, this allows to improve GhostDoc Document This performance when executing first time on large solution (at the expense of potentially missing base members outside of the project). Default behavior for GhostDoc to look for base members within the complete solution.
  • Changed: New spelling window link color in Dark theme for better readability
  • Added: Support for VS2015 vNext ASP.NET 5 projects
  • Added: Hide/Show Comments feature
  • Added: Option to add a TODO reminder to edit auto-generated comment ("TODO Edit XML Comment Template")
  • Added: Option to add an <autogeneratedoc /> tag to flag XML comments that have been auto-generated
  • Added: New Summary Override table in Options - allows to configure predefined summaries for specific member or type names instead of auto-generated
  • Added: (Community) Build Help Documentation - a limited Build Documentation feature is now available in the Community edition of GhostDoc. Limited to one (Classic) theme only, very little configuration options and includes a watermark.
  • Added: Ability to tag at the class/interface level and have ALL the public elements in that class implicitly tagged
  • Added: Included a 'seealso' when a class / interface / struct inherits from another
  • Added: (Ent) Added 'nobullet' class to list element in MAML
  • Added: Now allow to add folders to "Ignore Files by Pattern"
  • Added: Ignore folders in IgnoreFiles by Pattern, for example, "*\MyFolder\*"
  • Added: GlobalNamespaceAlias global property - when changed will show up in the help documentation instead of the default "global" namespace for types with no explicit namespace
  • Added: Support for C++ template classes in help file
  • Added: Support for C++ links in cref, for example, <see cref="CtestdocApp::MyTestFunc2"/>
  • Added: Option to select source code syntax language(s) included with the help documentation
  • Added: Option to have the default summary text focused and selected when using Document This command - allows to edit/override the summary quickly
  • Added: Automatically calculate correctly the 'see' and 'seealso' links for members
  • Added: Included standard font names into the 'complang' spelling dictionary
  • Added: Support for documenting .aspx, .ascx and .asmx pages
  • Added: New macro $(newLine) correctly inserts blank line within XML comment
  • Added: (Community) About menu command and dialog
  • Fixed: XML Comment When Document This in .h file the XML Comment added within the .h file, for .c
  • Fixed: Now have all of the assemblies signed with our code signing certificate
  • Fixed: Inherited XML Comments are now properly copied for partial interface members
  • Fixed: Inherited XML Comments are now properly copied for partial class members
  • Fixed: Class summary does not render twice anymore for C++ types
  • Fixed: Issue in the File Header template - incorrect rendering of multi-line summary comments
  • Fixed: Missing inherited <summary> when documenting a constructor
  • Fixed: Tagged With now works properly with C++ code
  • Fixed: Issue with "ASP.NET web site" project help file showing an EXE assembly
  • Fixed: Issue with C++ EXE project help showing .DLL assembly
  • Fixed: Build Help file dialog - the project list now accommodates for longer project names
  • Fixed: Importing Options section from configuration file is now working correctly
  • Fixed: Issue with not applying inherited documentation from the base generic class
  • Fixed: Issue with Visual Studio freezing when documenting variable argument list parameter in C++ code
  • Fixed: (Ent) Issue with the command line utility when help file configuration file does have any projects selected
  • Changed: Options -> Rules buttons 'Export' and 'Import' renamed to 'Save' and 'Load' respectively
  • Changed: Revised the Configuration Wizard' behavior on start-up
  • Changed: Renamed SubMain.GhostDoc.Setup.exe to SubMain.GhostDoc.ActionProxy.exe
  • Changed: No longer copy the following files into the Visual Studio\Extension directory - *.exe.config, *.exe, *.log
  • Changed: (Community) The solution properties file (<solution name>.GhostDoc.xml) is no longer stored in the solution folder when none of the solution properties default values have been modified

Version 4.9.15086 2015-03-27 (maintenance release)

  • Changed: Now solution settings file .GhostDoc.xml is only saved when the default setting changed (the Free version only)
  • Changed: Renamed SubMain.GhostDoc.Setup.exe to SubMain.GhostDoc.ActionProxy.exe to reflect the purpose of the tool

Version 4.9.15071 2015-03-12 (maintenance release)

  • Added: Option to change location of the user folder to improve performance when Documents folder is mapped to a network/remote drive. Options -> General -> User folder path
  • Added: Option to turn troubleshooting log off and set it Off by default - performance improvement. Options -> General -> Enable Error Log
  • Changed: Made setup changes to prevent occasional enterprise setup issues
  • Changed: Removed the Configuration file path Options, still available to modify directly in the settings file.
  • Fixed: (Ent) Addressed some MAML elements rendered incorrect help documentation output. Fixed file main_conceptual.xsl
  • Fixed: Issues activating unicode licenses
  • Fixed: Warning/error growl messages no longer grab focus
  • Fixed: Resolved issue of duplicate attribute decorators appearing in the generated help documentation

Version 4.9.14358 2014-12-24 (minor feature release)

  • Added: Solution Options -> Ignore files by pattern with '*.min.js' and 'jquery*.js' included as default
  • Added: Option to turn Spell Checker on/off during setup
  • Added: Support for SQL Server projects
  • Added: New properties to the Context helper class - Context.AssemblyVersion, Context.AssemblyCopyright and Context.AssemblyCompany to be used in the T4 templates
  • Changed: Setup performance improvement - no longer executes 'devenv /setup' command when installing/uninstalling GhostDoc
  • Fixed: Addressed performance issues introduced in build 14262
  • Fixed: Addressed Visual Studio stability issue
  • Fixed: Performance lag when adding file or reference to solution
  • Fixed: Improved performance when documenting overridden member
  • Fixed: Triple slash (///) shortcut now generates XML Comment template in C++
  • Fixed: Resolved issue of occasionally not adding file header while cursor is above namespace
  • Fixed: Repositioned spelling suggestions popup to avoid covering the misspelled word

Version 4.9.14262 2014-09-19 (feature release)

  • Added: VS2013 Update 3 support
  • Added: Build Help File - New 'Inherited from References' option in the Help Configuration 'Scopes to include' allows to hide on the class documentation page those members that are inherited from 3rd party references
  • Added: Triple slash (///) shortcut now generates XML Comment template (triple quote (''') in VB) - alternative to Ctrl-Shift-D. Can turn this off in Options -> General.
  • Added: Beta feature - support for documenting JavaScript code. Help documentation for JavaScript docs is not implemented in this build
  • Changed: Improved cursor placement requirements to generate comment template - now cursor can be placed anywhere within the method
  • Fixed: Issue when coping documentation from interface
  • Fixed: Issue with Visual Studio hanging up when loading C++ project in VS2013 Update 3
  • Fixed: Issue with C++ properties not showing up in generated help documentation
  • Fixed: Visual Studio crash when pressing Ctrl-Tab with spelling tooltip shown
  • Fixed: Issue with relative path for output folder in the Build Help File dialog
  • Fixed: Issue in web site format of help documentation - backslash in PHP files instead of slash
  • Fixed: Issues with Shared/Universal App projects
  • Fixed: Issue with C# generic substitutes

Version 4.9.14147 2014-05-27 (feature release)

  • Added: (Ent) Command line version - enables generating help documentation during build process for a specific Help Configuration
  • Added: Support for Visual Studio 2013 Update 2 Shared Projects/Universal Apps
  • Changed: GhostDoc is no longer using Visual Studio Add-In API
  • Fixed: Issue when building help file in VS2012 (.hhc file not found)
  • Fixed: Spell checker causing Visual Studio freeze
  • Fixed: Resolved indentation issues when formatting inherited XML Comments
  • Fixed: No longer dropping <exception> tags in the documentation of a derived member

Version 4.9.14093 2014-04-03 (bugfix release)

  • Fixed: Incorrect sort order of in the generated documentation in VS2010
  • Fixed: When GhostDoc unloaded with the Unload menu it did not unload the spell checker
  • Fixed: Unhandled exceptions related to loading references
  • Fixed: Adding a misspelled word to Solution/User dictionary does not immediately remove all other misspelling occurrences
  • Fixed: Issue with generating <example> tag

Version 4.9.14064 2014-03-05 (bugfix release)

  • Added: (Ent) Ability to add custom pages to generated help documentation via Conceptual Content concept
  • Added: (Pro) Now reuse existing <summary> and <remarks> when available while generating File Header
  • Added: (Pro) (Ent) Preview button in Offline Activation allows to see content of the activation email request (to be sent from another machine)
  • Added: (Pro) Now can set a delay value to start spell checking document after it's been opened
  • Fixed: (Pro) When solution has multiple projects with the same name they will be handled correctly now
  • Fixed: (Pro) Issue when user image folder files are read-only files
  • Fixed: Issue incorrectly documenting operators
  • Fixed: Issue with nested generic parameters to a function not properly shown in the produced help documentation TOC
  • Fixed: Issue with interface method type parameters rendering incorrectly in help documentation
  • Fixed: Now escaping escaping '<' and '>' characters in crefs
  • Fixed: In the <returns> element, local generic type parameters are now referenced by name
  • Fixed: Now multiple type parameters in return type are separated by comma
  • Fixed: (Pro) In help file braces in generic types were incorrectly rendered as angle brackets
  • Fixed: Function prototype now does not contain the additional part denoting the number of generic parameters
  • Fixed: (Pro) Type parameter constraints are now visible in the produced help documentation
  • Fixed: Issues with <returns> when method returns an array
  • Fixed: (Pro) Context.AssemblyName was incorrectly returning project name
  • Fixed: Issue with inherited exception constructor documentation
  • Fixed: (Pro) Issue with Re-Document This duplicating summary text

Version 4.8.x 2013-11-12 (VS2013 sim-ship release)

  • Added: Official Visual Studio 2013 support
  • Added: (Ent) /localService command line switch to Registration utility for license activation using Enterprise Licensing Server
  • Fixed: (Pro) MS Help Viewer documentation is now generated correctly
  • Fixed: (Pro)Build Help File now works when solution contains two or more projects with the same name
  • Fixed: (Pro) Issue determining code sample language in mixed language web-site project
  • Fixed: (Pro) Issue generating incorrect documentation for "On" methods

Version 4.7.x 2013-08-14 (feature release)

  • Added: Visual Studio 2013 support
  • Added: Introduced GhostDoc Enterprise
  • Added: (Pro) Build Help - introduced notion of Help Configuration - save custom configured help generation settings and switch between them easily
  • Added: (Pro) Build Help - Help Content Targeting - ability to create a (partial) 'filtered' help file based on attributes by using <tags/> in XML Comment and tag filtering in Help Configuration. If you need to have different help content for public API users, testers, internal documentation, etc, you can do that now!
  • Added: Abbreviations dictionary enables expanding abbreviations to full words (for example, 'args' -> 'arguments')
  • Added: Non-breaking Words list to preserve splitting when comment template is generated (for example, 'CheckBox' or 'ListView')
  • Added: (Pro) Option to skip documenting private/internal/protected members with Document File/Type batch commands
  • Added: (Pro) You now can embed/reference images into the Help markup
  • Added: (Pro) Build Help - Visual Studio toolbar now has Build Help menu in the dropdown (this is not available for IDE prior to VS2010)
  • Added: (Pro) Build Help - .NET Framework classes are now hyperlinked to corresponding Microsoft reference page for additional information
  • Added: (Pro) Build Help - namespace documentation support in Comment Preview and Build Help
  • Added: (Ent) Ability to customize Comment Preview
  • Added: (Ent) Ability to customize Help template
  • Added: (Pro) Build Help - option to include inherited members into the generated help, in addition to those explicitly declared within the type (currently C# and VB.NET only)
  • Added: (Pro) Build Help - Help Configuration "private", "protected" and "internal" scope are now Off by default
  • Added: (Ent) Build Help - option to hide "Generated by GhostDoc" footer
  • Added: (Ent) New SubMain.GhostDoc.Registration utility for command line activation of Enterprise licenses
  • Added: Default rule for the Main method
  • Added: Options to Backup Configuration and Backup Template Library links within the Upgrade Wizard dialog
  • Added: 'Never check for updates' checkbox in the AutoUpdate dialog
  • Changed: (Pro) Changed True/False in T4 templates to $(True)/$(False)
  • Changed: (Pro) Spell Checker - user/solution dictionaries are now case insensitive
  • Changed: (Pro) Build Help - Code reference attributes (<see cref="{TypeOrMember}"/>) now correctly resolve within the solution (was only within current project in v4.5)
  • Fixed: Spelling tooltip grabs focus in the VS Editor
  • Fixed: Context.AssemblyName now works correctly in all T4 templates
  • Fixed: Scaling for DPI over 120
  • Fixed: Macros changes in Options dialog not saved
  • Fixed: Issue with compiler directives
  • Fixed: "Async method summary should end with: as an asynchronous operation."
  • Fixed: Generated web site help right-hand pane content was not visible in IE10+
  • Fixed: GhostDoc incorrectly determined Boolean (in C#) return type in rules
  • Fixed: Unloading References is slow when GhostDoc installed
  • Fixed: Unable to retrieve documentation from nested Interfaces
  • Fixed: Issue with documenting methods that contain anonymous methods
  • Fixed: Incorrect path to the html files in SearchHelp.aspx (web site help)
  • Fixed: Issue building help for C++/CX project on Windows 8
  • Fixed: public const int documented as public static int
  • Fixed: The new custom rule window closes when modifying filter parameters
  • Fixed: Duplicate partial types issue in help file
  • Fixed: "Skip This Version" did not work properly
  • Fixed: Issue when documenting member with existing exceptions in the documentation
  • Fixed: "Change the parameter type" dialog does not work
  • Fixed: GhostDoc needs to warn when building CHM or web site help without .NET Framework 4.0 installed

Version 4.5.x 2013-01-11 (feature release)

  • Added: (Pro) New Template Libraries feature with Export/Import
  • Added: (Pro) New output formats for generated Help files: Html Help1, MS Help 2, MS Help Viewer, Website
  • Added: (Pro) Custom tag support in Preview Comments and Build Help File
  • Added: (Pro) AllMembers, Methods, Properties, Events, Fields, Operators sections to the generated Help file
  • Added: (Pro) Options Dialog: solution specific settings for Ignore lists, Solution Dictionary and Help File
  • Added: (Pro) Options Dialog: option to maintain User Dictionary
  • Added: (Pro) Options Dialog: options to define Help file scope, header and footer
  • Added: (Pro) Spelling suggestions window to replace SmartTag. The older SmartTag option can be turned back on in the Options
  • Added: (Pro) Setup EXE support now command line parameter /extract to extract MSI file into TEMP directory
  • Added: (Pro) Context.DestinationFile to all rules
  • Changed: Moved cache folder to %LocalAppData%
  • Fixed: Incorrect type name in exception <cref> tag when the type name contains generic parameters
  • Fixed: Duplicate partial class issue in generated CHM file
  • Fixed: Changed C#-line in documentary <code> </code> to the actual project language
  • Fixed: Freezing when loading references on solution load in Visual Studio
  • Fixed: "GhostDoc.settings is being used by another process" issue
  • Fixed: Removed trailing space in the <see> and <seealso> elements
  • Fixed: Constructor incorrectly documented when the type has generic parameters

Version 4.0.x 2012-09-12 (feature release)

  • Added: Visual Studio 2012 support
  • Added: (Pro) Code Spell Checker
  • Added: C/C++ language support
  • Added: XML Comment Preview feature - see your comments as they appear in the help file.
  • Added: (Pro) New Visual Studio toolbar with documenting, comment preview and spell checking commands
  • Added: StyleCop compliance - revised all templates to be compliant with StyleCop rules
  • Added: Exception Documentation - exceptions raised within a method are documented in the XML Comment
  • Added: (Pro) File Header menu and template
  • Added: (Pro) IntelliSense to GhostDoc T4 template editor
  • Added: (Pro) Support for comments in T4 templates
  • Fixed: Configuration Wizard showing up when GhostDoc configuration is stored in a shared folder or shared between multiple versions of VS
  • Fixed: "Configuration file has been modified outside this instance of Visual Studio" when GhostDoc is used with multiple versions of VS
  • Added: New Version Notification
  • Added: (Pro) Offline Activation for users behind strict firewall
  • Resolved: "To generate XML comment you must select a type or a member" issue
  • Fixed number of reported issues

Version 3.0.x 2010-12-01 (feature release)

  • Added: (Pro) Document Type - generates XML comments for the entire type/class
  • Added: (Pro) Document File - generates XML comments for the entire file
  • Added: (Pro) T4 template based rules replace the rule macros of the Free version.
  • Added: Support for VS2010
  • Added: Load/Unload menu items
  • Added: Help menu item
  • Added: Re-assign Shortcut option and menu item
  • Added: Rule for read-only property to turn off generation of the tag line
  • Added: Rule for private constructor
  • Added: Support for new tags - <inheritdoc>, <author> and <remarks>
  • Added: Support for enums, delegates and fields
  • Added: Option to modify Configuration Folder path
  • Added: Option to Keep Single Line when
  • Changed: Insert leading spaces instead of tabs
  • Fixed: Changed "gets or sets" summary prefix to just "Gets" when setter is private
  • Fixed: Automatically implemented properties issue

Version 2.5.x 2009-06-01 (1st SubMain release)

  • Added: Support for VS2010 Beta 1.
  • Fixed: Support for VB - GhostDoc now has full support for VB.
  • Removed: "Enable experimental support for VB" option in Settings as not necessary anymore.
  • Added: Improved product setup experience.
  • Added: Single setup for all supported versions of Visual Studio - VS2005, VS2008 and VS2010.
  • Added: From now on setup will detect older veriosn installed and automatically uninstall it.
  • Changed: Converted from VS Add-In to VS Package.
  • Fixed: Many installation issues related to the VS Add-In model - by converting to VS Package.

Version 2.1.3 2008-01-06 (bugfix release)

  • Fixed: No documentation was generated for the operators "&", "<" and ">".
  • Fixed: Rules for classes, events, interfaces and structs were not shown in the export dialog, making it impossible to exclude them from an export.
  • Changed: Tags for empty rule collections in config files are now removed (cosmetic change, does not break compatibility of the file format).
  • Added: Some "of the" triggers and prefixes, "no the" words and acronyms.

Version 2.1.2 2007-11-25 (bugfix release)

  • Fixed: GhostDoc versions for Visual Studio 2005 and Visual Studio 2008 interfered when installed side-by-side.
  • Changed: An upgrade installation by starting the MSI file while an older version is installed is no longer possible. Things became increasingly complicated, and it didn't work under Vista anyway, so I ditched it altogether. Note that this does not affect the upgrade of the configuration of earlier versions: the configuration file is not removed during uninstallation of the GhostDoc add-in, so if you install a newer version afterwards, you'll still be offered to upgrade your existing configuration. For installation instructions, please take a look at the ReadMe in the ZIP file.
  • Added: A few special words for ("of the" trigger and prefix words, "no the" words).

Version 2.1.0 2007-06-24 (feature release)

Just a small feature update for C# developers, but for VB.Net developers this is what 2.0.0 should have been like.

  • Added: Support for Visual Basic .NET has been added again (was disabled in version 2.0.0), but still is regarded as "experimental". The feature is turned off by default and you have to turn it on in the configuration dialog.
  • Added: The setup for the demo project now contains a VB.Net version (huge thanks to Daniel Root for his help).
  • Added: Full rule support for events (configurable default documentation, inherited documentation e.g. for interface implementations, and used-defined custom rules)
  • Added: New macro $(DeclaringTypeKind) that specifies the kind of type a member is defined in (i.e. class, struct or interface).
  • Changed: All occurrences of "class" in the default templates have been replaced by "$(DeclaringTypeKind)".
  • Changed: As the next version of Visual Studio (codename "Orcas" ) will be named Visual Studio 2008, all texts have been updated accordingly.
  • Fixed: Problems with parameter names starting with an '@' (e.g. "@class").
  • Fixed: Documentation of constructors of structs referring to the initialization of a "class" instance.

Version 2.0.0 2007-05-01 (feature release)

Ok, this was supposed to be version 1.9.6, but after adding more features than fixes, this turned into a full-blown feature release. Most of the things I added came from my own everyday use of GhostDoc, plus an external feature request here and there (if it was a matter of hours, not days to implement). Please note that GhostDoc has a much lower priority for me than in previous years, that's why most larger feature requests will be added to my issue tracking database without a real chance of being implemented in the near future. But that shouldn't stop you from visiting the GhostDoc forum (see the link on the SubMain Web Site) and adding your wishes. When I'm working on GhostDoc I'm always combing the open items in my database; sometimes it's really easy to add one feature while adding another.

So here's what's new in version 2.0:

  • Added: Support for Visual Studio codename "Orcas". Note that GhostDoc for Visual Studio 2005 and GhostDoc for Visual Studio "Orcas" are released in separate setups and have to be installed into separate folders. Both offer equal functionality and thus share the same configuration file, though. This will stay this way as long as GhostDoc 2.x is released both for 2005 and "Orcas".
  • Added: Support for generic methods, the type parameters are now documented using the <typeparam> tag. For type parameter names starting with 'T' (e.g. "TKey") documentation text is generated (e.g. "Type of the key"), for all other type parameter names the text is left empty. Note that this behavior is currently hard-coded.
  • Added: New text generation rules for classes, interfaces and structs (with support for generic type parameters). The default rules generate empty summaries and place the cursor so you can start typing the summary immediately. It is possible to change the summary template to insert e.g. the class name split into individual words, but honestly I don't want to ship GhostDoc with that behavior by default as I didn't find it too helpful. In addition to the default rules, it's also possible to define custom rules (e.g. for classes with a name ending on a specific suffix).
  • Added: A new macro $(End) for specifying the location of the text cursor after the documentation text has been generated.
  • Added: A new macro $(Rule) that inserts the display name of the rule that generated for documentation text. Useful for debugging custom rules, this macro can e.g. be used in the custom text that is added to new doc comments (see the last tab of the GhostDoc configuration dialog).
  • Added: A macro of the format $(%VarName%) inserts the value of the environment variable with the name "VarName" (or an empty string if no variable with that name exists).
  • Added: A few language elements are now supported with limited functionality, i.e. without specific rule types (new rule types may be added in future versions, but they didn't have a high priority to be included in 2.0 as the existing functionality already helps a lot):
    • enums - empty summaries for the enum and all of its values
    • enum values - empty summary
    • events - summary starting with "Occurs when"
    • delegates - empty summary
    • variables - empty summary
    The cursor is moved inside the summary tag so you can start typing right away. As usual, existing documentation will not be overridden.
  • Added: New method rules:
    • A rule for Dispose(bool disposing)
    • A rule for overloaded operators
    • Rules for implicit/explicit conversion operators
    On a side note, these new rules have been implemented using custom method rules, i.e. using only what was already available in earlier versions of GhostDoc.
  • Added: Before upgrading or importing a configuration, it is now possible to quickly create a backup copy by clicking the link in the lower left of the dialog. This is useful especially during an upgrade installation.
  • Changed: The experimental support for VB.Net has been disabled in this release. I was pretty tight on my time budget and couldn't spend any time on keeping support for C# and VB.Net in sync.
  • Changed: The demo project is no longer installed to a sub-folder of the GhostDoc directory (where it caused problems when working with a non-admin account). Instead, the demo project is now an optional feature with its own setup, proposing an installation path in the user's Visual Studio project folder.
  • Fixed: Error message when installing GhostDoc by double-clicking the MSI file on a Vista system.
  • Fixed: When defining custom rules, conditions for method and type names didn't work well with type parameters (generics).
  • Fixed: The "Document this" command worked only when the cursor was positioned in a specific way. This has been relaxed, the cursor may now also be positioned on the whitespace before the language element (in the same line as the identifier), or somewhere inside the documentation comment.

Version 1.9.5 2006-07-30 (contest entry release)

This release contains minor updates of the documentation and changes regarding the text generation.

  • Changed: References generated by the $(ShortName...) and the $(FullName...) macros no longer generate the "T:" prefix, as this prevented the compiler from detecting broken references to renamed classes (thanks to forum user erwind for pointing out various issues with the "kind of" identifiers). Note that GhostDoc currently does not remove the qualifiers from inherited documentation.
  • Changed: Most generated texts now use the $(FullNameAsSee) macro, with the exception of the summary for constructors.

Version 1.9.4 2006-05-25 (bugfix release)

A couple of issues were found shortly after the release of 1.9.3 yesterday.

  • Fixed: Installation "For everyone" not working in 1.9.3 (since preview 3).
  • Fixed: Configuration dialog using huge amounts of CPU time when clicking certain parts.
  • Fixed: Inherited documentation in VB.Net sometimes being garbled.

The usual disclaimer: VB.Net support is regarded as "experimental", it is turned off by default and you have to turn it on in the configuration dialog.

Version 1.9.3 2006-05-24 (bugfix release)

This is a bugfix release dealing mostly with installation problems.

  • Fixed: GhostDoc not appearing in Visual Studio on systems that had Extensibility.DLL missing in the GAC (caused by uninstallation of other add-ins with buggy installer).
  • Fixed: GhostDoc not working on international (i.e. non-US) versions of Visual Studio:
    • Assignment of keyboard shortcuts not working on non-US versions
    • "Tools" menu not found on "Chinese Simplified" systems
  • Fixed: Problems with multiple users on a single machine.
  • Fixed: Problems with users working under non-admin accounts
  • Fixed: Documentation of indexers in VB.Net (remaining known issue: VB.Net indexers are treated like C# indexers - no explicit <param> tag for the parameter, only the first parameter is mentioned)
  • Changed: Summaries of VB.Net properties in interfaces now start with "Gets or sets ..." (remaining known issue: ReadOnly properties are not handled correctly, but that's not easy to correct right now)

Because of the known issues mentioned above, VB.Net support will still remain "experimental" in this release, so it is turned off by default and you have to turn it on in the configuration dialog.

Version 1.9.2 2005-12-12 (bugfix release)

VB.Net support will still remain experimental in this release, so it is turned off by default and you have to turn it on in the configuration dialog. It will become official in the next feature release, which I’ll be working on over the Christmas holidays.

Important: When updating from 1.9.0 please follow the instructions in the ReadMe.htm file in the ZIP archive. Users of 1.9.1 please uninstall before installing – an upgrade installation will not work correctly*.

  • Fixed: Installation issues with the US version of Visual Studio 2005 on a non-US operating system version (e.g. German WinXP).
  • Fixed: "Custom text" feature (see "Options" tab on the configuration dialog) was broken since 1.9.0.
  • Fixed: The rule for event-related "On..." methods generated text where the name of the event was split into individual words. Now the original name of the event is preserved; in order to achieve that, new macros have been added (see below).
  • Added: New "Verbatim" property of the "Words" macro. Example: for the method name "SayHelloWorld"
    • $(MethodName.Words.ExceptFirst) returns "hello world"
    • $(MethodName.Words.Verbatim.ExceptFirst) returns "HelloWorld".

________________________
*)I’m using an installer class during setup which in an upgrade installation is affected by a bug in MSI (which is known since 2002, btw). An upgrade installation is only possible without problems if the code of the installer class does not change – I hope that the changes in 1.9.2 to the installation are good enough for a couple of versions ;-)

Version 1.9.1 2005-11-20 (bugfix release)

The VB.Net support will remain experimental in this release, so it is turned off by default and you have to turn it on in the configuration dialog. A couple of issues (caused by small differences between the C# and the VB.Net file code model) have been fixed, and things are looking good in general so I’m confident I can drop the experimental status pretty soon.

Important: When updating from 1.9.0, please uninstall 1.9.0, start Visual Studio once, exit and then install 1.9.1. If you have customized your configuration, please export it before uninstalling 1.9.0, and import it after installation of 1.9.1. All steps are explained in detail in the ReadMe.txt file in the ZIP archive.

  • Fixed: Use of generics causing documentation not being generated.
  • Fixed: Installation not possible if "My Documents" folder is on network drive/share.
  • Fixed: VB.Net support: Inherited documentation causing either error messages or mixed up comments.
  • Fixed: VB.Net support: Property accessors being treated as methods.
  • Fixed: VB.Net support: Minor differences between C# and VB.Net file code model causing trouble.
  • Fixed: Some add-in issues (uninstallation, add-in manager)
  • Changed: The add-in is no longer installed to a sub-folder of the AddIns directory. Instead, any location can be chosen now on the harddrive.
  • Changed: In the generated comment, references to types ("<see cref="..." />) are now using the "T:" prefix that you may know from the inherited comments. This is to avoid the (new) warnings that Visual Studio 2005 is generating.

Thanks to Markus Hogsved for feedback on VB.Net support.

Version 1.9.0 2005-11-07 (contest entry release)

This is the first release of GhostDoc for Visual Studio 2005 and it's my entry for the Larkware Contest 2005. Some parts of the add-in code are just a straight port, other parts were rewritten (all rule-specific stuff was independent from Visual Studio and its file code model anyway). Funny that most problems I had were parts of my code that were broken by bugfixes in Visual Studio extensibility that I actually wished for.

  • Added: Experimental support for Visual Basic .NET. This is not an official feature and is turned off by default (you have to switch it on in the configuration dialog, on the "Options" tab). So far things look actually pretty good (I only had to program a few VB.Net-specific parts), but I simply haven't done enough testing to be sure it is ok. I'll see how much more VB.Net-specific work would have to be done, and then I'll decide on how much I more time I'll invest in this direction.


GhostDoc Documentation

  • How To and FAQ
  • GhostDoc Edition Comparison - Community, Pro and Enterprise
  • Dialogs
  • Rules
  • Macros


How To

G h o s t D o c v2022.1

How To and FAQ

How to Do Things

  • How to Assign a Hotkey inside Visual Studio
  • How to Export and Import Configuration Settings

Frequently Asked Questions (FAQ)

  • What Does GhostDoc Add to Visual Studio?


What Does GhostDoc Add to Visual Studio?

GhostDoc installs the following items in Visual Studio:

  • A "GhostDoc" submenu in the Tools menu
    This menu contains the following entries:

  • A "GhostDoc" submenu in the code editor context menu
    If you are a mouse user, you'll most likely use this: Point the mouse into the body of e.g. a method. click the right mouse button and select "GhostDoc" submenu from the menu popping up..

  • A hotkey for calling "Document this" (optional)
    The recommended way to call GhostDoc's generation of XML documentation comments is by using a hotkey, so you can keep both hands on the keyboard.


How to Assign a Hotkey

G h o s t D o c v2022.1

How to Assign a Hotkey inside Visual Studio

  • Open GhostDoc options dialog (Tools - GhostDoc - Options) to assign/change shortcut for Document This command

  • Open Visual Studio's options dialog (Tools - Options), then select "Environment - Keyboard".
  • On the options page for defining keyboard bindings simply type "ghost" in the "show commands containing" input field.

  • Open the "Use new shortcut in" drop down list and pick "Text Editor".
  • Now choose a hotkey (good luck finding one that's not already in use ;-) and press Assign
  • Leave the dialog with OK and that's it.


How to Export and Import Configuration Settings

  • Inside Visual Studio, open GhostDoc's configuration dialog (Tools - GhostDoc - Options).
  • The links for Importing/Exporting are in the lower left corner:

Export

The configuration of GhostDoc (or parts of it) can be saved to a ".gdc" file, e.g. if you want to sync your configuration at home with your configuration at work, or if you want to pass your custom rules to your friends or colleagues.

Click the Export link to open the Export Dialog, where you can specify what to export, and where to store it.

Import

Click the Import link and specify the name and location of the ".gdc" (GhostDoc configuration) file to read the configuration settings from. GhostDoc will then compare this file to the current configuration; if differences for the import exist, the Import Dialog opens and allows you to choose which items will be added and/or merged into the current configuration.


How to Build Help Documentation

  • Inside Visual Studio, open GhostDoc's configuration dialog (Tools - GhostDoc - Build Help Documentation...).


How to Preview Comment

  • Inside Visual Studio, open GhostDoc's configuration dialog (Tools - GhostDoc - Preview comment).

    • and take a look at Comment Preview tool window:


How to Exclude From Documentation

  • Inside Visual Studio, open GhostDoc's configuration dialog (Tools - GhostDoc - Exclude This from documentation).

    • and find the member excluded from documentation:


How to Find Auto-generated Documentation

  • Inside Visual Studio, open GhostDoc's configuration dialog (Tools - GhostDoc - Find Auto-generated Documentation).

    • and find Documentation Maintenance tool window:


GUI

G h o s t D o c v2022.1

Dialogs

  • Configuration dialog
    • Rules tab
      • "Add Rule" dialog
      • "Edit Rule" dialog
      • Word list editor dialog
      • Template text editor dialog
    • Acronyms tab
    • "Of the" Reordering tab
    • "No the" Words tab
    • Options tab
    • Import dialog
    • Export dialog
    • Import dialog


Configuration Dialog

What's This?

This dialog allows you to customize GhostDoc to your needs. You can change the way documentation comments are created, remove rules that you don't like, and add new completely new rules.

What You See

The dialog is divided into the following tab sheets:

  • General - configure various aspects of GhostDoc not fitting into the categories covered by the other tab sheets.
  • Macros - configure textual representation of some keywords and set custom text for the documentation comment.
  • Rules - modify, remove or add text generation rules.
  • Abbreviations - specify which words are to be treated as abbreviations.
  • Acronyms - specify which words (in addition to all-consonant words) are to be treated as acronyms.
  • Dictionaries - generate predefined Summary instead of the auto-generated Summary.
  • "Of the" Reordering - modify trigger and stop words
  • "No the" Words - specify which words must not be preceded by a "the".
  • Non-breaking" Words - specify which words will not be split.
  • Auto Update - configure auto updates
  • Solution Options - configure solution options
  • Solution Ignore List - configure solution files ignore list

What You Can Do

In addition to editing the settings on the tab sheets, you can open other dialogs by clicking on the corresponding links:

  • Export : opens the export dialog.
  • Import opens the import dialog.


Configuration Dialog: General

What's This?

This section lets you configure various aspects of GhostDoc not fitting into the categories covered by the other tab sheets of the configuration dialog.

What You See

  • Shortcut dropdown.
  • Checkboxes to mark/highlight auto-generated comments.
  • Checkbox and numeric updown to specify row characters limit.
  • User folder path textbox.
  • Checkbox to enable error logging.

What You Can Do

  • Assign shortcut for Document This command
  • Mark auto-generated comments with <autogenerated /> tag
  • Mark auto-generated comments with TODO
  • Highlight auto-generated comments when Document This
  • Keep signle line when the code line exceed specified number of characters
  • Specify user folder path
  • Enable error logging


Configuration Dialog: Macros

What's This?

This section lets you configure textual representation of some keywords and set custom text for the documentation comment.

What You See

  • Dropdown lists for selecting the textual representation of the C# keywords "true", "false" and "null".
  • A text field for defining the custom text that will be added when a documentation comment is created for the first time.

What You Can Do

  • Select the textual representation of the keywords "true", "false", "null", depending on whether you prefer better readability in source code, or better results with tools that generate help files from the documentation comments.
  • Edit the custom text that will be appended to the documentation comment of a class member (method, property, etc.) when it is created for the first time. It can be used e.g. for marking the date and time a class member was added, using the "environment macros".

Tip

  • Pressing the "..." button next to the text field for the custom text will open a template text editor dialog, which makes adding macros to the text easier.


Configuration Dialog: Rules

What's This?

This tab sheet of the configuration dialog lets you modify, remove or add text generation rules that control the generation of documentation comments.

What You See

  • A tree containing all active rules, divided into different categories (rules for indexers, rules for methods, etc.) and sorted by priority. In each category, the rules with the highest priority appear first.

What You Can Do

  • Add a rule: Select a position where to insert a new rule and press the Add button to open the Add Rule dialog.
  • Edit a rule: Select the rule and press the Edit button to open the Edit Rule dialog.
  • Remove a rule: Select the rule and press the Remove button to remove it. Note that while built-in rules can be added again easily, custom rules are lost forever. It may be a good idea to either create a backup of your current configuration, or at least of the rule to be removed (both using the Export dialog).
  • Increase the priority of a rule: Select the rule and press the "Move up" button. Note that the priority of the default rules cannot be increased.
  • Decrease the priority of a rule: Select the rule and press the "Move down" button. Note that the priority of the default rules cannot be decreased.

Tips

  • Double clicking a rule opens the Edit Rule dialog.
  • You can use the insert key for adding, and the delete key for removing rules.
  • Right clicking a rule opens a context menu.


Configuration Dialog: Abbreviations

What's This?

GhostDoc expands abbreviations into their full name.

What You See

  • A list of abbreviations and their full names

What You Can Do

  • Add, remove, modify abbreviations.


Configuration Dialog: Acronyms

What's This?

When splitting a identifier into single words, GhostDoc tries to detect acronyms, so e.g. the "Html" in "BuildHtmlText()" will be translated to "HTML" instead of "html". GhostDoc automatically treats all words consisting of only consonants (e.g. HTML, XML) as acronyms. Other acronyms (words containing vocals, e.g. UML) have to be defined explicitly, which can be done on this tab sheet of the configuration dialog.

What You See

  • An edit field for entering new words to be added
  • A list of words already contained in the configuration

What You Can Do

  • Enter a new word and press the Add button to add it to the list.
  • Select a word in the list and press the Remove button to remove it.


Configuration Dialog: Dictionaries

What's This?

Provides a mechanism for specific commonly used member names to generate predefined Summary instead of the auto-generated Summary. Member Name is case sensitive.

For example,
Member Name: "MyLogger"
Summary: "Reference to the standard logging component."

will override auto-generated content and produce the following Summary:

/// <summary>
/// Reference to the standard logging component.
/// </summary>
private readonly MyLogger;

What You See

  • An edit field for entering new words to be added
  • A list of words already contained in the configuration

What You Can Do

  • Enter a new word and press the Add button to add it to the list.
  • Select a word in the list and press the Remove button to remove it.


Configuration Dialog: "Of the" Reordering

What's This?

So-called "of the" words trigger a reordering of an identifier's words. For example, if "size" is configured to be such an "of the" words, the identifier "FileBufferSize" will be translated to "Size of the file buffer"

This reordering can be tweaked by specifying adjectives; e.g. if "initial" is configured to be an adjective for "of the" words, then "InitialBufferSize" will be translated to "Initial size of the buffer" (instead of "Size of the initial buffer").

What You See

  • Edit fields for entering new "of the" trigger words and/or adjectives to be added.
  • List of words already contained in the configuration.

What You Can Do

  • Enter a new word and press the Add button to add it to the corresponding list.
  • Select a word in the list and press the Remove button to remove it.

Tips:

  • If you want to disable this feature completely, simply remove all words from the lists of "of the" trigger words.


Configuration Dialog: "No the" Words

What's This?

In certain situations GhostDoc inserts a "the" when creating sentences from identifier names. The so-called "no the" words are words that must not be preceded by a "the". Obviously the list cannot be complete, but because of the nature of identifier names (in practice only a rather small vocabulary of words is actually used) already a limited list is sufficient to get pretty good results.

What You See

  • An edit field for entering new words to be added
  • A list of words already contained in the configuration

What You Can Do

  • Enter a new word and press the Add button to add it to the list.
  • Select a word in the list and press the Remove button to remove it.


Configuration Dialog: Non-breaking Words

What's This?

Define words that will not be split when parsing member name.

What You See

  • An edit field for entering new words to be added
  • A list of words already contained in the configuration

What You Can Do

  • Enter a new word and press the Add button to add it to the list.
  • Select a word in the list and press the Remove button to remove it.


Configuration Dialog: Auto Update

What's This?

This section lets you configure auto updating options for GhostDoc.

What You See

  • Check for - specify new version checking frequency and be notified, if new version of GhostDoc is available.
  • Check Now button - check for update manually.


Configuration Dialog: Solution Options

What's This?

When turned ON, this allows to improve GhostDoc Document This performance executing first time on a large solution (at the expense of potentially missing base members outside of the project). The default behavior for GhostDoc to look for base members within the complete solution.

Copyright © 2003-2021 SubMain


Configuration Dialog: Solution Ignore List

What's This?

GhostDoc will ignore all the files specified in the list. Wildcards can also be used.

What You See

  • An edit field for entering new patterns to be added
  • A list of patterns already contained in the configuration

What You Can Do

  • Enter a new pattern and press the Add button to add it to the list.
  • Select a pattern in the list and press the Remove button to remove it.


"Add Rule" Dialog

What's This?

This dialog allows you to select a text generation rule to be added to the configuration.

What You See

  • A list of all rules for the current rule category. Rules that can only be added once, and already exist in the rule configuration, are grayed out.

Example: "Add rule" dialog for method rules

What You Can Do

  • Select a rule and press the OK button to add this rule. The Edit Rule dialog will then be opened next, so you can customize the rule that was just created.

    or
  • Press the Cancel button to exit the dialog without adding a rule.


"Edit Rule" Dialog

What's This?

This dialog allows you to edit certain aspects of a text generation rule. How much can be configured depends on the rule; some are very specialized, while others (especially custom rules) offer a high degree of freedom.

The configuration can be divided into two groups:

  • Settings for the match condition.
  • Settings for the text generation.

The text generation of a rule is largely template-driven, i.e. the user can specify texts consisting of constants parts and macros which are replaced dynamically during text generation. Note that if for a certain rule some templates appears to be missing, it may be that the corresponding texts are generated by some mechanism that isn't suited to be configured by a template and thus is more or less hard-coded in the rule.

What You See

  • An edit field for the name of the rule as it is displayed e.g. in the rule configuration tree.
  • The description field that gives a brief summary of the match condition of the rule. For some rules, certain aspects of the condition can be customized.
  • The other rule settings, e.g. templates for documentation tags.

Example: Dialog for method rules

What You Can Do

  • Edit the (display) name of the rule. Note that changing the name will not change the identity of the rule, i.e. in regard to exporting/importing it remains the same rule. So if you export the rule and import it on a different system, where the rule has the old name, you will not end up with two rules; instead, if you accept the import of the modified rule, the rule display name will be updated just like the other settings.
  • Edit the match condition (does not apply to all rules) by clicking on one of the links, which will bring up an editor for that part of the condition (e.g. a word list editor).
  • Edit the other rule settings. When you click on some of the settings (e.g. a template text), an additional button ( [image] ) appears at the end of the line. Pressing this button will bring up an external editor, e.g. a template editor.


Word List Editor Dialog

What You See

  • An edit field for entering new words to be added
  • A list of words already contained in the list

Example: Word List for the "State Check" Method Rule

What You Can Do

  • Enter a new word and press the Add button to add it to the list.
  • Select a word in the list and press the Remove button to remove it.


Template Editor Dialog

What's This?

This dialog is used for editing templates that control the text generation for a specific tag of the XML documentation comment. A template consists of constants parts, i.e. fixed texts, and macros which are replaced dynamically during text generation. The macros can be divided into the following groups:

  • Constants, e.g. for the representation of certain keywords (true, false, null)
  • Texts connected to certain aspects of the context in which the documentation is generated (e.g. the name of a method's return type, a text describing whether a property has a setter and/or getter, etc.).
  • Texts describing the "environment", e.g. the current user, date/time, machine name

What You See

  • An edit field for the template text. The parts of the text showing up as $(Name) are macros that will be replaced when the documentation is generated.
  • A tree showing the available macros.
  • A description of the currently selected macro.

Example: Dialog for a Method Rule

What You Can Do

  • Edit the template text. You can type macros by hand, but usually this is only recommended for simple macros like e.g. $(True).
  • Select a macro and insert it at the current cursor position by either pressing the Insert button, or by double clicking the macro.


Name Condition Editor Dialog

What's This?

This dialog allows you to specify the match condition for the name of e.g. a method or a property. If this and the other conditions of a rule are met, then this rule will be responsible for the text generation of the documentation comment.

What You See

  • A dropdown list for selecting the kind of condition.
    • <any> : will match any name
    • equals : exact match of the name
    • starts with : match name prefix
    • ends with : match name suffix
    • contains : match names containing a specific text
    • matches regular expression : match names using .NET framework regular expressions.
  • A text field next to the dropdown list, containing the match text.
  • A text field in the "Test" area for trying out the condition. If the text matches the condition, the indicator next to the text field turns green.

Example: Match for all names starting with "Show".

Example

  • How to configure a match for all names starting with "Show"


Name Condition Editor Dialog (Example)

G h o s t D o c v2022.1

<note>

This page only applies to the GhostDoc Community Edition.

</note>

Name Condition Editor Dialog

How to Configure a Match for all Names Starting with "Show"

Step 1: Select the kind of condition

Step 2: Enter the match text

Step 3: Try out the condition

Copyright © 2003-2021 SubMain


Type Condition Editor Dialog

What's This?

This dialog allows you to specify the match condition for a type, e.g. the return type of a method or the type of a property value. If this and the other conditions of a rule are met, then the rule will be responsible for the text generation of the documentation comment.

What You See

  • A dropdown list for selecting the kind of condition.
    • <any> : will match any type name
    • equals : exact match of the type name
    • starts with : match type name prefix
    • ends with : match type name suffix
    • contains : match type names containing a specific text
    • matches regular expression : match type names using .NET framework regular expressions.
  • A combo box next to the dropdown list, containing the match text. The dropdown list part of the combo box contains the full names of some basic types, (parts of) other type names can be entered in the text field part of the combo box.
  • A text field in the "Test" area for trying out the condition. If the text matches the condition, the indicator next to the text field turns green.

Example: Match for types ending on "Reader"

Examples

  • How to configure an exact match for "bool"
  • How to configure a match for types ending on "Reader"


Type Condition Editor Dialog (Example)

G h o s t D o c v2022.1

<note>

This page only applies to the GhostDoc Community Edition.

</note>

Type Condition Editor Dialog

How to Configure an Exact Match for "bool"

Step 1: Select the kind of condition

Step 2: Specify the type name

As types have to be specified with the full name, we'll have to use "System.Boolean" instead of "bool" for the match text. We enter the text directly in the text field, or choose it from the list of basic types:


Type Condition Editor Dialog (Example)

G h o s t D o c v2022.1

<note>

This page only applies to the GhostDoc Community Edition.

</note>

Type Condition Editor Dialog

How to Configure a Match for Types Ending on "Reader"

Step 1: Select the kind of condition

Step 2: Specify (part of) the type name

Step 3: Try out the condition

Copyright © 2003-2021 SubMain


Parameter Condition Editor Dialog

What's This?

This dialog allows you to specify the match condition for the parameter of e.g. a method or an indexer. If this and the other conditions of a rule are met, then this rule will be responsible for the text generation of the documentation comment.

What You See

  • Two dropdown lists for selecting the kind of conditions for the type name and the name of the parameter.
    • <any> : will match any name
    • equals : exact match of the name
    • starts with : match name prefix
    • ends with : match name suffix
    • contains : match names containing a specific text
    • matches regular expression : match names using .NET framework regular expressions.
  • A combo box next to the "Type" condition kind dropdown list, containing the match text for the parameter type name. The dropdown list part of the combo box contains the full names of some basic types, (parts of) other type names can be entered in the text field part of the combo box.
  • A text field next to the "Name" condition kind dropdown list, containing the match text for the parameter name.
  • Text fields in the "Test" area for trying out the conditions. If the text matches the corresponding condition, the indicator next to the text field turns green. If both conditions are met, the indicator next to "Result" turns green.

Example

  • How to configure a match for an event argument.


Parameter Condition Editor Dialog (Example)

G h o s t D o c v2022.1

<note>

This page only applies to the GhostDoc Community Edition.

</note>

Parameter Condition Editor Dialog

How to Configure a Match for an Event Argument

Step 1: Select the kind of condition for the type name

Step 2: Enter the match text for the type name

Step 3: Try out the condition for the type name

Copyright © 2003-2021 SubMain


Export Dialog

What's This?

This dialog allows you to export the current configuration (or only parts of it) to a ".gdc" file. You can use the export feature to

  • create backups of your configuration,
  • synchronize the configuration between Visual Studio installations on different machines (e.g. at home and at work), or
  • share your latest custom text generation rule with your friends and/or colleagues.

An exported configuration can be imported using the Import dialog.

What You See

The tree on the right side of the dialog shows the items that will be included in the exported configuration file, grouped by categories:

  • Acronyms
  • Abbreviations
  • "Of the" trigger words
  • "Of the" adjectives
  • "No the" words
  • Non-breaking words
  • Rules
  • Options

The state of a checkbox determines whether the corresponding item will be in the exported configuration file.

What You Can Do

  • Uncheck the items you don't want in the exported configuration file.
  • Check the items that you want to be part of the exported configuration file.
  • Press the Export button to perform the export.


Import Dialog

What's This?

This dialog allows you to import a configuration that was previously exported to a ".gdc" file using the Export dialog. Such a file can contain both complete configurations (for synchronizing configurations between Visual Studio installations on different machines) as well as e.g. the configuration for a single custom text generation rule you want to share with your friends. Importing a configuration will not remove any existing elements, and that you have full control over what will be added and/or modified.

What You See

The tree on the right side of the dialog shows the items that are new or different in the configuration to be imported, grouped by categories:

  • Acronyms
  • Abbreviations
  • "Of the" trigger words
  • "Of the" adjectives
  • "No the" words
  • Non-breaking words
  • Rules
  • Options

The state of a checkbox determines whether the corresponding item will be in the resulting configuration after the import.

What You Can Do

  • Uncheck the items you don't want in the resulting configuration after the import. If you uncheck an item under a "Different in configuration to import" branch of the tree, the original item will be kept.
  • Check the items that you want to be part of the resulting configuration after the import.
  • Press the Import button to perform the import.


Import Dialog

G h o s t D o c v2022.1

Upgrade Dialog

In the dialog, the tree on the right side shows the differences between the imported and the current configuration, grouped by different categories (categories without differences are not shown):

  • Acronyms
  • Abbreviations
  • "Of the" trigger words
  • "Of the" adjectives
  • "No the" words
  • Non-breaking words
  • Rules
  • Options

By default all items are checked, i.e. if you press the Import button without changing anything, the items of both configurations will be merged. Unchecked items will not be part of the configuration resulting from the import.


Rules

Introduction

In GhostDoc, the creation of XML documentation comments is controlled by text generation rules. When GhostDoc is told to build the documentation for a language element (e.g. a function), it first collects information about the signature (e.g. return type, name, parameter types and names) of the element, then searches a list of rules (ordered by priority) responsible for this element's type. The first rule found matching the signature will then generate the documentation text.

Rule Types

The current version of GhostDoc supports the following rule types:

  • Namespace rules
  • Class rules
  • Interface rules
  • Structs rules
  • Enum rules
  • Delegate rules
  • Field rules
  • Event rules
  • Property rules
  • Indexer rules
  • Constructor rules
  • Method rules
  • Parameter rules
  • Javascript Variables rules
  • Javascript Functions rules

Built-in Rules

Out-of-the box GhostDoc installs a number of pre-configured rules for each rule type. This rules can be customized (or even be removed) on the "Rules" tab of the configuration dialog. The only rules that cannot be removed are the default rules that provide a generic documentation text for their element type.

User-defined Rules

In addition to the built-in rules, GhostDoc offers used defined rules, where users can define match conditions and templates for the documentation text. The match conditions can test for "Equals", "StartsWith", "EndsWith", "Contains" or use regular expressions on type names, method/property names, parameter types and name, etc.


GhostDoc Documentation

G h o s t D o c v2022.1

GhostDoc Pro Documentation

  • What is GhostDoc Pro
  • GhostDoc Edition Comparison - Community, Pro and Enterprise
  • Code Spell Checker
  • Comment Preview
  • Build Help Documentation
  • File Header
  • Global Properties
  • Offline Activation
  • Find Missing Documentation
  • Expand/Collapse Documentation Comments
  • Find Auto-generated Documentation
  • Synchronize With Member Signature
  • Documentation Hints in Editor
  • Introduction to GhostDoc Pro T4 Templates
  • Templates
  • Macros
  • GhostDoc Pro API


G h o s t D o c v2022.1

GhostDoc Pro

What is GhostDoc Pro

GhostDoc Pro is for developers who want better productivity and advanced features.

GhostDoc Pro is right for you if you want to

  • Document the whole type/file
  • Have total control over your XML documentation content and style via T4 based XML Comment templates
  • Produce help documentation in multiple formats and modern themes
  • Maintain clean and up-to-date documentation with the documentation quality management features
  • Find auto-generated, missing documentation or the docs that are out of sync
  • Use flexible StyleCop compliant templates and template libraries
  • Have a built-in intelligent source code Spell Checker in Visual Studio

See Also

  • GhostDoc Edition Comparison - Community, Pro and Enterprise
  • GhostDoc Tutorials and Resources
  • Introduction to T4 Templates
  • GhostDoc Pro API


Code Spell Checker

Spell Checker built-in to the GhostDoc Pro allows to check spelling of code, comments and strings.

GhostDoc Pro Spell Checker Features

  • Menu/toolbar commands
    • Check Spelling - Active Document
    • Check Spelling - Selected Documents
    • Check Spelling - Current Project
    • Check Spelling - Entire Solution
    • Show Spelling Report
    • Enable Spell Checking
  • Check Spelling as you type
  • Spell Checking for XML Comments
  • Spell Checking for code elements
  • Spell Checking for strings and comments
  • Spelling SmartTag in the VS Code Editor
  • Added support for OpenOffice dictionaries and multiple languages
  • Ignore files and file extensions
  • Custom User Dictionary
  • Custom Dictionary by Solution

Spell Checker Functionality

  • Use Spell Checker through the GhostDoc Pro menu...

  • ...or Visual Studio toolbar.

  • Errors are highlighted in the source code and gathered in the Spelling Report.

  • Fix errors manually or through Spell Checker tooltip:

  • You can specify various Spell Checker options using Options dialog window:
    • Options -> GhostDoc Pro -> Spelling Options

    • Options -> GhostDoc Pro -> Spell Checker and User Dictionary

    • Options -> Solution Options -> Spelling Ignore List

    • Options -> Solution Options -> Solution Dictionary

See Also

  • What Is GhostDoc Pro
  • GhostDoc Edition Comparison - Community, Pro and Enterprise


Comment Preview

You can see your comments as they appear in the help file. This feature is implemented in both GhostDoc and GhostDoc Pro versions, but Pro version functionality is extended.

See Also

  • GhostDoc Edition Comparison - Community, Pro and Enterprise


Build Help Documentation

GhostDoc Pro allows to build .CHM help file for the entire solution with one click.

  • Just click Tools->GhostDoc Pro -> Build Help Documentation... menu item and choose file location:

You can customize the following:

  • Help configuration
  • Output directory for help files
  • Help format
  • Scope to include
  • Code Sample Languages
  • Header and footer text
  • Image Folder
  • Select projects to include in help file

See Also

  • What Is GhostDoc Pro
  • GhostDoc Edition Comparison - Community, Pro and Enterprise


File Header

GhostDoc Pro uses T4 template to generate header comment for a file.

  • You can modify it using "Options" dialog window.

Do the following to insert File Header:

  • Set text cursor in the text editor window on the first line of the file.
  • Choose "Document This" menu item from the context menu.

See Also

  • What Is GhostDoc Pro
  • GhostDoc Edition Comparison - Community, Pro and Enterprise


Global Properties

Global Properties feature allows to reference custom configured user properties within T4 templates.

  • Options -> Global Properties

See Also

  • What Is GhostDoc Pro
  • GhostDoc Edition Comparison - Community, Pro and Enterprise


Offline Activation

If your computer is behind strict firewall, you can activate your GhostDoc Pro using Offline Activation feature.

  • Choose Enter Registration Code menu item from GhostDoc Pro menu:

  • Press Offline Activation button on the User Registration dialog:

  • Offline Activation dialog window will be opened:

  • Enter your name and license key and press Send button. Your default e-mail client will be opened with prepared offline activation request.
  • You will receive unlock code in response on offline activation e-mail request.
  • Enter unlock code in the appropriate field on Offline Activation dialog window and press Unlock button.

See Also

  • GhostDoc Edition Comparison - Community, Pro and Enterprise


Expand/Collapse Documentation Comments

Expand/Collapse Documentation Comments feature allows to minimize the XML comments footprint in the code editor.

  • Click Tools->GhostDoc Pro -> Documentation Comments - Expand or Documentation Comments - Collapse menu item:

See Also

  • What Is GhostDoc Pro
  • GhostDoc Edition Comparison - Community, Pro and Enterprise


Find Missing Documentation

Find Missing Documentation feature allows to find members/types that do not have XML comments.

  • Click Tools -> GhostDoc Pro -> Find Missing Documentation menu item:

  • 'Missing Documentation' will open in the Documentation Maintenance tool window:

  • There are the following filters available:
    • Public includes public members and types
    • Internal includes internal members and types
    • Protected includes protected members and types
    • Private includes private members and types
    • Inherited XML Comment can be copied from a base member
  • Refresh - search for changes within the code or using the new filtering criteria
  • Add - use to add XML Comments to the selected member(s)

See Also

  • What Is GhostDoc Pro
  • GhostDoc Edition Comparison - Community, Pro and Enterprise


Find Auto-generated Documentation

Find Auto-generated Documentation feature allows to find members/types with XML comments auto-generated by GhostDoc.

  • Click Tools -> GhostDoc Pro -> Find Auto-generated Documentation menu item:

  • 'Auto-generated Documentation' will open in the Documentation Maintenance tool window:

  • The following filters are available:
    • Template Match compares with an XML comment generated via a T4 template
    • TODO looks for a TODO in the member/type XML Comment
    • <autogeneratedoc /> looks for an <autogeneratedoc /> tag in the member/type XML Comment
    • Inherited includes only members with XML Comment copied from their base members
  • Refresh - search for changes within the code or using the new filtering criteria
  • Remove button can be used to remove XML comments for the selected member(s)
  • Also, you can change search template library for the Template Match filter

See Also

  • What Is GhostDoc Pro
  • GhostDoc Edition Comparison - Community, Pro and Enterprise


Synchronize With Member Signature

Synchronize With Member Signature feature allows to discover members that have parameters, return types, and type parameters out of sync with the existing XML comments.

  • Click Tools -> GhostDoc Pro -> Synchronize with member signature menu item:

  • Documentation Maintenance tool window -> Synchronize with member signature tab:

  • There are the following filters available:
    • Public includes public members and types
    • Internal includes internal members and types
    • Protected includes protected members and types
    • Private includes private members and types
    • Inherited XML Comment can be copied from a base member
  • Refresh - search for changes within the code or using the new filtering criteria
  • Sync - use to synchronize XML comments with the selected member(s) signature

See Also

  • What Is GhostDoc Pro
  • GhostDoc Edition Comparison - Community, Pro and Enterprise


Documentation Hints in Editor

Documentation Hints in Editor feature allows to show hints in code editor.

  • Turn 'Enable Documentation Hints' toolbar option On or click the Tools-> GhostDoc Pro -> Enable Documentation Hints menu item.
  • The documentation hints and action icons will display where appropriate

The following documentation hint actions are available:

- Add XML Comment
- Ignore XML Comment
- Copy from base member
- Synchronize XML Comment with member signature
- Remove default comment
- Mark Edited

See Also

  • What Is GhostDoc Pro
  • GhostDoc Edition Comparison - Community, Pro and Enterprise


Introduction to GhostDoc Pro T4 Templates

What is T4?

T4 (Text Template Transformation Toolkit) is a text generation engine introduced by Microsoft and included as part of Visual Studio starting VS 2008. A text template, which is usually a file with a ".tt" extension, can include directives, text blocks and control blocks and produce a text output for various purposes. Control blocks can be written using the Visual C# or Visual Basic.

Components of the T4 template

Directives control how the template is processed. Each directive is enclosed in <#@ and #> symbols.

For example, the following directive specifies the programming language, which will be used to compile code blocks:

<#@ template language="C#" #>

A Text block inserts any text directly into the output file. The text inserted as it written in the template without any changes. There are no special requirements for text blocks.

For example, the following text block inserts empty XML comment in the output:

<#@ template language="C#" #>
/// <summary>
///
/// </summary>

Control blocks are pieces of program code written on C# or Visual Basic that generate some text output. Control blocks are enclosed in <# and #> symbols.

Control block types

There are three types of control blocks can be used in T4 templates: standard control blocks, expression control blocks and class feature control blocks.

A standard control block is just a piece of code enclosed in <# and #> symbols. It can generate text output using Write() or WriteLine() methods.

There are two standard control blocks in the example below. First one obtains the current code element using the Context class, which is the root class for all code for T4 templates in GhostDoc Pro. The second standard control block prints full name of the element to the output. Please note that control blocks can be mixed with any number of text blocks.

<#@ template language="C#" #>
<#  CodeElement codeElement = Context.CurrentCodeElement; #>
/// <summary>
///<# Write(codeElement.FullName); #>
/// </summary>

An expression control block is enclosed in <#= and #> symbols. It evaluates an expression, converts result to a string and inserts it into the output.

For example, we can rewrite previous example using the expression control block as:

<#@ template language="C#" #>
<#  CodeElement codeElement = Context.CurrentCodeElement; #>
/// <summary>
///<#= "Name: " + codeElement.FullName #>
/// </summary>

A class feature control block can be used to implement any utility properties or methods. It is enclosed in <#+ and #> symbols. All helper functionality required for the T4 template can be implemented in class feature control block.

The GenerateSummaryText() function is defined and called in the following example:

<#@ template language="C#" #>
<#  CodeElement codeElement = Context.CurrentCodeElement; #>
/// <summary>
<# GenerateSummaryText(); #>
/// </summary>
<#+
private void GenerateSummaryText()
{
    this.WriteLine("/// Name: " + codeElement.FullName);
}

#>

T4 templates in GhostDoc Pro

GhostDoc Pro implements custom host for T4 templating engine to provide complete control over XML Comment generation. All GhostDoc Pro templates are stored in a single configration file.

All comment generation rules in GhostDoc Pro are implemented as T4 templates. There is a separate T4 template for each code element such as class, field, property, method, etc. Properties of any code element can be accessed inside a template via the CodeElement class. Static class Context provides a number of utility methods and provides access to the current code element.

Any T4 template can be easily customized according to your specific requirements via Tools -> GhostDoc Pro -> Options -> Rules.

See Also

  • Learn more about T4 templates
  • GhostDoc Pro API


Rules

G h o s t D o c v2022.1

Templates

In GhostDoc Pro generation of XML documentation comments is driven by text generation rules that are implemented as T4 templates. When GhostDoc Pro "Document ..." command is triggered for a language element (for example, function), it executes T4 template appropriate for the code element to generate XML comment.

Template Types

Current version of GhostDoc Pro supports the following template types:

  • Class template
  • Constructor template
  • Delegate template
  • Enum template
  • Event template
  • Field template
  • File template
  • Indexer template
  • Interface template
  • JavaScript Function template
  • JavaScript Variable template
  • Method template
  • Namespace template
  • Property template
  • Struct template

Built-in Templates and Customization

Out of the box GhostDoc Pro pre-configured template for each code element type. These templates if required can be customized via Tools -> GhostDoc Pro -> Options -> Rules.

Code element templates use T4 syntax and either C# or Visual Basic programming language. Output of the T4 template is inserted in the source file when XML comment is generated gy GhostDoc Pro.

Copyright © 2003-2021 SubMain

See Also

  • Introduction to T4 Templates
  • GhostDoc Pro API


Class Template

Class template generates XML comment for class code elements. Default T4 template inserts <summary> tag, <typeparam> tags for each type parameter of the class, <remarks> tag and any custom tags already defined.

Sample Output

/// <summary>
///  Class MyClass.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <remarks></remarks>
public class MyClass<T>
{
...
}

Predefined T4 Template

<#@ template language="C#" #>
<#  CodeElement codeElement = Context.CurrentCodeElement; #>
/// <summary>
///<# GenerateSummaryText(); #>
/// </summary>
<#  if(codeElement.HasTypeParameters)
    {
        for(int i = 0; i < codeElement.TypeParameters.Length; i++)
        {
            TypeParameter typeParameter = codeElement.TypeParameters[i];
#>
/// <typeparam name="<#= typeParameter.Name #>"><# GenerateTypeParamText(typeParameter, i); #></typeparam>
<#        }
    }
#>
<#  if(codeElement.HasBaseTypes)
    {
        for(int i = 0; i < codeElement.BaseTypes.Length; i++)
        {
#>
/// <seealso cref="<#= codeElement.BaseTypes[i] #>" />
<#        }
    }
#>
<#= Context.GetNonGeneratedTags() #>
<# GenerateRemarksText(); #>
<#+
    private void GenerateSummaryText()
    {
        if(Context.HasExistingTagText("summary"))
        {
            this.WriteLine(Context.GetExistingTagText("summary"));
        }
        else if(Context.CurrentCodeElement.IsSealed)
        {
            this.WriteLine("Class " + Context.CurrentCodeElement.Name + ". This class cannot be inherited." + Context.ExecMacro("$(End)"));
        }
        else
        {
            this.WriteLine("Class " + Context.CurrentCodeElement.Name + "." + Context.ExecMacro("$(End)"));
        }
    }

    private void GenerateTypeParamText(TypeParameter typeParameter, int index)
    {
        if(Context.HasExistingTagText("typeparam", index))
        {
            this.Write(Context.GetExistingTagText("typeparam", index));
        }
        else
        {
            string typeParameterName = typeParameter.Name;
            if(typeParameterName != null)
            {
                if(typeParameterName.Length == 1)
                {
                    this.Write("");
                }
                else
                {
                    this.Write("The type of " + Context.ExecMacro(typeParameterName, "$(TheAndAll)") + ".");
                }
            }
        }
    }

    private void GenerateRemarksText()
    {
        if(Context.HasExistingTagText("remarks"))
        { #>
/// <remarks><#= Context.GetExistingTagText("remarks") #></remarks>
<#+        }
        else if (!string.IsNullOrEmpty(Context.GetGlobalProperty("DefaultBlankRemarksText")))
        {
            // Should you require a default comment, set it in
            // Options -> Global Properties -> DefaultBlankRemarksText
#>
/// <remarks><#= Context.GetGlobalProperty("DefaultBlankRemarksText") #></remarks>
<#+        }
    }
#>

See Also

  • Introduction to T4 Templates
  • GhostDoc Pro API
  • GhostDoc Macros


Constructor Template

Constructor template generates XML comment for constructor code elements. Default T4 template inserts <summary> tag, <param> tags for each parameter of the constructor, <remarks> tag and any custom tags already defined.

Sample Output

/// <summary>
/// Initializes new instance of the <see cref="MyClass{T}"/> class.
/// </summary>
/// <param name="param">The parameter.</param>
/// <exception cref="Exception"></exception>
/// <remarks></remarks>
public MyClass(string param)
{
...
}

Predefined T4 Template

<#@ template language="C#" #>
<#  CodeElement codeElement = Context.CurrentCodeElement; #>
/// <summary>
///<# GenerateSummaryText(); #>
/// </summary>
<#    if(codeElement.HasParameters)
    {
        for(int i = 0; i < codeElement.Parameters.Length; i++)
        {
            Parameter parameter = codeElement.Parameters[i];
#>
/// <param name="<#= parameter.Name #>"><# GenerateParamText(parameter, i); #></param>
<#        }
    }
#>
<#    if(Context.HasExceptions)
    {
        foreach (System.Collections.Generic.KeyValuePair<string, System.Collections.Generic.ICollection<string>> pair in Context.ExceptionDictionary)
        {
            string exceptionText = Context.GetExistingExceptionTagText(pair.Key); #>
/// <exception cref="<#= pair.Key #>"><#= ((exceptionText != null && exceptionText.Length > 0) ? exceptionText : Context.GetExceptionTagText(pair.Value)) #></exception>
<#        }
    }  #>
<#= Context.GetNonGeneratedExceptionTags() #>
<#= Context.GetNonGeneratedTags() #>
<# GenerateRemarksText(); #>
<#+
    private void GenerateSummaryText()
    {
        if(Context.HasExistingTagText("summary"))
        {
            this.WriteLine(Context.GetExistingTagText("summary"));
        }
        else if(Context.CurrentCodeElement.IsStatic)
        {
            this.WriteLine("Initializes static members of the " + Context.ExecMacro("$(DeclaringTypeName.ShortNameAsSee)") + " " + Context.ExecMacro("$(DeclaringTypeKind)") + ".");
        }
        else if(Context.CurrentCodeElement.IsPrivate &&
            !Context.CurrentCodeElement.HasParameters)
        {
            this.WriteLine("Prevents a default instance of the " + Context.ExecMacro("$(DeclaringTypeName.ShortNameAsSee)") + " " + Context.ExecMacro("$(DeclaringTypeKind)") + " from being created.");
        }
        else if(Context.HasInheritedTagText("summary") && Context.CurrentCodeElement.HasParameters && Context.GetInheritedTagText("summary").IndexOf("<see ") < 0)
        {
            // skip inherited comments with <see cref="<base type>" />
            this.WriteLine(Context.GetInheritedTagText("summary"));
        }
        else
        {
            this.WriteLine("Initializes a new instance of the " + Context.ExecMacro("$(DeclaringTypeName.ShortNameAsSee)") + " " + Context.ExecMacro("$(DeclaringTypeKind)") + ".");
        }
    }
    private void GenerateParamText(Parameter parameter, int index)
    {
        if(Context.HasExistingTagText("param", index))
        {
            this.Write(Context.GetExistingTagText("param", index));
        }
        else if(Context.HasInheritedTagText("param", index))
        {
            this.Write(Context.GetInheritedTagText("param", index));
        }
        else if(IsBooleanParameter(parameter))
        {
            this.Write("if set to " + Context.ExecMacro("$(True)") + " [" + Context.ExecMacro(parameter.Name, "$(All)") + "].");
        }
        else if(IsEventArgsParameter(parameter))
        {
            this.Write("The " + Context.ExecMacro(parameter.ReturnType.FullName, "$(TypeName.FullNameAsSee)") + " instance containing the event data.");
        }
        else if(Context.ContainsOfTheReordering(parameter.Name))
        {
            this.Write(Context.ExecMacro(parameter.Name, "$(OfTheReordering)"));
        }
        else
        {
            this.Write(Context.ExecMacro(parameter.Name, "$(TheAndAllAsSentence)") + ".");
        }
    }

    private bool IsBooleanParameter(Parameter parameter)
    {
        return (bool)(parameter.ReturnType != null &&
            parameter.ReturnType.FullName != null &&
            parameter.ReturnType.FullName.Length > 0 &&
            (string.Compare( parameter.ReturnType.FullName, "System.Boolean", true) == 0 ||
            string.Compare( parameter.ReturnType.FullName, "System.Nullable<bool>", true) == 0));
    }
    private bool IsEventArgsParameter(Parameter parameter)
    {
        return (bool)(parameter.ReturnType != null &&
            parameter.ReturnType.FullName != null &&
            parameter.ReturnType.FullName.Length >= "EventArgs".Length &&
            parameter.ReturnType.FullName.EndsWith("EventArgs"));
    }

    private void GenerateRemarksText()
    {
        if(Context.HasInheritedTagText("remarks"))
        { #>
/// <remarks><#= Context.GetInheritedTagText("remarks") #></remarks>
<#+        }
        else if(Context.HasExistingTagText("remarks"))
        { #>
/// <remarks><#= Context.GetExistingTagText("remarks") #></remarks>
<#+        }
        else if (!string.IsNullOrEmpty(Context.GetGlobalProperty("DefaultBlankRemarksText")))
        {
            // Should you require a default comment, set it in
            // Options -> Global Properties -> DefaultBlankRemarksText
#>
/// <remarks><#= Context.GetGlobalProperty("DefaultBlankRemarksText") #></remarks>
<#+        }
    }
#>

See Also

  • Introduction to T4 Templates
  • GhostDoc Pro API
  • GhostDoc Macros


Delegate Template

Delegate template generates XML comment for delegate code elements. Default T4 template inserts <summary> tag, <typeparam> tags for each type parameter of the delegate, <param> tags for each parameter of the delegate, <returns> tag for return type of the delegate, <remarks> tag and any custom tags already defined.

Sample Output

/// <summary>
/// Delegate MyDelegate
/// </summary>
/// <typeparam name="T">The type of the t.</typeparam>
/// <param name="param1">The param1.</param>
/// <param name="param2">The param2.</param>
/// <returns>System.String.</returns>
/// <remarks></remarks>
public delegate string MyDelegate<T>(int param1, string param2);

Predefined T4 Template

<#@ template language="C#" #>
<#  CodeElement codeElement = Context.CurrentCodeElement; #>
/// <summary>
///<# GenerateSummaryText(); #>
/// </summary>
<#    if(codeElement.HasTypeParameters)
    {
        for(int i = 0; i < codeElement.TypeParameters.Length; i++)
        {
            TypeParameter typeParameter = codeElement.TypeParameters[i];
#>
/// <typeparam name="<#= typeParameter.Name #>"><# GenerateTypeParamText(typeParameter, i); #></typeparam>
<#        }
    }

    if(codeElement.HasParameters)
    {
        for(int i = 0; i < codeElement.Parameters.Length; i++)
        {
            Parameter parameter = codeElement.Parameters[i];
#>
/// <param name="<#= parameter.Name #>"><# GenerateParamText(parameter, i); #></param>
<#        }
    }
GenerateReturnsText(); #>
<#= Context.GetNonGeneratedTags() #>
<# GenerateRemarksText(); #>
<#+
    private void GenerateSummaryText()
    {
        if(Context.HasExistingTagText("summary"))
        {
            this.WriteLine(Context.GetExistingTagText("summary"));
        }
        else
        {
            this.WriteLine("Delegate " + Context.CurrentCodeElement.Name + Context.ExecMacro("$(End)"));
        }
    }

    private void GenerateTypeParamText(TypeParameter typeParameter, int index)
    {
        if(Context.HasExistingTagText("typeparam", index))
        {
            this.Write(Context.GetExistingTagText("typeparam", index));
        }
        else
        {
            string typeParameterName = typeParameter.Name;
            if(typeParameterName != null)
            {
                if(typeParameterName.Length == 1)
                {
                    this.Write("");
                }
                else
                {
                    this.Write("The type of " + Context.ExecMacro(typeParameterName, "$(TheAndAll)") + ".");
                }
            }
        }
    }
    private void GenerateParamText(Parameter parameter, int index)
    {
        if(Context.HasExistingTagText("param", index))
        {
            this.Write(Context.GetExistingTagText("param", index));
        }
        else if(Context.HasInheritedTagText("param", index))
        {
            this.Write(Context.GetInheritedTagText("param", index));
        }
        else if(IsBooleanParameter(parameter))
        {
            this.Write("if set to " + Context.ExecMacro("$(True)") + " [" + Context.ExecMacro(parameter.Name, "$(All)") + "].");
        }
        else if(IsEventArgsParameter(parameter))
        {
            this.Write("The " + Context.ExecMacro(parameter.ReturnType.FullName, "$(TypeName.FullNameAsSee)") + " instance containing the event data.");
        }
        else if(Context.ContainsOfTheReordering(parameter.Name))
        {
            this.Write(Context.ExecMacro(parameter.Name, "$(OfTheReordering)"));
        }
        else
        {
            this.Write(Context.ExecMacro(parameter.Name, "$(TheAndAllAsSentence)") + ".");
        }
    }
    private void GenerateReturnsText()
    {
        if(Context.HasExistingTagText("returns"))
        {
#>
/// <returns><#= Context.GetExistingTagText("returns") #></returns>
<#+
        }
        else if(Context.CurrentCodeElement.HasReturnType &&
            Context.CurrentCodeElement.ReturnType.FullName.Length > 0 &&
            String.Compare( Context.CurrentCodeElement.ReturnType.FullName, "System.Boolean", true) == 0)
        {
#>
/// <returns><#= Context.ExecMacro("$(True)") #> if XXXX, <#= Context.ExecMacro("$(False)") #> otherwise.</returns>
<#+
        }
        else if(Context.CurrentCodeElement.HasReturnType &&
            !(Context.CurrentCodeElement.ReturnType.FullName.Length == 0 ||
            String.Compare( Context.CurrentCodeElement.ReturnType.FullName, "void", true) == 0))
        {
#>
/// <returns><#= Context.ExecMacro("$(ReturnTypeName.FullName).") #></returns>
<#+
        }
    }

    private bool IsBooleanParameter(Parameter parameter)
    {
        return (bool)(parameter.ReturnType != null &&
            parameter.ReturnType.FullName != null &&
            parameter.ReturnType.FullName.Length > 0 &&
            (string.Compare( parameter.ReturnType.FullName, "System.Boolean", true) == 0 ||
            string.Compare( parameter.ReturnType.FullName, "System.Nullable<bool>", true) == 0));
    }
    private bool IsEventArgsParameter(Parameter parameter)
    {
        return (bool)(parameter.ReturnType != null &&
            parameter.ReturnType.FullName != null &&
            parameter.ReturnType.FullName.Length >= "EventArgs".Length &&
            parameter.ReturnType.FullName.EndsWith("EventArgs"));
    }

    private void GenerateRemarksText()
    {
        if(Context.HasInheritedTagText("remarks"))
        { #>
/// <remarks><#= Context.GetInheritedTagText("remarks") #></remarks>
<#+        }
        else if(Context.HasExistingTagText("remarks"))
        { #>
/// <remarks><#= Context.GetExistingTagText("remarks") #></remarks>
<#+        }
        else if (!string.IsNullOrEmpty(Context.GetGlobalProperty("DefaultBlankRemarksText")))
        {
            // Should you require a default comment, set it in
            // Options -> Global Properties -> DefaultBlankRemarksText
#>
/// <remarks><#= Context.GetGlobalProperty("DefaultBlankRemarksText") #></remarks>
<#+        }
    }
#>

See Also

  • Introduction to T4 Templates
  • GhostDoc Pro API
  • GhostDoc Macros


Enum Template

Enum template generates XML comment for enum code elements. Default T4 template inserts <summary> tag, <remarks> tag and any custom tags already defined.

Sample Output

/// <summary>
/// Enum MyEnum
/// </summary>
/// <remarks></remarks>
enum MyEnum
{
...
}

Predefined T4 Template

<#@ template language="C#" #>
/// <summary>
///<# GenerateSummaryText(); #>
/// </summary>
<#= Context.GetNonGeneratedTags() #>
<# GenerateRemarksText(); #>
<#+
    private void GenerateSummaryText()
    {
        if(Context.HasExistingTagText("summary"))
        {
            this.WriteLine(Context.GetExistingTagText("summary"));
        }
        else
        {
            this.WriteLine("Enum " + Context.CurrentCodeElement.Name + Context.ExecMacro("$(End)"));
        }
    }

    private void GenerateRemarksText()
    {
        if(Context.HasExistingTagText("remarks"))
        { #>
/// <remarks><#= Context.GetExistingTagText("remarks") #></remarks>
<#+        }
        else if (!string.IsNullOrEmpty(Context.GetGlobalProperty("DefaultBlankRemarksText")))
        {
            // Should you require a default comment, set it in
            // Options -> Global Properties -> DefaultBlankRemarksText
#>
/// <remarks><#= Context.GetGlobalProperty("DefaultBlankRemarksText") #></remarks>
<#+        }
    }
#>

See Also

  • Introduction to T4 Templates
  • GhostDoc Pro API
  • GhostDoc Macros


Event Template

Event template generates XML comment for event code elements. Default T4 template inserts <summary> tag, <remarks> tag and any custom tags already defined.

Sample Output

/// <summary>
/// Occurs when [my event].
/// </summary>
/// <exception cref="Exception"></exception>
/// <remarks></remarks>
public event MyEventHandler MyEvent;

Predefined T4 Template

<#@ template language="C#" #>
/// <summary>
///<# GenerateSummaryText(); #>
/// </summary>
<#    if(Context.HasExceptions)
    {
        foreach (System.Collections.Generic.KeyValuePair<string, System.Collections.Generic.ICollection<string>> pair in Context.ExceptionDictionary)
        {
            string exceptionText = Context.GetExistingExceptionTagText(pair.Key); #>
/// <exception cref="<#= pair.Key #>"><#= ((exceptionText != null && exceptionText.Length > 0) ? exceptionText : Context.GetExceptionTagText(pair.Value)) #></exception>
<#        }
    }  #>
<#= Context.GetNonGeneratedExceptionTags() #>
<#= Context.GetNonGeneratedTags() #>
<# GenerateRemarksText(); #>
<#+
    private void GenerateSummaryText()
    {
        if(Context.HasExistingTagText("summary"))
        {
            this.WriteLine(Context.GetExistingTagText("summary"));
        }
        else if(Context.HasInheritedTagText("summary"))
        {
            this.WriteLine(Context.GetInheritedTagText("summary"));
        }
        else if(!string.IsNullOrEmpty(Context.GetSummaryOverride(Context.CurrentCodeElement.Name)))
        {
            this.WriteLine(Context.GetSummaryOverride(Context.CurrentCodeElement.Name));
        }
        else
        {
            this.WriteLine(Context.ExecMacro("Occurs when [$(EventName.Words.All)]."));
        }
    }

    private void GenerateRemarksText()
    {
        if(Context.HasInheritedTagText("remarks"))
        { #>
/// <remarks><#= Context.GetInheritedTagText("remarks") #></remarks>
<#+        }
        else if(Context.HasExistingTagText("remarks"))
        { #>
/// <remarks><#= Context.GetExistingTagText("remarks") #></remarks>
<#+        }
        else if (!string.IsNullOrEmpty(Context.GetGlobalProperty("DefaultBlankRemarksText")))
        {
            // Should you require a default comment, set it in
            // Options -> Global Properties -> DefaultBlankRemarksText
#>
/// <remarks><#= Context.GetGlobalProperty("DefaultBlankRemarksText") #></remarks>
<#+        }
    }
#>

See Also

  • Introduction to T4 Templates
  • GhostDoc Pro API
  • GhostDoc Macros


Field Template

Field template generates XML comment for field code elements. Default T4 template inserts <summary> tag and any custom tags already defined.

Sample Output

/// <summary>
/// My field
/// </summary>
public string MyField;

Predefined T4 Template

<#@ template language="C#" #>
/// <summary>
///<# GenerateSummaryText(); #>
/// </summary>
<#= Context.GetNonGeneratedTags() #>
<#+
    private void GenerateSummaryText()
    {
        if(Context.HasExistingTagText("summary"))
        {
            this.WriteLine(Context.GetExistingTagText("summary"));
        }
        else if(Context.HasInheritedTagText("summary"))
        {
            this.WriteLine(Context.GetInheritedTagText("summary"));
        }
        else if(!string.IsNullOrEmpty(Context.GetSummaryOverride(Context.CurrentCodeElement.Name)))
        {
            this.WriteLine(Context.GetSummaryOverride(Context.CurrentCodeElement.Name));
        }
        else
        {
            this.WriteLine(Context.ExecMacro("$(FieldName.Words.TheAndAllAsSentence)$(End)"));
        }
    }
#>

See Also

  • Introduction to T4 Templates
  • GhostDoc Pro API
  • GhostDoc Macros


File Template

File template generates XML comment for file. Default T4 template inserts predefined header for file.

Sample Output

// ***********************************************************************
// Assembly         : MyAssembly
// Author           : John Doe
// Created          : 05-25-2012
//
// Last Modified By : Michael Smith
// Last Modified On : 06-14-2012
// ***********************************************************************
// <copyright file="my_file.cs" company="MyCompany LLC">
//     MyCompany LLC. All rights reserved.
// </copyright>
// <summary></summary>
// ***********************************************************************

Predefined T4 Template

<#@ template language="C#" #>
// ***********************************************************************
// Assembly         : <#= !String.IsNullOrEmpty(Context.FileHeaderExistingAssembly) ? Context.FileHeaderExistingAssembly : Context.AssemblyName #>
// Author           : <#= !String.IsNullOrEmpty(Context.FileHeaderExistingAuthor) ? Context.FileHeaderExistingAuthor : Context.GetGlobalProperty("UserName") #>
// Created          : <#= !String.IsNullOrEmpty(Context.FileHeaderExistingCreatedDate) ? Context.FileHeaderExistingCreatedDate : Context.DestinationFileCreationDateTime.ToString("MM-dd-yyyy") #>
//
// Last Modified By : <#= !String.IsNullOrEmpty(Context.FileHeaderExistingLastModifiedUser) ? Context.FileHeaderExistingLastModifiedUser : Context.GetGlobalProperty("UserName") #>
// Last Modified On : <#= Context.DestinationFileModificationDateTime.ToString("MM-dd-yyyy") #>
// ***********************************************************************
// <copyright file="<#= !String.IsNullOrEmpty(Context.FileHeaderExistingCopyrightFile) ? Context.FileHeaderExistingCopyrightFile : System.IO.Path.GetFileName(Context.DestinationFile) #>" company="<#= !String.IsNullOrEmpty(Context.FileHeaderExistingCopyrightCompany) ? Context.FileHeaderExistingCopyrightCompany : !String.IsNullOrEmpty(Context.AssemblyCompany) ? Context.AssemblyCompany : Context.GetGlobalProperty("CompanyName") #>">
//     <#= !String.IsNullOrEmpty(Context.GetExistingTagText("copyright")) ? Context.GetExistingTagText("copyright") : !String.IsNullOrEmpty(Context.AssemblyCopyright) ? Context.AssemblyCopyright : "Copyright (c) " + Context.GetGlobalProperty("CompanyName") + ". All rights reserved." #>
// </copyright>
<# GenerateSummaryText(); #>
<# GenerateRemarksText(); #>
// ***********************************************************************

<#+
    private void GenerateSummaryText()
    {
        string existingSummaryText = Context.GetExistingTagText("summary");
        if(!String.IsNullOrEmpty(existingSummaryText))
        {
              string[] lines = existingSummaryText.Split(new string[] { Environment.NewLine, @"\r", @"\n" }, StringSplitOptions.RemoveEmptyEntries);
            if(lines != null && lines.Length > 1)
            { #>
// <summary>
<#+                for(int i = 0; i < lines.Length; i++)
                { #>
// <#= lines[i].Trim() #>
<#+                }#>
// </summary>
<#+                }
                else
                { #>
// <summary><#= existingSummaryText #></summary>
<#+                }
        }
        else
        { #>
// <summary></summary>
<#+        }
     }
    private void GenerateRemarksText()
    {
        string existingSummaryText = Context.GetExistingTagText("remarks");
        if(!String.IsNullOrEmpty(existingSummaryText))
        {
              string[] lines = existingSummaryText.Split(new string[] { Environment.NewLine, @"\r", @"\n" }, StringSplitOptions.RemoveEmptyEntries);
            if(lines != null && lines.Length > 0)
            { #>
// <remarks>
<#+                for(int i = 0; i < lines.Length; i++)
                { #>
// <#= lines[i].Trim() #>
<#+                }#>
// </remarks>
<#+                }
                else
                { #>
// <remarks><#= existingSummaryText #></remarks>
<#+                }
        }
     }
#>

See Also

  • Introduction to T4 Templates
  • GhostDoc Pro API
  • GhostDoc Macros


Interface Template

Interface template generates XML comment for interface code elements. Default T4 template inserts <summary> tag, <typeparam> tags for each type parameter of the class, <remarks> tag and any custom tags already defined.

Sample Output

/// <summary>
/// Interface MyInterface
/// </summary>
/// <typeparam name="T"></typeparam>
/// <remarks></remarks>
interface MyInterface<T>
{
...
}

Predefined T4 Template

<#@ template language="C#" #>
<#  CodeElement codeElement = Context.CurrentCodeElement; #>
/// <summary>
///<# GenerateSummaryText(); #>
/// </summary>
<#    if(codeElement.HasTypeParameters)
    {
        for(int i = 0; i < codeElement.TypeParameters.Length; i++)
        {
            TypeParameter typeParameter = codeElement.TypeParameters[i];
#>
/// <typeparam name="<#= typeParameter.Name #>"><# GenerateTypeParamText(typeParameter, i); #></typeparam>
<#        }
    }
#>
<#  if(codeElement.HasBaseTypes)
    {
        for(int i = 0; i < codeElement.BaseTypes.Length; i++)
        {
#>
/// <seealso cref="<#= codeElement.BaseTypes[i] #>" />
<#        }
    }
#>
<#= Context.GetNonGeneratedTags() #>
<# GenerateRemarksText(); #>
<#+
    private void GenerateSummaryText()
    {
        if(Context.HasExistingTagText("summary"))
        {
            this.WriteLine(Context.GetExistingTagText("summary"));
        }
        else
        {
            this.WriteLine("Interface " + Context.CurrentCodeElement.Name + Context.ExecMacro("$(End)"));
        }
    }
    private void GenerateTypeParamText(TypeParameter typeParameter, int index)
    {
        if(Context.HasExistingTagText("typeparam", index))
        {
            this.Write(Context.GetExistingTagText("typeparam", index));
        }
        else
        {
            string typeParameterName = typeParameter.Name;
            if(typeParameterName != null)
            {
                if(typeParameterName.Length == 1)
                {
                    this.Write("");
                }
                else
                {
                    this.Write("The type of " + Context.ExecMacro(typeParameterName, "$(TheAndAll)") + ".");
                }
            }
        }
    }

    private void GenerateRemarksText()
    {
        if(Context.HasExistingTagText("remarks"))
        { #>
/// <remarks><#= Context.GetExistingTagText("remarks") #></remarks>
<#+        }
        else if (!string.IsNullOrEmpty(Context.GetGlobalProperty("DefaultBlankRemarksText")))
        {
            // Should you require a default comment, set it in
            // Options -> Global Properties -> DefaultBlankRemarksText
#>
/// <remarks><#= Context.GetGlobalProperty("DefaultBlankRemarksText") #></remarks>
<#+        }
    }
#>

See Also

  • Introduction to T4 Templates
  • GhostDoc Pro API
  • GhostDoc Macros


Indexer Template

Indexer template generates XML comment for indexer code elements. Default T4 template inserts <summary> tag, <remarks> tag and any custom tags already defined.

Sample Output

/// <summary>
/// Gets or sets the <see cref="System.String" /> at the specified index.
/// </summary>
/// <param name="index">The index.</param>
/// <returns>System.String.</returns>
/// <remarks></remarks>
public string this[int index]
{
...
}

Predefined T4 Template

<#@ template language="C#" #>
/// <summary>
///<# GenerateSummaryText(); #>
/// </summary>
<#    CodeElement codeElement = Context.CurrentCodeElement;
    if(codeElement.HasParameters)
    {
        for(int i = 0; i < codeElement.Parameters.Length; i++)
        {
            Parameter parameter = codeElement.Parameters[i];
#>
/// <param name="<#= parameter.Name #>"><# GenerateParamText(parameter, i); #></param>
<#        }
    }

    GenerateReturnsText();
    if(Context.HasExceptions)
    {
        foreach (System.Collections.Generic.KeyValuePair<string, System.Collections.Generic.ICollection<string>> pair in Context.ExceptionDictionary)
        {
            string exceptionText = Context.GetExistingExceptionTagText(pair.Key); #>
/// <exception cref="<#= pair.Key #>"><#= ((exceptionText != null && exceptionText.Length > 0) ? exceptionText : Context.GetExceptionTagText(pair.Value)) #></exception>
<#        }
    }  #>
<#= Context.GetNonGeneratedExceptionTags() #>
<#= Context.GetNonGeneratedTags() #>
<# GenerateRemarksText(); #>
<#+
    private void GenerateSummaryText()
    {
        if(Context.HasExistingTagText("summary"))
        {
            this.WriteLine(Context.GetExistingTagText("summary"));
        }
        else if(Context.HasInheritedTagText("summary"))
        {
            this.WriteLine(Context.GetInheritedTagText("summary"));
        }
        else if(Context.CurrentCodeElement.HasParameters &&
            Context.CurrentCodeElement.Parameters[0].Name == "index")
        {
            this.WriteLine(Context.ExecMacro("$(IndexerAccessText) the $(IndexerTypeName.FullNameAsSee) at the specified index."));
        }
        else
        {
            this.WriteLine(Context.ExecMacro("$(IndexerAccessText) the $(IndexerTypeName.FullNameAsSee) with the specified $(Parameters.First.Name.Words.All)."));
        }
    }

    private void GenerateParamText(Parameter parameter, int index)
    {
        if(Context.HasExistingTagText("param", index))
        {
            this.Write(Context.GetExistingTagText("param", index));
        }
        else if(Context.HasInheritedTagText("param", index))
        {
            this.Write(Context.GetInheritedTagText("param", index));
        }
        else if(IsBooleanParameter(parameter))
        {
            this.Write("if set to " + Context.ExecMacro("$(True)") + " [" + Context.ExecMacro(parameter.Name, "$(All)") + "].");
        }
        else if(IsEventArgsParameter(parameter))
        {
            this.Write("The " + Context.ExecMacro(parameter.ReturnType.FullName, "$(TypeName.FullNameAsSee)") + " instance containing the event data.");
        }
        else if(Context.ContainsOfTheReordering(parameter.Name))
        {
            this.Write(Context.ExecMacro(parameter.Name, "$(OfTheReordering)"));
        }
        else
        {
            this.Write(Context.ExecMacro(parameter.Name, "$(TheAndAllAsSentence)") + ".");
        }
    }

    private bool IsBooleanParameter(Parameter parameter)
    {
        return (bool)(parameter.ReturnType != null &&
            parameter.ReturnType.FullName != null &&
            parameter.ReturnType.FullName.Length > 0 &&
            (string.Compare( parameter.ReturnType.FullName, "System.Boolean", true) == 0 ||
            string.Compare( parameter.ReturnType.FullName, "System.Nullable<bool>", true) == 0));
    }

    private bool IsEventArgsParameter(Parameter parameter)
    {
        return (bool)(parameter.ReturnType != null &&
            parameter.ReturnType.FullName != null &&
            parameter.ReturnType.FullName.Length >= "EventArgs".Length &&
            parameter.ReturnType.FullName.EndsWith("EventArgs"));
    }

    private void GenerateReturnsText()
    {
        if(Context.HasExistingTagText("returns"))
        {
#>
/// <returns><#= Context.GetExistingTagText("returns") #></returns>
<#+
        }
        else if(Context.HasInheritedTagText("returns"))
        {
#>
/// <returns><#= Context.GetInheritedTagText("returns") #></returns>
<#+
        }
        else if(Context.CurrentCodeElement.HasReturnType &&
            Context.CurrentCodeElement.ReturnType.FullName.Length > 0 &&
            String.Compare( Context.CurrentCodeElement.ReturnType.FullName, "System.Boolean", true) == 0)
        {
#>
/// <returns><#= Context.ExecMacro("$(True)") #> if XXXX, <#= Context.ExecMacro("$(False)") #> otherwise.</returns>
<#+
        }
        else if(Context.CurrentCodeElement.HasReturnType &&
            !(Context.CurrentCodeElement.ReturnType.FullName.Length == 0 ||
            String.Compare( Context.CurrentCodeElement.ReturnType.FullName, "void", true) == 0))
        {
#>
/// <returns><#= Context.ExecMacro("$(ReturnTypeName.FullName).") #></returns>
<#+
        }
    }

    private void GenerateRemarksText()
    {
        if(Context.HasInheritedTagText("remarks"))
        { #>
/// <remarks><#= Context.GetInheritedTagText("remarks") #></remarks>
<#+        }
        else if(Context.HasExistingTagText("remarks"))
        { #>
/// <remarks><#= Context.GetExistingTagText("remarks") #></remarks>
<#+        }
        else if (!string.IsNullOrEmpty(Context.GetGlobalProperty("DefaultBlankRemarksText")))
        {
            // Should you require a default comment, set it in
            // Options -> Global Properties -> DefaultBlankRemarksText
#>
/// <remarks><#= Context.GetGlobalProperty("DefaultBlankRemarksText") #></remarks>
<#+        }
    }
#>

See Also

  • Introduction to T4 Templates
  • GhostDoc Pro API
  • GhostDoc Macros


Javascript Function Template

Javascript Function template generates XML comment for Javascript function code elements. Default T4 template inserts <summary> tag, <param> tags for each parameter of the method, <returns> tag for return type of the method, <remarks> tag and any custom tags already defined.

Sample Output

/// <summary>
/// Processes the data.
/// </summary>
/// <param name="param1">The param1.</param>
/// <param name="param2">The param2.</param>
/// <remarks></remarks>
function processData(param1, param2) {
}

Predefined T4 Template

<#@ template language="C#" #>
<#  CodeElement codeElement = Context.CurrentCodeElement; #>
/// <summary>
///<# GenerateSummaryText(); #>
/// </summary>
<# if(codeElement.HasParameters)
    {
        for(int i = 0; i < codeElement.Parameters.Length; i++)
        {
            Parameter parameter = codeElement.Parameters[i];
#>
/// <param name="<#= parameter.Name #>"><# GenerateParamText(parameter, i); #></param>
<#        }
    }
GenerateReturnsText(); #>
<#= Context.GetNonGeneratedTags() #>
<# GenerateRemarksText(); #>
<#+
    private void GenerateSummaryText()
    {
        if(Context.HasExistingTagText("summary"))
        {
            this.WriteLine(Context.GetExistingTagText("summary"));
        }
        else if(!string.IsNullOrEmpty(Context.GetSummaryOverride(Context.CurrentCodeElement.Name)))
        {
            this.WriteLine(Context.GetSummaryOverride(Context.CurrentCodeElement.Name));
        }
        else if(IsOnMethod())
        {
            if(Context.CurrentCodeElement.HasParameters)
            {
                this.WriteLine(Context.ExecMacro("Handles the <see cref=\"E:$(MethodName.Words.Verbatim.ExceptFirst)\" /> event."));
            }
            else
            {
                this.WriteLine(Context.ExecMacro("Called when $(End)[$(MethodName.Words.ExceptFirst)]."));
            }
        }
        else if(IsStateCheckMethod())
        {
            bool bWithParameters = Context.CurrentCodeElement.HasParameters;
            Words words = Context.GetWords(Context.CurrentCodeElement.Name);
            bool bSingleWord = (words != null && words.Count == 2);
            if (bWithParameters)
            {
                if (bSingleWord)
                {
                    this.WriteLine(Context.ExecMacro("Determines whether the specified $(Parameters.First.Name.Words.All) $(MethodName.Words.All)."));
                }
                else
                {
                    this.WriteLine(Context.ExecMacro("Determines whether $(End)[$(MethodName.Words.All)] [the specified $(Parameters.First.Name.Words.All)]."));
                }
            }
            else if (bSingleWord)
            {
                this.WriteLine(Context.ExecMacro("Determines whether this instance $(MethodName.Words.All)."));
            }
            else
            {
                this.WriteLine(Context.ExecMacro("Determines whether $(End)[$(MethodName.Words.All)]."));
            }
        }
        else if(IsCapabilityCheckMethod())
        {
            bool bWithParameters = Context.CurrentCodeElement.HasParameters;
            Words words = Context.GetWords(Context.CurrentCodeElement.Name);
            bool bSingleWord = (words != null && words.Count == 2);
            if (bWithParameters)
            {
                if (bSingleWord)
                {
                    this.WriteLine(Context.ExecMacro("Determines whether this instance $(MethodName.Words.All) the specified $(Parameters.First.Name.Words.All)."));
                }
                else
                {
                    this.WriteLine(Context.ExecMacro("Determines whether this instance $(End)[$(MethodName.Words.All)] the specified $(Parameters.First.Name.Words.All)."));
                }
            }
            else if (bSingleWord)
            {
                this.WriteLine(Context.ExecMacro("Determines whether this instance $(MethodName.Words.All)."));
            }
            else
            {
                this.WriteLine(Context.ExecMacro("Determines whether this instance $(End)[$(MethodName.Words.All)]."));
            }
        }
        else if(IsSingleWordMethod())
        {
            if(Context.CurrentCodeElement.HasParameters)
            {
                this.WriteLine(Context.ExecMacro("$(MethodName.Words.FirstAsVerbStartingSentence) the specified $(Parameters.First.Name.Words.All)."));
            }
            else
            {
                this.WriteLine(Context.ExecMacro("$(MethodName.Words.FirstAsVerbStartingSentence) this instance."));
            }
        }
        else if(Context.ContainsOfTheReordering(Context.CurrentCodeElement.Name))
        {
            this.WriteLine(Context.ExecMacro("$(OfTheReordering)"));
        }
        else
        {
            if(Context.CurrentCodeElement.IsMethod && Context.CurrentCodeElement.Name.Length > 0)
            {
                this.WriteLine(Context.ExecMacro("$(DefaultMethodName)"));
            }
            else
            {
                this.WriteLine(Context.ExecMacro("$(End)"));
            }
        }
  }

    private void GenerateParamText(Parameter parameter, int index)
    {
        if(Context.HasExistingTagText("param", index))
        {
            this.Write(Context.GetExistingTagText("param", index));
        }
        else if(Context.ContainsOfTheReordering(parameter.Name))
        {
            this.Write(Context.ExecMacro(parameter.Name, "$(OfTheReordering)"));
        }
        else
        {
            this.Write(Context.ExecMacro(parameter.Name, "$(TheAndAllAsSentence)") + ".");
        }
    }

    private void GenerateReturnsText()
    {
        if(Context.HasExistingTagText("returns"))
        {
#>
/// <returns><#= Context.GetExistingTagText("returns") #></returns>
<#+
        }
        else if(IsStateCheckMethod())
        {
            bool bWithParameters = Context.CurrentCodeElement.HasParameters;
            Words words = Context.GetWords(Context.CurrentCodeElement.Name);
            bool bSingleWord = (words != null && words.Count == 2);
            if (bWithParameters)
            {
                if (bSingleWord)
                {
#>
/// <returns><#= Context.ExecMacro("$(True) if the specified $(Parameters.First.Name.Words.All) $(MethodName.Words.All); otherwise, $(False).") #></returns>
<#+
                }
                else
                {
#>
/// <returns><#= Context.ExecMacro("$(True) if [$(MethodName.Words.All)] [the specified $(Parameters.First.Name.Words.All)]; otherwise, $(False).") #></returns>
<#+
                }
            }
            else if (bSingleWord)
            {
#>
/// <returns><#= Context.ExecMacro("$(True) if this instance $(MethodName.Words.All); otherwise, $(False).") #></returns>
<#+
            }
            else
            {
#>
/// <returns><#= Context.ExecMacro("$(True) if [$(MethodName.Words.All)]; otherwise, $(False).") #></returns>
<#+
            }
        }
        else if(IsCapabilityCheckMethod())
        {
            bool bWithParameters = Context.CurrentCodeElement.HasParameters;
            Words words = Context.GetWords(Context.CurrentCodeElement.Name);
            bool bSingleWord = (words != null && words.Count == 2);
            if (bWithParameters)
            {
                if (bSingleWord)
                {
#>
/// <returns><#= Context.ExecMacro("$(True) if this instance $(MethodName.Words.All) the specified $(Parameters.First.Name.Words.All); otherwise, $(False).") #></returns>
<#+
                }
                else
                {
#>
/// <returns><#= Context.ExecMacro("$(True) if this instance [$(MethodName.Words.All)] the specified $(Parameters.First.Name.Words.All); otherwise, $(False).") #></returns>
<#+
                }
            }
            else if (bSingleWord)
            {
#>
/// <returns><#= Context.ExecMacro("$(True) if this instance $(MethodName.Words.All); otherwise, $(False).") #></returns>
<#+
            }
            else
            {
#>
/// <returns><#= Context.ExecMacro("$(True) if this instance [$(MethodName.Words.All)]; otherwise, $(False).") #></returns>
<#+
            }
        }
    }

    private bool IsOnMethod()
    {
        CodeElement codeElement = Context.CurrentCodeElement;

        Words words = Context.GetWords(codeElement.Name);
        return (bool)(words != null && words.Count > 1 && codeElement.Name != null &&
            codeElement.Name.Length > "On".Length && codeElement.Name.StartsWith("On"));
    }

    private bool IsStateCheckMethod()
    {
        string[] triggerWords = new string[] { "is", "has", "contains" };

        CodeElement codeElement = Context.CurrentCodeElement;

        Words words = Context.GetWords(codeElement.Name);
        return (bool)(words != null && Array.IndexOf(triggerWords, words.First) >= 0);
    }
    private bool IsCapabilityCheckMethod()
    {
        string[] triggerWords = new string[] { "can" };

        CodeElement codeElement = Context.CurrentCodeElement;

        Words words = Context.GetWords(codeElement.Name);
        return (bool)(words != null && Array.IndexOf(triggerWords, words.First) >= 0);
    }

    private bool IsSingleWordMethod()
    {
        CodeElement codeElement = Context.CurrentCodeElement;

        Words words = Context.GetWords(codeElement.Name);
        return (bool)(words != null && words.Count == 1);
    }
    private bool IsOfTheSuffixMethod()
    {
        CodeElement codeElement = Context.CurrentCodeElement;

        Words words = Context.GetWords(codeElement.Name);
        return (bool)(words != null && words.Count == 1);
    }

    private void GenerateRemarksText()
    {
        if(Context.HasExistingTagText("remarks"))
        { #>
/// <remarks><#= Context.GetExistingTagText("remarks") #></remarks>
<#+        }
        else if (!string.IsNullOrEmpty(Context.GetGlobalProperty("DefaultBlankRemarksText")))
        {
            // Should you require a default comment, set it in
            // Options -> Global Properties -> DefaultBlankRemarksText
#>
/// <remarks><#= Context.GetGlobalProperty("DefaultBlankRemarksText") #></remarks>
<#+        }
    }
#>

See Also

  • Introduction to T4 Templates
  • GhostDoc Pro API
  • GhostDoc Macros


Javascript Variable Template

Javascript Variable template generates XML comment for Javascript variable code elements. Default T4 template inserts <summary> tag and any custom tags already defined.

Sample Output

/// <var>My field</var>
var myField;

Predefined T4 Template

<#@ template language="C#" #>
/// <var><# GenerateSummaryText(); #></var>

<#+
    private void GenerateSummaryText()
    {
        if(Context.HasExistingTagText("var"))
        {
            this.Write(Context.GetExistingTagText("var"));
        }
        else if(!string.IsNullOrEmpty(Context.GetSummaryOverride(Context.CurrentCodeElement.Name)))
        {
            this.Write(Context.GetSummaryOverride(Context.CurrentCodeElement.Name));
        }
        else
        {
            this.Write(Context.ExecMacro("$(FieldName.Words.TheAndAllAsSentence)$(End)"));
        }
    }
#>

See Also

  • Introduction to T4 Templates
  • GhostDoc Pro API
  • GhostDoc Macros


Method Template

Method template generates XML comment for method code elements. Default T4 template inserts <summary> tag, <typeparam> tags for each type parameter of the method, <param> tags for each parameter of the method, <returns> tag for return type of the method, <remarks> tag and any custom tags already defined.

Sample Output

/// <summary>
/// Processes the data.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="param1">The param1.</param>
/// <param name="param2">The param2.</param>
/// <exception cref="Exception"></exception>
/// <returns></returns>
/// <remarks></remarks>
public string ProcessData<T>(T param1, int param2)
{
}

Predefined T4 Template

<#@ template language="C#" #>
<#  CodeElement codeElement = Context.CurrentCodeElement; #>
/// <summary>
///<# GenerateSummaryText(); #>
/// </summary>
<#    if(codeElement.HasTypeParameters)
    {
        for(int i = 0; i < codeElement.TypeParameters.Length; i++)
        {
            TypeParameter typeParameter = codeElement.TypeParameters[i];
#>
/// <typeparam name="<#= typeParameter.Name #>"><# GenerateTypeParamText(typeParameter, i); #></typeparam>
<#        }
    }

    if(codeElement.HasParameters)
    {
        for(int i = 0; i < codeElement.Parameters.Length; i++)
        {
            Parameter parameter = codeElement.Parameters[i];
#>
/// <param name="<#= parameter.Name #>"><# GenerateParamText(parameter, i); #></param>
<#        }
    }
GenerateReturnsText(); #>
<#    if(Context.HasExceptions)
    {
        foreach (System.Collections.Generic.KeyValuePair<string, System.Collections.Generic.ICollection<string>> pair in Context.ExceptionDictionary)
        {
            string exceptionText = Context.GetExistingExceptionTagText(pair.Key); #>
/// <exception cref="<#= pair.Key #>"><#= ((exceptionText != null && exceptionText.Length > 0) ? exceptionText : Context.GetExceptionTagText(pair.Value)) #></exception>
<#        }
    }  #>
<#= Context.GetNonGeneratedExceptionTags() #>
<#= Context.GetNonGeneratedTags() #>
<# GenerateRemarksText(); #>
<#+
    private void GenerateSummaryText()
    {
        if(Context.HasExistingTagText("summary"))
        {
            this.WriteLine(Context.GetExistingTagText("summary"));
        }
        else if(IsAsyncMethod())
        {
            this.WriteLine(Context.ExecMacro("$(MethodName.Words.ExceptLast)") + " as an asynchronous operation.");
        }
        else if(IsMainMethod())
        {
            this.WriteLine("Defines the entry point of the application.");
        }
        else if(IsGetHashCodeMethod())
        {
            this.WriteLine("Returns a hash code for this instance.");
        }
        else if(IsEqualsMethod())
        {
            this.WriteLine("Determines whether the specified <see cref=\"System.Object\" /> is equal to this instance.");
        }
        else if(IsToStringMethod())
        {
            this.WriteLine("Returns a <see cref=\"System.String\" /> that represents this instance.");
        }
        else if(Context.HasInheritedTagText("summary"))
        {
            this.WriteLine(Context.GetInheritedTagText("summary"));
        }
        else if(!string.IsNullOrEmpty(Context.GetSummaryOverride(Context.CurrentCodeElement.Name)))
        {
            this.WriteLine(Context.GetSummaryOverride(Context.CurrentCodeElement.Name));
        }
        else if(IsOnMethod())
        {
            if(Context.CurrentCodeElement.HasParameters && IsEventArgsParameter(Context.CurrentCodeElement.Parameters[Context.CurrentCodeElement.Parameters.Length - 1]))
            {
                this.WriteLine(Context.ExecMacro("Handles the <see cref=\"E:$(MethodName.Words.Verbatim.ExceptFirst)\" /> event."));
            }
            else
            {
                this.WriteLine(Context.ExecMacro("Called when $(End)[$(MethodName.Words.ExceptFirst)]."));
            }
        }
        else if(IsControlEventHandlerMethod())
        {
            string name = Context.CurrentCodeElement.Name;
            int index = name.LastIndexOf('_');
            if(index >= 0)
            {
                this.WriteLine(string.Format(
                    "Handles the {0} event of the {1} control.",
                    name.Substring(index + 1),
                    name.Substring(0, index)));
            }
            else
            {
                this.WriteLine("[ERROR: No underscore found in name]");
            }
        }
        else if(IsFinalizeMethod())
        {
            // commented for StypeCop compliance (SA1643)
            // this.WriteLine(Context.ExecMacro("Releases unmanaged resources and performs other cleanup operations before the $(DeclaringTypeName.ShortNameAsSee) is reclaimed by garbage collection."));
            this.WriteLine(Context.ExecMacro("Finalizes an instance of the $(DeclaringTypeName.ShortNameAsSee) class."));
        }
        else if(IsStateCheckMethod())
        {
            bool bWithParameters = Context.CurrentCodeElement.HasParameters;
            Words words = Context.GetWords(Context.CurrentCodeElement.Name);
            bool bSingleWord = (words != null && words.Count == 2);
            if (bWithParameters)
            {
                if (bSingleWord)
                {
                    this.WriteLine(Context.ExecMacro("Determines whether the specified $(Parameters.First.Name.Words.All) $(MethodName.Words.All)."));
                }
                else
                {
                    this.WriteLine(Context.ExecMacro("Determines whether $(End)[$(MethodName.Words.All)] [the specified $(Parameters.First.Name.Words.All)]."));
                }
            }
            else if (bSingleWord)
            {
                this.WriteLine(Context.ExecMacro("Determines whether this instance $(MethodName.Words.All)."));
            }
            else
            {
                this.WriteLine(Context.ExecMacro("Determines whether $(End)[$(MethodName.Words.All)]."));
            }
        }
        else if(IsCapabilityCheckMethod())
        {
            bool bWithParameters = Context.CurrentCodeElement.HasParameters;
            Words words = Context.GetWords(Context.CurrentCodeElement.Name);
            bool bSingleWord = (words != null && words.Count == 2);
            if (bWithParameters)
            {
                if (bSingleWord)
                {
                    this.WriteLine(Context.ExecMacro("Determines whether this instance $(MethodName.Words.All) the specified $(Parameters.First.Name.Words.All)."));
                }
                else
                {
                    this.WriteLine(Context.ExecMacro("Determines whether this instance $(End)[$(MethodName.Words.All)] the specified $(Parameters.First.Name.Words.All)."));
                }
            }
            else if (bSingleWord)
            {
                this.WriteLine(Context.ExecMacro("Determines whether this instance $(MethodName.Words.All)."));
            }
            else
            {
                this.WriteLine(Context.ExecMacro("Determines whether this instance $(End)[$(MethodName.Words.All)]."));
            }
        }
        else if(IsImplicitOperatorMethod())
        {
            this.WriteLine(Context.ExecMacro("Performs an implicit conversion from $(Parameters.First.TypeName.FullNameAsSee) to $(ReturnTypeName.FullNameAsSee)."));
        }
        else if(IsExplicitOperatorMethod())
        {
            this.WriteLine(Context.ExecMacro("Performs an explicit conversion from $(Parameters.First.TypeName.FullNameAsSee) to $(ReturnTypeName.FullNameAsSee)."));
        }
        else if(Context.CurrentCodeElement.IsOperator)
        {
            this.WriteLine(Context.ExecMacro("Implements the $(MethodName.ActualName)."));
        }
        else if(IsDisposeMethod())
        {
            this.WriteLine("Releases unmanaged and - optionally - managed resources.");
        }
        else if(IsSingleWordMethod())
        {
            if(Context.CurrentCodeElement.HasParameters)
            {
                this.WriteLine(Context.ExecMacro("$(MethodName.Words.FirstAsVerbStartingSentence) the specified $(Parameters.First.Name.Words.All)."));
            }
            else
            {
                this.WriteLine(Context.ExecMacro("$(MethodName.Words.FirstAsVerbStartingSentence) this instance."));
            }
        }
        else if(Context.ContainsOfTheReordering(Context.CurrentCodeElement.Name))
        {
            this.WriteLine(Context.ExecMacro("$(OfTheReordering)"));
        }
        else
        {
            if(Context.CurrentCodeElement.IsMethod)
            {
                this.WriteLine(Context.ExecMacro("$(DefaultMethodName)"));
            }
            else
            {
                this.WriteLine(Context.ExecMacro("$(End)"));
            }
        }
    }

    private void GenerateTypeParamText(TypeParameter typeParameter, int index)
    {
        if(Context.HasExistingTagText("typeparam", index))
        {
            this.Write(Context.GetExistingTagText("typeparam", index));
        }
        else if(Context.HasInheritedTagText("typeparam", index))
        {
            this.Write(Context.GetInheritedTagText("typeparam", index));
        }
        else
        {
            string typeParameterName = typeParameter.Name;
            if(typeParameterName != null)
            {
                if(typeParameterName.Length == 1)
                {
                    this.Write("");
                }
                else
                {
                    this.Write("The type of " + Context.ExecMacro(typeParameterName, "$(TheAndAll)") + ".");
                }
            }
        }
    }

    private void GenerateParamText(Parameter parameter, int index)
    {
        if(Context.HasExistingTagText("param", index))
        {
            this.Write(Context.GetExistingTagText("param", index));
        }
        else if(Context.HasInheritedTagText("param", index))
        {
            this.Write(Context.GetInheritedTagText("param", index));
        }
        else if(IsEqualsMethod() && index == 0)
        {
            this.Write("The <see cref=\"System.Object\" /> to compare with this instance.");
        }
        else if(IsDisposeMethod() && index == 0)
        {
            this.Write(Context.ExecMacro("$(True) to release both managed and unmanaged resources; $(False) to release only unmanaged resources."));
        }
        else if(IsControlEventHandlerMethod() && index == 0)
        {
            this.Write("The source of the event.");
        }
        else if(IsBooleanParameter(parameter))
        {
            this.Write("if set to " + Context.ExecMacro("$(True)") + " [" + Context.ExecMacro(parameter.Name, "$(All)") + "].");
        }
        else if(IsEventArgsParameter(parameter))
        {
            this.Write("The " + Context.ExecMacro(parameter.ReturnType.FullName, "$(TypeName.FullNameAsSee)") + " instance containing the event data.");
        }
        else if(Context.ContainsOfTheReordering(parameter.Name))
        {
            this.Write(Context.ExecMacro(parameter.Name, "$(OfTheReordering)"));
        }
        else
        {
            this.Write(Context.ExecMacro(parameter.Name, "$(TheAndAllAsSentence)") + ".");
        }
    }

    private void GenerateReturnsText()
    {
        if(Context.HasExistingTagText("returns"))
        {
#>
/// <returns><#= Context.GetExistingTagText("returns") #></returns>
<#+
        }
        else if(IsGetHashCodeMethod())
        {
#>
/// <returns>A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table.</returns>
<#+
        }
        else if(IsEqualsMethod())
        {
#>
/// <returns><#= Context.ExecMacro("$(True) if the specified <see cref=\"System.Object\" /> is equal to this instance; otherwise, $(False).") #></returns>
<#+
        }
        else if(IsToStringMethod())
        {
#>
/// <returns>A <see cref="System.String" /> that represents this instance.</returns>
<#+
        }
        else if(Context.HasInheritedTagText("returns"))
        {
#>
/// <returns><#= Context.GetInheritedTagText("returns") #></returns>
<#+
        }
        else if(IsStateCheckMethod() && IsBooleanMethod())
        {
            bool bWithParameters = Context.CurrentCodeElement.HasParameters;
            Words words = Context.GetWords(Context.CurrentCodeElement.Name);
            bool bSingleWord = (words != null && words.Count == 2);
            if (bWithParameters)
            {
                if (bSingleWord)
                {
#>
/// <returns><#= Context.ExecMacro("$(True) if the specified $(Parameters.First.Name.Words.All) $(MethodName.Words.All); otherwise, $(False).") #></returns>
<#+
                }
                else
                {
#>
/// <returns><#= Context.ExecMacro("$(True) if [$(MethodName.Words.All)] [the specified $(Parameters.First.Name.Words.All)]; otherwise, $(False).") #></returns>
<#+
                }
            }
            else if (bSingleWord)
            {
#>
/// <returns><#= Context.ExecMacro("$(True) if this instance $(MethodName.Words.All); otherwise, $(False).") #></returns>
<#+
            }
            else
            {
#>
/// <returns><#= Context.ExecMacro("$(True) if [$(MethodName.Words.All)]; otherwise, $(False).") #></returns>
<#+
            }
        }
        else if(IsCapabilityCheckMethod() && IsBooleanMethod())
        {
            bool bWithParameters = Context.CurrentCodeElement.HasParameters;
            Words words = Context.GetWords(Context.CurrentCodeElement.Name);
            bool bSingleWord = (words != null && words.Count == 2);
            if (bWithParameters)
            {
                if (bSingleWord)
                {
#>
/// <returns><#= Context.ExecMacro("$(True) if this instance $(MethodName.Words.All) the specified $(Parameters.First.Name.Words.All); otherwise, $(False).") #></returns>
<#+
                }
                else
                {
#>
/// <returns><#= Context.ExecMacro("$(True) if this instance [$(MethodName.Words.All)] the specified $(Parameters.First.Name.Words.All); otherwise, $(False).") #></returns>
<#+
                }
            }
            else if (bSingleWord)
            {
#>
/// <returns><#= Context.ExecMacro("$(True) if this instance $(MethodName.Words.All); otherwise, $(False).") #></returns>
<#+
            }
            else
            {
#>
/// <returns><#= Context.ExecMacro("$(True) if this instance [$(MethodName.Words.All)]; otherwise, $(False).") #></returns>
<#+
            }
        }
        else if(IsImplicitOperatorMethod())
        {
#>
/// <returns>The result of the conversion.</returns>
<#+
        }
        else if(IsExplicitOperatorMethod())
        {
#>
/// <returns>The result of the conversion.</returns>
<#+
        }
        else if(Context.CurrentCodeElement.IsOperator)
        {
#>
/// <returns>The result of the operator.</returns>
<#+
        }
        else if(Context.CurrentCodeElement.HasReturnType &&
            Context.CurrentCodeElement.ReturnType.FullName.Length > 0 &&
            String.Compare( Context.CurrentCodeElement.ReturnType.FullName, "System.Boolean", true) == 0)
        {
#>
/// <returns><#= Context.ExecMacro("$(True)") #> if XXXX, <#= Context.ExecMacro("$(False)") #> otherwise.</returns>
<#+
        }
        else if(Context.CurrentCodeElement.HasReturnType &&
            !(Context.CurrentCodeElement.ReturnType.FullName.Length == 0 ||
            String.Compare( Context.CurrentCodeElement.ReturnType.FullName, "void", true) == 0))
        {
#>
/// <returns><#= Context.ExecMacro("$(ReturnTypeName.FullName).") #></returns>
<#+
        }
    }

    private bool IsBooleanParameter(Parameter parameter)
    {
        return (bool)(parameter.ReturnType != null &&
            parameter.ReturnType.FullName != null &&
            parameter.ReturnType.FullName.Length > 0 &&
            (string.Compare( parameter.ReturnType.FullName, "System.Boolean", true) == 0 ||
            string.Compare( parameter.ReturnType.FullName, "System.Nullable<bool>", true) == 0));
    }

    private bool IsEventArgsParameter(Parameter parameter)
    {
        return (bool)(parameter.ReturnType != null &&
            parameter.ReturnType.FullName != null &&
            parameter.ReturnType.FullName.Length >= "EventArgs".Length &&
            parameter.ReturnType.FullName.EndsWith("EventArgs"));
    }

    private bool IsBooleanMethod()
    {
        CodeElement codeElement = Context.CurrentCodeElement;

        return (bool)(codeElement.ReturnType != null &&
            codeElement.ReturnType.FullName != null &&
            codeElement.ReturnType.FullName.Length > 0 &&
            string.Compare( codeElement.ReturnType.FullName, "System.Boolean", true) == 0);
    }

    private bool IsGetHashCodeMethod()
    {
        CodeElement codeElement = Context.CurrentCodeElement;

        return (bool)(codeElement.Name == "GetHashCode" &&
            codeElement.ReturnType != null &&
            codeElement.ReturnType.FullName != null &&
            codeElement.ReturnType.FullName.Length > 0 &&
            string.Compare( codeElement.ReturnType.FullName, "System.Int32", true) == 0);
    }
    private bool IsEqualsMethod()
    {
        CodeElement codeElement = Context.CurrentCodeElement;

        return (bool)(codeElement.Name == "Equals" &&
            codeElement.ReturnType != null &&
            codeElement.ReturnType.FullName != null &&
            codeElement.ReturnType.FullName.Length > 0 &&
            string.Compare( codeElement.ReturnType.FullName, "System.Boolean", true) == 0 &&
            codeElement.HasParameters && codeElement.Parameters.Length == 1 &&
            codeElement.Parameters[0].ReturnType != null &&
            codeElement.Parameters[0].ReturnType.FullName != null &&
            codeElement.Parameters[0].ReturnType.FullName.Length > 0 &&
            string.Compare( codeElement.Parameters[0].ReturnType.FullName, "System.Object", true) == 0);
    }
    private bool IsToStringMethod()
    {
        CodeElement codeElement = Context.CurrentCodeElement;

        return (bool)(codeElement.Name == "ToString" &&
            codeElement.ReturnType != null &&
            codeElement.ReturnType.FullName != null &&
            codeElement.ReturnType.FullName.Length > 0 &&
            string.Compare( codeElement.ReturnType.FullName, "System.String", true) == 0);
    }
    private bool IsOnMethod()
    {
        CodeElement codeElement = Context.CurrentCodeElement;

        Words words = Context.GetWords(codeElement.Name);
        return (bool)(words != null && words.Count > 1 && codeElement.Name != null &&
            codeElement.Name.Length > "On".Length && codeElement.Name.StartsWith("On"));
    }

    private bool IsControlEventHandlerMethod()
    {
        CodeElement codeElement = Context.CurrentCodeElement;

        return (bool)(codeElement.HasParameters && codeElement.Parameters.Length == 2 &&
            codeElement.Parameters[0].ReturnType != null &&
            codeElement.Parameters[0].ReturnType.FullName != null &&
            codeElement.Parameters[0].ReturnType.FullName.Length > 0 &&
            string.Compare( codeElement.Parameters[0].ReturnType.FullName, "System.Object", true) == 0 &&
            codeElement.Parameters[1].ReturnType != null &&
            codeElement.Parameters[1].ReturnType.FullName != null &&
            codeElement.Parameters[1].ReturnType.FullName.Length >= "EventArgs".Length &&
            codeElement.Parameters[1].ReturnType.FullName.EndsWith("EventArgs") &&
            codeElement.Name.LastIndexOf('_') != -1);
    }

    private bool IsFinalizeMethod()
    {
        CodeElement codeElement = Context.CurrentCodeElement;

        return (bool)(codeElement.Name != null && codeElement.Name.Length > 1 &&
            codeElement.Name.StartsWith("~"));
    }
    private bool IsStateCheckMethod()
    {
        string[] triggerWords = new string[] { "is", "has", "contains" };

        CodeElement codeElement = Context.CurrentCodeElement;

        Words words = Context.GetWords(codeElement.Name);
        return (bool)(words != null && Array.IndexOf(triggerWords, words.First) >= 0);
    }
    private bool IsCapabilityCheckMethod()
    {
        string[] triggerWords = new string[] { "can" };

        CodeElement codeElement = Context.CurrentCodeElement;

        Words words = Context.GetWords(codeElement.Name);
        return (bool)(words != null && Array.IndexOf(triggerWords, words.First) >= 0);
    }

    private bool IsImplicitOperatorMethod()
    {
        CodeElement codeElement = Context.CurrentCodeElement;

        return (bool)(codeElement.Name != null && codeElement.Name.Length > "implicit operator".Length &&
            codeElement.Name != null && codeElement.Name.StartsWith("implicit operator"));
    }

    private bool IsExplicitOperatorMethod()
    {
        CodeElement codeElement = Context.CurrentCodeElement;

        return (bool)(codeElement.Name != null && codeElement.Name.Length > "explicit operator".Length &&
            codeElement.Name.StartsWith("explicit operator"));
    }
    private bool IsDisposeMethod()
    {
        CodeElement codeElement = Context.CurrentCodeElement;

        return (bool)(codeElement.Name == "Dispose" &&
            codeElement.HasParameters && codeElement.Parameters.Length == 1 &&
            codeElement.Parameters[0].ReturnType != null &&
            codeElement.Parameters[0].ReturnType.FullName != null &&
            codeElement.Parameters[0].ReturnType.FullName.Length > 0 &&
            string.Compare( codeElement.Parameters[0].ReturnType.FullName, "System.Boolean", true) == 0);
    }

    private bool IsSingleWordMethod()
    {
        CodeElement codeElement = Context.CurrentCodeElement;

        Words words = Context.GetWords(codeElement.Name);
        return (bool)(words != null && words.Count == 1);
    }
    private bool IsOfTheSuffixMethod()
    {
        CodeElement codeElement = Context.CurrentCodeElement;

        Words words = Context.GetWords(codeElement.Name);
        return (bool)(words != null && words.Count == 1);
    }

    private bool IsAsyncMethod()
    {
        CodeElement codeElement = Context.CurrentCodeElement;
        return (bool)(codeElement.IsAsync && codeElement.Name.Length > "Async".Length && codeElement.Name.EndsWith("Async"));
    }

    private bool IsMainMethod()
    {
        CodeElement codeElement = Context.CurrentCodeElement;

        return (bool)(codeElement.Name == "Main" && codeElement.IsStatic &&
            ((codeElement.HasParameters && codeElement.Parameters.Length == 1) || !codeElement.HasParameters));
    }

    private void GenerateRemarksText()
    {
        if(Context.HasInheritedTagText("remarks"))
        { #>
/// <remarks><#= Context.GetInheritedTagText("remarks") #></remarks>
<#+        }
        else if(Context.HasExistingTagText("remarks"))
        { #>
/// <remarks><#= Context.GetExistingTagText("remarks") #></remarks>
<#+        }
        else if (!string.IsNullOrEmpty(Context.GetGlobalProperty("DefaultBlankRemarksText")))
        {
            // Should you require a default comment, set it in
            // Options -> Global Properties -> DefaultBlankRemarksText
#>
/// <remarks><#= Context.GetGlobalProperty("DefaultBlankRemarksText") #></remarks>
<#+        }
    }
#>

See Also

  • Introduction to T4 Templates
  • GhostDoc Pro API
  • GhostDoc Macros


Namespace Template

Namespace template generates XML comment for namespace code elements. Default T4 template inserts <summary> tag, <remarks> tag and any custom tags already defined.

Sample Output

/// <summary>
///
/// </summary>
/// <remarks></remarks>
namespace WindowsFormsApplication1
{
...
}

Predefined T4 Template

<#@ template language="C#" #>
/// <summary>
///<# GenerateSummaryText(); #>
/// </summary>
<#= Context.GetNonGeneratedTags() #>
<# GenerateRemarksText(); #>
<#+
    private void GenerateSummaryText()
    {
        if(Context.HasExistingTagText("summary"))
        {
            this.WriteLine(Context.GetExistingTagText("summary"));
        }
        else
        {
            this.WriteLine("The " + Context.CurrentCodeElement.Name + " namespace." + Context.ExecMacro("$(End)"));
        }
    }

    private void GenerateRemarksText()
    {
        if(Context.HasExistingTagText("remarks"))
        { #>
/// <remarks><#= Context.GetExistingTagText("remarks") #></remarks>
<#+        }
        else if (!string.IsNullOrEmpty(Context.GetGlobalProperty("DefaultBlankRemarksText")))
        {
            // Should you require a default comment, set it in
            // Options -> Global Properties -> DefaultBlankRemarksText
#>
/// <remarks><#= Context.GetGlobalProperty("DefaultBlankRemarksText") #></remarks>
<#+        }
    }
#>

See Also

  • Introduction to T4 Templates
  • GhostDoc Pro API
  • GhostDoc Macros


Property Template

Property template generates XML comment for property code elements. Default T4 template inserts <summary> tag, <value> tag for return value of the property, <remarks> tag and any custom tags already defined.

Sample Output

/// <summary>
/// Gets or sets my property.
/// </summary>
/// <exception cref="Exception"></exception>
/// <value>My property.</value>
/// <remarks></remarks>
public string MyProperty
{
    get { }
    set { }
}

Predefined T4 Template

<#@ template language="C#" #>
/// <summary>
///<# GenerateSummaryText(); #>
/// </summary>
<# GenerateValueText(); #>
<#    if(Context.HasExceptions)
    {
        foreach (System.Collections.Generic.KeyValuePair<string, System.Collections.Generic.ICollection<string>> pair in Context.ExceptionDictionary)
        {
            string exceptionText = Context.GetExistingExceptionTagText(pair.Key); #>
/// <exception cref="<#= pair.Key #>"><#= ((exceptionText != null && exceptionText.Length > 0) ? exceptionText : Context.GetExceptionTagText(pair.Value)) #></exception>
<#        }
    }  #>
<#= Context.GetNonGeneratedExceptionTags() #>
<#= Context.GetNonGeneratedTags() #>
<# GenerateRemarksText(); #>
<#+
    private void GenerateSummaryText()
    {
        CodeElement codeElement = Context.CurrentCodeElement;

        if(Context.HasExistingTagText("summary"))
        {
            this.WriteLine(Context.GetExistingTagText("summary"));
        }
        else if(Context.HasInheritedTagText("summary"))
        {
            this.WriteLine(Context.GetInheritedTagText("summary"));
        }
        else if(!string.IsNullOrEmpty(Context.GetSummaryOverride(Context.CurrentCodeElement.Name)))
        {
            this.WriteLine(Context.GetSummaryOverride(Context.CurrentCodeElement.Name));
        }
        else if(IsBooleanProperty())
        {
            if(IsStateCheckBooleanProperty())
            {
                // state check boolean property
                this.WriteLine(Context.ExecMacro("$(PropertyAccessText) a value indicating whether this instance $(PropertyName.Words.All)."));
            }
            else if(IsSingleWordBooleanProperty())
            {
                // single word boolean property
                this.WriteLine(Context.ExecMacro("$(PropertyAccessText) a value indicating whether this $(DeclaringTypeName.ShortNameAsSee) is $(PropertyName.Words.First)."));
            }
            else
            {
                // boolean property
                this.WriteLine(Context.ExecMacro("$(PropertyAccessText) a value indicating whether $(End)[$(PropertyName.Words.All)]."));
            }
        }
        else if(Context.ContainsOfTheReordering(codeElement.Name))
        {
            this.WriteLine(Context.ExecMacro(codeElement.Name, "$(OfTheReordering)", Context.ExecMacro("$(PropertyAccessText)")));
        }
        else
        {
            this.WriteLine(Context.ExecMacro("$(PropertyAccessText) $(PropertyName.Words.TheAndAll)."));
        }
    }

    private void GenerateValueText()
    {
        CodeElement codeElement = Context.CurrentCodeElement;

        if(Context.HasExistingTagText("value"))
        {
#>
/// <value><#= Context.GetExistingTagText("value") #></value>
<#+
        }
        else if(Context.HasInheritedTagText("value"))
        {
#>
/// <value><#= Context.GetInheritedTagText("value") #></value>
<#+
        }
        else /*if(Context.CurrentCodeElement.HasSet) - commented for StypeCop compliance (SA1609) */
        {
            if(IsBooleanProperty())
            {
                if(IsNullalbleBooleanProperty())
                {
#>
/// <value><#= Context.ExecMacro("$(Null) if [$(PropertyName.Words.All)] contains no value, $(True) if [$(PropertyName.Words.All)]; otherwise, $(False).") #></value>
<#+
                }
                else if(IsStateCheckBooleanProperty())
                {
                    // state check boolean property
#>
/// <value><#= Context.ExecMacro("$(True) if this instance $(PropertyName.Words.All); otherwise, $(False).") #></value>
<#+
                }
                else if(IsSingleWordBooleanProperty())
                {
                    // single word boolean property
#>
/// <value><#= Context.ExecMacro("$(True) if $(PropertyName.Words.First); otherwise, $(False).") #></value>
<#+
                }
                else
                {
                    // boolean property
#>
/// <value><#= Context.ExecMacro("$(True) if [$(PropertyName.Words.All)]; otherwise, $(False).") #></value>
<#+
                }
            }
            else if(Context.ContainsOfTheReordering(codeElement.Name))
            {
                string valueTagText = Context.ExecMacro(codeElement.Name, "$(OfTheReordering)", "");
                valueTagText = Words.ToSentenceCase(valueTagText.TrimStart());
#>
/// <value><#= valueTagText #></value>
<#+
            }
            else
            {
#>
/// <value><#= Context.ExecMacro("$(PropertyName.Words.TheAndAllAsSentence).") #></value>
<#+
            }
        }
    }

    private bool IsNullalbleBooleanProperty()
    {
        CodeElement codeElement = Context.CurrentCodeElement;
        return (bool)(codeElement.ReturnType != null && codeElement.ReturnType.IsNullable);
    }

    private bool IsStateCheckBooleanProperty()
    {
        string[] triggerWords = new string[] { "can", "is", "has" };

        CodeElement codeElement = Context.CurrentCodeElement;

        Words words = Context.GetWords(codeElement.Name);
        return (bool)(words != null && Array.IndexOf(triggerWords, words.First) >= 0);
    }

    private bool IsSingleWordBooleanProperty()
    {
        CodeElement codeElement = Context.CurrentCodeElement;

        Words words = Context.GetWords(codeElement.Name);
        return (bool)(words != null && words.Count == 1);
    }

    private bool IsBooleanProperty()
    {
        CodeElement codeElement = Context.CurrentCodeElement;
        return (bool)(codeElement.ReturnType != null &&
            codeElement.ReturnType.FullName != null &&
            codeElement.ReturnType.FullName.Length > 0 &&
            (string.Compare( codeElement.ReturnType.FullName, "System.Boolean", true) == 0 ||
            string.Compare( codeElement.ReturnType.FullName, "System.Nullable<bool>", true) == 0));
    }

    private void GenerateRemarksText()
    {
        if(Context.HasInheritedTagText("remarks"))
        { #>
/// <remarks><#= Context.GetInheritedTagText("remarks") #></remarks>
<#+        }
        else if(Context.HasExistingTagText("remarks"))
        { #>
/// <remarks><#= Context.GetExistingTagText("remarks") #></remarks>
<#+        }
        else if (!string.IsNullOrEmpty(Context.GetGlobalProperty("DefaultBlankRemarksText")))
        {
            // Should you require a default comment, set it in
            // Options -> Global Properties -> DefaultBlankRemarksText
#>
/// <remarks><#= Context.GetGlobalProperty("DefaultBlankRemarksText") #></remarks>
<#+        }
    }
#>

See Also

  • Introduction to T4 Templates
  • GhostDoc Pro API
  • GhostDoc Macros


Struct Template

Struct template generates XML comment for struct code elements. Default T4 template inserts <summary> tag, <typeparam> tags for each type parameter of the class, <remarks> tag and any custom tags already defined.

Sample Output

/// <summary>
/// Struct MyStruct
/// </summary>
/// <typeparam name="T"></typeparam>
/// <remarks></remarks>
struct MyStruct<T>
{
...
}

Predefined T4 Template

<#@ template language="C#" #>
<#  CodeElement codeElement = Context.CurrentCodeElement; #>
/// <summary>
///<# GenerateSummaryText(); #>
/// </summary>
<#    if(codeElement.HasTypeParameters)
    {
        for(int i = 0; i < codeElement.TypeParameters.Length; i++)
        {
            TypeParameter typeParameter = codeElement.TypeParameters[i];
#>
/// <typeparam name="<#= typeParameter.Name #>"><# GenerateTypeParamText(typeParameter, i); #></typeparam>
<#        }
    }
#>
<#  if(codeElement.HasBaseTypes)
    {
        for(int i = 0; i < codeElement.BaseTypes.Length; i++)
        {
#>
/// <seealso cref="<#= codeElement.BaseTypes[i] #>" />
<#        }
    }
#>
<#= Context.GetNonGeneratedTags() #>
<# GenerateRemarksText(); #>
<#+
    private void GenerateSummaryText()
    {
        if(Context.HasExistingTagText("summary"))
        {
            this.WriteLine(Context.GetExistingTagText("summary"));
        }
        else
        {
            this.WriteLine("Struct " + Context.CurrentCodeElement.Name + Context.ExecMacro("$(End)"));
        }
    }

    private void GenerateTypeParamText(TypeParameter typeParameter, int index)
    {
        if(Context.HasExistingTagText("typeparam", index))
        {
            this.Write(Context.GetExistingTagText("typeparam", index));
        }
        else
        {
            string typeParameterName = typeParameter.Name;
            if(typeParameterName != null)
            {
                if(typeParameterName.Length == 1)
                {
                    this.Write("");
                }
                else
                {
                    this.Write("The type of " + Context.ExecMacro(typeParameterName, "$(TheAndAll)") + ".");
                }
            }
        }
    }

    private void GenerateRemarksText()
    {
        if(Context.HasExistingTagText("remarks"))
        { #>
/// <remarks><#= Context.GetExistingTagText("remarks") #></remarks>
<#+        }
        else if (!string.IsNullOrEmpty(Context.GetGlobalProperty("DefaultBlankRemarksText")))
        {
            // Should you require a default comment, set it in
            // Options -> Global Properties -> DefaultBlankRemarksText
#>
/// <remarks><#= Context.GetGlobalProperty("DefaultBlankRemarksText") #></remarks>
<#+        }
    }
#>

See Also

  • Introduction to T4 Templates
  • GhostDoc Pro API
  • GhostDoc Macros


GhostDoc Pro Overview and Resources

G h o s t D o c v2022.1

GhostDoc Enterprise

Overview

GhostDoc Enterprise is for advanced users and larger teams looking for premium features, integration, and unattended deployment.

GhostDoc Enterprise is right for you if, on top of the Pro features, you are looking for

  • Full-featured documentation builder
  • Add custom content, like Welcome, License, etc.
  • Command line version for CI integration and generating docs with your build
  • Create your own documentation themes and layouts
  • Silent deployment and silent activation
  • Priority support

Resources

  • GhostDoc Enterprise - Command Line Parameters
  • GhostDoc Enterprise Silent Registration - Command Line Parameters
  • Conceptual Content - Adding Custom Content to API Documentation created with GhostDoc
  • Conceptual Content - How to include Tables
  • Conceptual Content - How to Include Bulleted and Ordered Lists
  • More GhostDoc Tutorials and Resources

See Also

  • GhostDoc Edition Comparison - Community, Pro and Enterprise
  • GhostDoc Tutorials and Resources


Rules

G h o s t D o c v2022.1

Reference: Macros

The following are macros supported by GhostDoc and GhostDoc Pro:

  • $(All) - All words, divided by space characters.
  • Configurable
    • $(False) - The textual representation of the "false" keyword.
    • $(True) - The textual representation of the "true" keyword.
  • $(DeclaringTypeKind) - The kind of type (class, struct, interface) containing the member.
  • DeclaringTypeName
    • $(DeclaringTypeName.ShortNameAsSee) - The short name of the type (i.e. not including the namespace) formatted as a "see" tag.
  • $(End) - Specifies the place where the cursor will be located after the documentation has been generated.
  • $(newLine) - Inserts an empty XML Comment line with the leading /// (''').
  • $(blankLine) - Inserts a blank line.
  • EventName
    • EventName.Words
      • $(EventName.Words.All) - All words of the event name, divided by space characters.
      • $(EventName.Words.AllAsSentence) - All words, divided by space characters, the first word starting with an uppercase letter.
      • $(EventName.Words.BetweenFirstAndLast) - All words between the first and the last, divided by space characters.
      • $(EventName.Words.ExceptFirst) - All words except the first, divided by space characters.
      • $(EventName.Words.ExceptLast) - All words except the last, divided by space characters.
      • $(EventName.Words.ExceptLastPascalCase) - All words in Pascal case except the last, divided by space characters.
      • $(EventName.Words.ExceptLastTwo) - All words except the last two, divided by space characters.
      • $(EventName.Words.ExceptLastTwoPascalCase) - All words in Pascal case except the last two, divided by space characters.
      • $(EventName.Words.First) - The first of the individual words.
      • $(EventName.Words.FirstAsStartOfSentence) - The first of the individual words, first character converted to upper case.
      • $(EventName.Words.Last) - The last of the individual words.
      • $(EventName.Words.TheAndAll) - All words, divided by space characters, preceded by "the" ("the" will be omittted if the first word is a "no the" word).
      • $(EventName.Words.TheAndAllAsSentence) - All words of the event name, divided by space characters, preceded by "The" ("The" will be omittted if the first word is a "no the" word).
      • $(EventName.Words.TheAndFirst) - The first of the individual words, preceded by "the" ("the" will be omittted if the first word is a "no the" word).
      • $(EventName.Words.TheAndFirstAsStartOfSentence) - The first of the individual words, preceded by "The" ("The" will be omittted if the first word is a "no the" word).
      • EventName.Words.Verbatim
        • $(EventName.Words.Verbatim.BetweenFirstAndLast) - All words between the first and the last, divided by space characters.
        • $(EventName.Words.Verbatim.ExceptFirst) - All words except the first, divided by space characters.
        • $(EventName.Words.Verbatim.ExceptLast) - The verbatim text except the last word.
        • $(EventName.Words.Verbatim.ExceptLastTwo) - All words except the last two, divided by space characters.
        • $(EventName.Words.Verbatim.First) - The first of the individual words, in its original casing.
        • $(EventName.Words.Verbatim.Last) - The last of the individual words, in its original casing.
  • FieldName
    • FieldName.Words
      • $(FieldName.Words.All) - All words of the field name, divided by space characters.
      • $(FieldName.Words.AllAsSentence) - All words, divided by space characters, the first word starting with an uppercase letter.
      • $(FieldName.Words.BetweenFirstAndLast) - All words between the first and the last, divided by space characters.
      • $(FieldName.Words.ExceptFirst) - All words except the first, divided by space characters.
      • $(FieldName.Words.ExceptLast) - All words except the last, divided by space characters.
      • $(FieldName.Words.ExceptLastPascalCase) - All words in Pascal case except the last, divided by space characters.
      • $(FieldName.Words.ExceptLastTwo) - All words except the last two, divided by space characters.
      • $(FieldName.Words.ExceptLastTwoPascalCase) - All words in Pascal case except the last two, divided by space characters.
      • $(FieldName.Words.First) - The first of the individual words.
      • $(FieldName.Words.FirstAsStartOfSentence) - The first of the individual words, first character converted to upper case.
      • $(FieldName.Words.Last) - The last of the individual words.
      • $(FieldName.Words.TheAndAll) - All words, divided by space characters, preceded by "the" ("the" will be omittted if the first word is a "no the" word).
      • $(FieldName.Words.TheAndAllAsSentence) - All words of the field name, divided by space characters, preceded by "The" ("The" will be omittted if the first word is a "no the" word).
      • $(FieldName.Words.TheAndFirst) - The first of the individual words, preceded by "the" ("the" will be omittted if the first word is a "no the" word).
      • $(FieldName.Words.TheAndFirstAsStartOfSentence) - The first of the individual words, preceded by "The" ("The" will be omittted if the first word is a "no the" word).
      • FieldName.Words.Verbatim
        • $(FieldName.Words.Verbatim.BetweenFirstAndLast) - All words between the first and the last, divided by space characters.
        • $(FieldName.Words.Verbatim.ExceptFirst) - All words except the first, divided by space characters.
        • $(FieldName.Words.Verbatim.ExceptLast) - The verbatim text except the last word.
        • $(FieldName.Words.Verbatim.ExceptLastTwo) - All words except the last two, divided by space characters.
        • $(FieldName.Words.Verbatim.First) - The first of the individual words, in its original casing.
        • $(FieldName.Words.Verbatim.Last) - The last of the individual words, in its original casing.
  • $(IndexerAccessText) - Textual description of the access to the indexer.
  • IndexerTypeName
    • $(IndexerTypeName.FullNameAsSee) - The full name (i.e. including namespace and name), formatted as a "see" tag.
  • MethodName
    • $(MethodName.ActualName) - The actual name (without '.' ).
    • MethodName.Words
      • $(MethodName.Words.All) - All words of the method name, divided by space characters.
      • $(MethodName.Words.AllAsSentence) - All words, divided by space characters, the first word starting with an uppercase letter.
      • $(MethodName.Words.BetweenFirstAndLast) - All words between the first and the last, divided by space characters.
      • $(MethodName.Words.ExceptFirst) - All words except the first, divided by space characters.
      • $(MethodName.Words.ExceptLast) - All words except the last, divided by space characters.
      • $(MethodName.Words.ExceptLastPascalCase) - All words in Pascal case except the last, divided by space characters.
      • $(MethodName.Words.ExceptLastTwo) - All words except the last two, divided by space characters.
      • $(MethodName.Words.ExceptLastTwoPascalCase) - All words in Pascal case except the last two, divided by space characters.
      • $(MethodName.Words.First) - The first of the individual words.
      • $(MethodName.Words.FirstAsStartOfSentence) - The first of the individual words, first character converted to upper case.
      • $(MethodName.Words.Last) - The last of the individual words.
      • $(MethodName.Words.TheAndAll) - All words, divided by space characters, preceded by "the" ("the" will be omittted if the first word is a "no the" word).
      • $(MethodName.Words.TheAndAllAsSentence) - All words of the method name, divided by space characters, preceded by "The" ("The" will be omittted if the first word is a "no the" word).
      • $(MethodName.Words.TheAndFirst) - The first of the individual words, preceded by "the" ("the" will be omittted if the first word is a "no the" word).
      • $(MethodName.Words.TheAndFirstAsStartOfSentence) - The first of the individual words, preceded by "The" ("The" will be omittted if the first word is a "no the" word).
      • MethodName.Words.Verbatim
        • $(MethodName.Words.Verbatim.BetweenFirstAndLast) - All words between the first and the last, divided by space characters.
        • $(MethodName.Words.Verbatim.ExceptFirst) - All words except the first, divided by space characters.
        • $(MethodName.Words.Verbatim.ExceptLast) - The verbatim text except the last word.
        • $(MethodName.Words.Verbatim.ExceptLastTwo) - All words except the last two, divided by space characters.
        • $(MethodName.Words.Verbatim.First) - The first of the individual words, in its original casing.
        • $(MethodName.Words.Verbatim.Last) - The last of the individual words, in its original casing.
  • $(OfTheReordering) - Certain words trigger a reordering of an identifier's words (e.g. "size": "FileBufferSize" -> "Size of the file buffer"). Prefix words tweak this reordering as they will stay in front of the "of the" word (e.g. "initial": "InitialBufferSize" -> "Initial size of the buffer").
  • $(OfTheReorderingToLowerCase) - Lower case version of the $(OfTheReordering) macro, for example: "InitialBufferSize" -> "initial size of the buffer".
  • Parameters
    • Parameters.First
      • Parameters.First.Name
        • Parameters.First.Name.Words
          • $(Parameters.First.Name.Words.All) - All words of the first parameter name, divided by space characters.
      • Parameters.First.TypeName
        • $(Parameters.First.TypeName.FullNameAsSee) - The full name (i.e. including namespace and name), formatted as a "see" tag.
  • $(PropertyAccessText) - The textual description of the access to the property (Gets, Sets, Gets or sets) .
  • PropertyName
    • PropertyName.Words
      • $(PropertyName.Words.All) - All words of the property name, divided by space characters.
      • $(PropertyName.Words.AllAsSentence) - All words, divided by space characters, the first word starting with an uppercase letter.
      • $(PropertyName.Words.BetweenFirstAndLast) - All words between the first and the last, divided by space characters.
      • $(PropertyName.Words.ExceptFirst) - All words except the first, divided by space characters.
      • $(PropertyName.Words.ExceptLast) - All words except the last, divided by space characters.
      • $(PropertyName.Words.ExceptLastPascalCase) - All words in Pascal case except the last, divided by space characters.
      • $(PropertyName.Words.ExceptLastTwo) - All words except the last two, divided by space characters.
      • $(PropertyName.Words.ExceptLastTwoPascalCase) - All words in Pascal case except the last two, divided by space characters.
      • $(PropertyName.Words.First) - The first of the individual words.
      • $(PropertyName.Words.FirstAsStartOfSentence) - The first of the individual words, first character converted to upper case.
      • $(PropertyName.Words.Last) - The last of the individual words.
      • $(PropertyName.Words.TheAndAll) - All words, divided by space characters, preceded by "the" ("the" will be omittted if the first word is a "no the" word).
      • $(PropertyName.Words.TheAndAllAsSentence) - All words of the property name, divided by space characters, preceded by "The" ("The" will be omittted if the first word is a "no the" word).
      • $(PropertyName.Words.TheAndFirst) - The first of the individual words, preceded by "the" ("the" will be omittted if the first word is a "no the" word).
      • $(PropertyName.Words.TheAndFirstAsStartOfSentence) - The first of the individual words, preceded by "The" ("The" will be omittted if the first word is a "no the" word).
      • PropertyName.Words.Verbatim
        • $(PropertyName.Words.Verbatim.BetweenFirstAndLast) - All words between the first and the last, divided by space characters.
        • $(PropertyName.Words.Verbatim.ExceptFirst) - All words except the first, divided by space characters.
        • $(PropertyName.Words.Verbatim.ExceptLast) - The verbatim text except the last word.
        • $(PropertyName.Words.Verbatim.ExceptLastTwo) - All words except the last two, divided by space characters.
        • $(PropertyName.Words.Verbatim.First) - The first of the individual words, in its original casing.
        • $(PropertyName.Words.Verbatim.Last) - The last of the individual words, in its original casing.
  • ReturnTypeName
    • $(ReturnTypeName.FullNameAsSee) - The full name (i.e. including namespace and name), formatted as a "see" tag.
    • ReturnTypeName.Words
      • $(ReturnTypeName.Words.All) - All words of the return type name, divided by space characters.
      • $(ReturnTypeName.Words.AllAsSentence) - All words, divided by space characters, the first word starting with an uppercase letter.
      • $(ReturnTypeName.Words.BetweenFirstAndLast) - All words between the first and the last, divided by space characters.
      • $(ReturnTypeName.Words.ExceptFirst) - All words except the first, divided by space characters.
      • $(ReturnTypeName.Words.ExceptLast) - All words except the last, divided by space characters.
      • $(ReturnTypeName.Words.ExceptLastPascalCase) - All words in Pascal case except the last, divided by space characters.
      • $(ReturnTypeName.Words.ExceptLastTwo) - All words except the last two, divided by space characters.
      • $(ReturnTypeName.Words.ExceptLastTwoPascalCase) - All words in Pascal case except the last two, divided by space characters.
      • $(ReturnTypeName.Words.First) - The first of the individual words.
      • $(ReturnTypeName.Words.FirstAsStartOfSentence) - The first of the individual words, first character converted to upper case.
      • $(ReturnTypeName.Words.Last) - The last of the individual words.
      • $(ReturnTypeName.Words.TheAndAll) - All words, divided by space characters, preceded by "the" ("the" will be omittted if the first word is a "no the" word).
      • $(ReturnTypeName.Words.TheAndAllAsSentence) - All words of the return type name, divided by space characters, preceded by "The" ("The" will be omittted if the first word is a "no the" word).
      • $(ReturnTypeName.Words.TheAndFirst) - The first of the individual words, preceded by "the" ("the" will be omittted if the first word is a "no the" word).
      • $(ReturnTypeName.Words.TheAndFirstAsStartOfSentence) - The first of the individual words, preceded by "The" ("The" will be omittted if the first word is a "no the" word).
      • ReturnTypeName.Words.Verbatim
        • $(ReturnTypeName.Words.Verbatim.BetweenFirstAndLast) - All words between the first and the last, divided by space characters.
        • $(ReturnTypeName.Words.Verbatim.ExceptFirst) - All words except the first, divided by space characters.
        • $(ReturnTypeName.Words.Verbatim.ExceptLast) - The verbatim text except the last word.
        • $(ReturnTypeName.Words.Verbatim.ExceptLastTwo) - All words except the last two, divided by space characters.
        • $(ReturnTypeName.Words.Verbatim.First) - The first of the individual words, in its original casing.
        • $(ReturnTypeName.Words.Verbatim.Last) - The last of the individual words, in its original casing.
  • $(TheAndAll) - All words, divided by space characters, preceded by "the" ("the" will be omittted if the first word is a "no the" word).
  • $(TheAndAllAsSentence) - All words, divided by space characters, preceded by "The" ("The" will be omittted if the first word is a "no the" word).
  • TypeName
    • $(TypeName.FullNameAsSee) - The full name (i.e. including namespace and name), formatted as a "see" tag.
    • TypeName.Words
      • $(TypeName.Words.All) - All words of the type name, divided by space characters.
      • $(TypeName.Words.AllAsSentence) - All words, divided by space characters, the first word starting with an uppercase letter.
      • $(TypeName.Words.BetweenFirstAndLast) - All words between the first and the last, divided by space characters.
      • $(TypeName.Words.ExceptFirst) - All words except the first, divided by space characters.
      • $(TypeName.Words.ExceptLast) - All words except the last, divided by space characters.
      • $(TypeName.Words.ExceptLastPascalCase) - All words in Pascal case except the last, divided by space characters.
      • $(TypeName.Words.ExceptLastTwo) - All words except the last two, divided by space characters.
      • $(TypeName.Words.ExceptLastTwoPascalCase) - All words in Pascal case except the last two, divided by space characters.
      • $(TypeName.Words.First) - The first of the individual words.
      • $(TypeName.Words.FirstAsStartOfSentence) - The first of the individual words, first character converted to upper case.
      • $(TypeName.Words.Last) - The last of the individual words.
      • $(TypeName.Words.TheAndAll) - All words, divided by space characters, preceded by "the" ("the" will be omittted if the first word is a "no the" word).
      • $(TypeName.Words.TheAndAllAsSentence) - All words of the type name, divided by space characters, preceded by "The" ("The" will be omittted if the first word is a "no the" word).
      • $(TypeName.Words.TheAndFirst) - The first of the individual words, preceded by "the" ("the" will be omittted if the first word is a "no the" word).
      • $(TypeName.Words.TheAndFirstAsStartOfSentence) - The first of the individual words, preceded by "The" ("The" will be omittted if the first word is a "no the" word).
      • TypeName.Words.Verbatim
        • $(TypeName.Words.Verbatim.BetweenFirstAndLast) - All words between the first and the last, divided by space characters.
        • $(TypeName.Words.Verbatim.ExceptFirst) - All words except the first, divided by space characters.
        • $(TypeName.Words.Verbatim.ExceptLast) - The verbatim text except the last word.
        • $(TypeName.Words.Verbatim.ExceptLastTwo) - All words except the last two, divided by space characters.
        • $(TypeName.Words.Verbatim.First) - The first of the individual words, in its original casing.
        • $(TypeName.Words.Verbatim.Last) - The last of the individual words, in its original casing.


License - GhostDoc Community Edition

G h o s t D o c v2022.1

For the latest version, please see our online copy of the EULA.

This license agreement applies to GhostDoc Community edition. If you are looking for the GhostDoc Pro or Enterprise edition EULA, you will find it here - License - GhostDoc Pro and Enterprise.

End-User License Agreement

GhostDoc Community Edition

This End-User License Agreement ("EULA") is a legal agreement between you and vbCity.com, LLC dba SubMain ("SubMain") and applies to the SOFTWARE PRODUCT named above. "You" as the term is used herein, includes individuals as well as business entities, such as corporations, limited liability companies, and partnerships. If you do not agree to the terms of this EULA, do not install, copy, or use the SOFTWARE PRODUCT.

IF YOU COMPLY WITH THESE LICENSE TERMS, YOU HAVE THE RIGHTS BELOW.

The SOFTWARE PRODUCT is protected by copyright laws and international copyright treaties, as well as other intellectual property laws and treaties.

INSTALLATION AND USE RIGHTS

  1. Individual License. If you are an individual working on your own applications to sell or for any other purpose, you may use the SOFTWARE PRODUCT to develop and test those applications.
  2. Organizational License. If you are an organization, your users may use the SOFTWARE PRODUCT as follows:
    • Any number of your users may use the SOFTWARE PRODUCT to develop and test applications released under Open Source Initiative (OSI) approved open source software licenses.
    • Any number of your users may use the SOFTWARE PRODUCT to develop and test your applications as part of online or in-person classroom training and education, or for performing academic research.
    • If none of the above apply, and you are also not an enterprise (defined below), then up to 3 of your individual users can use the SOFTWARE PRODUCT to develop and test your applications.
    • If you are an enterprise, your employees and contractors may not use the SOFTWARE PRODUCT to develop or test your applications, except for: (i) open source and, (ii) education purposes as permitted above.

      • An "enterprise" is any organization and its affiliates who collectively have either (a) more than 250 PCs or users or (b) one million U.S. dollars (or the equivalent in other currencies) in annual revenues, and "affiliates" means those entities that control (via majority ownership), are controlled by, or are under common control with an organization.

SCOPE OF LICENSE

The SOFTWARE PRODUCT is licensed, not sold. This agreement only gives you some rights to use the software. SubMain reserves all other rights. The SOFTWARE PRODUCT is licensed on a per-user basis. SubMain grants you the following rights provided that you comply with all terms and conditions of this EULA:

  • SubMain grants you a personal, non-exclusive, royalty-free license to install and use the SOFTWARE PRODUCT for design, development, and testing purposes. You may install and use the SOFTWARE PRODUCT on up to 3 computers so long as you are the only individual using the SOFTWARE PRODUCT.
  • You must comply with any technical limitation in the SOFTWARE PRODUCT that only allow you to use it in a certain way. You may not work around any technical limitations.
  • You may not reverse- engineer, decompile, or disassemble the SOFTWARE PRODUCT, except and only to the extent that such activity is expressly permitted by applicable law notwithstanding this limitation.
  • You may not use the SOFTWARE PRODUCT in whole or any part of it as a library for your products and tools.
  • You may not share, publish, rent or lease the SOFTWARE PRODUCT, provide the SOFTWARE PRODUCT for others to use, or transfer the SOFTWARE PRODUCT or this agreement to any third party.
  • You may not upload this package to any 3rd party websites or services.
  • You may not remove, minimize, block or modify any notices of SubMain in the SOFTWARE PRODUCT.
  • No rights are granted for the use of illegal copies of the SOFTWARE PRODUCT, or for legal copies of the SOFTWARE PRODUCT obtained by unlawful means.

DATA

  1. Data Collection. The SOFTWARE PRODUCT may collect information about you and your use of the SOFTWARE PRODUCT, and send that to SubMain. SubMain may use this information to provide services and improve our products and services. You may opt-out of many of these scenarios, but not all, as described in the product documentation. Our privacy statement is located at https://submain.com/fwlink/privacy. You can learn more about data collection and use in the help documentation and our privacy statement. Your use of the SOFTWARE PRODUCT operates as your consent to these practices.

SUPPORT

Because the software is "as is," we may not provide support services for it.

ENTIRE AGREEMENT

This agreement, and the terms for supplements, updates, Internet-based services and support services that you use, are the entire agreement for the SOFTWARE PRODUCT and support services.

LIMITATION OF LIABILITY

NO LIABILITY FOR CONSEQUENTIAL DAMAGES. To the maximum extent permitted by applicable law, in no event shall SubMain or its suppliers be liable for any damages whatsoever (including, without limitation, damages for loss of business profit, business interruption, loss of business information, or any other pecuniary loss) arising out of the use of, or inability to use, this software product, even if SubMain has been advised of the possibility of such damages.

COPYRIGHT

Copyright © 2003-2021 vbCity.com, LLC dba SubMain. All rights reserved.

The spellchecker engine is based on modified version of NetSpell which is Copyright (c) 2003, Paul Welter All rights reserved.

Documentation preview is based on the MSDN 2010 branding which is partial copyright 2010 Jozef Izzo All rights reserved.

The code colorizer library is Copyright © 2003-2015, Jonathan de Halleux, All Rights Reserved.


License - GhostDoc Pro and Enterprise

G h o s t D o c v2022.1

For the latest version, please see our online copy of the EULA.

This license agreement applies to GhostDoc Pro and GhostDoc Enterprise Edition. If you are looking for the GhostDoc Community edition EULA, you will find it here - License - GhostDoc Community.

End-User License Agreement

GhostDoc Pro and GhostDoc Enterprise Edition

This End-User License Agreement ("EULA") is a legal agreement between you and vbCity.com, LLC dba SubMain ("SubMain") and applies to the SOFTWARE PRODUCT named above. "You" as the term is used herein, includes individuals as well as business entities, such as corporations, limited liability companies, and partnerships. If you do not agree to the terms of this EULA, do not install, copy, or use the SOFTWARE PRODUCT.

IF YOU COMPLY WITH THESE LICENSE TERMS, YOU HAVE THE RIGHTS BELOW.

The SOFTWARE PRODUCT is protected by copyright laws and international copyright treaties, as well as other intellectual property laws and treaties.

SCOPE OF LICENSE

The SOFTWARE PRODUCT is licensed, not sold. This agreement only gives you some rights to use the software. SubMain reserves all other rights. The SOFTWARE PRODUCT is licensed on a per-user basis. SubMain grants you the following rights provided that you comply with all terms and conditions of this EULA:

  • SubMain grants you a personal, non-exclusive, royalty-free license to install and use the SOFTWARE PRODUCT for design, development, and testing purposes. You may install and use the SOFTWARE PRODUCT on up to 3 computers so long as you are the only individual using the SOFTWARE PRODUCT.
  • You must comply with any technical limitation in the SOFTWARE PRODUCT that only allow you to use it in a certain way. You may not work around any technical limitations.
  • You may not reverse- engineer, decompile, or disassemble the SOFTWARE PRODUCT, except and only to the extent that such activity is expressly permitted by applicable law notwithstanding this limitation.
  • You may not use the SOFTWARE PRODUCT in whole or any part of it as a library for your products and tools.
  • You may not share, publish, rent or lease the SOFTWARE PRODUCT, or provide the SOFTWARE PRODUCT for others to use.
  • You may not upload this package to any 3rd party websites or services.
  • You may not remove, minimize, block or modify any notices of SubMain in the SOFTWARE PRODUCT.
  • You may permanently transfer all of your rights under this EULA, provided you retain no copies, you transfer all of the SOFTWARE PRODUCT (including all component parts, the media and printed materials, any upgrades and this EULA), and the recipient agrees to the terms of this EULA. If the SOFTWARE PRODUCT is an upgrade, any transfer must include all prior versions of the SOFTWARE PRODUCT.
  • No rights are granted for the use of illegal copies of the SOFTWARE PRODUCT, or for legal copies of the SOFTWARE PRODUCT obtained by unlawful means.

DATA

  • Data Collection. The SOFTWARE PRODUCT may collect information about you and your use of the SOFTWARE PRODUCT, and send that to SubMain. SubMain may use this information to provide services and improve our products and services. You may opt-out of many of these scenarios, but not all, as described in the product documentation. Our privacy statement is located at https://submain.com/fwlink/privacy. You can learn more about data collection and use in the help documentation and our privacy statement. Your use of the SOFTWARE PRODUCT operates as your consent to these practices.

ENTIRE AGREEMENT

This agreement, and the terms for supplements, updates, Internet-based services and support services that you use, are the entire agreement for the SOFTWARE PRODUCT and support services.

TRIAL LICENSE

If the SOFTWARE PRODUCT has been provided to you under a time-limited trial license for evaluation or other purposes, your right to use the SOFTWARE PRODUCT ends after the time period specified in the trial. After the trial period has elapsed, you must either stop using the SOFTWARE PRODUCT, or purchase a legal license and obtain your registration key. You must not change the system date or take other steps to circumvent time restrictions while using the trial version of the SOFTWARE PRODUCT. Such an attempt will cause the termination of the trial period, and your rights to use the SOFTWARE PRODUCT.

LIMITATION OF LIABILITY

NO LIABILITY FOR CONSEQUENTIAL DAMAGES. To the maximum extent permitted by applicable law, in no event shall SubMain or its suppliers be liable for any damages whatsoever (including, without limitation, damages for loss of business profit, business interruption, loss of business information, or any other pecuniary loss) arising out of the use of, or inability to use, this software product, even if SubMain has been advised of the possibility of such damages.

COPYRIGHT

Copyright © 2003-2021 vbCity.com, LLC dba SubMain. All rights reserved.

The spellchecker engine is based on modified version of NetSpell which is Copyright (c) 2003, Paul Welter All rights reserved.

Documentation preview is based on the MSDN 2010 branding which is partial copyright 2010 Jozef Izzo All rights reserved.

The code colorizer library is Copyright © 2003-2015, Jonathan de Halleux, All Rights Reserved.


Support

G h o s t D o c v2022.1

Support Options

We are committed to providing our customers with the highest level of support possible. To that end, we have multiple support mechanisms in place.

If you are new to GhostDoc, please review the Getting Started tutorial and the Edition Comparison matrix.

1. Browse our Support Knowledge Base

2. Post in our Support Community

GhostDoc Discussion Forum

3. Email us

To reach our support/sales staff fill in our Feedback Form or email us at support@submain.com

Do you use a spam filter? We answer all email to this address within one business day. If you have not received a response, please double check that you don't have any spam filters installed which are blocking our messages to you. If you maintain an incoming whitelist, please allow all messages from the submain.com domain.


How To

G h o s t D o c v2022.1

Rules

  • Rules Overview
  • Macros