Click or drag to resize
Commenter Service

The Commenter package provides support for extensions to support the Comment and Uncomment commands in Visual Studio using MEF.

Library Status: Public

Installation and Distribution

To ensure broad compatibility across a wide range of project configurations and Visual Studio versions, the Commenter Service is distributed through several different NuGet packages.

Commenter Service Extension

In the project which creates your VSIX file (i.e. the project which contains the source.extension.vsixmanifest file, add a NuGet reference to the Tvl.VisualStudio.Commenter package. After installing the NuGet package, you will need to configure your extension to inform Visual Studio of the dependency by including the following block in your source.extension.vsixmanifest file.

Important note Important

At this time, two versions of the VSIX manifest file are available. Make sure to use the code snippet relevant to the version used by your project. A version 1 manifest starts with <Vsix Version="1.0.0", and a version 2 manifest starts with <PackageManifest Version="2.0.0".

Version 1 Manifest
<Reference Id="Tvl.VisualStudio.Commenter.F3FD3E6D-611C-4703-B160-0C425AAFBACF">
  <Name>Visual Studio Commenter Services</Name>
  <VsixPath>Tvl.VisualStudio.Commenter.vsix</VsixPath>
</Reference>
Version 2 Manifest
<Dependency d:Source="File"
  DisplayName="Visual Studio Commenter Services"
  Id="Tvl.VisualStudio.Commenter.F3FD3E6D-611C-4703-B160-0C425AAFBACF"
  Version="[1.0.0,)"
  d:InstallSource="Embed"
  Location="Tvl.VisualStudio.Commenter.vsix" />
Note Note

A future release of this extension may include a feature to configure the source.extension.vsixmanifest file automatically.

Commenter Interfaces Library

The Commenter Interfaces Library should be installed in any package which uses the Commenter Service. The library is available in the Tvl.VisualStudio.Commenter.Interfaces NuGet package, which supports extensions targeting any combination of Visual Studio versions starting with 2010.

Commenter Utility Library

The Commenter Utility Library includes a default implementation of ICommenter which is suitable for most languages that use line and/or block comments. The installation instructions for this utility library should be followed for any project which needs to export a standard commenter component for a new content type.

Using the Commenter Service

This service allows extension developers to easily support the Comment and Uncomment commands for new languages in Visual Studio.

Providing a Standard Commenter

The easiest way to provide commenting features is to use the standard FormatCommenter implementation of the ICommenter interface. The following steps show how to create an instance of FormatCommenter and provide it to the Commenter Service by exporting an instance of ICommenterProvider.

  1. Create a new class derived from ICommenterProvider. This class is exported using the MEF ExportAttribute for one or more specific content types using the ContentTypeAttribute. The commenter in the example supports C++-style line and block comments, for the SimpleC content type.

    C#
    [Export(typeof(ICommenterProvider))]
    [ContentType("SimpleC")]
    public sealed class SimpleCCommenterProvider : ICommenterProvider
    {
        public ICommenter TryCreateCommenter(ITextBuffer textBuffer)
        {
            // TODO: provide a commenter
            throw new NotImplementedException();
        }
    }
  2. Define the comment format(s) the commenter will support.

    C#
    private static readonly LineCommentFormat LineCommentFormat =
        new LineCommentFormat("//");
    private static readonly BlockCommentFormat BlockCommentFormat =
        new BlockCommentFormat("/*", "*/");
  3. Implement the TryCreateCommenter(ITextBuffer) method by returning an instance of FormatCommenter. The following code is the complete implementation of ICommenterProvider required to support the Comment and Uncomment commands for a simple language.

    C#
    [Export(typeof(ICommenterProvider))]
    [ContentType("SimpleC")]
    public sealed class SimpleCCommenterProvider : ICommenterProvider
    {
        private static readonly LineCommentFormat LineCommentFormat =
            new LineCommentFormat("//");
        private static readonly BlockCommentFormat BlockCommentFormat =
            new BlockCommentFormat("/*", "*/");
    
        public ICommenter TryCreateCommenter(ITextBuffer textBuffer)
        {
            Func<FormatCommenter> factory =
                () => new FormatCommenter(textBuffer, LineCommentFormat, BlockCommentFormat);
            return textBuffer.Properties.GetOrCreateSingletonProperty(factory);
        }
    }

Providing a Commenter for a Language Without Block Comments

The standard commenter supports any combination of line and/or block comments. The following example shows a class which provides a commenter for Visual Basic files, which supports line comments but not block comments.

C#
[Export(typeof(ICommenterProvider))]
[ContentType("SimpleVB")]
public sealed class SimpleBatCommenterProvider : ICommenterProvider
{
    private static readonly LineCommentFormat LineCommentFormat =
        new LineCommentFormat("'");

    public ICommenter TryCreateCommenter(ITextBuffer textBuffer)
    {
        Func<FormatCommenter> factory =
            () => new FormatCommenter(textBuffer, LineCommentFormat);
        return textBuffer.Properties.GetOrCreateSingletonProperty(factory);
    }
}
Implementation Details

Since this extension exports a new MEF service for use across multiple extensions and multiple versions of Visual Studio, extremely careful consideration must be given to several implementation details to ensure consumers will not encounter conflicts in the future or be subjected to cumbersome workarounds.

  • Assembly Versioning: To ensure long-term compatibility of this extension with many other extensions, all communication between the MEF-exported Commenter service and consumers of the API is performed through a dedicated interfaces assembly, Tvl.VisualStudio.Commenter.Interfaces. Following the initial release of this extension, the contracts defined by this assembly (e.g. the strong name and API) will never change. If the source for this assembly is ever updated, it will only be in ways that are guaranteed to not cause problems for existing installations, such as updated XML documentation or updating the NuGet packaging to simplify the installation process.

  • Assembly Binding: Since the Tvl.VisualStudio.Commenter.Interfaces assembly does not appear in a <MefComponent> element within source.extension.vsixmanifest, there are a number of situations with traditional deployments where Visual Studio may be unable to locate the assembly at runtime. To avoid this situation, the Tvl.VisualStudio.Commenter extension created for the implementation of the Commenter Service registers its installation folder in the Visual Studio binding path using the [ProvideBindingPath] registration attribute. This feature ensures that the Commenter interfaces assembly will be available to all Visual Studio extensions, regardless of the manner in which they are deployed.

See Also