<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Sam&#039;s Blog &#187; Tutorials</title>
	<atom:link href="http://blog.280z28.org/archives/category/tutorials/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.280z28.org</link>
	<description>Because it&#039;s easier than editing the HTML by hand.</description>
	<lastBuildDate>Tue, 26 Jan 2010 00:23:59 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Creating a WPF Tool Window for Visual Studio 2010</title>
		<link>http://blog.280z28.org/archives/2010/01/95/</link>
		<comments>http://blog.280z28.org/archives/2010/01/95/#comments</comments>
		<pubDate>Mon, 25 Jan 2010 22:10:18 +0000</pubDate>
		<dc:creator>280Z28</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Tutorials]]></category>

		<guid isPermaLink="false">http://blog.280z28.org/?p=95</guid>
		<description><![CDATA[I’ve been working on Visual Studio 2010 extensibility for some time now, and I must say that creating a tool window was not the easiest task in the world.

First Attempt: Create an MEF-friendly IToolWindowService


  The original goal of this project was creating an MEF service that allowed exporting classes implementing IToolWindowProvider, and have the [...]]]></description>
			<content:encoded><![CDATA[<p>I’ve been working on Visual Studio 2010 extensibility for some time now, and I must say that creating a tool window was not the easiest task in the world.</p>

<h2>First Attempt: Create an MEF-friendly IToolWindowService</h2>

<p>
  The original goal of this project was creating an MEF service that allowed exporting classes implementing IToolWindowProvider, and have the service manage the creation of the tool windows and their entries on the View &gt; Other Windows menu. This <em>worked</em>, but had several drawbacks that eventually led to the conclusion that this was the wrong approach. First and foremost, this method forced the assemblies providing tool windows to load even when the tool windows weren’t visible. The performance implications of this rule out using MEF as a general solution to this problem. That said, here are some other “little things” that I didn’t have worked out in the MEF solution:
</p>

<ul>
  <li>Tool windows would not save their visible state; they were always hidden the next time Visual Studio was opened.</li>
  <li>The menu commands to show the tool windows were not available until a source file of {insert some hard-coded type} was opened. This is because the service loaded itself by exporting IVsTextViewCreationListener. When I tried to use the “any” content type, I found that the service would cause an InvalidOperationException when the environment loaded because the tool windows were created while the environment was using an IEnumerator to traverse the current windows.</li>
</ul>

<h2>Overview of the Improved Process</h2>

<p>Here is an outline of the general process of creating a new tool window. Following the outline, I’ll explain in detail what each step requires.</p>

<ul>
  <li>Create a VSIX project</li>
  <li>Configure the project to offer a VSPackage and a command table</li>
  <li>Create the WPF control your tool window will be displaying</li>
  <li>Include my helper class WpfToolWindowPane in your project</li>
  <li>Derive a class from WpfToolWindowPane for your tool window</li>
  <li>Set up menu commands</li>
</ul>

<h2>Create a VSIX project</h2>

<p>I’m basing this off of the VSIX project, because it’s a nice clean project template. It’s also beneficial because users that already have a VSIX project can easily add a tool window to it.</p>

<ol>
  <li>
    Create a project using the “VSIX Project” template (Visual C# &gt; Extensibility). Choose a <strong>different</strong> solution name than project name or you’ll run into issues later.
  </li>
  <li>Delete the file VSIXProject.cs.</li>
  <li>Right click the file “source.extension.manifest” and select View Code. Update the Name, Author, and Description fields with information about your extension. Save and close the file.</li>
  <li>
    Right click the project in Solution Explorer and select Unload Project. Then right click it again and select “Edit <em>MyProject</em>.csproj”
  </li>
  <li>
    Locate the line that says <u>&lt;IncludeAssemblyInVSIXContainer&gt;false&lt;/IncludeAssemblyInVSIXContainer&gt;</u> and change the value to <strong>true</strong>. Save and close the file.
  </li>
  <li>Right click the project in Solution Explorer and select Reload Project. If Visual Studio gives an error about a project with the same name already being open, restart Visual Studio and try again.</li>
</ol>

<h2>Configure the project to offer a VSPackage and a command table</h2>

<ol>
  <li>
    Add an XML file to the project named “<em>MyProject</em>.vsct”. In the properties pane for it, change the Build Action to <strong>VSCTCompile</strong>.
  </li>
  <li>
    Add a resources file to the project named “VSPackage.resx” (use exactly that name). Open the file in the resources editor, and at the top set the Access Modifier to <strong>No code generation</strong>. Save and close the file.
  </li>
  <li>Unload the project again and open it for editing.</li>
  <li>
    Set GeneratePkgDefFile to <strong>true</strong>.
  </li>
  <li>
    Below the line with GeneratePkgDefFile, add <u>&lt;RegisterWithCodebase&gt;true&lt;/RegisterWithCodebase&gt;</u>.
  </li>
  <li>
    Set CopyBuildOutputToOutputDirectory to <strong>true</strong>.
  </li>
  <li>
    Locate the line containing <u>
      &lt;VSCTCompile Include=&quot;<em>MyProject</em>.vsct&quot;/&gt;
    </u> and change it to <u>
      &lt;VSCTCompile Include=&quot;<em>MyProject</em>.vsct&quot;&gt;&lt;ResourceName&gt;1000&lt;/ResourceName&gt;&lt;SubType&gt;Designer&lt;/SubType&gt;&lt;/VSCTCompile&gt;
    </u>.
  </li>
  <li>
    Find the line containing <u>&lt;EmbeddedResource Include=&quot;VSPackage.resx&quot;&gt;</u>, and add both <u>&lt;MergeWithCTO&gt;true&lt;/MergeWithCTO&gt;</u> and <u>&lt;LogicalName&gt;VSPackage.resources&lt;/LogicalName&gt;</u> as children.
  </li>
  <li>Save, close, and reload the project file.</li>
  <li>
    Add a new class to the project named <em>MyProject</em>Package. Derive the class from Microsoft.VisualStudio.Shell.Package. Set the class GUID by adding the attribute <u>[Guid(&quot;00000000-0000-0000-0000-000000000000&quot;)]</u> (use the Create GUID tool to create the actual value you’ll use here). Add the attribute <u>[PackageRegistration(UseManagedResourcesOnly = true)]</u> to tell Visual Studio to register the class as a VSPackage. Provide the command table (vsct) by adding the attribute <u>[ProvideMenuResource(1000, 1)]</u>.
  </li>
</ol>

<h2>Create the WPF control your tool window will be displaying</h2>

<p>For this part, you can create any control derived directly or indirectly from System.Windows.Control.</p>

<h2>Include the helper class WpfToolWindowPane in your project</h2>

<p>
  This helper class handles most of the code required for providing a tool window. You can download <a href="http://blog.280z28.org/go.php?http://www.280z28.org/downloads/vsx/WpfToolWindowPane.cs" title="(104 hits)">WpfToolWindowPane.cs</a> here.
</p>

<h2>Derive a class from WpfToolWindowPane for your tool window</h2>

<ol>
  <li>
    Add a new class named <em>ToolName</em>ToolWindowPane to your project and derive it from WpfToolWindowPane. Use the Create GUID tool to create a guid for <em>ToolName</em>ToolWindowPane, and add a GuidAttribute to it.
  </li>
  <li>
    In the constructor, set the Caption of your tool window with <u>
      base.Caption = &quot;<em>Tool Window Name</em>&quot;;
    </u>.
  </li>
  <li>
    Override the CreateToolWindowControl() method to return a new instance of the control you created earlier. The method can be as simple as <u>
      return new <em>ToolName</em>Control(base.GlobalServiceProvider);
    </u>.
  </li>
</ol>

<h2>Set up menu commands</h2>

<p>The last step is adding a command to the View &gt; Other Windows menu so your tool window can be opened.</p>

<h3>Setting up the command table</h3>

<p>Open the MyProject.vsct file and fill it with the following. Use the same Guid for guidMyProjectPackage as you used for the MyProjectPackage class. For the other two placeholders, create new Guids.</p>


<div class="wp_syntax"><div class="code"><pre class="xml" style="font-family:monospace;"><span style="color: #009900;">&lt; ?xml <span style="color: #000066;">version</span>=<span style="color: #ff0000;">&quot;1.0&quot;</span> <span style="color: #000066;">encoding</span>=<span style="color: #ff0000;">&quot;utf-8&quot;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;commandtable</span> <span style="color: #000066;">xmlns</span>=<span style="color: #ff0000;">&quot;http://schemas.microsoft.com/VisualStudio/2005-10-18/CommandTable&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;extern</span> <span style="color: #000066;">href</span>=<span style="color: #ff0000;">&quot;vsshlids.h&quot;</span><span style="color: #000000; font-weight: bold;">/&gt;</span></span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;commands</span> <span style="color: #000066;">package</span>=<span style="color: #ff0000;">&quot;guidMyProjectPackage&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;buttons<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
      <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;button</span> <span style="color: #000066;">guid</span>=<span style="color: #ff0000;">&quot;guidMyProjectPackageCmdSet&quot;</span> <span style="color: #000066;">id</span>=<span style="color: #ff0000;">&quot;cmdidShowToolName&quot;</span> <span style="color: #000066;">priority</span>=<span style="color: #ff0000;">&quot;0x100&quot;</span> <span style="color: #000066;">type</span>=<span style="color: #ff0000;">&quot;Button&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
        <span style="color: #808080; font-style: italic;">&lt;!--&lt;Icon guid=&quot;guidShowToolNameCmdBmp&quot; id=&quot;bmpShowToolName&quot;/&gt;--&gt;</span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;strings<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
          <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;buttontext<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>Tool Name<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/buttontext<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/strings<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
      <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/button<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/buttons<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
&nbsp;
    <span style="color: #808080; font-style: italic;">&lt;!--&lt;Bitmaps&gt;</span>
<span style="color: #808080; font-style: italic;">      &lt;bitmap guid=&quot;guidShowToolNameCmdBmp&quot; href=&quot;Resources\ToolIcon.png&quot; usedList=&quot;bmpShowToolName&quot;/&gt;</span>
<span style="color: #808080; font-style: italic;">    --&gt;</span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/commands<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
&nbsp;
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;commandplacements<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;commandplacement</span> <span style="color: #000066;">guid</span>=<span style="color: #ff0000;">&quot;guidMyProjectPackageCmdSet&quot;</span> <span style="color: #000066;">id</span>=<span style="color: #ff0000;">&quot;cmdidShowToolName&quot;</span> <span style="color: #000066;">priority</span>=<span style="color: #ff0000;">&quot;0x100&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
      <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;parent</span> <span style="color: #000066;">guid</span>=<span style="color: #ff0000;">&quot;guidSHLMainMenu&quot;</span> <span style="color: #000066;">id</span>=<span style="color: #ff0000;">&quot;IDG_VS_WNDO_OTRWNDWS1&quot;</span> <span style="color: #000000; font-weight: bold;">/&gt;</span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/commandplacement<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/commandplacements<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
&nbsp;
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;symbols<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;guidsymbol</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;guidMyProjectPackage&quot;</span> <span style="color: #000066;">value</span>=<span style="color: #ff0000;">&quot;{00000000-0000-0000-0000-000000000000}&quot;</span> <span style="color: #000000; font-weight: bold;">/&gt;</span></span>
&nbsp;
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;guidsymbol</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;guidMyProjectPackageCmdSet&quot;</span> <span style="color: #000066;">value</span>=<span style="color: #ff0000;">&quot;{00000000-0000-0000-0000-000000000000}&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
      <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;idsymbol</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;cmdidShowToolName&quot;</span> <span style="color: #000066;">value</span>=<span style="color: #ff0000;">&quot;0x2001&quot;</span> <span style="color: #000000; font-weight: bold;">/&gt;</span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/guidsymbol<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
&nbsp;
    <span style="color: #808080; font-style: italic;">&lt;!--&lt;GuidSymbol name=&quot;guidShowToolNameCmdBmp&quot; value=&quot;{00000000-0000-0000-0000-000000000000}&quot;&gt;</span>
<span style="color: #808080; font-style: italic;">      &lt;idsymbol name=&quot;bmpShowToolName&quot; value=&quot;1&quot; /&gt;</span>
<span style="color: #808080; font-style: italic;">    --&gt;</span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/symbols<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/commandtable<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre></div></div>


<h3>Add a Constants class to your project</h3>

<p>Add a class named Constants to your project to make the Guids you used in the command table accessible to your code.</p>


<div class="wp_syntax"><div class="code"><pre class="csharp" style="font-family:monospace;"><span style="color: #0600FF;">internal</span> <span style="color: #0600FF;">static</span> <span style="color: #FF0000;">class</span> Constants
<span style="color: #000000;">&#123;</span>
  <span style="color: #0600FF;">public</span> <span style="color: #0600FF;">const</span> <span style="color: #FF0000;">int</span> ToolWindowCommandId <span style="color: #008000;">=</span> 0x2001<span style="color: #008000;">;</span>
  <span style="color: #0600FF;">public</span> <span style="color: #0600FF;">const</span> <span style="color: #FF0000;">string</span> MyProjectPackageCmdSet <span style="color: #008000;">=</span> <span style="color: #666666;">&quot;{00000000-0000-0000-0000-000000000000}&quot;</span><span style="color: #008000;">;</span>
  <span style="color: #0600FF;">public</span> <span style="color: #0600FF;">static</span> <span style="color: #0600FF;">readonly</span> Guid GuidMyProjectPackageCmdSet <span style="color: #008000;">=</span> <span style="color: #008000;">new</span> Guid<span style="color: #000000;">&#40;</span>MyProjectPackageCmdSet<span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
<span style="color: #000000;">&#125;</span></pre></div></div>


<h3>Handling the menu command</h3>

<p>
  Open the MyProjectPackage class. Add a new attribute to provide your tool window: <u>[ProvideToolWindow(typeof(ToolNameToolWindowPane))]</u>. Add the following code to the body of the class:
</p>


<div class="wp_syntax"><div class="code"><pre class="csharp" style="font-family:monospace;"><span style="color: #0600FF;">protected</span> <span style="color: #0600FF;">override</span> <span style="color: #0600FF;">void</span> Initialize<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span>
<span style="color: #000000;">&#123;</span>
  <span style="color: #0600FF;">base</span>.<span style="color: #0000FF;">Initialize</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
  WpfToolWindowPane.<span style="color: #0000FF;">ProvideToolWindowCommand</span><span style="color: #008000;">&lt;</span>ToolNameToolWindowPane<span style="color: #008000;">&gt;</span><span style="color: #000000;">&#40;</span><span style="color: #0600FF;">this</span>, Constants.<span style="color: #0000FF;">GuidMyProjectPackageCmdSet</span>, Constants.<span style="color: #0000FF;">ToolWindowCommandId</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
<span style="color: #000000;">&#125;</span></pre></div></div>

]]></content:encoded>
			<wfw:commentRss>http://blog.280z28.org/archives/2010/01/95/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>MEF support for the Output Window in Visual Studio 2010</title>
		<link>http://blog.280z28.org/archives/2009/11/79/</link>
		<comments>http://blog.280z28.org/archives/2009/11/79/#comments</comments>
		<pubDate>Wed, 25 Nov 2009 23:17:29 +0000</pubDate>
		<dc:creator>280Z28</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Tutorials]]></category>

		<guid isPermaLink="false">http://blog.280z28.org/?p=79</guid>
		<description><![CDATA[As some people have noticed, the Visual Studio 2010 SDK doesn&#8217;t have great support for the Output Window from MEF extensions. This post aims to change that. Like several other components I&#8217;m writing about, I hope to provide this one in a &#8220;general extensibility helper&#8221; that could be installed separately from extensions that use it [...]]]></description>
			<content:encoded><![CDATA[<p>As some people have noticed, the Visual Studio 2010 SDK doesn&#8217;t have great support for the Output Window from MEF extensions. This post aims to change that. Like several other components I&#8217;m writing about, I hope to provide this one in a &#8220;general extensibility helper&#8221; that could be installed separately from extensions that use it so its features can be shared among them.</p>

<p>There are a couple goals here:</p>

<ul>
<li>Provide a service for accessing the output window panes</li>
<li>Provide a simple method of creating new output window panes</li>
</ul>

<p>I&#8217;ll start with the usage (since that&#8217;s the interface people will normally see) and follow it with the implementation.</p>

<h2>Defining an output window pane</h2>

<p>Now this is easy.</p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
</pre></td><td class="code"><pre class="csharp" style="font-family:monospace;"><span style="color: #0600FF;">namespace</span> JavaLanguageService
<span style="color: #000000;">&#123;</span>
    <span style="color: #0600FF;">using</span> <span style="color: #008080;">System.ComponentModel.Composition</span><span style="color: #008000;">;</span>
    <span style="color: #0600FF;">using</span> <span style="color: #008080;">Microsoft.VisualStudio.Utilities</span><span style="color: #008000;">;</span>
    <span style="color: #0600FF;">using</span> <span style="color: #008080;">JavaLanguageService.Panes</span><span style="color: #008000;">;</span>
&nbsp;
    <span style="color: #0600FF;">public</span> <span style="color: #0600FF;">static</span> <span style="color: #FF0000;">class</span> Services
    <span style="color: #000000;">&#123;</span>
        <span style="color: #000000;">&#91;</span>Export<span style="color: #000000;">&#93;</span>
        <span style="color: #000000;">&#91;</span>Name<span style="color: #000000;">&#40;</span><span style="color: #666666;">&quot;ANTLR IntelliSense Engine&quot;</span><span style="color: #000000;">&#41;</span><span style="color: #000000;">&#93;</span>
        <span style="color: #0600FF;">internal</span> <span style="color: #0600FF;">static</span> OutputWindowDefinition AntlrIntellisenseOutputWindowDefinition<span style="color: #008000;">;</span>
    <span style="color: #000000;">&#125;</span>
<span style="color: #000000;">&#125;</span></pre></td></tr></table></div>


<h2>Using an output window</h2>

<p>First you import the <code>IOutputWindowService</code>:</p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
</pre></td><td class="code"><pre class="csharp" style="font-family:monospace;"><span style="color: #000000;">&#91;</span>Import<span style="color: #000000;">&#93;</span>
<span style="color: #0600FF;">internal</span> IOutputWindowService OutputWindowService<span style="color: #008000;">;</span></pre></td></tr></table></div>


<p>Then you use it to get an output window, which you can write to:</p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
</pre></td><td class="code"><pre class="csharp" style="font-family:monospace;">var outputWindow <span style="color: #008000;">=</span> OutputWindowService.<span style="color: #0000FF;">TryGetPane</span><span style="color: #000000;">&#40;</span><span style="color: #666666;">&quot;ANTLR IntelliSense Engine&quot;</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
<span style="color: #0600FF;">if</span> <span style="color: #000000;">&#40;</span>outputWindow <span style="color: #008000;">!=</span> <span style="color: #0600FF;">null</span><span style="color: #000000;">&#41;</span>
    outputWindow.<span style="color: #0000FF;">WriteLine</span><span style="color: #000000;">&#40;</span>message<span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span></pre></td></tr></table></div>


<p>If you want to write to one of the standard panes, pass one of the following to <code>TryGetPane</code>:</p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
</pre></td><td class="code"><pre class="csharp" style="font-family:monospace;"><span style="color: #0600FF;">public</span> <span style="color: #0600FF;">static</span> <span style="color: #FF0000;">class</span> PredefinedOutputWindowPanes
<span style="color: #000000;">&#123;</span>
    <span style="color: #0600FF;">public</span> <span style="color: #0600FF;">static</span> <span style="color: #0600FF;">readonly</span> <span style="color: #FF0000;">string</span> General<span style="color: #008000;">;</span>
    <span style="color: #0600FF;">public</span> <span style="color: #0600FF;">static</span> <span style="color: #0600FF;">readonly</span> <span style="color: #FF0000;">string</span> Debug<span style="color: #008000;">;</span>
    <span style="color: #0600FF;">public</span> <span style="color: #0600FF;">static</span> <span style="color: #0600FF;">readonly</span> <span style="color: #FF0000;">string</span> Build<span style="color: #008000;">;</span>
<span style="color: #000000;">&#125;</span></pre></td></tr></table></div>


<h2>The <code>IOutputWindowPane</code> and <code>IOutputWindowService</code> interfaces</h2>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
</pre></td><td class="code"><pre class="csharp" style="font-family:monospace;"><span style="color: #0600FF;">namespace</span> JavaLanguageService.<span style="color: #0000FF;">Panes</span>
<span style="color: #000000;">&#123;</span>
    <span style="color: #0600FF;">using</span> <span style="color: #008080;">System</span><span style="color: #008000;">;</span>
&nbsp;
    <span style="color: #0600FF;">public</span> <span style="color: #FF0000;">interface</span> IOutputWindowPane <span style="color: #008000;">:</span> IDisposable
    <span style="color: #000000;">&#123;</span>
        <span style="color: #FF0000;">string</span> Name
        <span style="color: #000000;">&#123;</span>
            get<span style="color: #008000;">;</span>
            set<span style="color: #008000;">;</span>
        <span style="color: #000000;">&#125;</span>
&nbsp;
        <span style="color: #0600FF;">void</span> Activate<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
        <span style="color: #0600FF;">void</span> Hide<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
        <span style="color: #0600FF;">void</span> Write<span style="color: #000000;">&#40;</span><span style="color: #FF0000;">string</span> text<span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
        <span style="color: #0600FF;">void</span> WriteLine<span style="color: #000000;">&#40;</span><span style="color: #FF0000;">string</span> text<span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
    <span style="color: #000000;">&#125;</span>
<span style="color: #000000;">&#125;</span></pre></td></tr></table></div>



<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
</pre></td><td class="code"><pre class="csharp" style="font-family:monospace;"><span style="color: #0600FF;">namespace</span> JavaLanguageService.<span style="color: #0000FF;">Panes</span>
<span style="color: #000000;">&#123;</span>
    <span style="color: #0600FF;">public</span> <span style="color: #FF0000;">interface</span> IOutputWindowService
    <span style="color: #000000;">&#123;</span>
        IOutputWindowPane TryGetPane<span style="color: #000000;">&#40;</span><span style="color: #FF0000;">string</span> name<span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
    <span style="color: #000000;">&#125;</span>
<span style="color: #000000;">&#125;</span></pre></td></tr></table></div>



<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
</pre></td><td class="code"><pre class="csharp" style="font-family:monospace;"><span style="color: #0600FF;">namespace</span> JavaLanguageService.<span style="color: #0000FF;">Panes</span>
<span style="color: #000000;">&#123;</span>
    <span style="color: #0600FF;">public</span> <span style="color: #0600FF;">sealed</span> <span style="color: #FF0000;">class</span> OutputWindowDefinition
    <span style="color: #000000;">&#123;</span>
    <span style="color: #000000;">&#125;</span>
<span style="color: #000000;">&#125;</span></pre></td></tr></table></div>



<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
</pre></td><td class="code"><pre class="csharp" style="font-family:monospace;"><span style="color: #0600FF;">namespace</span> JavaLanguageService.<span style="color: #0000FF;">Panes</span>
<span style="color: #000000;">&#123;</span>
    <span style="color: #0600FF;">public</span> <span style="color: #0600FF;">static</span> <span style="color: #FF0000;">class</span> PredefinedOutputWindowPanes
    <span style="color: #000000;">&#123;</span>
        <span style="color: #0600FF;">public</span> <span style="color: #0600FF;">static</span> <span style="color: #0600FF;">readonly</span> <span style="color: #FF0000;">string</span> General <span style="color: #008000;">=</span> <span style="color: #666666;">&quot;General&quot;</span><span style="color: #008000;">;</span>
        <span style="color: #0600FF;">public</span> <span style="color: #0600FF;">static</span> <span style="color: #0600FF;">readonly</span> <span style="color: #FF0000;">string</span> Debug <span style="color: #008000;">=</span> <span style="color: #666666;">&quot;Debug&quot;</span><span style="color: #008000;">;</span>
        <span style="color: #0600FF;">public</span> <span style="color: #0600FF;">static</span> <span style="color: #0600FF;">readonly</span> <span style="color: #FF0000;">string</span> Build <span style="color: #008000;">=</span> <span style="color: #666666;">&quot;Build&quot;</span><span style="color: #008000;">;</span>
    <span style="color: #000000;">&#125;</span>
<span style="color: #000000;">&#125;</span></pre></td></tr></table></div>


<h2>The internal implementation</h2>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
</pre></td><td class="code"><pre class="csharp" style="font-family:monospace;"><span style="color: #0600FF;">namespace</span> JavaLanguageService.<span style="color: #0000FF;">Panes</span>
<span style="color: #000000;">&#123;</span>
    <span style="color: #0600FF;">internal</span> <span style="color: #FF0000;">interface</span> IOutputWindowDefinitionMetadata
    <span style="color: #000000;">&#123;</span>
        <span style="color: #FF0000;">string</span> Name
        <span style="color: #000000;">&#123;</span>
            get<span style="color: #008000;">;</span>
        <span style="color: #000000;">&#125;</span>
    <span style="color: #000000;">&#125;</span>
<span style="color: #000000;">&#125;</span></pre></td></tr></table></div>



<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
</pre></td><td class="code"><pre class="csharp" style="font-family:monospace;"><span style="color: #0600FF;">namespace</span> JavaLanguageService.<span style="color: #0000FF;">Panes</span>
<span style="color: #000000;">&#123;</span>
    <span style="color: #0600FF;">using</span> <span style="color: #008080;">System</span><span style="color: #008000;">;</span>
    <span style="color: #0600FF;">using</span> <span style="color: #008080;">System.Collections.Generic</span><span style="color: #008000;">;</span>
    <span style="color: #0600FF;">using</span> <span style="color: #008080;">System.ComponentModel.Composition</span><span style="color: #008000;">;</span>
    <span style="color: #0600FF;">using</span> <span style="color: #008080;">System.Linq</span><span style="color: #008000;">;</span>
    <span style="color: #0600FF;">using</span> <span style="color: #008080;">JavaLanguageService.Extensions</span><span style="color: #008000;">;</span>
    <span style="color: #0600FF;">using</span> <span style="color: #008080;">Microsoft.VisualStudio</span><span style="color: #008000;">;</span>
    <span style="color: #0600FF;">using</span> <span style="color: #008080;">Microsoft.VisualStudio.Shell.Interop</span><span style="color: #008000;">;</span>
    <span style="color: #0600FF;">using</span> <span style="color: #008080;">IOleServiceProvider </span><span style="color: #008000;">=</span> Microsoft.<span style="color: #0000FF;">VisualStudio</span>.<span style="color: #0000FF;">OLE</span>.<span style="color: #0000FF;">Interop</span>.<span style="color: #0000FF;">IServiceProvider</span><span style="color: #008000;">;</span>
&nbsp;
    <span style="color: #000000;">&#91;</span>Export<span style="color: #000000;">&#40;</span><span style="color: #008000;">typeof</span><span style="color: #000000;">&#40;</span>IOutputWindowService<span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span><span style="color: #000000;">&#93;</span>
    <span style="color: #0600FF;">internal</span> <span style="color: #0600FF;">sealed</span> <span style="color: #FF0000;">class</span> OutputWindowService <span style="color: #008000;">:</span> IOutputWindowService
    <span style="color: #000000;">&#123;</span>
        <span style="color: #000000;">&#91;</span>Import<span style="color: #000000;">&#93;</span>
        <span style="color: #0600FF;">public</span> IServiceProvider GlobalServiceProvider<span style="color: #008000;">;</span>
&nbsp;
        <span style="color: #000000;">&#91;</span>ImportMany<span style="color: #000000;">&#93;</span>
        <span style="color: #0600FF;">internal</span> List<span style="color: #008000;">&lt;</span>Lazy<span style="color: #008000;">&lt;</span>OutputWindowDefinition, IOutputWindowDefinitionMetadata<span style="color: #008000;">&gt;&gt;</span> OutputWindowDefinitions<span style="color: #008000;">;</span>
&nbsp;
        <span style="color: #0600FF;">private</span> <span style="color: #0600FF;">readonly</span> Dictionary<span style="color: #008000;">&lt;</span><span style="color: #FF0000;">string</span>, Guid<span style="color: #008000;">&gt;</span> _outputWindows <span style="color: #008000;">=</span>
            <span style="color: #008000;">new</span> Dictionary<span style="color: #008000;">&lt;</span><span style="color: #FF0000;">string</span>, Guid<span style="color: #008000;">&gt;</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span>
            <span style="color: #000000;">&#123;</span>
                <span style="color: #000000;">&#123;</span> PredefinedOutputWindowPanes.<span style="color: #0000FF;">Build</span>, VSConstants.<span style="color: #0000FF;">GUID_BuildOutputWindowPane</span> <span style="color: #000000;">&#125;</span>,
                <span style="color: #000000;">&#123;</span> PredefinedOutputWindowPanes.<span style="color: #0000FF;">Debug</span>, VSConstants.<span style="color: #0000FF;">GUID_OutWindowDebugPane</span> <span style="color: #000000;">&#125;</span>,
                <span style="color: #000000;">&#123;</span> PredefinedOutputWindowPanes.<span style="color: #0000FF;">General</span>, VSConstants.<span style="color: #0000FF;">GUID_OutWindowGeneralPane</span> <span style="color: #000000;">&#125;</span>,
            <span style="color: #000000;">&#125;</span><span style="color: #008000;">;</span>
&nbsp;
        <span style="color: #0600FF;">private</span> <span style="color: #0600FF;">readonly</span> Dictionary<span style="color: #008000;">&lt;</span><span style="color: #FF0000;">string</span>, IOutputWindowPane<span style="color: #008000;">&gt;</span> _panes <span style="color: #008000;">=</span> <span style="color: #008000;">new</span> Dictionary<span style="color: #008000;">&lt;</span><span style="color: #FF0000;">string</span>, IOutputWindowPane<span style="color: #008000;">&gt;</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
&nbsp;
        <span style="color: #0600FF;">public</span> IOutputWindowPane TryGetPane<span style="color: #000000;">&#40;</span><span style="color: #FF0000;">string</span> name<span style="color: #000000;">&#41;</span>
        <span style="color: #000000;">&#123;</span>
            IOutputWindowPane pane <span style="color: #008000;">=</span> null<span style="color: #008000;">;</span>
            <span style="color: #0600FF;">if</span> <span style="color: #000000;">&#40;</span>_panes.<span style="color: #0000FF;">TryGetValue</span><span style="color: #000000;">&#40;</span>name, <span style="color: #0600FF;">out</span> pane<span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span>
                <span style="color: #0600FF;">return</span> pane<span style="color: #008000;">;</span>
&nbsp;
            var olesp <span style="color: #008000;">=</span> <span style="color: #000000;">&#40;</span>IOleServiceProvider<span style="color: #000000;">&#41;</span>GlobalServiceProvider.<span style="color: #0000FF;">GetService</span><span style="color: #000000;">&#40;</span><span style="color: #008000;">typeof</span><span style="color: #000000;">&#40;</span>IOleServiceProvider<span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
            var outputWindow <span style="color: #008000;">=</span> olesp.<span style="color: #0000FF;">TryGetGlobalService</span><span style="color: #008000;">&lt;</span>SVsOutputWindow, IVsOutputWindow<span style="color: #008000;">&gt;</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
            <span style="color: #0600FF;">if</span> <span style="color: #000000;">&#40;</span>outputWindow <span style="color: #008000;">==</span> <span style="color: #0600FF;">null</span><span style="color: #000000;">&#41;</span>
                <span style="color: #0600FF;">return</span> null<span style="color: #008000;">;</span>
&nbsp;
            Guid guid<span style="color: #008000;">;</span>
            <span style="color: #0600FF;">if</span> <span style="color: #000000;">&#40;</span><span style="color: #008000;">!</span>_outputWindows.<span style="color: #0000FF;">TryGetValue</span><span style="color: #000000;">&#40;</span>name, <span style="color: #0600FF;">out</span> guid<span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span>
            <span style="color: #000000;">&#123;</span>
                var definition <span style="color: #008000;">=</span> OutputWindowDefinitions.<span style="color: #0000FF;">FirstOrDefault</span><span style="color: #000000;">&#40;</span>lazy <span style="color: #008000;">=&gt;</span> lazy.<span style="color: #0000FF;">Metadata</span>.<span style="color: #0000FF;">Name</span>.<span style="color: #0000FF;">Equals</span><span style="color: #000000;">&#40;</span>name<span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
                <span style="color: #0600FF;">if</span> <span style="color: #000000;">&#40;</span>definition <span style="color: #008000;">==</span> <span style="color: #0600FF;">null</span><span style="color: #000000;">&#41;</span>
                    <span style="color: #0600FF;">return</span> null<span style="color: #008000;">;</span>
&nbsp;
                guid <span style="color: #008000;">=</span> Guid.<span style="color: #0000FF;">NewGuid</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
                <span style="color: #008080; font-style: italic;">// this controls whether the pane is listed in the output panes dropdown list, *not* whether the pane is initially selected</span>
                <span style="color: #FF0000;">bool</span> visible <span style="color: #008000;">=</span> true<span style="color: #008000;">;</span>
                <span style="color: #FF0000;">bool</span> clearWithSolution <span style="color: #008000;">=</span> false<span style="color: #008000;">;</span>
&nbsp;
                <span style="color: #0600FF;">if</span> <span style="color: #000000;">&#40;</span>ErrorHandler.<span style="color: #0000FF;">Failed</span><span style="color: #000000;">&#40;</span>ErrorHandler.<span style="color: #0000FF;">CallWithCOMConvention</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span> <span style="color: #008000;">=&gt;</span> outputWindow.<span style="color: #0000FF;">CreatePane</span><span style="color: #000000;">&#40;</span><span style="color: #0600FF;">ref</span> guid, definition.<span style="color: #0000FF;">Metadata</span>.<span style="color: #0000FF;">Name</span>, Convert.<span style="color: #0000FF;">ToInt32</span><span style="color: #000000;">&#40;</span>visible<span style="color: #000000;">&#41;</span>, Convert.<span style="color: #0000FF;">ToInt32</span><span style="color: #000000;">&#40;</span>clearWithSolution<span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span>
                    <span style="color: #0600FF;">return</span> null<span style="color: #008000;">;</span>
&nbsp;
                _outputWindows.<span style="color: #0000FF;">Add</span><span style="color: #000000;">&#40;</span>definition.<span style="color: #0000FF;">Metadata</span>.<span style="color: #0000FF;">Name</span>, guid<span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
            <span style="color: #000000;">&#125;</span>
&nbsp;
            IVsOutputWindowPane vspane <span style="color: #008000;">=</span> null<span style="color: #008000;">;</span>
            <span style="color: #0600FF;">if</span> <span style="color: #000000;">&#40;</span>ErrorHandler.<span style="color: #0000FF;">Failed</span><span style="color: #000000;">&#40;</span>ErrorHandler.<span style="color: #0000FF;">CallWithCOMConvention</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span> <span style="color: #008000;">=&gt;</span> outputWindow.<span style="color: #0000FF;">GetPane</span><span style="color: #000000;">&#40;</span><span style="color: #0600FF;">ref</span> guid, <span style="color: #0600FF;">out</span> vspane<span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span>
                <span style="color: #0600FF;">return</span> null<span style="color: #008000;">;</span>
&nbsp;
            pane <span style="color: #008000;">=</span> <span style="color: #008000;">new</span> VsOutputWindowPaneAdapter<span style="color: #000000;">&#40;</span>vspane<span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
            _panes<span style="color: #000000;">&#91;</span>name<span style="color: #000000;">&#93;</span> <span style="color: #008000;">=</span> pane<span style="color: #008000;">;</span>
            <span style="color: #0600FF;">return</span> pane<span style="color: #008000;">;</span>
        <span style="color: #000000;">&#125;</span>
    <span style="color: #000000;">&#125;</span>
<span style="color: #000000;">&#125;</span></pre></td></tr></table></div>



<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
</pre></td><td class="code"><pre class="csharp" style="font-family:monospace;"><span style="color: #0600FF;">namespace</span> JavaLanguageService.<span style="color: #0000FF;">Panes</span>
<span style="color: #000000;">&#123;</span>
    <span style="color: #0600FF;">using</span> <span style="color: #008080;">System</span><span style="color: #008000;">;</span>
    <span style="color: #0600FF;">using</span> <span style="color: #008080;">System.Diagnostics.Contracts</span><span style="color: #008000;">;</span>
    <span style="color: #0600FF;">using</span> <span style="color: #008080;">Microsoft.VisualStudio</span><span style="color: #008000;">;</span>
    <span style="color: #0600FF;">using</span> <span style="color: #008080;">Microsoft.VisualStudio.Shell.Interop</span><span style="color: #008000;">;</span>
&nbsp;
    <span style="color: #0600FF;">internal</span> <span style="color: #0600FF;">sealed</span> <span style="color: #FF0000;">class</span> VsOutputWindowPaneAdapter <span style="color: #008000;">:</span> IOutputWindowPane, IDisposable
    <span style="color: #000000;">&#123;</span>
        <span style="color: #0600FF;">private</span> IVsOutputWindowPane _pane<span style="color: #008000;">;</span>
&nbsp;
        <span style="color: #0600FF;">public</span> VsOutputWindowPaneAdapter<span style="color: #000000;">&#40;</span>IVsOutputWindowPane pane<span style="color: #000000;">&#41;</span>
        <span style="color: #000000;">&#123;</span>
            Contract.<span style="color: #0000FF;">Requires</span><span style="color: #008000;">&lt;</span>ArgumentNullException<span style="color: #008000;">&gt;</span><span style="color: #000000;">&#40;</span>pane <span style="color: #008000;">!=</span> <span style="color: #0600FF;">null</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
            <span style="color: #0600FF;">this</span>._pane <span style="color: #008000;">=</span> pane<span style="color: #008000;">;</span>
        <span style="color: #000000;">&#125;</span>
&nbsp;
        <span style="color: #0600FF;">public</span> <span style="color: #FF0000;">string</span> Name
        <span style="color: #000000;">&#123;</span>
            get
            <span style="color: #000000;">&#123;</span>
                <span style="color: #FF0000;">string</span> name <span style="color: #008000;">=</span> null<span style="color: #008000;">;</span>
                ErrorHandler.<span style="color: #0000FF;">ThrowOnFailure</span><span style="color: #000000;">&#40;</span><span style="color: #0600FF;">this</span>._pane.<span style="color: #0000FF;">GetName</span><span style="color: #000000;">&#40;</span><span style="color: #0600FF;">ref</span> name<span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
                <span style="color: #0600FF;">return</span> name<span style="color: #008000;">;</span>
            <span style="color: #000000;">&#125;</span>
            set
            <span style="color: #000000;">&#123;</span>
                ErrorHandler.<span style="color: #0000FF;">ThrowOnFailure</span><span style="color: #000000;">&#40;</span><span style="color: #0600FF;">this</span>._pane.<span style="color: #0000FF;">SetName</span><span style="color: #000000;">&#40;</span>value<span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
            <span style="color: #000000;">&#125;</span>
        <span style="color: #000000;">&#125;</span>
&nbsp;
        <span style="color: #0600FF;">public</span> <span style="color: #0600FF;">void</span> Dispose<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span>
        <span style="color: #000000;">&#123;</span>
            _pane <span style="color: #008000;">=</span> null<span style="color: #008000;">;</span>
        <span style="color: #000000;">&#125;</span>
&nbsp;
        <span style="color: #0600FF;">public</span> <span style="color: #0600FF;">void</span> Activate<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span>
        <span style="color: #000000;">&#123;</span>
            ErrorHandler.<span style="color: #0000FF;">ThrowOnFailure</span><span style="color: #000000;">&#40;</span><span style="color: #0600FF;">this</span>._pane.<span style="color: #0000FF;">Activate</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
        <span style="color: #000000;">&#125;</span>
&nbsp;
        <span style="color: #0600FF;">public</span> <span style="color: #0600FF;">void</span> Hide<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span>
        <span style="color: #000000;">&#123;</span>
            ErrorHandler.<span style="color: #0000FF;">ThrowOnFailure</span><span style="color: #000000;">&#40;</span><span style="color: #0600FF;">this</span>._pane.<span style="color: #0000FF;">Hide</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
        <span style="color: #000000;">&#125;</span>
&nbsp;
        <span style="color: #0600FF;">public</span> <span style="color: #0600FF;">void</span> Write<span style="color: #000000;">&#40;</span><span style="color: #FF0000;">string</span> text<span style="color: #000000;">&#41;</span>
        <span style="color: #000000;">&#123;</span>
            Contract.<span style="color: #0000FF;">Requires</span><span style="color: #008000;">&lt;</span>ArgumentNullException<span style="color: #008000;">&gt;</span><span style="color: #000000;">&#40;</span>text <span style="color: #008000;">!=</span> <span style="color: #0600FF;">null</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
            ErrorHandler.<span style="color: #0000FF;">ThrowOnFailure</span><span style="color: #000000;">&#40;</span><span style="color: #0600FF;">this</span>._pane.<span style="color: #0000FF;">OutputStringThreadSafe</span><span style="color: #000000;">&#40;</span>text<span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
        <span style="color: #000000;">&#125;</span>
&nbsp;
        <span style="color: #0600FF;">public</span> <span style="color: #0600FF;">void</span> WriteLine<span style="color: #000000;">&#40;</span><span style="color: #FF0000;">string</span> text<span style="color: #000000;">&#41;</span>
        <span style="color: #000000;">&#123;</span>
            Contract.<span style="color: #0000FF;">Requires</span><span style="color: #008000;">&lt;</span>ArgumentNullException<span style="color: #008000;">&gt;</span><span style="color: #000000;">&#40;</span>text <span style="color: #008000;">!=</span> <span style="color: #0600FF;">null</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
            <span style="color: #0600FF;">if</span> <span style="color: #000000;">&#40;</span><span style="color: #008000;">!</span>text.<span style="color: #0000FF;">EndsWith</span><span style="color: #000000;">&#40;</span>Environment.<span style="color: #0000FF;">NewLine</span><span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span>
                text <span style="color: #008000;">+=</span> Environment.<span style="color: #0000FF;">NewLine</span><span style="color: #008000;">;</span>
&nbsp;
            Write<span style="color: #000000;">&#40;</span>text<span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
        <span style="color: #000000;">&#125;</span>
    <span style="color: #000000;">&#125;</span>
<span style="color: #000000;">&#125;</span></pre></td></tr></table></div>


<h2>Finally, one extension method that&#8217;s used to help with the <code>IOleServiceProvider</code></h2>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
</pre></td><td class="code"><pre class="csharp" style="font-family:monospace;"><span style="color: #0600FF;">namespace</span> JavaLanguageService.<span style="color: #0000FF;">Extensions</span>
<span style="color: #000000;">&#123;</span>
    <span style="color: #0600FF;">using</span> <span style="color: #008080;">System</span><span style="color: #008000;">;</span>
    <span style="color: #0600FF;">using</span> <span style="color: #008080;">System.Diagnostics.Contracts</span><span style="color: #008000;">;</span>
    <span style="color: #0600FF;">using</span> <span style="color: #008080;">System.Runtime.InteropServices</span><span style="color: #008000;">;</span>
    <span style="color: #0600FF;">using</span> <span style="color: #008080;">Microsoft.VisualStudio</span><span style="color: #008000;">;</span>
    <span style="color: #0600FF;">using</span> <span style="color: #008080;">IOleServiceProvider </span><span style="color: #008000;">=</span> Microsoft.<span style="color: #0000FF;">VisualStudio</span>.<span style="color: #0000FF;">OLE</span>.<span style="color: #0000FF;">Interop</span>.<span style="color: #0000FF;">IServiceProvider</span><span style="color: #008000;">;</span>
&nbsp;
    <span style="color: #0600FF;">public</span> <span style="color: #0600FF;">static</span> <span style="color: #FF0000;">class</span> ServiceProviderExtensions
    <span style="color: #000000;">&#123;</span>
        <span style="color: #0600FF;">public</span> <span style="color: #0600FF;">static</span> TServiceInterface TryGetGlobalService<span style="color: #008000;">&lt;</span>TServiceClass, TServiceInterface<span style="color: #008000;">&gt;</span><span style="color: #000000;">&#40;</span><span style="color: #0600FF;">this</span> IOleServiceProvider sp<span style="color: #000000;">&#41;</span>
            where TServiceInterface <span style="color: #008000;">:</span> <span style="color: #FF0000;">class</span>
        <span style="color: #000000;">&#123;</span>
            Contract.<span style="color: #0000FF;">Requires</span><span style="color: #008000;">&lt;</span>NullReferenceException<span style="color: #008000;">&gt;</span><span style="color: #000000;">&#40;</span>sp <span style="color: #008000;">!=</span> <span style="color: #0600FF;">null</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
&nbsp;
            Guid guidService <span style="color: #008000;">=</span> <span style="color: #008000;">typeof</span><span style="color: #000000;">&#40;</span>TServiceInterface<span style="color: #000000;">&#41;</span>.<span style="color: #0000FF;">GUID</span><span style="color: #008000;">;</span>
            Guid riid <span style="color: #008000;">=</span> <span style="color: #008000;">typeof</span><span style="color: #000000;">&#40;</span>TServiceInterface<span style="color: #000000;">&#41;</span>.<span style="color: #0000FF;">GUID</span><span style="color: #008000;">;</span>
            IntPtr obj <span style="color: #008000;">=</span> IntPtr.<span style="color: #0000FF;">Zero</span><span style="color: #008000;">;</span>
            <span style="color: #FF0000;">int</span> result <span style="color: #008000;">=</span> ErrorHandler.<span style="color: #0000FF;">CallWithCOMConvention</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span> <span style="color: #008000;">=&gt;</span> sp.<span style="color: #0000FF;">QueryService</span><span style="color: #000000;">&#40;</span><span style="color: #0600FF;">ref</span> guidService, <span style="color: #0600FF;">ref</span> riid, <span style="color: #0600FF;">out</span> obj<span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
            <span style="color: #0600FF;">if</span> <span style="color: #000000;">&#40;</span>ErrorHandler.<span style="color: #0000FF;">Failed</span><span style="color: #000000;">&#40;</span>result<span style="color: #000000;">&#41;</span> <span style="color: #008000;">||</span> obj <span style="color: #008000;">==</span> IntPtr.<span style="color: #0000FF;">Zero</span><span style="color: #000000;">&#41;</span>
                <span style="color: #0600FF;">return</span> null<span style="color: #008000;">;</span>
&nbsp;
            <span style="color: #0600FF;">try</span>
            <span style="color: #000000;">&#123;</span>
                TServiceInterface service <span style="color: #008000;">=</span> <span style="color: #000000;">&#40;</span>TServiceInterface<span style="color: #000000;">&#41;</span>Marshal.<span style="color: #0000FF;">GetObjectForIUnknown</span><span style="color: #000000;">&#40;</span>obj<span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
                <span style="color: #0600FF;">return</span> service<span style="color: #008000;">;</span>
            <span style="color: #000000;">&#125;</span>
            <span style="color: #0600FF;">finally</span>
            <span style="color: #000000;">&#123;</span>
                Marshal.<span style="color: #0000FF;">Release</span><span style="color: #000000;">&#40;</span>obj<span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
            <span style="color: #000000;">&#125;</span>
        <span style="color: #000000;">&#125;</span>
    <span style="color: #000000;">&#125;</span>
<span style="color: #000000;">&#125;</span></pre></td></tr></table></div>

]]></content:encoded>
			<wfw:commentRss>http://blog.280z28.org/archives/2009/11/79/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>A general brace matching tagger for Visual Studio 2010</title>
		<link>http://blog.280z28.org/archives/2009/11/74/</link>
		<comments>http://blog.280z28.org/archives/2009/11/74/#comments</comments>
		<pubDate>Wed, 25 Nov 2009 22:32:39 +0000</pubDate>
		<dc:creator>280Z28</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Tutorials]]></category>

		<guid isPermaLink="false">http://blog.280z28.org/?p=74</guid>
		<description><![CDATA[I haven&#8217;t perfected it yet, but here is a fairly general brace matching tagger that seems to work very well. It relies on the classifier for the content type properly tagging comments and literals with classification types derived from PredefinedClassificationTypeNames.Comment and PredefinedClassificationTypeNames.Literal, which any decent classifier will do.

This example really shows a big improvement in [...]]]></description>
			<content:encoded><![CDATA[<p>I haven&#8217;t perfected it yet, but here is a fairly general brace matching tagger that seems to work very well. It relies on the classifier for the content type properly tagging comments and literals with classification types derived from <code>PredefinedClassificationTypeNames.Comment</code> and <code>PredefinedClassificationTypeNames.Literal</code>, which any decent classifier will do.</p>

<p>This example really shows a big improvement in Visual Studio 2010. None of my Visual Studio 2008 language services have brace matching this effective and they&#8217;re getting jealous.</p>

<p>Here is an example of providing a brace matcher for a &#8220;java&#8221; content type:</p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
</pre></td><td class="code"><pre class="csharp" style="font-family:monospace;"><span style="color: #0600FF;">namespace</span> JavaLanguageService
<span style="color: #000000;">&#123;</span>
    <span style="color: #0600FF;">using</span> <span style="color: #008080;">System.Collections.Generic</span><span style="color: #008000;">;</span>
    <span style="color: #0600FF;">using</span> <span style="color: #008080;">System.ComponentModel.Composition</span><span style="color: #008000;">;</span>
    <span style="color: #0600FF;">using</span> <span style="color: #008080;">CustomLanguageService.Text</span><span style="color: #008000;">;</span>
    <span style="color: #0600FF;">using</span> <span style="color: #008080;">Microsoft.VisualStudio.Text</span><span style="color: #008000;">;</span>
    <span style="color: #0600FF;">using</span> <span style="color: #008080;">Microsoft.VisualStudio.Text.Classification</span><span style="color: #008000;">;</span>
    <span style="color: #0600FF;">using</span> <span style="color: #008080;">Microsoft.VisualStudio.Text.Editor</span><span style="color: #008000;">;</span>
    <span style="color: #0600FF;">using</span> <span style="color: #008080;">Microsoft.VisualStudio.Text.Tagging</span><span style="color: #008000;">;</span>
    <span style="color: #0600FF;">using</span> <span style="color: #008080;">Microsoft.VisualStudio.Utilities</span><span style="color: #008000;">;</span>
&nbsp;
    <span style="color: #000000;">&#91;</span>Export<span style="color: #000000;">&#40;</span><span style="color: #008000;">typeof</span><span style="color: #000000;">&#40;</span>IViewTaggerProvider<span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span><span style="color: #000000;">&#93;</span>
    <span style="color: #000000;">&#91;</span>ContentType<span style="color: #000000;">&#40;</span>Constants.<span style="color: #0000FF;">JavaContentType</span><span style="color: #000000;">&#41;</span><span style="color: #000000;">&#93;</span>
    <span style="color: #000000;">&#91;</span>TagType<span style="color: #000000;">&#40;</span><span style="color: #008000;">typeof</span><span style="color: #000000;">&#40;</span>TextMarkerTag<span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span><span style="color: #000000;">&#93;</span>
    <span style="color: #0600FF;">public</span> <span style="color: #0600FF;">sealed</span> <span style="color: #FF0000;">class</span> JavaBraceMatchingTaggerProvider <span style="color: #008000;">:</span> IViewTaggerProvider
    <span style="color: #000000;">&#123;</span>
        <span style="color: #000000;">&#91;</span>Import<span style="color: #000000;">&#93;</span>
        <span style="color: #0600FF;">public</span> IClassifierAggregatorService AggregatorService<span style="color: #008000;">;</span>
&nbsp;
        <span style="color: #0600FF;">public</span> ITagger<span style="color: #008000;">&lt;</span>T<span style="color: #008000;">&gt;</span> CreateTagger<span style="color: #008000;">&lt;</span>T<span style="color: #008000;">&gt;</span><span style="color: #000000;">&#40;</span>ITextView textView, ITextBuffer buffer<span style="color: #000000;">&#41;</span> where T <span style="color: #008000;">:</span> ITag
        <span style="color: #000000;">&#123;</span>
            <span style="color: #0600FF;">if</span> <span style="color: #000000;">&#40;</span>textView <span style="color: #008000;">==</span> <span style="color: #0600FF;">null</span><span style="color: #000000;">&#41;</span>
                <span style="color: #0600FF;">return</span> null<span style="color: #008000;">;</span>
&nbsp;
            var aggregator <span style="color: #008000;">=</span> AggregatorService.<span style="color: #0000FF;">GetClassifier</span><span style="color: #000000;">&#40;</span>buffer<span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
            var pairs <span style="color: #008000;">=</span> <span style="color: #008000;">new</span> KeyValuePair<span style="color: #008000;">&lt;</span><span style="color: #FF0000;">char</span>, <span style="color: #FF0000;">char</span><span style="color: #008000;">&gt;</span><span style="color: #000000;">&#91;</span><span style="color: #000000;">&#93;</span>
                <span style="color: #000000;">&#123;</span>
                    <span style="color: #008000;">new</span> KeyValuePair<span style="color: #008000;">&lt;</span><span style="color: #FF0000;">char</span>, <span style="color: #FF0000;">char</span><span style="color: #008000;">&gt;</span><span style="color: #000000;">&#40;</span><span style="color: #666666;">'('</span>, <span style="color: #666666;">')'</span><span style="color: #000000;">&#41;</span>,
                    <span style="color: #008000;">new</span> KeyValuePair<span style="color: #008000;">&lt;</span><span style="color: #FF0000;">char</span>, <span style="color: #FF0000;">char</span><span style="color: #008000;">&gt;</span><span style="color: #000000;">&#40;</span><span style="color: #666666;">'{'</span>, <span style="color: #666666;">'}'</span><span style="color: #000000;">&#41;</span>,
                    <span style="color: #008000;">new</span> KeyValuePair<span style="color: #008000;">&lt;</span><span style="color: #FF0000;">char</span>, <span style="color: #FF0000;">char</span><span style="color: #008000;">&gt;</span><span style="color: #000000;">&#40;</span><span style="color: #666666;">'['</span>, <span style="color: #666666;">']'</span><span style="color: #000000;">&#41;</span>
                <span style="color: #000000;">&#125;</span><span style="color: #008000;">;</span>
            <span style="color: #0600FF;">return</span> <span style="color: #008000;">new</span> BraceMatchingTagger<span style="color: #000000;">&#40;</span>textView, buffer, aggregator, pairs<span style="color: #000000;">&#41;</span> <span style="color: #0600FF;">as</span> ITagger<span style="color: #008000;">&lt;</span>T<span style="color: #008000;">&gt;;</span>
        <span style="color: #000000;">&#125;</span>
    <span style="color: #000000;">&#125;</span>
<span style="color: #000000;">&#125;</span></pre></td></tr></table></div>


<p>And here is the brace matching tagger. Depending on the characteristics of your language, you may be able to use this will little to no modification.</p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
</pre></td><td class="code"><pre class="csharp" style="font-family:monospace;"><span style="color: #0600FF;">namespace</span> CustomLanguageService.<span style="color: #0000FF;">Text</span>
<span style="color: #000000;">&#123;</span>
    <span style="color: #0600FF;">using</span> <span style="color: #008080;">System</span><span style="color: #008000;">;</span>
    <span style="color: #0600FF;">using</span> <span style="color: #008080;">System.Collections.Generic</span><span style="color: #008000;">;</span>
    <span style="color: #0600FF;">using</span> <span style="color: #008080;">System.Collections.ObjectModel</span><span style="color: #008000;">;</span>
    <span style="color: #0600FF;">using</span> <span style="color: #008080;">System.Diagnostics.Contracts</span><span style="color: #008000;">;</span>
    <span style="color: #0600FF;">using</span> <span style="color: #008080;">System.Linq</span><span style="color: #008000;">;</span>
    <span style="color: #0600FF;">using</span> <span style="color: #008080;">Microsoft.VisualStudio.Language.StandardClassification</span><span style="color: #008000;">;</span>
    <span style="color: #0600FF;">using</span> <span style="color: #008080;">Microsoft.VisualStudio.Text</span><span style="color: #008000;">;</span>
    <span style="color: #0600FF;">using</span> <span style="color: #008080;">Microsoft.VisualStudio.Text.Classification</span><span style="color: #008000;">;</span>
    <span style="color: #0600FF;">using</span> <span style="color: #008080;">Microsoft.VisualStudio.Text.Editor</span><span style="color: #008000;">;</span>
    <span style="color: #0600FF;">using</span> <span style="color: #008080;">Microsoft.VisualStudio.Text.Tagging</span><span style="color: #008000;">;</span>
&nbsp;
    <span style="color: #0600FF;">internal</span> <span style="color: #0600FF;">sealed</span> <span style="color: #FF0000;">class</span> BraceMatchingTagger <span style="color: #008000;">:</span> ITagger<span style="color: #008000;">&lt;</span>TextMarkerTag<span style="color: #008000;">&gt;</span>
    <span style="color: #000000;">&#123;</span>
        <span style="color: #0600FF;">public</span> <span style="color: #0600FF;">event</span> EventHandler<span style="color: #008000;">&lt;</span>SnapshotSpanEventArgs<span style="color: #008000;">&gt;</span> TagsChanged<span style="color: #008000;">;</span>
&nbsp;
        <span style="color: #0600FF;">public</span> BraceMatchingTagger<span style="color: #000000;">&#40;</span>ITextView textView, ITextBuffer sourceBuffer, IClassifier aggregator, IEnumerable<span style="color: #008000;">&lt;</span>KeyValuePair<span style="color: #008000;">&lt;</span><span style="color: #FF0000;">char</span>, <span style="color: #FF0000;">char</span><span style="color: #008000;">&gt;&gt;</span> matchingCharacters<span style="color: #000000;">&#41;</span>
        <span style="color: #000000;">&#123;</span>
            Contract.<span style="color: #0000FF;">Requires</span><span style="color: #008000;">&lt;</span>ArgumentNullException<span style="color: #008000;">&gt;</span><span style="color: #000000;">&#40;</span>textView <span style="color: #008000;">!=</span> <span style="color: #0600FF;">null</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
            Contract.<span style="color: #0000FF;">Requires</span><span style="color: #008000;">&lt;</span>ArgumentNullException<span style="color: #008000;">&gt;</span><span style="color: #000000;">&#40;</span>sourceBuffer <span style="color: #008000;">!=</span> <span style="color: #0600FF;">null</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
            Contract.<span style="color: #0000FF;">Requires</span><span style="color: #008000;">&lt;</span>ArgumentNullException<span style="color: #008000;">&gt;</span><span style="color: #000000;">&#40;</span>aggregator <span style="color: #008000;">!=</span> <span style="color: #0600FF;">null</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
            Contract.<span style="color: #0000FF;">Requires</span><span style="color: #008000;">&lt;</span>ArgumentNullException<span style="color: #008000;">&gt;</span><span style="color: #000000;">&#40;</span>matchingCharacters <span style="color: #008000;">!=</span> <span style="color: #0600FF;">null</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
&nbsp;
            <span style="color: #0600FF;">this</span>.<span style="color: #0000FF;">TextView</span> <span style="color: #008000;">=</span> textView<span style="color: #008000;">;</span>
            <span style="color: #0600FF;">this</span>.<span style="color: #0000FF;">SourceBuffer</span> <span style="color: #008000;">=</span> sourceBuffer<span style="color: #008000;">;</span>
            <span style="color: #0600FF;">this</span>.<span style="color: #0000FF;">Aggregator</span> <span style="color: #008000;">=</span> aggregator<span style="color: #008000;">;</span>
            <span style="color: #0600FF;">this</span>.<span style="color: #0000FF;">MatchingCharacters</span> <span style="color: #008000;">=</span> matchingCharacters.<span style="color: #0000FF;">ToList</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span>.<span style="color: #0000FF;">AsReadOnly</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
&nbsp;
            <span style="color: #0600FF;">this</span>.<span style="color: #0000FF;">TextView</span>.<span style="color: #0000FF;">Caret</span>.<span style="color: #0000FF;">PositionChanged</span> <span style="color: #008000;">+=</span> Caret_PositionChanged<span style="color: #008000;">;</span>
            <span style="color: #0600FF;">this</span>.<span style="color: #0000FF;">TextView</span>.<span style="color: #0000FF;">LayoutChanged</span> <span style="color: #008000;">+=</span> TextView_LayoutChanged<span style="color: #008000;">;</span>
        <span style="color: #000000;">&#125;</span>
&nbsp;
        <span style="color: #0600FF;">public</span> ITextView TextView
        <span style="color: #000000;">&#123;</span>
            get<span style="color: #008000;">;</span>
            <span style="color: #0600FF;">private</span> set<span style="color: #008000;">;</span>
        <span style="color: #000000;">&#125;</span>
&nbsp;
        <span style="color: #0600FF;">public</span> ITextBuffer SourceBuffer
        <span style="color: #000000;">&#123;</span>
            get<span style="color: #008000;">;</span>
            <span style="color: #0600FF;">private</span> set<span style="color: #008000;">;</span>
        <span style="color: #000000;">&#125;</span>
&nbsp;
        <span style="color: #0600FF;">public</span> IClassifier Aggregator
        <span style="color: #000000;">&#123;</span>
            get<span style="color: #008000;">;</span>
            <span style="color: #0600FF;">private</span> set<span style="color: #008000;">;</span>
        <span style="color: #000000;">&#125;</span>
&nbsp;
        <span style="color: #0600FF;">public</span> ReadOnlyCollection<span style="color: #008000;">&lt;</span>KeyValuePair<span style="color: #008000;">&lt;</span><span style="color: #FF0000;">char</span>, <span style="color: #FF0000;">char</span><span style="color: #008000;">&gt;&gt;</span> MatchingCharacters
        <span style="color: #000000;">&#123;</span>
            get<span style="color: #008000;">;</span>
            <span style="color: #0600FF;">private</span> set<span style="color: #008000;">;</span>
        <span style="color: #000000;">&#125;</span>
&nbsp;
        <span style="color: #0600FF;">private</span> SnapshotPoint<span style="color: #008000;">?</span> CurrentChar
        <span style="color: #000000;">&#123;</span>
            get<span style="color: #008000;">;</span>
            set<span style="color: #008000;">;</span>
        <span style="color: #000000;">&#125;</span>
&nbsp;
        <span style="color: #0600FF;">private</span> <span style="color: #0600FF;">static</span> <span style="color: #FF0000;">bool</span> IsInCommentOrLiteral<span style="color: #000000;">&#40;</span>IClassifier aggregator, SnapshotPoint point, PositionAffinity affinity<span style="color: #000000;">&#41;</span>
        <span style="color: #000000;">&#123;</span>
            Contract.<span style="color: #0000FF;">Requires</span><span style="color: #000000;">&#40;</span>aggregator <span style="color: #008000;">!=</span> <span style="color: #0600FF;">null</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
&nbsp;
            <span style="color: #008080; font-style: italic;">// TODO: handle affinity</span>
            SnapshotSpan span <span style="color: #008000;">=</span> <span style="color: #008000;">new</span> SnapshotSpan<span style="color: #000000;">&#40;</span>point, <span style="color: #FF0000;">1</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
&nbsp;
            var classifications <span style="color: #008000;">=</span> aggregator.<span style="color: #0000FF;">GetClassificationSpans</span><span style="color: #000000;">&#40;</span>span<span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
            var relevant <span style="color: #008000;">=</span> classifications.<span style="color: #0000FF;">FirstOrDefault</span><span style="color: #000000;">&#40;</span>classificationSpan <span style="color: #008000;">=&gt;</span> classificationSpan.<span style="color: #0000FF;">Span</span>.<span style="color: #0000FF;">Contains</span><span style="color: #000000;">&#40;</span>point<span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
            <span style="color: #0600FF;">if</span> <span style="color: #000000;">&#40;</span>relevant <span style="color: #008000;">==</span> <span style="color: #0600FF;">null</span> <span style="color: #008000;">||</span> relevant.<span style="color: #0000FF;">ClassificationType</span> <span style="color: #008000;">==</span> <span style="color: #0600FF;">null</span><span style="color: #000000;">&#41;</span>
                <span style="color: #0600FF;">return</span> false<span style="color: #008000;">;</span>
&nbsp;
            <span style="color: #0600FF;">return</span> relevant.<span style="color: #0000FF;">ClassificationType</span>.<span style="color: #0000FF;">IsOfType</span><span style="color: #000000;">&#40;</span>PredefinedClassificationTypeNames.<span style="color: #0000FF;">Comment</span><span style="color: #000000;">&#41;</span>
                <span style="color: #008000;">||</span> relevant.<span style="color: #0000FF;">ClassificationType</span>.<span style="color: #0000FF;">IsOfType</span><span style="color: #000000;">&#40;</span>PredefinedClassificationTypeNames.<span style="color: #0000FF;">Literal</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
        <span style="color: #000000;">&#125;</span>
&nbsp;
        <span style="color: #0600FF;">private</span> <span style="color: #FF0000;">bool</span> IsMatchStartCharacter<span style="color: #000000;">&#40;</span><span style="color: #FF0000;">char</span> c<span style="color: #000000;">&#41;</span>
        <span style="color: #000000;">&#123;</span>
            <span style="color: #0600FF;">return</span> MatchingCharacters.<span style="color: #0000FF;">Any</span><span style="color: #000000;">&#40;</span>pair <span style="color: #008000;">=&gt;</span> pair.<span style="color: #0000FF;">Key</span> <span style="color: #008000;">==</span> c<span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
        <span style="color: #000000;">&#125;</span>
&nbsp;
        <span style="color: #0600FF;">private</span> <span style="color: #FF0000;">bool</span> IsMatchCloseCharacter<span style="color: #000000;">&#40;</span><span style="color: #FF0000;">char</span> c<span style="color: #000000;">&#41;</span>
        <span style="color: #000000;">&#123;</span>
            <span style="color: #0600FF;">return</span> MatchingCharacters.<span style="color: #0000FF;">Any</span><span style="color: #000000;">&#40;</span>pair <span style="color: #008000;">=&gt;</span> pair.<span style="color: #0000FF;">Value</span> <span style="color: #008000;">==</span> c<span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
        <span style="color: #000000;">&#125;</span>
&nbsp;
        <span style="color: #0600FF;">private</span> <span style="color: #FF0000;">char</span> GetMatchCloseCharacter<span style="color: #000000;">&#40;</span><span style="color: #FF0000;">char</span> c<span style="color: #000000;">&#41;</span>
        <span style="color: #000000;">&#123;</span>
            <span style="color: #0600FF;">return</span> MatchingCharacters.<span style="color: #0000FF;">First</span><span style="color: #000000;">&#40;</span>pair <span style="color: #008000;">=&gt;</span> pair.<span style="color: #0000FF;">Key</span> <span style="color: #008000;">==</span> c<span style="color: #000000;">&#41;</span>.<span style="color: #0000FF;">Value</span><span style="color: #008000;">;</span>
        <span style="color: #000000;">&#125;</span>
&nbsp;
        <span style="color: #0600FF;">private</span> <span style="color: #FF0000;">char</span> GetMatchOpenCharacter<span style="color: #000000;">&#40;</span><span style="color: #FF0000;">char</span> c<span style="color: #000000;">&#41;</span>
        <span style="color: #000000;">&#123;</span>
            <span style="color: #0600FF;">return</span> MatchingCharacters.<span style="color: #0000FF;">First</span><span style="color: #000000;">&#40;</span>pair <span style="color: #008000;">=&gt;</span> pair.<span style="color: #0000FF;">Value</span> <span style="color: #008000;">==</span> c<span style="color: #000000;">&#41;</span>.<span style="color: #0000FF;">Key</span><span style="color: #008000;">;</span>
        <span style="color: #000000;">&#125;</span>
&nbsp;
        <span style="color: #0600FF;">private</span> <span style="color: #0600FF;">static</span> <span style="color: #FF0000;">bool</span> FindMatchingCloseChar<span style="color: #000000;">&#40;</span>SnapshotPoint start, IClassifier aggregator, <span style="color: #FF0000;">char</span> open, <span style="color: #FF0000;">char</span> close, <span style="color: #FF0000;">int</span> maxLines, <span style="color: #0600FF;">out</span> SnapshotSpan pairSpan<span style="color: #000000;">&#41;</span>
        <span style="color: #000000;">&#123;</span>
            pairSpan <span style="color: #008000;">=</span> <span style="color: #008000;">new</span> SnapshotSpan<span style="color: #000000;">&#40;</span>start.<span style="color: #0000FF;">Snapshot</span>, <span style="color: #FF0000;">1</span>, <span style="color: #FF0000;">1</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
            ITextSnapshotLine line <span style="color: #008000;">=</span> start.<span style="color: #0000FF;">GetContainingLine</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
            <span style="color: #FF0000;">string</span> lineText <span style="color: #008000;">=</span> line.<span style="color: #0000FF;">GetText</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
            <span style="color: #FF0000;">int</span> lineNumber <span style="color: #008000;">=</span> line.<span style="color: #0000FF;">LineNumber</span><span style="color: #008000;">;</span>
            <span style="color: #FF0000;">int</span> offset <span style="color: #008000;">=</span> start.<span style="color: #0000FF;">Position</span> <span style="color: #008000;">-</span> line.<span style="color: #0000FF;">Start</span>.<span style="color: #0000FF;">Position</span> <span style="color: #008000;">+</span> <span style="color: #FF0000;">1</span><span style="color: #008000;">;</span>
&nbsp;
            <span style="color: #FF0000;">int</span> stopLineNumber <span style="color: #008000;">=</span> start.<span style="color: #0000FF;">Snapshot</span>.<span style="color: #0000FF;">LineCount</span> <span style="color: #008000;">-</span> <span style="color: #FF0000;">1</span><span style="color: #008000;">;</span>
            <span style="color: #0600FF;">if</span> <span style="color: #000000;">&#40;</span>maxLines <span style="color: #008000;">&gt;</span> <span style="color: #FF0000;">0</span><span style="color: #000000;">&#41;</span>
                stopLineNumber <span style="color: #008000;">=</span> Math.<span style="color: #0000FF;">Min</span><span style="color: #000000;">&#40;</span>stopLineNumber, lineNumber <span style="color: #008000;">+</span> maxLines<span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
&nbsp;
            <span style="color: #FF0000;">int</span> openCount <span style="color: #008000;">=</span> <span style="color: #FF0000;">0</span><span style="color: #008000;">;</span>
            <span style="color: #0600FF;">while</span> <span style="color: #000000;">&#40;</span><span style="color: #0600FF;">true</span><span style="color: #000000;">&#41;</span>
            <span style="color: #000000;">&#123;</span>
                <span style="color: #0600FF;">while</span> <span style="color: #000000;">&#40;</span>offset <span style="color: #008000;">&lt;</span> line.<span style="color: #0000FF;">Length</span><span style="color: #000000;">&#41;</span>
                <span style="color: #000000;">&#123;</span>
                    <span style="color: #FF0000;">char</span> currentChar <span style="color: #008000;">=</span> lineText<span style="color: #000000;">&#91;</span>offset<span style="color: #000000;">&#93;</span><span style="color: #008000;">;</span>
                    <span style="color: #008080; font-style: italic;">// TODO: is this the correct affinity</span>
                    <span style="color: #0600FF;">if</span> <span style="color: #000000;">&#40;</span>currentChar <span style="color: #008000;">==</span> close <span style="color: #008000;">&amp;&amp;</span> <span style="color: #008000;">!</span>IsInCommentOrLiteral<span style="color: #000000;">&#40;</span>aggregator, <span style="color: #008000;">new</span> SnapshotPoint<span style="color: #000000;">&#40;</span>start.<span style="color: #0000FF;">Snapshot</span>, offset <span style="color: #008000;">+</span> line.<span style="color: #0000FF;">Start</span>.<span style="color: #0000FF;">Position</span><span style="color: #000000;">&#41;</span>, PositionAffinity.<span style="color: #0000FF;">Successor</span><span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span>
                    <span style="color: #000000;">&#123;</span>
                        <span style="color: #0600FF;">if</span> <span style="color: #000000;">&#40;</span>openCount <span style="color: #008000;">&gt;</span> <span style="color: #FF0000;">0</span><span style="color: #000000;">&#41;</span>
                        <span style="color: #000000;">&#123;</span>
                            openCount<span style="color: #008000;">--;</span>
                        <span style="color: #000000;">&#125;</span>
                        <span style="color: #0600FF;">else</span>
                        <span style="color: #000000;">&#123;</span>
                            pairSpan <span style="color: #008000;">=</span> <span style="color: #008000;">new</span> SnapshotSpan<span style="color: #000000;">&#40;</span>start.<span style="color: #0000FF;">Snapshot</span>, line.<span style="color: #0000FF;">Start</span> <span style="color: #008000;">+</span> offset, <span style="color: #FF0000;">1</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
                            <span style="color: #0600FF;">return</span> true<span style="color: #008000;">;</span>
                        <span style="color: #000000;">&#125;</span>
                    <span style="color: #000000;">&#125;</span>
                    <span style="color: #008080; font-style: italic;">// TODO: is this the correct affinity</span>
                    <span style="color: #0600FF;">else</span> <span style="color: #0600FF;">if</span> <span style="color: #000000;">&#40;</span>currentChar <span style="color: #008000;">==</span> open <span style="color: #008000;">&amp;&amp;</span> <span style="color: #008000;">!</span>IsInCommentOrLiteral<span style="color: #000000;">&#40;</span>aggregator, <span style="color: #008000;">new</span> SnapshotPoint<span style="color: #000000;">&#40;</span>start.<span style="color: #0000FF;">Snapshot</span>, offset <span style="color: #008000;">+</span> line.<span style="color: #0000FF;">Start</span>.<span style="color: #0000FF;">Position</span><span style="color: #000000;">&#41;</span>, PositionAffinity.<span style="color: #0000FF;">Successor</span><span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span>
                    <span style="color: #000000;">&#123;</span>
                        openCount<span style="color: #008000;">++;</span>
                    <span style="color: #000000;">&#125;</span>
&nbsp;
                    offset<span style="color: #008000;">++;</span>
                <span style="color: #000000;">&#125;</span>
&nbsp;
                <span style="color: #008080; font-style: italic;">// move on to the next line</span>
                lineNumber<span style="color: #008000;">++;</span>
                <span style="color: #0600FF;">if</span> <span style="color: #000000;">&#40;</span>lineNumber <span style="color: #008000;">&gt;</span> stopLineNumber<span style="color: #000000;">&#41;</span>
                    break<span style="color: #008000;">;</span>
&nbsp;
                line <span style="color: #008000;">=</span> line.<span style="color: #0000FF;">Snapshot</span>.<span style="color: #0000FF;">GetLineFromLineNumber</span><span style="color: #000000;">&#40;</span>lineNumber<span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
                lineText <span style="color: #008000;">=</span> line.<span style="color: #0000FF;">GetText</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
                offset <span style="color: #008000;">=</span> <span style="color: #FF0000;">0</span><span style="color: #008000;">;</span>
            <span style="color: #000000;">&#125;</span>
&nbsp;
            <span style="color: #0600FF;">return</span> false<span style="color: #008000;">;</span>
        <span style="color: #000000;">&#125;</span>
&nbsp;
        <span style="color: #0600FF;">private</span> <span style="color: #0600FF;">static</span> <span style="color: #FF0000;">bool</span> FindMatchingOpenChar<span style="color: #000000;">&#40;</span>SnapshotPoint start, IClassifier aggregator, <span style="color: #FF0000;">char</span> open, <span style="color: #FF0000;">char</span> close, <span style="color: #FF0000;">int</span> maxLines, <span style="color: #0600FF;">out</span> SnapshotSpan pairSpan<span style="color: #000000;">&#41;</span>
        <span style="color: #000000;">&#123;</span>
            pairSpan <span style="color: #008000;">=</span> <span style="color: #008000;">new</span> SnapshotSpan<span style="color: #000000;">&#40;</span>start, start<span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
            ITextSnapshotLine line <span style="color: #008000;">=</span> start.<span style="color: #0000FF;">GetContainingLine</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
            <span style="color: #FF0000;">int</span> lineNumber <span style="color: #008000;">=</span> line.<span style="color: #0000FF;">LineNumber</span><span style="color: #008000;">;</span>
            <span style="color: #FF0000;">int</span> offset <span style="color: #008000;">=</span> start <span style="color: #008000;">-</span> line.<span style="color: #0000FF;">Start</span> <span style="color: #008000;">-</span> <span style="color: #FF0000;">1</span><span style="color: #008000;">;</span>
&nbsp;
            <span style="color: #008080; font-style: italic;">// if the offset is negative, move to the previous line</span>
            <span style="color: #0600FF;">if</span> <span style="color: #000000;">&#40;</span>offset <span style="color: #008000;">&lt;</span> <span style="color: #FF0000;">0</span><span style="color: #000000;">&#41;</span>
            <span style="color: #000000;">&#123;</span>
                lineNumber<span style="color: #008000;">--;</span>
                line <span style="color: #008000;">=</span> line.<span style="color: #0000FF;">Snapshot</span>.<span style="color: #0000FF;">GetLineFromLineNumber</span><span style="color: #000000;">&#40;</span>lineNumber<span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
                offset <span style="color: #008000;">=</span> line.<span style="color: #0000FF;">Length</span> <span style="color: #008000;">-</span> <span style="color: #FF0000;">1</span><span style="color: #008000;">;</span>
            <span style="color: #000000;">&#125;</span>
&nbsp;
            <span style="color: #FF0000;">string</span> lineText <span style="color: #008000;">=</span> line.<span style="color: #0000FF;">GetText</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
&nbsp;
            <span style="color: #FF0000;">int</span> stopLineNumber <span style="color: #008000;">=</span> <span style="color: #FF0000;">0</span><span style="color: #008000;">;</span>
            <span style="color: #0600FF;">if</span> <span style="color: #000000;">&#40;</span>maxLines <span style="color: #008000;">&gt;</span> <span style="color: #FF0000;">0</span><span style="color: #000000;">&#41;</span>
                stopLineNumber <span style="color: #008000;">=</span> Math.<span style="color: #0000FF;">Max</span><span style="color: #000000;">&#40;</span>stopLineNumber, lineNumber <span style="color: #008000;">-</span> maxLines<span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
&nbsp;
            <span style="color: #FF0000;">int</span> closeCount <span style="color: #008000;">=</span> <span style="color: #FF0000;">0</span><span style="color: #008000;">;</span>
            <span style="color: #0600FF;">while</span> <span style="color: #000000;">&#40;</span><span style="color: #0600FF;">true</span><span style="color: #000000;">&#41;</span>
            <span style="color: #000000;">&#123;</span>
                <span style="color: #0600FF;">while</span> <span style="color: #000000;">&#40;</span>offset <span style="color: #008000;">&gt;=</span> <span style="color: #FF0000;">0</span><span style="color: #000000;">&#41;</span>
                <span style="color: #000000;">&#123;</span>
                    <span style="color: #FF0000;">char</span> currentChar <span style="color: #008000;">=</span> lineText<span style="color: #000000;">&#91;</span>offset<span style="color: #000000;">&#93;</span><span style="color: #008000;">;</span>
                    <span style="color: #008080; font-style: italic;">// TODO: is this the correct affinity</span>
                    <span style="color: #0600FF;">if</span> <span style="color: #000000;">&#40;</span>currentChar <span style="color: #008000;">==</span> open <span style="color: #008000;">&amp;&amp;</span> <span style="color: #008000;">!</span>IsInCommentOrLiteral<span style="color: #000000;">&#40;</span>aggregator, <span style="color: #008000;">new</span> SnapshotPoint<span style="color: #000000;">&#40;</span>start.<span style="color: #0000FF;">Snapshot</span>, offset <span style="color: #008000;">+</span> line.<span style="color: #0000FF;">Start</span>.<span style="color: #0000FF;">Position</span><span style="color: #000000;">&#41;</span>, PositionAffinity.<span style="color: #0000FF;">Successor</span><span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span>
                    <span style="color: #000000;">&#123;</span>
                        <span style="color: #0600FF;">if</span> <span style="color: #000000;">&#40;</span>closeCount <span style="color: #008000;">&gt;</span> <span style="color: #FF0000;">0</span><span style="color: #000000;">&#41;</span>
                        <span style="color: #000000;">&#123;</span>
                            closeCount<span style="color: #008000;">--;</span>
                        <span style="color: #000000;">&#125;</span>
                        <span style="color: #0600FF;">else</span>
                        <span style="color: #000000;">&#123;</span>
                            pairSpan <span style="color: #008000;">=</span> <span style="color: #008000;">new</span> SnapshotSpan<span style="color: #000000;">&#40;</span>line.<span style="color: #0000FF;">Start</span> <span style="color: #008000;">+</span> offset, <span style="color: #FF0000;">1</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
                            <span style="color: #0600FF;">return</span> true<span style="color: #008000;">;</span>
                        <span style="color: #000000;">&#125;</span>
                    <span style="color: #000000;">&#125;</span>
                    <span style="color: #008080; font-style: italic;">// TODO: is this the correct affinity</span>
                    <span style="color: #0600FF;">else</span> <span style="color: #0600FF;">if</span> <span style="color: #000000;">&#40;</span>currentChar <span style="color: #008000;">==</span> close <span style="color: #008000;">&amp;&amp;</span> <span style="color: #008000;">!</span>IsInCommentOrLiteral<span style="color: #000000;">&#40;</span>aggregator, <span style="color: #008000;">new</span> SnapshotPoint<span style="color: #000000;">&#40;</span>start.<span style="color: #0000FF;">Snapshot</span>, offset <span style="color: #008000;">+</span> line.<span style="color: #0000FF;">Start</span>.<span style="color: #0000FF;">Position</span><span style="color: #000000;">&#41;</span>, PositionAffinity.<span style="color: #0000FF;">Successor</span><span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span>
                    <span style="color: #000000;">&#123;</span>
                        closeCount<span style="color: #008000;">++;</span>
                    <span style="color: #000000;">&#125;</span>
&nbsp;
                    offset<span style="color: #008000;">--;</span>
                <span style="color: #000000;">&#125;</span>
&nbsp;
                <span style="color: #008080; font-style: italic;">// move to the previous line</span>
                lineNumber<span style="color: #008000;">--;</span>
                <span style="color: #0600FF;">if</span> <span style="color: #000000;">&#40;</span>lineNumber <span style="color: #008000;">&lt;</span> stopLineNumber<span style="color: #000000;">&#41;</span>
                    break<span style="color: #008000;">;</span>
&nbsp;
                line <span style="color: #008000;">=</span> line.<span style="color: #0000FF;">Snapshot</span>.<span style="color: #0000FF;">GetLineFromLineNumber</span><span style="color: #000000;">&#40;</span>lineNumber<span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
                lineText <span style="color: #008000;">=</span> line.<span style="color: #0000FF;">GetText</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
                offset <span style="color: #008000;">=</span> line.<span style="color: #0000FF;">Length</span> <span style="color: #008000;">-</span> <span style="color: #FF0000;">1</span><span style="color: #008000;">;</span>
            <span style="color: #000000;">&#125;</span>
&nbsp;
            <span style="color: #0600FF;">return</span> false<span style="color: #008000;">;</span>
        <span style="color: #000000;">&#125;</span>
&nbsp;
        <span style="color: #0600FF;">public</span> IEnumerable<span style="color: #008000;">&lt;</span>ITagSpan<span style="color: #008000;">&lt;</span>TextMarkerTag<span style="color: #008000;">&gt;&gt;</span> GetTags<span style="color: #000000;">&#40;</span>NormalizedSnapshotSpanCollection spans<span style="color: #000000;">&#41;</span>
        <span style="color: #000000;">&#123;</span>
            <span style="color: #0600FF;">if</span> <span style="color: #000000;">&#40;</span>spans.<span style="color: #0000FF;">Count</span> <span style="color: #008000;">==</span> <span style="color: #FF0000;">0</span><span style="color: #000000;">&#41;</span>
                yield break<span style="color: #008000;">;</span>
&nbsp;
            <span style="color: #008080; font-style: italic;">// don't do anything if the current SnapshotPoint is not initialized or at the end of the buffer</span>
            <span style="color: #0600FF;">if</span> <span style="color: #000000;">&#40;</span><span style="color: #008000;">!</span>CurrentChar.<span style="color: #0000FF;">HasValue</span> <span style="color: #008000;">||</span> CurrentChar.<span style="color: #0000FF;">Value</span>.<span style="color: #0000FF;">Position</span> <span style="color: #008000;">&gt;=</span> CurrentChar.<span style="color: #0000FF;">Value</span>.<span style="color: #0000FF;">Snapshot</span>.<span style="color: #0000FF;">Length</span><span style="color: #000000;">&#41;</span>
                yield break<span style="color: #008000;">;</span>
&nbsp;
            <span style="color: #008080; font-style: italic;">// hold on to a snapshot of the current character</span>
            var currentChar <span style="color: #008000;">=</span> CurrentChar.<span style="color: #0000FF;">Value</span><span style="color: #008000;">;</span>
&nbsp;
            <span style="color: #0600FF;">if</span> <span style="color: #000000;">&#40;</span>IsInCommentOrLiteral<span style="color: #000000;">&#40;</span>Aggregator, currentChar, TextView.<span style="color: #0000FF;">Caret</span>.<span style="color: #0000FF;">Position</span>.<span style="color: #0000FF;">Affinity</span><span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span>
                yield break<span style="color: #008000;">;</span>
&nbsp;
            <span style="color: #008080; font-style: italic;">// if the requested snapshot isn't the same as the one the brace is on, translate our spans to the expected snapshot</span>
            currentChar <span style="color: #008000;">=</span> currentChar.<span style="color: #0000FF;">TranslateTo</span><span style="color: #000000;">&#40;</span>spans<span style="color: #000000;">&#91;</span><span style="color: #FF0000;">0</span><span style="color: #000000;">&#93;</span>.<span style="color: #0000FF;">Snapshot</span>, PointTrackingMode.<span style="color: #0000FF;">Positive</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
&nbsp;
            <span style="color: #008080; font-style: italic;">// get the current char and the previous char</span>
            <span style="color: #FF0000;">char</span> currentText <span style="color: #008000;">=</span> currentChar.<span style="color: #0000FF;">GetChar</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
            <span style="color: #008080; font-style: italic;">// if current char is 0 (beginning of buffer), don't move it back</span>
            SnapshotPoint lastChar <span style="color: #008000;">=</span> currentChar <span style="color: #008000;">==</span> <span style="color: #FF0000;">0</span> <span style="color: #008000;">?</span> currentChar <span style="color: #008000;">:</span> currentChar <span style="color: #008000;">-</span> <span style="color: #FF0000;">1</span><span style="color: #008000;">;</span>
            <span style="color: #FF0000;">char</span> lastText <span style="color: #008000;">=</span> lastChar.<span style="color: #0000FF;">GetChar</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
            SnapshotSpan pairSpan <span style="color: #008000;">=</span> <span style="color: #008000;">new</span> SnapshotSpan<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
&nbsp;
            <span style="color: #0600FF;">if</span> <span style="color: #000000;">&#40;</span>IsMatchStartCharacter<span style="color: #000000;">&#40;</span>currentText<span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span>
            <span style="color: #000000;">&#123;</span>
                <span style="color: #FF0000;">char</span> closeChar <span style="color: #008000;">=</span> GetMatchCloseCharacter<span style="color: #000000;">&#40;</span>currentText<span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
                <span style="color: #008080; font-style: italic;">/* TODO: Need to improve handling of larger blocks. this won't highlight if the matching brace is more
                 *       than 1 screen's worth of lines away. Changing this to 10 * TextView.TextViewLines.Count seemed
                 *       to improve the situation.
                 */</span>
                <span style="color: #0600FF;">if</span> <span style="color: #000000;">&#40;</span>BraceMatchingTagger.<span style="color: #0000FF;">FindMatchingCloseChar</span><span style="color: #000000;">&#40;</span>currentChar, Aggregator, currentText, closeChar, TextView.<span style="color: #0000FF;">TextViewLines</span>.<span style="color: #0000FF;">Count</span>, <span style="color: #0600FF;">out</span> pairSpan<span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span>
                <span style="color: #000000;">&#123;</span>
                    yield <span style="color: #0600FF;">return</span> <span style="color: #008000;">new</span> TagSpan<span style="color: #008000;">&lt;</span>TextMarkerTag<span style="color: #008000;">&gt;</span><span style="color: #000000;">&#40;</span><span style="color: #008000;">new</span> SnapshotSpan<span style="color: #000000;">&#40;</span>currentChar, <span style="color: #FF0000;">1</span><span style="color: #000000;">&#41;</span>, PredefinedTextMarkerTags.<span style="color: #0000FF;">BraceHighlight</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
                    yield <span style="color: #0600FF;">return</span> <span style="color: #008000;">new</span> TagSpan<span style="color: #008000;">&lt;</span>TextMarkerTag<span style="color: #008000;">&gt;</span><span style="color: #000000;">&#40;</span>pairSpan, PredefinedTextMarkerTags.<span style="color: #0000FF;">BraceHighlight</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
                <span style="color: #000000;">&#125;</span>
            <span style="color: #000000;">&#125;</span>
            <span style="color: #0600FF;">else</span> <span style="color: #0600FF;">if</span> <span style="color: #000000;">&#40;</span>IsMatchCloseCharacter<span style="color: #000000;">&#40;</span>lastText<span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span>
            <span style="color: #000000;">&#123;</span>
                var open <span style="color: #008000;">=</span> GetMatchOpenCharacter<span style="color: #000000;">&#40;</span>lastText<span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
                <span style="color: #0600FF;">if</span> <span style="color: #000000;">&#40;</span>BraceMatchingTagger.<span style="color: #0000FF;">FindMatchingOpenChar</span><span style="color: #000000;">&#40;</span>lastChar, Aggregator, open, lastText, TextView.<span style="color: #0000FF;">TextViewLines</span>.<span style="color: #0000FF;">Count</span>, <span style="color: #0600FF;">out</span> pairSpan<span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span>
                <span style="color: #000000;">&#123;</span>
                    yield <span style="color: #0600FF;">return</span> <span style="color: #008000;">new</span> TagSpan<span style="color: #008000;">&lt;</span>TextMarkerTag<span style="color: #008000;">&gt;</span><span style="color: #000000;">&#40;</span><span style="color: #008000;">new</span> SnapshotSpan<span style="color: #000000;">&#40;</span>lastChar, <span style="color: #FF0000;">1</span><span style="color: #000000;">&#41;</span>, PredefinedTextMarkerTags.<span style="color: #0000FF;">BraceHighlight</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
                    yield <span style="color: #0600FF;">return</span> <span style="color: #008000;">new</span> TagSpan<span style="color: #008000;">&lt;</span>TextMarkerTag<span style="color: #008000;">&gt;</span><span style="color: #000000;">&#40;</span>pairSpan, PredefinedTextMarkerTags.<span style="color: #0000FF;">BraceHighlight</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
                <span style="color: #000000;">&#125;</span>
            <span style="color: #000000;">&#125;</span>
        <span style="color: #000000;">&#125;</span>
&nbsp;
        <span style="color: #0600FF;">private</span> <span style="color: #0600FF;">void</span> UpdateAtCaretPosition<span style="color: #000000;">&#40;</span>CaretPosition caretPosition<span style="color: #000000;">&#41;</span>
        <span style="color: #000000;">&#123;</span>
            CurrentChar <span style="color: #008000;">=</span> caretPosition.<span style="color: #0000FF;">Point</span>.<span style="color: #0000FF;">GetPoint</span><span style="color: #000000;">&#40;</span>SourceBuffer, caretPosition.<span style="color: #0000FF;">Affinity</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
            <span style="color: #0600FF;">if</span> <span style="color: #000000;">&#40;</span><span style="color: #008000;">!</span>CurrentChar.<span style="color: #0000FF;">HasValue</span><span style="color: #000000;">&#41;</span>
                return<span style="color: #008000;">;</span>
&nbsp;
            var t <span style="color: #008000;">=</span> TagsChanged<span style="color: #008000;">;</span>
            <span style="color: #0600FF;">if</span> <span style="color: #000000;">&#40;</span>t <span style="color: #008000;">!=</span> <span style="color: #0600FF;">null</span><span style="color: #000000;">&#41;</span>
                t<span style="color: #000000;">&#40;</span><span style="color: #0600FF;">this</span>, <span style="color: #008000;">new</span> SnapshotSpanEventArgs<span style="color: #000000;">&#40;</span><span style="color: #008000;">new</span> SnapshotSpan<span style="color: #000000;">&#40;</span>SourceBuffer.<span style="color: #0000FF;">CurrentSnapshot</span>, <span style="color: #FF0000;">0</span>, SourceBuffer.<span style="color: #0000FF;">CurrentSnapshot</span>.<span style="color: #0000FF;">Length</span><span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
        <span style="color: #000000;">&#125;</span>
&nbsp;
        <span style="color: #0600FF;">private</span> <span style="color: #0600FF;">void</span> TextView_LayoutChanged<span style="color: #000000;">&#40;</span><span style="color: #FF0000;">object</span> sender, TextViewLayoutChangedEventArgs e<span style="color: #000000;">&#41;</span>
        <span style="color: #000000;">&#123;</span>
            <span style="color: #0600FF;">if</span> <span style="color: #000000;">&#40;</span>e.<span style="color: #0000FF;">NewSnapshot</span> <span style="color: #008000;">!=</span> e.<span style="color: #0000FF;">OldSnapshot</span><span style="color: #000000;">&#41;</span>
                UpdateAtCaretPosition<span style="color: #000000;">&#40;</span>TextView.<span style="color: #0000FF;">Caret</span>.<span style="color: #0000FF;">Position</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
        <span style="color: #000000;">&#125;</span>
&nbsp;
        <span style="color: #0600FF;">private</span> <span style="color: #0600FF;">void</span> Caret_PositionChanged<span style="color: #000000;">&#40;</span><span style="color: #FF0000;">object</span> sender, CaretPositionChangedEventArgs e<span style="color: #000000;">&#41;</span>
        <span style="color: #000000;">&#123;</span>
            UpdateAtCaretPosition<span style="color: #000000;">&#40;</span>e.<span style="color: #0000FF;">NewPosition</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
        <span style="color: #000000;">&#125;</span>
    <span style="color: #000000;">&#125;</span>
<span style="color: #000000;">&#125;</span></pre></td></tr></table></div>

]]></content:encoded>
			<wfw:commentRss>http://blog.280z28.org/archives/2009/11/74/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Tool tips for squiggles and URLs in Visual Studio 2010</title>
		<link>http://blog.280z28.org/archives/2009/11/61/</link>
		<comments>http://blog.280z28.org/archives/2009/11/61/#comments</comments>
		<pubDate>Wed, 25 Nov 2009 21:37:34 +0000</pubDate>
		<dc:creator>280Z28</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Tutorials]]></category>

		<guid isPermaLink="false">http://blog.280z28.org/?p=61</guid>
		<description><![CDATA[I&#8217;ve been experimenting with Visual Studio&#8217;s new extensibility model, and ran into a problem with squiggles. It seems that despite having an internal IQuickInfoSource for the SquiggleTag and IUrlTag, it&#8217;s not hooked up to a IIntellisenseController so it never appears. Here is a general implementation for an SquiggleQuickInfoIntellisenseController and UrlQuickInfoIntellisenseController that will provide QuickInfo for [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been experimenting with Visual Studio&#8217;s new extensibility model, and ran into a problem with squiggles. It seems that despite having an internal <code>IQuickInfoSource</code> for the <code>SquiggleTag</code> and <code>IUrlTag</code>, it&#8217;s not hooked up to a <code>IIntellisenseController</code> so <a href="http://blog.280z28.org/go.php?http://social.msdn.microsoft.com/Forums/en-US/vseditorprerelease/thread/5f02b7ed-f8cc-4e1b-904d-2962d189d796" title="(308 hits)">it never appears</a>. Here is a general implementation for an <code>SquiggleQuickInfoIntellisenseController</code> and <code>UrlQuickInfoIntellisenseController</code> that will provide QuickInfo for squiggle tags and URLs provided by custom implementations of <code>ITagger&lt;SquiggleTag&gt;</code>. The controller itself is a generic that supports any <code>ITag</code> that comes with a <code>IQuickInfoSource</code>.</p>

<h3>This code is <em>very heavily</em> based on an existing internal IntelliSense controller in Visual Studio 2010 that&#8217;s used for a different tag type.</h3>

<p>First we have the <code>IIntellisenseControllerProvider</code> for squiggles and URLs:</p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
</pre></td><td class="code"><pre class="csharp" style="font-family:monospace;"><span style="color: #0600FF;">namespace</span> CustomLanguageServices.<span style="color: #0000FF;">Text</span>
<span style="color: #000000;">&#123;</span>
    <span style="color: #0600FF;">using</span> <span style="color: #008080;">System</span><span style="color: #008000;">;</span>
    <span style="color: #0600FF;">using</span> <span style="color: #008080;">System.Collections.Generic</span><span style="color: #008000;">;</span>
    <span style="color: #0600FF;">using</span> <span style="color: #008080;">System.ComponentModel.Composition</span><span style="color: #008000;">;</span>
    <span style="color: #0600FF;">using</span> <span style="color: #008080;">Microsoft.VisualStudio.Language.Intellisense</span><span style="color: #008000;">;</span>
    <span style="color: #0600FF;">using</span> <span style="color: #008080;">Microsoft.VisualStudio.Text</span><span style="color: #008000;">;</span>
    <span style="color: #0600FF;">using</span> <span style="color: #008080;">Microsoft.VisualStudio.Text.Editor</span><span style="color: #008000;">;</span>
    <span style="color: #0600FF;">using</span> <span style="color: #008080;">Microsoft.VisualStudio.Text.Tagging</span><span style="color: #008000;">;</span>
    <span style="color: #0600FF;">using</span> <span style="color: #008080;">Microsoft.VisualStudio.Utilities</span><span style="color: #008000;">;</span>
&nbsp;
    <span style="color: #000000;">&#91;</span>Export<span style="color: #000000;">&#40;</span><span style="color: #008000;">typeof</span><span style="color: #000000;">&#40;</span>IIntellisenseControllerProvider<span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span><span style="color: #000000;">&#93;</span>
    <span style="color: #000000;">&#91;</span>ContentType<span style="color: #000000;">&#40;</span><span style="color: #666666;">&quot;text&quot;</span><span style="color: #000000;">&#41;</span><span style="color: #000000;">&#93;</span>
    <span style="color: #0600FF;">public</span> <span style="color: #0600FF;">sealed</span> <span style="color: #FF0000;">class</span> SquiggleQuickInfoControllerProvider <span style="color: #008000;">:</span> IIntellisenseControllerProvider
    <span style="color: #000000;">&#123;</span>
        <span style="color: #000000;">&#91;</span>Import<span style="color: #000000;">&#93;</span>
        <span style="color: #0600FF;">public</span> IQuickInfoBroker QuickInfoBroker<span style="color: #008000;">;</span>
&nbsp;
        <span style="color: #000000;">&#91;</span>Import<span style="color: #000000;">&#93;</span>
        <span style="color: #0600FF;">public</span> IViewTagAggregatorFactoryService TagAggregatorFactoryService<span style="color: #008000;">;</span>
&nbsp;
        <span style="color: #0600FF;">public</span> IIntellisenseController TryCreateIntellisenseController<span style="color: #000000;">&#40;</span>ITextView textView, IList<span style="color: #008000;">&lt;</span>ITextBuffer<span style="color: #008000;">&gt;</span> subjectBuffers<span style="color: #000000;">&#41;</span>
        <span style="color: #000000;">&#123;</span>
            Func<span style="color: #008000;">&lt;</span>TagQuickInfoController<span style="color: #008000;">&lt;</span>SquiggleTag<span style="color: #008000;">&gt;&gt;</span> creator <span style="color: #008000;">=</span>
                <span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span> <span style="color: #008000;">=&gt;</span>
                <span style="color: #000000;">&#123;</span>
                    var tagAggregator <span style="color: #008000;">=</span> TagAggregatorFactoryService.<span style="color: #0000FF;">CreateTagAggregator</span><span style="color: #008000;">&lt;</span>SquiggleTag<span style="color: #008000;">&gt;</span><span style="color: #000000;">&#40;</span>textView<span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
                    var controller <span style="color: #008000;">=</span> <span style="color: #008000;">new</span> TagQuickInfoController<span style="color: #008000;">&lt;</span>SquiggleTag<span style="color: #008000;">&gt;</span><span style="color: #000000;">&#40;</span>QuickInfoBroker, textView, tagAggregator<span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
                    <span style="color: #0600FF;">return</span> controller<span style="color: #008000;">;</span>
                <span style="color: #000000;">&#125;</span><span style="color: #008000;">;</span>
&nbsp;
            <span style="color: #0600FF;">return</span> textView.<span style="color: #0000FF;">Properties</span>.<span style="color: #0000FF;">GetOrCreateSingletonProperty</span><span style="color: #000000;">&#40;</span>creator<span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
        <span style="color: #000000;">&#125;</span>
    <span style="color: #000000;">&#125;</span>
&nbsp;
    <span style="color: #000000;">&#91;</span>Export<span style="color: #000000;">&#40;</span><span style="color: #008000;">typeof</span><span style="color: #000000;">&#40;</span>IIntellisenseControllerProvider<span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span><span style="color: #000000;">&#93;</span>
    <span style="color: #000000;">&#91;</span>ContentType<span style="color: #000000;">&#40;</span><span style="color: #666666;">&quot;text&quot;</span><span style="color: #000000;">&#41;</span><span style="color: #000000;">&#93;</span>
    <span style="color: #0600FF;">public</span> <span style="color: #0600FF;">sealed</span> <span style="color: #FF0000;">class</span> UrlQuickInfoControllerProvider <span style="color: #008000;">:</span> IIntellisenseControllerProvider
    <span style="color: #000000;">&#123;</span>
        <span style="color: #000000;">&#91;</span>Import<span style="color: #000000;">&#93;</span>
        <span style="color: #0600FF;">public</span> IQuickInfoBroker QuickInfoBroker<span style="color: #008000;">;</span>
&nbsp;
        <span style="color: #000000;">&#91;</span>Import<span style="color: #000000;">&#93;</span>
        <span style="color: #0600FF;">public</span> IViewTagAggregatorFactoryService TagAggregatorFactoryService<span style="color: #008000;">;</span>
&nbsp;
        <span style="color: #0600FF;">public</span> IIntellisenseController TryCreateIntellisenseController<span style="color: #000000;">&#40;</span>ITextView textView, IList<span style="color: #008000;">&lt;</span>ITextBuffer<span style="color: #008000;">&gt;</span> subjectBuffers<span style="color: #000000;">&#41;</span>
        <span style="color: #000000;">&#123;</span>
            Func<span style="color: #008000;">&lt;</span>TagQuickInfoController<span style="color: #008000;">&lt;</span>IUrlTag<span style="color: #008000;">&gt;&gt;</span> creator <span style="color: #008000;">=</span>
                <span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span> <span style="color: #008000;">=&gt;</span>
                <span style="color: #000000;">&#123;</span>
                    var tagAggregator <span style="color: #008000;">=</span> TagAggregatorFactoryService.<span style="color: #0000FF;">CreateTagAggregator</span><span style="color: #008000;">&lt;</span>IUrlTag<span style="color: #008000;">&gt;</span><span style="color: #000000;">&#40;</span>textView<span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
                    var controller <span style="color: #008000;">=</span> <span style="color: #008000;">new</span> TagQuickInfoController<span style="color: #008000;">&lt;</span>IUrlTag<span style="color: #008000;">&gt;</span><span style="color: #000000;">&#40;</span>QuickInfoBroker, textView, tagAggregator<span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
                    <span style="color: #0600FF;">return</span> controller<span style="color: #008000;">;</span>
                <span style="color: #000000;">&#125;</span><span style="color: #008000;">;</span>
&nbsp;
            <span style="color: #0600FF;">return</span> textView.<span style="color: #0000FF;">Properties</span>.<span style="color: #0000FF;">GetOrCreateSingletonProperty</span><span style="color: #000000;">&#40;</span>creator<span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
        <span style="color: #000000;">&#125;</span>
    <span style="color: #000000;">&#125;</span>
<span style="color: #000000;">&#125;</span></pre></td></tr></table></div>


<p>And then we have the actual <code>IIntellisenseController</code>:</p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
</pre></td><td class="code"><pre class="csharp" style="font-family:monospace;"><span style="color: #0600FF;">namespace</span> CustomLanguageService.<span style="color: #0000FF;">Text</span>
<span style="color: #000000;">&#123;</span>
    <span style="color: #0600FF;">using</span> <span style="color: #008080;">Microsoft.VisualStudio.Language.Intellisense</span><span style="color: #008000;">;</span>
    <span style="color: #0600FF;">using</span> <span style="color: #008080;">Microsoft.VisualStudio.Text</span><span style="color: #008000;">;</span>
    <span style="color: #0600FF;">using</span> <span style="color: #008080;">Microsoft.VisualStudio.Text.Editor</span><span style="color: #008000;">;</span>
    <span style="color: #0600FF;">using</span> <span style="color: #008080;">Microsoft.VisualStudio.Text.Tagging</span><span style="color: #008000;">;</span>
&nbsp;
    <span style="color: #0600FF;">public</span> <span style="color: #FF0000;">class</span> TagQuickInfoController<span style="color: #008000;">&lt;</span>T<span style="color: #008000;">&gt;</span> <span style="color: #008000;">:</span> IIntellisenseController
        where T <span style="color: #008000;">:</span> ITag
    <span style="color: #000000;">&#123;</span>
        <span style="color: #0600FF;">private</span> IQuickInfoBroker _quickInfoBroker<span style="color: #008000;">;</span>
        <span style="color: #0600FF;">private</span> ITextView _textView<span style="color: #008000;">;</span>
        <span style="color: #0600FF;">private</span> ITagAggregator<span style="color: #008000;">&lt;</span>T<span style="color: #008000;">&gt;</span> _tagAggregator<span style="color: #008000;">;</span>
        <span style="color: #0600FF;">private</span> ITextBuffer _surfaceBuffer<span style="color: #008000;">;</span>
        <span style="color: #0600FF;">private</span> IQuickInfoSession _session<span style="color: #008000;">;</span>
&nbsp;
        <span style="color: #0600FF;">public</span> TagQuickInfoController<span style="color: #000000;">&#40;</span>IQuickInfoBroker quickInfoBroker, ITextView textView, ITagAggregator<span style="color: #008000;">&lt;</span>T<span style="color: #008000;">&gt;</span> tagAggregator<span style="color: #000000;">&#41;</span>
        <span style="color: #000000;">&#123;</span>
            <span style="color: #0600FF;">this</span>._quickInfoBroker <span style="color: #008000;">=</span> quickInfoBroker<span style="color: #008000;">;</span>
            <span style="color: #0600FF;">this</span>._textView <span style="color: #008000;">=</span> textView<span style="color: #008000;">;</span>
            <span style="color: #0600FF;">this</span>._tagAggregator <span style="color: #008000;">=</span> tagAggregator<span style="color: #008000;">;</span>
&nbsp;
            <span style="color: #0600FF;">this</span>._surfaceBuffer <span style="color: #008000;">=</span> textView.<span style="color: #0000FF;">TextViewModel</span>.<span style="color: #0000FF;">DataBuffer</span><span style="color: #008000;">;</span>
            <span style="color: #0600FF;">this</span>._surfaceBuffer.<span style="color: #0000FF;">Changed</span> <span style="color: #008000;">+=</span> OnSurfaceBuffer_Changed<span style="color: #008000;">;</span>
            <span style="color: #0600FF;">this</span>._textView.<span style="color: #0000FF;">MouseHover</span> <span style="color: #008000;">+=</span> OnTextView_MouseHover<span style="color: #008000;">;</span>
            <span style="color: #0600FF;">this</span>._textView.<span style="color: #0000FF;">Caret</span>.<span style="color: #0000FF;">PositionChanged</span> <span style="color: #008000;">+=</span> OnCaret_PositionChanged<span style="color: #008000;">;</span>
        <span style="color: #000000;">&#125;</span>
&nbsp;
        <span style="color: #0600FF;">public</span> <span style="color: #0600FF;">void</span> ConnectSubjectBuffer<span style="color: #000000;">&#40;</span>ITextBuffer subjectBuffer<span style="color: #000000;">&#41;</span>
        <span style="color: #000000;">&#123;</span>
        <span style="color: #000000;">&#125;</span>
&nbsp;
        <span style="color: #0600FF;">public</span> <span style="color: #0600FF;">void</span> Detach<span style="color: #000000;">&#40;</span>ITextView textView<span style="color: #000000;">&#41;</span>
        <span style="color: #000000;">&#123;</span>
            <span style="color: #0600FF;">this</span>._surfaceBuffer.<span style="color: #0000FF;">Changed</span> <span style="color: #008000;">-=</span> OnSurfaceBuffer_Changed<span style="color: #008000;">;</span>
            <span style="color: #0600FF;">this</span>._textView.<span style="color: #0000FF;">MouseHover</span> <span style="color: #008000;">-=</span> OnTextView_MouseHover<span style="color: #008000;">;</span>
            <span style="color: #0600FF;">this</span>._textView.<span style="color: #0000FF;">Caret</span>.<span style="color: #0000FF;">PositionChanged</span> <span style="color: #008000;">-=</span> OnCaret_PositionChanged<span style="color: #008000;">;</span>
            <span style="color: #0600FF;">if</span> <span style="color: #000000;">&#40;</span><span style="color: #0600FF;">this</span>._tagAggregator <span style="color: #008000;">!=</span> <span style="color: #0600FF;">null</span><span style="color: #000000;">&#41;</span>
            <span style="color: #000000;">&#123;</span>
                <span style="color: #0600FF;">this</span>._tagAggregator.<span style="color: #0000FF;">Dispose</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
                <span style="color: #0600FF;">this</span>._tagAggregator <span style="color: #008000;">=</span> null<span style="color: #008000;">;</span>
            <span style="color: #000000;">&#125;</span>
        <span style="color: #000000;">&#125;</span>
&nbsp;
        <span style="color: #0600FF;">public</span> <span style="color: #0600FF;">void</span> DisconnectSubjectBuffer<span style="color: #000000;">&#40;</span>ITextBuffer subjectBuffer<span style="color: #000000;">&#41;</span>
        <span style="color: #000000;">&#123;</span>
        <span style="color: #000000;">&#125;</span>
&nbsp;
        <span style="color: #0600FF;">internal</span> <span style="color: #0600FF;">void</span> DismissSession<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span>
        <span style="color: #000000;">&#123;</span>
            <span style="color: #0600FF;">if</span> <span style="color: #000000;">&#40;</span><span style="color: #000000;">&#40;</span><span style="color: #0600FF;">this</span>._session <span style="color: #008000;">!=</span> <span style="color: #0600FF;">null</span><span style="color: #000000;">&#41;</span> <span style="color: #008000;">&amp;&amp;</span> <span style="color: #008000;">!</span><span style="color: #0600FF;">this</span>._session.<span style="color: #0000FF;">IsDismissed</span><span style="color: #000000;">&#41;</span>
            <span style="color: #000000;">&#123;</span>
                <span style="color: #0600FF;">this</span>._session.<span style="color: #0000FF;">Dismiss</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
                <span style="color: #0600FF;">this</span>._session <span style="color: #008000;">=</span> null<span style="color: #008000;">;</span>
            <span style="color: #000000;">&#125;</span>
        <span style="color: #000000;">&#125;</span>
&nbsp;
        <span style="color: #0600FF;">private</span> <span style="color: #FF0000;">bool</span> EnsureSessionStillValid<span style="color: #000000;">&#40;</span>SnapshotPoint point<span style="color: #000000;">&#41;</span>
        <span style="color: #000000;">&#123;</span>
            <span style="color: #0600FF;">if</span> <span style="color: #000000;">&#40;</span><span style="color: #0600FF;">this</span>._session <span style="color: #008000;">!=</span> <span style="color: #0600FF;">null</span><span style="color: #000000;">&#41;</span>
            <span style="color: #000000;">&#123;</span>
                <span style="color: #0600FF;">if</span> <span style="color: #000000;">&#40;</span><span style="color: #0600FF;">this</span>._session.<span style="color: #0000FF;">IsDismissed</span><span style="color: #000000;">&#41;</span>
                <span style="color: #000000;">&#123;</span>
                    <span style="color: #0600FF;">this</span>._session <span style="color: #008000;">=</span> null<span style="color: #008000;">;</span>
                    <span style="color: #0600FF;">return</span> false<span style="color: #008000;">;</span>
                <span style="color: #000000;">&#125;</span>
                <span style="color: #0600FF;">if</span> <span style="color: #000000;">&#40;</span><span style="color: #000000;">&#40;</span><span style="color: #0600FF;">this</span>._session.<span style="color: #0000FF;">ApplicableToSpan</span>.<span style="color: #0000FF;">TextBuffer</span> <span style="color: #008000;">==</span> point.<span style="color: #0000FF;">Snapshot</span>.<span style="color: #0000FF;">TextBuffer</span><span style="color: #000000;">&#41;</span> <span style="color: #008000;">&amp;&amp;</span> <span style="color: #0600FF;">this</span>._session.<span style="color: #0000FF;">ApplicableToSpan</span>.<span style="color: #0000FF;">GetSpan</span><span style="color: #000000;">&#40;</span>point.<span style="color: #0000FF;">Snapshot</span><span style="color: #000000;">&#41;</span>.<span style="color: #0000FF;">IntersectsWith</span><span style="color: #000000;">&#40;</span><span style="color: #008000;">new</span> Span<span style="color: #000000;">&#40;</span>point.<span style="color: #0000FF;">Position</span>, <span style="color: #FF0000;">0</span><span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span>
                <span style="color: #000000;">&#123;</span>
                    <span style="color: #0600FF;">return</span> true<span style="color: #008000;">;</span>
                <span style="color: #000000;">&#125;</span>
                <span style="color: #0600FF;">this</span>._session.<span style="color: #0000FF;">Dismiss</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
                <span style="color: #0600FF;">this</span>._session <span style="color: #008000;">=</span> null<span style="color: #008000;">;</span>
            <span style="color: #000000;">&#125;</span>
            <span style="color: #0600FF;">return</span> false<span style="color: #008000;">;</span>
        <span style="color: #000000;">&#125;</span>
&nbsp;
        <span style="color: #0600FF;">private</span> <span style="color: #FF0000;">bool</span> TryExtractQuickInfoFromMarkers<span style="color: #000000;">&#40;</span><span style="color: #FF0000;">int</span> position<span style="color: #000000;">&#41;</span>
        <span style="color: #000000;">&#123;</span>
            IMappingTagSpan<span style="color: #008000;">&lt;</span>T<span style="color: #008000;">&gt;</span> mappingTagSpan <span style="color: #008000;">=</span> null<span style="color: #008000;">;</span>
&nbsp;
            <span style="color: #0600FF;">foreach</span> <span style="color: #000000;">&#40;</span>IMappingTagSpan<span style="color: #008000;">&lt;</span>T<span style="color: #008000;">&gt;</span> span <span style="color: #0600FF;">in</span> <span style="color: #0600FF;">this</span>._tagAggregator.<span style="color: #0000FF;">GetTags</span><span style="color: #000000;">&#40;</span><span style="color: #008000;">new</span> SnapshotSpan<span style="color: #000000;">&#40;</span><span style="color: #0600FF;">this</span>._textView.<span style="color: #0000FF;">TextSnapshot</span>, position, <span style="color: #FF0000;">1</span><span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span>
            <span style="color: #000000;">&#123;</span>
                <span style="color: #0600FF;">if</span> <span style="color: #000000;">&#40;</span>span.<span style="color: #0000FF;">Tag</span> <span style="color: #008000;">!=</span> <span style="color: #0600FF;">null</span><span style="color: #000000;">&#41;</span>
                    mappingTagSpan <span style="color: #008000;">=</span> span<span style="color: #008000;">;</span>
            <span style="color: #000000;">&#125;</span>
&nbsp;
            <span style="color: #0600FF;">if</span> <span style="color: #000000;">&#40;</span>mappingTagSpan <span style="color: #008000;">!=</span> <span style="color: #0600FF;">null</span><span style="color: #000000;">&#41;</span>
            <span style="color: #000000;">&#123;</span>
                NormalizedSnapshotSpanCollection spans <span style="color: #008000;">=</span> mappingTagSpan.<span style="color: #0000FF;">Span</span>.<span style="color: #0000FF;">GetSpans</span><span style="color: #000000;">&#40;</span><span style="color: #0600FF;">this</span>._textView.<span style="color: #0000FF;">TextBuffer</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
                <span style="color: #0600FF;">if</span> <span style="color: #000000;">&#40;</span>spans.<span style="color: #0000FF;">Count</span> <span style="color: #008000;">&gt;</span> <span style="color: #FF0000;">0</span><span style="color: #000000;">&#41;</span>
                <span style="color: #000000;">&#123;</span>
                    <span style="color: #0600FF;">this</span>.<span style="color: #0000FF;">DismissSession</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
                    SnapshotSpan span <span style="color: #008000;">=</span> spans<span style="color: #000000;">&#91;</span><span style="color: #FF0000;">0</span><span style="color: #000000;">&#93;</span><span style="color: #008000;">;</span>
                    ITrackingPoint triggerPoint <span style="color: #008000;">=</span> span.<span style="color: #0000FF;">Snapshot</span>.<span style="color: #0000FF;">CreateTrackingPoint</span><span style="color: #000000;">&#40;</span>span.<span style="color: #0000FF;">Start</span>.<span style="color: #0000FF;">Position</span>, PointTrackingMode.<span style="color: #0000FF;">Positive</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
                    <span style="color: #0600FF;">this</span>._session <span style="color: #008000;">=</span> <span style="color: #0600FF;">this</span>._quickInfoBroker.<span style="color: #0000FF;">CreateQuickInfoSession</span><span style="color: #000000;">&#40;</span><span style="color: #0600FF;">this</span>._textView, triggerPoint, <span style="color: #0600FF;">true</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
                    <span style="color: #0600FF;">this</span>._session.<span style="color: #0000FF;">Start</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
                    <span style="color: #0600FF;">return</span> true<span style="color: #008000;">;</span>
                <span style="color: #000000;">&#125;</span>
            <span style="color: #000000;">&#125;</span>
&nbsp;
            <span style="color: #0600FF;">return</span> false<span style="color: #008000;">;</span>
        <span style="color: #000000;">&#125;</span>
&nbsp;
        <span style="color: #0600FF;">private</span> <span style="color: #0600FF;">void</span> OnSurfaceBuffer_Changed<span style="color: #000000;">&#40;</span><span style="color: #FF0000;">object</span> sender, TextContentChangedEventArgs e<span style="color: #000000;">&#41;</span>
        <span style="color: #000000;">&#123;</span>
            <span style="color: #0600FF;">this</span>.<span style="color: #0000FF;">DismissSession</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
        <span style="color: #000000;">&#125;</span>
&nbsp;
        <span style="color: #0600FF;">private</span> <span style="color: #0600FF;">void</span> OnTextView_MouseHover<span style="color: #000000;">&#40;</span><span style="color: #FF0000;">object</span> sender, MouseHoverEventArgs e<span style="color: #000000;">&#41;</span>
        <span style="color: #000000;">&#123;</span>
            SnapshotPoint<span style="color: #008000;">?</span> nullable <span style="color: #008000;">=</span> e.<span style="color: #0000FF;">TextPosition</span>.<span style="color: #0000FF;">GetPoint</span><span style="color: #000000;">&#40;</span><span style="color: #0600FF;">this</span>._surfaceBuffer, PositionAffinity.<span style="color: #0000FF;">Successor</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
            <span style="color: #0600FF;">if</span> <span style="color: #000000;">&#40;</span><span style="color: #008000;">!</span>nullable.<span style="color: #0000FF;">HasValue</span><span style="color: #000000;">&#41;</span>
                return<span style="color: #008000;">;</span>
&nbsp;
            SnapshotPoint point <span style="color: #008000;">=</span> nullable.<span style="color: #0000FF;">Value</span><span style="color: #008000;">;</span>
            <span style="color: #0600FF;">if</span> <span style="color: #000000;">&#40;</span><span style="color: #0600FF;">this</span>.<span style="color: #0000FF;">EnsureSessionStillValid</span><span style="color: #000000;">&#40;</span>point<span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span>
                return<span style="color: #008000;">;</span>
&nbsp;
            <span style="color: #0600FF;">if</span> <span style="color: #000000;">&#40;</span><span style="color: #0600FF;">this</span>._tagAggregator <span style="color: #008000;">!=</span> <span style="color: #0600FF;">null</span><span style="color: #000000;">&#41;</span>
            <span style="color: #000000;">&#123;</span>
                <span style="color: #0600FF;">this</span>.<span style="color: #0000FF;">TryExtractQuickInfoFromMarkers</span><span style="color: #000000;">&#40;</span>e.<span style="color: #0000FF;">Position</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
            <span style="color: #000000;">&#125;</span>
        <span style="color: #000000;">&#125;</span>
&nbsp;
        <span style="color: #0600FF;">private</span> <span style="color: #0600FF;">void</span> OnCaret_PositionChanged<span style="color: #000000;">&#40;</span><span style="color: #FF0000;">object</span> sender, CaretPositionChangedEventArgs e<span style="color: #000000;">&#41;</span>
        <span style="color: #000000;">&#123;</span>
            <span style="color: #0600FF;">this</span>.<span style="color: #0000FF;">DismissSession</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
        <span style="color: #000000;">&#125;</span>
    <span style="color: #000000;">&#125;</span>
<span style="color: #000000;">&#125;</span></pre></td></tr></table></div>

]]></content:encoded>
			<wfw:commentRss>http://blog.280z28.org/archives/2009/11/61/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Visual Studio language services: Improved brace matching hooks</title>
		<link>http://blog.280z28.org/archives/2009/03/27/</link>
		<comments>http://blog.280z28.org/archives/2009/03/27/#comments</comments>
		<pubDate>Wed, 25 Mar 2009 23:29:52 +0000</pubDate>
		<dc:creator>280Z28</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Tutorials]]></category>

		<guid isPermaLink="false">http://blog.280z28.org/archives/2009/03/27/</guid>
		<description><![CDATA[By default, brace matching is performed in response to the left and right arrow keys. It should be done in response to several additional commands, as shown below.


Movement by clicking the mouse is handled in your override of ViewFilter.HandlePreExec:




1
2
3
4
5
6
7
8
9
10
public override bool HandlePreExec&#40; ref Guid guidCmdGroup, uint nCmdId, uint nCmdexecopt, IntPtr pvaIn, IntPtr pvaOut &#41; 
&#123; [...]]]></description>
			<content:encoded><![CDATA[<p>By default, brace matching is performed in response to the left and right arrow keys. It <em>should</em> be done in response to several additional commands, as shown below.</p>

<p><span id="more-27"></span>
Movement by clicking the mouse is handled in your override of <tt>ViewFilter.HandlePreExec</tt>:</p>

<div style="overflow:auto">


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
</pre></td><td class="code"><pre class="csharp" style="font-family:monospace;"><span style="color: #0600FF;">public</span> <span style="color: #0600FF;">override</span> <span style="color: #FF0000;">bool</span> HandlePreExec<span style="color: #000000;">&#40;</span> <span style="color: #0600FF;">ref</span> Guid guidCmdGroup, <span style="color: #FF0000;">uint</span> nCmdId, <span style="color: #FF0000;">uint</span> nCmdexecopt, IntPtr pvaIn, IntPtr pvaOut <span style="color: #000000;">&#41;</span> 
<span style="color: #000000;">&#123;</span> 
    <span style="color: #0600FF;">if</span> <span style="color: #000000;">&#40;</span> guidCmdGroup <span style="color: #008000;">==</span> VSConstants.<span style="color: #0000FF;">VSStd2K</span> <span style="color: #000000;">&#41;</span> 
    <span style="color: #000000;">&#123;</span>
        <span style="color: #0600FF;">if</span> <span style="color: #000000;">&#40;</span> <span style="color: #000000;">&#40;</span>VsCommands2K<span style="color: #000000;">&#41;</span>cmd <span style="color: #008000;">==</span> VsCommands2K.<span style="color: #0000FF;">ECMD_LEFTCLICK</span> <span style="color: #000000;">&#41;</span>
            <span style="color: #0600FF;">base</span>.<span style="color: #0000FF;">Source</span>.<span style="color: #0000FF;">OnCommand</span><span style="color: #000000;">&#40;</span> <span style="color: #0600FF;">base</span>.<span style="color: #0000FF;">TextView</span>, <span style="color: #000000;">&#40;</span>VsCommands2K<span style="color: #000000;">&#41;</span>cmd, <span style="color: #666666;">'<span style="color: #008080; font-weight: bold;">\0</span>'</span> <span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
    <span style="color: #000000;">&#125;</span>
&nbsp;
    <span style="color: #0600FF;">return</span> <span style="color: #0600FF;">base</span>.<span style="color: #0000FF;">HandlePreExec</span><span style="color: #000000;">&#40;</span> <span style="color: #0600FF;">ref</span> guidCmdGroup, nCmdId, nCmdexecopt, pvaIn, pvaOut <span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
<span style="color: #000000;">&#125;</span></pre></td></tr></table></div>


</div>

<p>Movement by keystrokes is handled in your override of <tt>ViewFilter.HandlePostExec</tt>:</p>

<div style="overflow:auto">


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
</pre></td><td class="code"><pre class="csharp" style="font-family:monospace;"><span style="color: #0600FF;">public</span> <span style="color: #0600FF;">override</span> <span style="color: #0600FF;">void</span> HandlePostExec<span style="color: #000000;">&#40;</span> <span style="color: #0600FF;">ref</span> Guid guidCmdGroup, <span style="color: #FF0000;">uint</span> nCmdId, <span style="color: #FF0000;">uint</span> nCmdexecopt, IntPtr pvaIn, IntPtr pvaOut, <span style="color: #FF0000;">bool</span> bufferWasChanged <span style="color: #000000;">&#41;</span>
<span style="color: #000000;">&#123;</span>
    <span style="color: #0600FF;">if</span> <span style="color: #000000;">&#40;</span> guidCmdGroup <span style="color: #008000;">==</span> VSConstants.<span style="color: #0000FF;">VSStd2K</span> <span style="color: #000000;">&#41;</span>
    <span style="color: #000000;">&#123;</span>
        <span style="color: #0600FF;">switch</span> <span style="color: #000000;">&#40;</span> <span style="color: #000000;">&#40;</span>VsCommands2K<span style="color: #000000;">&#41;</span>nCmdId <span style="color: #000000;">&#41;</span>
        <span style="color: #000000;">&#123;</span>
        <span style="color: #0600FF;">case</span> VsCommands2K.<span style="color: #0000FF;">LEFT_EXT_COL</span><span style="color: #008000;">:</span>
        <span style="color: #0600FF;">case</span> VsCommands2K.<span style="color: #0000FF;">RIGHT_EXT_COL</span><span style="color: #008000;">:</span>
        <span style="color: #0600FF;">case</span> VsCommands2K.<span style="color: #0000FF;">UP</span><span style="color: #008000;">:</span>
        <span style="color: #0600FF;">case</span> VsCommands2K.<span style="color: #0000FF;">UP_EXT</span><span style="color: #008000;">:</span>
        <span style="color: #0600FF;">case</span> VsCommands2K.<span style="color: #0000FF;">UP_EXT_COL</span><span style="color: #008000;">:</span>
        <span style="color: #0600FF;">case</span> VsCommands2K.<span style="color: #0000FF;">DOWN</span><span style="color: #008000;">:</span>
        <span style="color: #0600FF;">case</span> VsCommands2K.<span style="color: #0000FF;">DOWN_EXT</span><span style="color: #008000;">:</span>
        <span style="color: #0600FF;">case</span> VsCommands2K.<span style="color: #0000FF;">DOWN_EXT_COL</span><span style="color: #008000;">:</span>
        <span style="color: #0600FF;">case</span> VsCommands2K.<span style="color: #0000FF;">HOME</span><span style="color: #008000;">:</span>
        <span style="color: #0600FF;">case</span> VsCommands2K.<span style="color: #0000FF;">HOME_EXT</span><span style="color: #008000;">:</span>
        <span style="color: #0600FF;">case</span> VsCommands2K.<span style="color: #0000FF;">BOL</span><span style="color: #008000;">:</span>
        <span style="color: #0600FF;">case</span> VsCommands2K.<span style="color: #0000FF;">BOL_EXT</span><span style="color: #008000;">:</span>
        <span style="color: #0600FF;">case</span> VsCommands2K.<span style="color: #0000FF;">BOL_EXT_COL</span><span style="color: #008000;">:</span>
        <span style="color: #0600FF;">case</span> VsCommands2K.<span style="color: #0000FF;">FIRSTCHAR</span><span style="color: #008000;">:</span>
        <span style="color: #0600FF;">case</span> VsCommands2K.<span style="color: #0000FF;">FIRSTCHAR_EXT</span><span style="color: #008000;">:</span>
        <span style="color: #0600FF;">case</span> VsCommands2K.<span style="color: #0000FF;">EOL</span><span style="color: #008000;">:</span>
        <span style="color: #0600FF;">case</span> VsCommands2K.<span style="color: #0000FF;">EOL_EXT</span><span style="color: #008000;">:</span>
        <span style="color: #0600FF;">case</span> VsCommands2K.<span style="color: #0000FF;">EOL_EXT_COL</span><span style="color: #008000;">:</span>
        <span style="color: #0600FF;">case</span> VsCommands2K.<span style="color: #0000FF;">LASTCHAR</span><span style="color: #008000;">:</span>
        <span style="color: #0600FF;">case</span> VsCommands2K.<span style="color: #0000FF;">LASTCHAR_EXT</span><span style="color: #008000;">:</span>
        <span style="color: #0600FF;">case</span> VsCommands2K.<span style="color: #0000FF;">PAGEUP</span><span style="color: #008000;">:</span>
        <span style="color: #0600FF;">case</span> VsCommands2K.<span style="color: #0000FF;">PAGEUP_EXT</span><span style="color: #008000;">:</span>
        <span style="color: #0600FF;">case</span> VsCommands2K.<span style="color: #0000FF;">PAGEDN</span><span style="color: #008000;">:</span>
        <span style="color: #0600FF;">case</span> VsCommands2K.<span style="color: #0000FF;">PAGEDN_EXT</span><span style="color: #008000;">:</span>
        <span style="color: #0600FF;">case</span> VsCommands2K.<span style="color: #0000FF;">WORDNEXT</span><span style="color: #008000;">:</span>
        <span style="color: #0600FF;">case</span> VsCommands2K.<span style="color: #0000FF;">WORDNEXT_EXT</span><span style="color: #008000;">:</span>
        <span style="color: #0600FF;">case</span> VsCommands2K.<span style="color: #0000FF;">WORDNEXT_EXT_COL</span><span style="color: #008000;">:</span>
        <span style="color: #0600FF;">case</span> VsCommands2K.<span style="color: #0000FF;">WORDPREV</span><span style="color: #008000;">:</span>
        <span style="color: #0600FF;">case</span> VsCommands2K.<span style="color: #0000FF;">WORDPREV_EXT</span><span style="color: #008000;">:</span>
        <span style="color: #0600FF;">case</span> VsCommands2K.<span style="color: #0000FF;">WORDPREV_EXT_COL</span><span style="color: #008000;">:</span>
        <span style="color: #0600FF;">case</span> VsCommands2K.<span style="color: #0000FF;">BOTTOMLINE</span><span style="color: #008000;">:</span>
        <span style="color: #0600FF;">case</span> VsCommands2K.<span style="color: #0000FF;">BOTTOMLINE_EXT</span><span style="color: #008000;">:</span>
        <span style="color: #0600FF;">case</span> VsCommands2K.<span style="color: #0000FF;">TOPLINE</span><span style="color: #008000;">:</span>
        <span style="color: #0600FF;">case</span> VsCommands2K.<span style="color: #0000FF;">TOPLINE_EXT</span><span style="color: #008000;">:</span>
            <span style="color: #008080; font-style: italic;">// check general trigger characters for intellisense</span>
            <span style="color: #0600FF;">base</span>.<span style="color: #0000FF;">Source</span>.<span style="color: #0000FF;">OnCommand</span><span style="color: #000000;">&#40;</span> <span style="color: #0600FF;">base</span>.<span style="color: #0000FF;">TextView</span>, <span style="color: #000000;">&#40;</span>VsCommands2K<span style="color: #000000;">&#41;</span>nCmdId, <span style="color: #666666;">'<span style="color: #008080; font-weight: bold;">\0</span>'</span> <span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
            break<span style="color: #008000;">;</span>
        <span style="color: #000000;">&#125;</span>
    <span style="color: #000000;">&#125;</span>
&nbsp;
    <span style="color: #0600FF;">base</span>.<span style="color: #0000FF;">HandlePostExec</span><span style="color: #000000;">&#40;</span> <span style="color: #0600FF;">ref</span> guidCmdGroup, nCmdId, nCmdexecopt, pvaIn, pvaOut, bufferWasChanged <span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
<span style="color: #000000;">&#125;</span></pre></td></tr></table></div>


</div>
]]></content:encoded>
			<wfw:commentRss>http://blog.280z28.org/archives/2009/03/27/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>ManagedMyC: Type and member dropdown bars</title>
		<link>http://blog.280z28.org/archives/2008/10/24/</link>
		<comments>http://blog.280z28.org/archives/2008/10/24/#comments</comments>
		<pubDate>Sun, 19 Oct 2008 22:34:10 +0000</pubDate>
		<dc:creator>280Z28</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Tutorials]]></category>

		<guid isPermaLink="false">http://blog.280z28.org/archives/2008/10/24/</guid>
		<description><![CDATA[This is part 4 of [many?] posts about creating an ANTLR-based language service for Visual Studio.

Now that we have an AST with information about the top-level members in our source files, we can use the tree parser to gather this information and make it available for the dropdown bars. For now, the MyC language doesn&#8217;t [...]]]></description>
			<content:encoded><![CDATA[<p>This is part 4 of [many?] posts about creating an ANTLR-based language service for Visual Studio.</p>

<p>Now that we have an AST with information about the top-level members in our source files, we can use the tree parser to gather this information and make it available for the dropdown bars. For now, the MyC language doesn&#8217;t support user types like structs, enums, or classes, so we&#8217;re stuck with listing the members in the file.</p>

<p><span id="more-24"></span></p>

<h2>Gathering type &#038; member information</h2>

<p>The type &amp; member dropdown bars use instances of the <tt>DropDownMember</tt> class to present their information. For now, we&#8217;ll use this class directly in the gathering stage (in the tree parser). <b style="color:red">The Visual Studio 2008 SDK version 1.0 has a major bug in the DropDownMember class, and using it <em>will</em> crash Visual Studio. You need to use the version 1.1 SDK instead.</b></p>

<p>Since the language service (<tt>MyCLanguageService</tt>) is unaware that the parser uses a separate tree parser to process the AST, add the following properties to the <tt>MyCParser</tt> class (in your helper file for it). We&#8217;ll use them to expose the results from the walker.</p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
</pre></td><td class="code"><pre class="csharp" style="font-family:monospace;"><span style="color: #0600FF;">public</span> IList<span style="color: #008000;">&lt;</span>DropDownMember<span style="color: #008000;">&gt;</span> Types
<span style="color: #000000;">&#123;</span>
    get
    <span style="color: #000000;">&#123;</span>
        <span style="color: #0600FF;">throw</span> <span style="color: #008000;">new</span> NotImplementedException<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
    <span style="color: #000000;">&#125;</span>
<span style="color: #000000;">&#125;</span>
&nbsp;
<span style="color: #0600FF;">public</span> IList<span style="color: #008000;">&lt;</span>DropDownMember<span style="color: #008000;">&gt;</span> Members
<span style="color: #000000;">&#123;</span>
    get
    <span style="color: #000000;">&#123;</span>
        <span style="color: #0600FF;">throw</span> <span style="color: #008000;">new</span> NotImplementedException<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
    <span style="color: #000000;">&#125;</span>
<span style="color: #000000;">&#125;</span>
&nbsp;
<span style="color: #0600FF;">public</span> MyCWalker Walker
<span style="color: #000000;">&#123;</span>
    get<span style="color: #008000;">;</span>
    <span style="color: #0600FF;">private</span> set<span style="color: #008000;">;</span>
<span style="color: #000000;">&#125;</span></pre></td></tr></table></div>


<p>Since the Types and Members are relevant to a particular source file, we&#8217;ll hold these in the <tt>MyCSource</tt> class, like the braces are. Add the following properties to the <tt>MyCSource</tt> class:</p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
</pre></td><td class="code"><pre class="csharp" style="font-family:monospace;"><span style="color: #0600FF;">public</span> IList<span style="color: #008000;">&lt;</span>DropDownMember<span style="color: #008000;">&gt;</span> Types
<span style="color: #000000;">&#123;</span>
    get<span style="color: #008000;">;</span>
    set<span style="color: #008000;">;</span>
<span style="color: #000000;">&#125;</span>
<span style="color: #0600FF;">public</span> IList<span style="color: #008000;">&lt;</span>DropDownMember<span style="color: #008000;">&gt;</span> Members
<span style="color: #000000;">&#123;</span>
    get<span style="color: #008000;">;</span>
    set<span style="color: #008000;">;</span>
<span style="color: #000000;">&#125;</span></pre></td></tr></table></div>


<p>The language service moves the types &amp; members to the <tt>MyCSource</tt> object during the <tt>ParseSource</tt> request. Find the lines in the <tt>MyCLanguageService.ParseSource</tt> function where the braces are stored, and store the types &amp; members at the same time:</p>

<pre>// store the parse results
source.ParseResult = null;
source.Braces = parser.Braces;
<span style="background-color:yellow">source.Types = parser.Types;
source.Members = parser.Members;</span>
</pre>

<p>Next, we need to use the tree parser to create a DropDownMember in the Members property for each variable declaration and function definition. To help out, we create the <tt>AddType</tt> and <tt>AddMember</tt> functions in <tt>MyCWalkerHelper.cs</tt> (similar to the <tt>Match</tt> and <tt>Region</tt> functions in <tt>MyCParserHelper.cs</tt>). The helper file becomes:</p>

<div style="overflow:auto">


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
</pre></td><td class="code"><pre class="csharp" style="font-family:monospace;"><span style="color: #0600FF;">using</span> <span style="color: #008080;">System.Collections.Generic</span><span style="color: #008000;">;</span>
<span style="color: #0600FF;">using</span> <span style="color: #008080;">Antlr.Runtime</span><span style="color: #008000;">;</span>
<span style="color: #0600FF;">using</span> <span style="color: #008080;">Antlr.Runtime.Tree</span><span style="color: #008000;">;</span>
<span style="color: #0600FF;">using</span> <span style="color: #008080;">Microsoft.VisualStudio.Package</span><span style="color: #008000;">;</span>
<span style="color: #0600FF;">using</span> <span style="color: #008080;">Microsoft.VisualStudio.TextManager.Interop</span><span style="color: #008000;">;</span>
&nbsp;
<span style="color: #0600FF;">namespace</span> ManagedMyC
<span style="color: #000000;">&#123;</span>
    <span style="color: #0600FF;">partial</span> <span style="color: #FF0000;">class</span> MyCWalker
    <span style="color: #000000;">&#123;</span>
        <span style="color: #0600FF;">public</span> MyCWalker<span style="color: #000000;">&#40;</span> MyCParser parser, CommonTree tree <span style="color: #000000;">&#41;</span>
            <span style="color: #008000;">:</span> <span style="color: #0600FF;">this</span><span style="color: #000000;">&#40;</span> <span style="color: #008000;">new</span> CommonTreeNodeStream<span style="color: #000000;">&#40;</span> tree <span style="color: #000000;">&#41;</span> <span style="color: #000000;">&#41;</span>
        <span style="color: #000000;">&#123;</span>
            <span style="color: #000000;">&#40;</span> <span style="color: #000000;">&#40;</span>CommonTreeNodeStream<span style="color: #000000;">&#41;</span>input <span style="color: #000000;">&#41;</span>.<span style="color: #0000FF;">TokenStream</span> <span style="color: #008000;">=</span> parser.<span style="color: #0000FF;">TokenStream</span><span style="color: #008000;">;</span>
        <span style="color: #000000;">&#125;</span>
&nbsp;
        <span style="color: #0600FF;">public</span> List<span style="color: #008000;">&lt;</span>DropDownMember<span style="color: #008000;">&gt;</span> UnsortedTypes
        <span style="color: #000000;">&#123;</span>
            get<span style="color: #008000;">;</span>
            <span style="color: #0600FF;">private</span> set<span style="color: #008000;">;</span>
        <span style="color: #000000;">&#125;</span>
        <span style="color: #0600FF;">public</span> List<span style="color: #008000;">&lt;</span>DropDownMember<span style="color: #008000;">&gt;</span> UnsortedMembers
        <span style="color: #000000;">&#123;</span>
            get<span style="color: #008000;">;</span>
            <span style="color: #0600FF;">private</span> set<span style="color: #008000;">;</span>
        <span style="color: #000000;">&#125;</span>
&nbsp;
        <span style="color: #0600FF;">public</span> <span style="color: #0600FF;">void</span> WalkAST<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span>
        <span style="color: #000000;">&#123;</span>
            UnsortedTypes <span style="color: #008000;">=</span> <span style="color: #008000;">new</span> List<span style="color: #008000;">&lt;</span>DropDownMember<span style="color: #008000;">&gt;</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
            UnsortedMembers <span style="color: #008000;">=</span> <span style="color: #008000;">new</span> List<span style="color: #008000;">&lt;</span>DropDownMember<span style="color: #008000;">&gt;</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
            program<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
        <span style="color: #000000;">&#125;</span>
&nbsp;
        <span style="color: #0600FF;">void</span> AddType<span style="color: #000000;">&#40;</span> <span style="color: #FF0000;">string</span> name, IToken start, IToken stop, IconImageIndex glyph <span style="color: #000000;">&#41;</span>
        <span style="color: #000000;">&#123;</span>
            <span style="color: #0600FF;">if</span> <span style="color: #000000;">&#40;</span> name <span style="color: #008000;">==</span> <span style="color: #0600FF;">null</span> <span style="color: #008000;">||</span> start <span style="color: #008000;">==</span> <span style="color: #0600FF;">null</span> <span style="color: #008000;">||</span> stop <span style="color: #008000;">==</span> <span style="color: #0600FF;">null</span> <span style="color: #000000;">&#41;</span>
                return<span style="color: #008000;">;</span>
&nbsp;
            DropDownMember type <span style="color: #008000;">=</span> <span style="color: #008000;">new</span> DropDownMember<span style="color: #000000;">&#40;</span>
                name,
                TextSpanHelper.<span style="color: #0000FF;">Merge</span><span style="color: #000000;">&#40;</span> MyCParser.<span style="color: #0000FF;">ToTextSpan</span><span style="color: #000000;">&#40;</span> start <span style="color: #000000;">&#41;</span>, MyCParser.<span style="color: #0000FF;">ToTextSpan</span><span style="color: #000000;">&#40;</span> stop <span style="color: #000000;">&#41;</span> <span style="color: #000000;">&#41;</span>,
                <span style="color: #000000;">&#40;</span><span style="color: #FF0000;">int</span><span style="color: #000000;">&#41;</span>glyph,
                DROPDOWNFONTATTR.<span style="color: #0000FF;">FONTATTR_PLAIN</span> <span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
&nbsp;
            UnsortedTypes.<span style="color: #0000FF;">Add</span><span style="color: #000000;">&#40;</span> type <span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
        <span style="color: #000000;">&#125;</span>
        <span style="color: #0600FF;">void</span> AddMember<span style="color: #000000;">&#40;</span> <span style="color: #FF0000;">string</span> name, IToken start, IToken stop, IconImageIndex glyph <span style="color: #000000;">&#41;</span>
        <span style="color: #000000;">&#123;</span>
            <span style="color: #0600FF;">if</span> <span style="color: #000000;">&#40;</span> name <span style="color: #008000;">==</span> <span style="color: #0600FF;">null</span> <span style="color: #008000;">||</span> start <span style="color: #008000;">==</span> <span style="color: #0600FF;">null</span> <span style="color: #008000;">||</span> stop <span style="color: #008000;">==</span> <span style="color: #0600FF;">null</span> <span style="color: #000000;">&#41;</span>
                return<span style="color: #008000;">;</span>
&nbsp;
            DropDownMember member <span style="color: #008000;">=</span> <span style="color: #008000;">new</span> DropDownMember<span style="color: #000000;">&#40;</span>
                name,
                TextSpanHelper.<span style="color: #0000FF;">Merge</span><span style="color: #000000;">&#40;</span> MyCParser.<span style="color: #0000FF;">ToTextSpan</span><span style="color: #000000;">&#40;</span> start <span style="color: #000000;">&#41;</span>, MyCParser.<span style="color: #0000FF;">ToTextSpan</span><span style="color: #000000;">&#40;</span> stop <span style="color: #000000;">&#41;</span> <span style="color: #000000;">&#41;</span>,
                <span style="color: #000000;">&#40;</span><span style="color: #FF0000;">int</span><span style="color: #000000;">&#41;</span>glyph,
                DROPDOWNFONTATTR.<span style="color: #0000FF;">FONTATTR_PLAIN</span> <span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
&nbsp;
            UnsortedMembers.<span style="color: #0000FF;">Add</span><span style="color: #000000;">&#40;</span> member <span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
        <span style="color: #000000;">&#125;</span>
    <span style="color: #000000;">&#125;</span>
<span style="color: #000000;">&#125;</span></pre></td></tr></table></div>


</div>

<p>We update the tree parser to use these functions:</p>

<div style="border:1px dashed;overflow:auto"><pre>tree grammar MyCWalker;

options
{
    language=CSharp2;
    tokenVocab=MyC;
    ASTLabelType=CommonTree;
}

@namespace { ManagedMyC }

program
    :   declarations
    ;

declarations
    :   declaration*
    ;

declaration
    :   declaration_
    ;

declaration_
    :   ^(  AST_FUNCDEF
            class1? type?
            IDENTIFIER
            p=parameters
            block
<span style="background-color:yellow">          {
                AddMember(
                    string.Format( "{0}({1})", $IDENTIFIER.text, $p.ptext ),
                    $IDENTIFIER.Token,
                    $block.close,
                    IconImageIndex.Method
                    );
            }</span>
        )
    |   simple_declaration
    ;

simple_declarations1
    :   simple_declaration+
    ;

simple_declaration
    :   ^(  AST_DECL class1? type
            <span style="background-color:yellow">(</span>  IDENTIFIER
                <span style="background-color:yellow">{ AddMember($IDENTIFIER.text, $IDENTIFIER.Token, $IDENTIFIER.Token, IconImageIndex.Variable); }</span>
            <span style="background-color:yellow">)</span>+
        )
    ;

parameters <span style="background-color:yellow">returns [string ptext]
@init
{
    System.Collections.Generic.List<string> param_list = new System.Collections.Generic.List</string><string>();
}</string></span>
    :   ^(  AST_PARAMS
            <span style="background-color:yellow">(</span>  parameter
                <span style="background-color:yellow">{ param_list.Add($parameter.text); }</span>
            <span style="background-color:yellow">)</span>*
        )
        <span style="background-color:yellow">{ $ptext = string.Join( ", ", param_list.ToArray() ); }</span>
    ;

parameter
    :   ^(type IDENTIFIER)
    ;

class1
    :   'static'
    |   'auto'
    |   'extern'
    ;

type
    :   'int'
    |   'void'
    ;

block <span style="background-color:yellow">returns [IToken close]</span>
    :   open_block /*block_content1?*/ close_block
        <span style="background-color:yellow">{ $close = $close_block.start.Token; }</span>
    ;

open_block
    :   '{'
    ;

close_block
    :   '}'
    ;</pre></div>

<p>The final step is to implement the Types &amp; Members properties in <tt>MyCParserHelper.cs</tt> to return the information from the walker.</p>

<div style="overflow:auto">


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
</pre></td><td class="code"><pre class="csharp" style="font-family:monospace;"><span style="color: #0600FF;">public</span> IList<span style="color: #008000;">&lt;</span>DropDownMember<span style="color: #008000;">&gt;</span> Types
<span style="color: #000000;">&#123;</span>
    get
    <span style="color: #000000;">&#123;</span>
        <span style="color: #0600FF;">if</span> <span style="color: #000000;">&#40;</span> Walker <span style="color: #008000;">==</span> <span style="color: #0600FF;">null</span> <span style="color: #008000;">||</span> Walker.<span style="color: #0000FF;">UnsortedTypes</span> <span style="color: #008000;">==</span> <span style="color: #0600FF;">null</span> <span style="color: #000000;">&#41;</span>
            <span style="color: #0600FF;">return</span> <span style="color: #008000;">new</span> DropDownMember<span style="color: #000000;">&#91;</span><span style="color: #FF0000;">0</span><span style="color: #000000;">&#93;</span><span style="color: #008000;">;</span>
        <span style="color: #0600FF;">return</span> Walker.<span style="color: #0000FF;">UnsortedTypes</span>.<span style="color: #0000FF;">OrderBy</span><span style="color: #000000;">&#40;</span> type <span style="color: #008000;">=&gt;</span> PositionIndicator<span style="color: #000000;">&#40;</span> type <span style="color: #000000;">&#41;</span> <span style="color: #000000;">&#41;</span>.<span style="color: #0000FF;">ToArray</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
    <span style="color: #000000;">&#125;</span>
<span style="color: #000000;">&#125;</span>
&nbsp;
<span style="color: #0600FF;">public</span> IList<span style="color: #008000;">&lt;</span>DropDownMember<span style="color: #008000;">&gt;</span> Members
<span style="color: #000000;">&#123;</span>
    get
    <span style="color: #000000;">&#123;</span>
        <span style="color: #0600FF;">if</span> <span style="color: #000000;">&#40;</span> Walker <span style="color: #008000;">==</span> <span style="color: #0600FF;">null</span> <span style="color: #008000;">||</span> Walker.<span style="color: #0000FF;">UnsortedMembers</span> <span style="color: #008000;">==</span> <span style="color: #0600FF;">null</span> <span style="color: #000000;">&#41;</span>
            <span style="color: #0600FF;">return</span> <span style="color: #008000;">new</span> DropDownMember<span style="color: #000000;">&#91;</span><span style="color: #FF0000;">0</span><span style="color: #000000;">&#93;</span><span style="color: #008000;">;</span>
        <span style="color: #0600FF;">return</span> Walker.<span style="color: #0000FF;">UnsortedMembers</span>.<span style="color: #0000FF;">OrderBy</span><span style="color: #000000;">&#40;</span> member <span style="color: #008000;">=&gt;</span> PositionIndicator<span style="color: #000000;">&#40;</span> member <span style="color: #000000;">&#41;</span> <span style="color: #000000;">&#41;</span>.<span style="color: #0000FF;">ToArray</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
    <span style="color: #000000;">&#125;</span>
<span style="color: #000000;">&#125;</span>
&nbsp;
<span style="color: #0600FF;">static</span> <span style="color: #FF0000;">int</span> PositionIndicator<span style="color: #000000;">&#40;</span> DropDownMember member <span style="color: #000000;">&#41;</span>
<span style="color: #000000;">&#123;</span>
    <span style="color: #0600FF;">return</span> <span style="color: #000000;">&#40;</span> member.<span style="color: #0000FF;">Span</span>.<span style="color: #0000FF;">iStartLine</span> <span style="color: #008000;">&lt;&lt;</span> <span style="color: #FF0000;">10</span> <span style="color: #000000;">&#41;</span> <span style="color: #008000;">+</span> member.<span style="color: #0000FF;">Span</span>.<span style="color: #0000FF;">iStartIndex</span><span style="color: #008000;">;</span>
<span style="color: #000000;">&#125;</span></pre></td></tr></table></div>


</div>

<h2>Using the type &#038; member information for type &#038; member dropdown bars</h2>

<p>The <tt>TypeAndMemberDropdownBars</tt> class is abstract, so we need to derive our own class from it.</p>

<div style="overflow:auto">


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
</pre></td><td class="code"><pre class="csharp" style="font-family:monospace;"><span style="color: #0600FF;">using</span> <span style="color: #008080;">Microsoft.VisualStudio.Package</span><span style="color: #008000;">;</span>
<span style="color: #0600FF;">using</span> <span style="color: #008080;">Microsoft.VisualStudio.TextManager.Interop</span><span style="color: #008000;">;</span>
&nbsp;
<span style="color: #0600FF;">using</span> <span style="color: #008080;">ArrayList </span><span style="color: #008000;">=</span> <span style="color: #000000;">System.<span style="color: #0000FF;">Collections</span></span>.<span style="color: #0000FF;">ArrayList</span><span style="color: #008000;">;</span>
&nbsp;
<span style="color: #0600FF;">namespace</span> ManagedMyC
<span style="color: #000000;">&#123;</span>
    <span style="color: #0600FF;">public</span> <span style="color: #FF0000;">class</span> MyCTypeAndMemberDropdownBars <span style="color: #008000;">:</span> TypeAndMemberDropdownBars
    <span style="color: #000000;">&#123;</span>
        <span style="color: #0600FF;">public</span> MyCTypeAndMemberDropdownBars<span style="color: #000000;">&#40;</span> MyCLanguageService languageService <span style="color: #000000;">&#41;</span>
            <span style="color: #008000;">:</span> <span style="color: #0600FF;">base</span><span style="color: #000000;">&#40;</span> languageService <span style="color: #000000;">&#41;</span>
        <span style="color: #000000;">&#123;</span>
        <span style="color: #000000;">&#125;</span>
&nbsp;
        <span style="color: #0600FF;">public</span> <span style="color: #0600FF;">override</span> <span style="color: #FF0000;">bool</span> OnSynchronizeDropdowns<span style="color: #000000;">&#40;</span> LanguageService languageService, IVsTextView textView, <span style="color: #FF0000;">int</span> line, <span style="color: #FF0000;">int</span> col, ArrayList dropDownTypes, ArrayList dropDownMembers, <span style="color: #0600FF;">ref</span> <span style="color: #FF0000;">int</span> selectedTypeIndex, <span style="color: #0600FF;">ref</span> <span style="color: #FF0000;">int</span> selectedMemberIndex <span style="color: #000000;">&#41;</span>
        <span style="color: #000000;">&#123;</span>
            <span style="color: #008080; font-style: italic;">// TODO</span>
            <span style="color: #0600FF;">return</span> false<span style="color: #008000;">;</span>
        <span style="color: #000000;">&#125;</span>
    <span style="color: #000000;">&#125;</span>
<span style="color: #000000;">&#125;</span></pre></td></tr></table></div>


</div>

<p>To use this new class, we overload the <tt>CreateDropDownHelper</tt> function in <tt>MyCLanguageService</tt>.</p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
</pre></td><td class="code"><pre class="csharp" style="font-family:monospace;"><span style="color: #0600FF;">public</span> <span style="color: #0600FF;">override</span> TypeAndMemberDropdownBars CreateDropDownHelper<span style="color: #000000;">&#40;</span> IVsTextView forView <span style="color: #000000;">&#41;</span>
<span style="color: #000000;">&#123;</span>
    <span style="color: #0600FF;">return</span> <span style="color: #008000;">new</span> MyCTypeAndMemberDropdownBars<span style="color: #000000;">&#40;</span> <span style="color: #0600FF;">this</span> <span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
<span style="color: #000000;">&#125;</span></pre></td></tr></table></div>


<p>We&#8217;ll also need some helper functions in the <tt>MyCSource</tt> class to filter the available types and members information. This information may seem like overkill at this point, but as I mentioned earlier, my intention with this post is to demonstrate a &#8220;solid implementation of the <tt>TypeAndMemberDropdownBars</tt>&#8220;. This method has proven powerful, flexible, and reliable for several languages so far.</p>

<div style="overflow:auto">


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
</pre></td><td class="code"><pre class="csharp" style="font-family:monospace;"><span style="color: #008080;">#region Type &amp; member dropdowns support</span>
<span style="color: #008080; font-style: italic;">/// &lt;summary&gt;</span>
<span style="color: #008080; font-style: italic;">/// Gets the members of the current Source to show in the Types list of the</span>
<span style="color: #008080; font-style: italic;">/// TypeAndMemberDropdownBars.</span>
<span style="color: #008080; font-style: italic;">/// &lt;/summary&gt;</span>
<span style="color: #008080; font-style: italic;">/// &lt;returns&gt;An enumeration of items to show in the Types dropdown.&lt;/returns&gt;</span>
<span style="color: #0600FF;">public</span> <span style="color: #0600FF;">virtual</span> IEnumerable<span style="color: #008000;">&lt;</span>DropDownMember<span style="color: #008000;">&gt;</span> GetDropDownTypes<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span>
<span style="color: #000000;">&#123;</span>
    <span style="color: #0600FF;">if</span> <span style="color: #000000;">&#40;</span> Types <span style="color: #008000;">==</span> <span style="color: #0600FF;">null</span> <span style="color: #000000;">&#41;</span>
        <span style="color: #0600FF;">return</span> null<span style="color: #008000;">;</span>
&nbsp;
    <span style="color: #0600FF;">return</span> <span style="color: #000000;">&#40;</span> from type <span style="color: #0600FF;">in</span> Types
             orderby type.<span style="color: #0000FF;">Label</span>
             select type <span style="color: #000000;">&#41;</span>
           .<span style="color: #0000FF;">ToArray</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
<span style="color: #000000;">&#125;</span>
<span style="color: #008080; font-style: italic;">/// &lt;summary&gt;</span>
<span style="color: #008080; font-style: italic;">/// Gets the members of the selected type to show in the Members list of the</span>
<span style="color: #008080; font-style: italic;">/// TypeAndMemberDropdownBars.</span>
<span style="color: #008080; font-style: italic;">/// &lt;/summary&gt;</span>
<span style="color: #008080; font-style: italic;">/// &lt;param name=&quot;type&quot;&gt;The item currently selected in the Types dropdown.&lt;/param&gt;</span>
<span style="color: #008080; font-style: italic;">/// &lt;param name=&quot;excludeSpans&quot;&gt;A list of TextSpans that are used to filter the list of members.</span>
<span style="color: #008080; font-style: italic;">/// Typically, these spans are sub-spans of the selected type representing nested types, where</span>
<span style="color: #008080; font-style: italic;">/// members within those spans are actually members of a nested type ant should not be shown.&lt;/param&gt;</span>
<span style="color: #008080; font-style: italic;">/// &lt;returns&gt;An enumeration of items to show in the Members dropdown.&lt;/returns&gt;</span>
<span style="color: #0600FF;">public</span> <span style="color: #0600FF;">virtual</span> IEnumerable<span style="color: #008000;">&lt;</span>DropDownMember<span style="color: #008000;">&gt;</span> GetDropDownMembers<span style="color: #000000;">&#40;</span> DropDownMember type, IEnumerable<span style="color: #008000;">&lt;</span>TextSpan<span style="color: #008000;">&gt;</span> excludeSpans <span style="color: #000000;">&#41;</span>
<span style="color: #000000;">&#123;</span>
    <span style="color: #0600FF;">if</span> <span style="color: #000000;">&#40;</span> Members <span style="color: #008000;">==</span> <span style="color: #0600FF;">null</span> <span style="color: #000000;">&#41;</span>
        <span style="color: #0600FF;">return</span> null<span style="color: #008000;">;</span>
&nbsp;
    var members <span style="color: #008000;">=</span> <span style="color: #000000;">&#40;</span> from member <span style="color: #0600FF;">in</span> Members.<span style="color: #0000FF;">ToArray</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span>
                    where <span style="color: #000000;">&#40;</span>type <span style="color: #008000;">==</span> <span style="color: #0600FF;">null</span><span style="color: #000000;">&#41;</span> <span style="color: #008000;">||</span> TextSpanHelper.<span style="color: #0000FF;">IsEmbedded</span><span style="color: #000000;">&#40;</span> member.<span style="color: #0000FF;">Span</span>, type.<span style="color: #0000FF;">Span</span> <span style="color: #000000;">&#41;</span>
                    where <span style="color: #008000;">!</span>excludeSpans.<span style="color: #0000FF;">Any</span><span style="color: #000000;">&#40;</span> span <span style="color: #008000;">=&gt;</span> TextSpanHelper.<span style="color: #0000FF;">IsEmbedded</span><span style="color: #000000;">&#40;</span> member.<span style="color: #0000FF;">Span</span>, span <span style="color: #000000;">&#41;</span> <span style="color: #000000;">&#41;</span>
                    orderby member.<span style="color: #0000FF;">Label</span>
                    select member <span style="color: #000000;">&#41;</span>
                  .<span style="color: #0000FF;">ToArray</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
&nbsp;
    <span style="color: #0600FF;">return</span> members<span style="color: #008000;">;</span>
<span style="color: #000000;">&#125;</span>
&nbsp;
<span style="color: #008080; font-style: italic;">/// &lt;summary&gt;</span>
<span style="color: #008080; font-style: italic;">/// Gets the default item to show in the Types dropdown of the TypeAndMemberDropdownBars.</span>
<span style="color: #008080; font-style: italic;">/// This function is called when the cursor is not in the span of any type in the list.</span>
<span style="color: #008080; font-style: italic;">/// &lt;/summary&gt;</span>
<span style="color: #008080; font-style: italic;">/// &lt;param name=&quot;types&quot;&gt;The types shown in the Types dropdown.&lt;/param&gt;</span>
<span style="color: #008080; font-style: italic;">/// &lt;returns&gt;The index of the type that should be visible in the Types dropdown.&lt;/returns&gt;</span>
<span style="color: #0600FF;">public</span> <span style="color: #0600FF;">virtual</span> <span style="color: #FF0000;">int</span> GetDefaultType<span style="color: #000000;">&#40;</span> IEnumerable<span style="color: #008000;">&lt;</span>DropDownMember<span style="color: #008000;">&gt;</span> types <span style="color: #000000;">&#41;</span>
<span style="color: #000000;">&#123;</span>
    <span style="color: #0600FF;">return</span> <span style="color: #000000;">&#40;</span> types.<span style="color: #0000FF;">FirstOrDefault</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span> <span style="color: #008000;">==</span> <span style="color: #0600FF;">null</span> <span style="color: #000000;">&#41;</span> <span style="color: #008000;">?</span> <span style="color: #008000;">-</span><span style="color: #FF0000;">1</span> <span style="color: #008000;">:</span> <span style="color: #FF0000;">0</span><span style="color: #008000;">;</span>
<span style="color: #000000;">&#125;</span>
<span style="color: #008080; font-style: italic;">/// &lt;summary&gt;</span>
<span style="color: #008080; font-style: italic;">/// Gets the default item to show in the Members dropdown of the TypeAndMemberDropdownBars.</span>
<span style="color: #008080; font-style: italic;">/// This function is called when the cursor is not inside the span of any members of the</span>
<span style="color: #008080; font-style: italic;">/// selected type.</span>
<span style="color: #008080; font-style: italic;">/// &lt;/summary&gt;</span>
<span style="color: #008080; font-style: italic;">/// &lt;param name=&quot;selectedType&quot;&gt;The item currently selected in the Types dropdown.&lt;/param&gt;</span>
<span style="color: #008080; font-style: italic;">/// &lt;param name=&quot;members&quot;&gt;The members of the selected type shown in the Members dropdown.&lt;/param&gt;</span>
<span style="color: #008080; font-style: italic;">/// &lt;returns&gt;The index of the member that should be visible in the Members dropdown.&lt;/returns&gt;</span>
<span style="color: #0600FF;">public</span> <span style="color: #0600FF;">virtual</span> <span style="color: #FF0000;">int</span> GetDefaultMember<span style="color: #000000;">&#40;</span> DropDownMember selectedType, IEnumerable<span style="color: #008000;">&lt;</span>DropDownMember<span style="color: #008000;">&gt;</span> members <span style="color: #000000;">&#41;</span>
<span style="color: #000000;">&#123;</span>
    <span style="color: #0600FF;">return</span> <span style="color: #000000;">&#40;</span> members.<span style="color: #0000FF;">FirstOrDefault</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span> <span style="color: #008000;">==</span> <span style="color: #0600FF;">null</span> <span style="color: #000000;">&#41;</span> <span style="color: #008000;">?</span> <span style="color: #008000;">-</span><span style="color: #FF0000;">1</span> <span style="color: #008000;">:</span> <span style="color: #FF0000;">0</span><span style="color: #008000;">;</span>
<span style="color: #000000;">&#125;</span>
<span style="color: #008080;">#endregion</span></pre></td></tr></table></div>


</div>

<p>And now for the beast: the implementation of <tt>OnSynchronizeDropdowns</tt><tt>. Side note: <span style="color:red">if you find this code helpful, it would make me feel good if you drop me a thanks - there's a lot of work in this.</span> <img src='http://blog.280z28.org/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </tt></p>

<div style="overflow:auto">


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
</pre></td><td class="code"><pre class="csharp" style="font-family:monospace;"><span style="color: #0600FF;">using</span> <span style="color: #008080;">System.Collections.Generic</span><span style="color: #008000;">;</span>
<span style="color: #0600FF;">using</span> <span style="color: #008080;">System.Linq</span><span style="color: #008000;">;</span>
<span style="color: #0600FF;">using</span> <span style="color: #008080;">Microsoft.VisualStudio.Package</span><span style="color: #008000;">;</span>
<span style="color: #0600FF;">using</span> <span style="color: #008080;">Microsoft.VisualStudio.TextManager.Interop</span><span style="color: #008000;">;</span>
&nbsp;
<span style="color: #0600FF;">using</span> <span style="color: #008080;">ArrayList </span><span style="color: #008000;">=</span> <span style="color: #000000;">System.<span style="color: #0000FF;">Collections</span></span>.<span style="color: #0000FF;">ArrayList</span><span style="color: #008000;">;</span>
&nbsp;
<span style="color: #0600FF;">namespace</span> ManagedMyC
<span style="color: #000000;">&#123;</span>
&nbsp;
    <span style="color: #0600FF;">public</span> <span style="color: #FF0000;">class</span> MyCTypeAndMemberDropdownBars <span style="color: #008000;">:</span> TypeAndMemberDropdownBars
    <span style="color: #000000;">&#123;</span>
        <span style="color: #0600FF;">public</span> MyCTypeAndMemberDropdownBars<span style="color: #000000;">&#40;</span> MyCLanguageService languageService <span style="color: #000000;">&#41;</span>
            <span style="color: #008000;">:</span> <span style="color: #0600FF;">base</span><span style="color: #000000;">&#40;</span> languageService <span style="color: #000000;">&#41;</span>
        <span style="color: #000000;">&#123;</span>
        <span style="color: #000000;">&#125;</span>
&nbsp;
        <span style="color: #008080; font-style: italic;">// If you find this code helpful, it would make me feel good if you drop me a thanks - there's a lot of work in this.</span>
        <span style="color: #0600FF;">public</span> <span style="color: #0600FF;">override</span> <span style="color: #FF0000;">bool</span> OnSynchronizeDropdowns<span style="color: #000000;">&#40;</span> LanguageService languageService, IVsTextView textView, <span style="color: #FF0000;">int</span> line, <span style="color: #FF0000;">int</span> col, ArrayList dropDownTypes, ArrayList dropDownMembers, <span style="color: #0600FF;">ref</span> <span style="color: #FF0000;">int</span> selectedTypeIndex, <span style="color: #0600FF;">ref</span> <span style="color: #FF0000;">int</span> selectedMemberIndex <span style="color: #000000;">&#41;</span>
        <span style="color: #000000;">&#123;</span>
            MyCSource source <span style="color: #008000;">=</span> languageService.<span style="color: #0000FF;">GetSource</span><span style="color: #000000;">&#40;</span> textView <span style="color: #000000;">&#41;</span> <span style="color: #0600FF;">as</span> MyCSource<span style="color: #008000;">;</span>
            <span style="color: #0600FF;">if</span> <span style="color: #000000;">&#40;</span> source <span style="color: #008000;">==</span> <span style="color: #0600FF;">null</span> <span style="color: #000000;">&#41;</span>
                <span style="color: #0600FF;">return</span> false<span style="color: #008000;">;</span>
&nbsp;
            DropDownMember selectedType <span style="color: #008000;">=</span> null<span style="color: #008000;">;</span>
            DropDownMember selectedMember <span style="color: #008000;">=</span> null<span style="color: #008000;">;</span>
&nbsp;
            <span style="color: #0600FF;">if</span> <span style="color: #000000;">&#40;</span> selectedTypeIndex <span style="color: #008000;">&gt;=</span> <span style="color: #FF0000;">0</span> <span style="color: #008000;">&amp;&amp;</span> dropDownTypes.<span style="color: #0000FF;">Count</span> <span style="color: #008000;">&gt;</span> selectedTypeIndex <span style="color: #000000;">&#41;</span>
                selectedType <span style="color: #008000;">=</span> dropDownTypes<span style="color: #000000;">&#91;</span>selectedTypeIndex<span style="color: #000000;">&#93;</span> <span style="color: #0600FF;">as</span> DropDownMember<span style="color: #008000;">;</span>
&nbsp;
            <span style="color: #0600FF;">if</span> <span style="color: #000000;">&#40;</span> selectedMemberIndex <span style="color: #008000;">&gt;=</span> <span style="color: #FF0000;">0</span> <span style="color: #008000;">&amp;&amp;</span> dropDownMembers.<span style="color: #0000FF;">Count</span> <span style="color: #008000;">&gt;</span> selectedMemberIndex <span style="color: #000000;">&#41;</span>
                selectedMember <span style="color: #008000;">=</span> dropDownMembers<span style="color: #000000;">&#91;</span>selectedMemberIndex<span style="color: #000000;">&#93;</span> <span style="color: #0600FF;">as</span> DropDownMember<span style="color: #008000;">;</span>
&nbsp;
            IEnumerable<span style="color: #008000;">&lt;</span>DropDownMember<span style="color: #008000;">&gt;</span> types <span style="color: #008000;">=</span> source.<span style="color: #0000FF;">GetDropDownTypes</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
            <span style="color: #0600FF;">if</span> <span style="color: #000000;">&#40;</span> types <span style="color: #008000;">==</span> <span style="color: #0600FF;">null</span> <span style="color: #000000;">&#41;</span>
                <span style="color: #0600FF;">return</span> false<span style="color: #008000;">;</span>
&nbsp;
            <span style="color: #0600FF;">if</span> <span style="color: #000000;">&#40;</span> source.<span style="color: #0000FF;">TypesUpdated</span> <span style="color: #000000;">&#41;</span>
            <span style="color: #000000;">&#123;</span>
                dropDownTypes.<span style="color: #0000FF;">Clear</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
                dropDownTypes.<span style="color: #0000FF;">AddRange</span><span style="color: #000000;">&#40;</span> types.<span style="color: #0000FF;">ToList</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span> <span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
                source.<span style="color: #0000FF;">TypesUpdated</span> <span style="color: #008000;">=</span> false<span style="color: #008000;">;</span>
            <span style="color: #000000;">&#125;</span>
&nbsp;
            DropDownMember typeScope <span style="color: #008000;">=</span> <span style="color: #000000;">&#40;</span> from type <span style="color: #0600FF;">in</span> types
                                         where TextSpanHelper.<span style="color: #0000FF;">ContainsInclusive</span><span style="color: #000000;">&#40;</span> type.<span style="color: #0000FF;">Span</span>, line, col <span style="color: #000000;">&#41;</span>
                                         orderby <span style="color: #000000;">&#40;</span> type.<span style="color: #0000FF;">Span</span>.<span style="color: #0000FF;">iStartLine</span> <span style="color: #008000;">&lt;&lt;</span> <span style="color: #FF0000;">16</span> <span style="color: #000000;">&#41;</span> <span style="color: #008000;">+</span> type.<span style="color: #0000FF;">Span</span>.<span style="color: #0000FF;">iStartIndex</span>
                                         select type <span style="color: #000000;">&#41;</span>
                                       .<span style="color: #0000FF;">LastOrDefault</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
&nbsp;
            <span style="color: #0600FF;">if</span> <span style="color: #000000;">&#40;</span> typeScope <span style="color: #008000;">!=</span> <span style="color: #0600FF;">null</span> <span style="color: #000000;">&#41;</span>
                selectedTypeIndex <span style="color: #008000;">=</span> dropDownTypes.<span style="color: #0000FF;">IndexOf</span><span style="color: #000000;">&#40;</span> typeScope <span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
            <span style="color: #0600FF;">else</span> <span style="color: #0600FF;">if</span> <span style="color: #000000;">&#40;</span> selectedTypeIndex <span style="color: #008000;">&lt;</span> <span style="color: #FF0000;">0</span> <span style="color: #008000;">||</span> selectedTypeIndex <span style="color: #008000;">&gt;=</span> dropDownTypes.<span style="color: #0000FF;">Count</span> <span style="color: #000000;">&#41;</span>
                selectedTypeIndex <span style="color: #008000;">=</span> source.<span style="color: #0000FF;">GetDefaultType</span><span style="color: #000000;">&#40;</span> types <span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
&nbsp;
            IEnumerable<span style="color: #008000;">&lt;</span>TextSpan<span style="color: #008000;">&gt;</span> excludeSpans <span style="color: #008000;">=</span> null<span style="color: #008000;">;</span>
            <span style="color: #0600FF;">if</span> <span style="color: #000000;">&#40;</span> typeScope <span style="color: #008000;">!=</span> <span style="color: #0600FF;">null</span> <span style="color: #000000;">&#41;</span>
            <span style="color: #000000;">&#123;</span>
                <span style="color: #008080; font-style: italic;">// exclude sub-spans so members of nested types don't show as members of the current type</span>
                excludeSpans <span style="color: #008000;">=</span> from type <span style="color: #0600FF;">in</span> types
                               where TextSpanHelper.<span style="color: #0000FF;">IsEmbedded</span><span style="color: #000000;">&#40;</span> type.<span style="color: #0000FF;">Span</span>, typeScope.<span style="color: #0000FF;">Span</span> <span style="color: #000000;">&#41;</span>
                               where <span style="color: #008000;">!</span>TextSpanHelper.<span style="color: #0000FF;">IsSameSpan</span><span style="color: #000000;">&#40;</span> typeScope.<span style="color: #0000FF;">Span</span>, type.<span style="color: #0000FF;">Span</span> <span style="color: #000000;">&#41;</span>
                               select type.<span style="color: #0000FF;">Span</span><span style="color: #008000;">;</span>
            <span style="color: #000000;">&#125;</span>
            <span style="color: #0600FF;">else</span>
            <span style="color: #000000;">&#123;</span>
                excludeSpans <span style="color: #008000;">=</span> Enumerable.<span style="color: #0000FF;">Empty</span><span style="color: #008000;">&lt;</span>TextSpan<span style="color: #008000;">&gt;</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
            <span style="color: #000000;">&#125;</span>
&nbsp;
            IEnumerable<span style="color: #008000;">&lt;</span>DropDownMember<span style="color: #008000;">&gt;</span> members <span style="color: #008000;">=</span> source.<span style="color: #0000FF;">GetDropDownMembers</span><span style="color: #000000;">&#40;</span> typeScope, excludeSpans <span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
            <span style="color: #0600FF;">if</span> <span style="color: #000000;">&#40;</span> members <span style="color: #008000;">==</span> <span style="color: #0600FF;">null</span> <span style="color: #000000;">&#41;</span>
                <span style="color: #0600FF;">return</span> false<span style="color: #008000;">;</span>
&nbsp;
            <span style="color: #0600FF;">if</span> <span style="color: #000000;">&#40;</span> source.<span style="color: #0000FF;">MembersUpdated</span> <span style="color: #008000;">||</span> selectedType <span style="color: #008000;">!=</span> typeScope <span style="color: #000000;">&#41;</span>
            <span style="color: #000000;">&#123;</span>
                dropDownMembers.<span style="color: #0000FF;">Clear</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
                dropDownMembers.<span style="color: #0000FF;">AddRange</span><span style="color: #000000;">&#40;</span> members.<span style="color: #0000FF;">ToList</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span> <span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
                source.<span style="color: #0000FF;">MembersUpdated</span> <span style="color: #008000;">=</span> false<span style="color: #008000;">;</span>
            <span style="color: #000000;">&#125;</span>
&nbsp;
            DropDownMember memberScope <span style="color: #008000;">=</span> <span style="color: #000000;">&#40;</span> from member <span style="color: #0600FF;">in</span> members
                                           where TextSpanHelper.<span style="color: #0000FF;">ContainsInclusive</span><span style="color: #000000;">&#40;</span> member.<span style="color: #0000FF;">Span</span>, line, col <span style="color: #000000;">&#41;</span>
                                           orderby <span style="color: #000000;">&#40;</span> member.<span style="color: #0000FF;">Span</span>.<span style="color: #0000FF;">iStartLine</span> <span style="color: #008000;">&lt;&lt;</span> <span style="color: #FF0000;">16</span> <span style="color: #000000;">&#41;</span> <span style="color: #008000;">+</span> member.<span style="color: #0000FF;">Span</span>.<span style="color: #0000FF;">iStartIndex</span>
                                           select member <span style="color: #000000;">&#41;</span>
                                         .<span style="color: #0000FF;">LastOrDefault</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
&nbsp;
            <span style="color: #0600FF;">if</span> <span style="color: #000000;">&#40;</span> memberScope <span style="color: #008000;">!=</span> <span style="color: #0600FF;">null</span> <span style="color: #000000;">&#41;</span>
                selectedMemberIndex <span style="color: #008000;">=</span> dropDownMembers.<span style="color: #0000FF;">IndexOf</span><span style="color: #000000;">&#40;</span> memberScope <span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
            <span style="color: #0600FF;">else</span> <span style="color: #0600FF;">if</span> <span style="color: #000000;">&#40;</span> selectedMemberIndex <span style="color: #008000;">&lt;</span> <span style="color: #FF0000;">0</span> <span style="color: #008000;">||</span> selectedMemberIndex <span style="color: #008000;">&gt;=</span> dropDownMembers.<span style="color: #0000FF;">Count</span> <span style="color: #000000;">&#41;</span>
                selectedMemberIndex <span style="color: #008000;">=</span> source.<span style="color: #0000FF;">GetDefaultMember</span><span style="color: #000000;">&#40;</span> selectedType, members <span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
&nbsp;
            <span style="color: #0600FF;">if</span> <span style="color: #000000;">&#40;</span> selectedTypeIndex <span style="color: #008000;">&gt;=</span> <span style="color: #FF0000;">0</span> <span style="color: #000000;">&#41;</span>
            <span style="color: #000000;">&#123;</span>
                <span style="color: #008080; font-style: italic;">// gray out the displayed type if the cursor is no longer in its span</span>
                <span style="color: #000000;">&#40;</span> <span style="color: #000000;">&#40;</span>DropDownMember<span style="color: #000000;">&#41;</span>dropDownTypes<span style="color: #000000;">&#91;</span>selectedTypeIndex<span style="color: #000000;">&#93;</span> <span style="color: #000000;">&#41;</span>.<span style="color: #0000FF;">FontAttr</span> <span style="color: #008000;">=</span>
                    <span style="color: #000000;">&#40;</span> typeScope <span style="color: #008000;">==</span> <span style="color: #0600FF;">null</span> <span style="color: #000000;">&#41;</span> <span style="color: #008000;">?</span> DROPDOWNFONTATTR.<span style="color: #0000FF;">FONTATTR_GRAY</span> <span style="color: #008000;">:</span> DROPDOWNFONTATTR.<span style="color: #0000FF;">FONTATTR_PLAIN</span><span style="color: #008000;">;</span>
            <span style="color: #000000;">&#125;</span>
            <span style="color: #0600FF;">if</span> <span style="color: #000000;">&#40;</span> selectedMemberIndex <span style="color: #008000;">&gt;=</span> <span style="color: #FF0000;">0</span> <span style="color: #000000;">&#41;</span>
            <span style="color: #000000;">&#123;</span>
                <span style="color: #008080; font-style: italic;">// gray out the displayed member if the cursor is no longer in its span</span>
                <span style="color: #000000;">&#40;</span> <span style="color: #000000;">&#40;</span>DropDownMember<span style="color: #000000;">&#41;</span>dropDownMembers<span style="color: #000000;">&#91;</span>selectedMemberIndex<span style="color: #000000;">&#93;</span> <span style="color: #000000;">&#41;</span>.<span style="color: #0000FF;">FontAttr</span> <span style="color: #008000;">=</span>
                    <span style="color: #000000;">&#40;</span> memberScope <span style="color: #008000;">==</span> <span style="color: #0600FF;">null</span> <span style="color: #000000;">&#41;</span> <span style="color: #008000;">?</span> DROPDOWNFONTATTR.<span style="color: #0000FF;">FONTATTR_GRAY</span> <span style="color: #008000;">:</span> DROPDOWNFONTATTR.<span style="color: #0000FF;">FONTATTR_PLAIN</span><span style="color: #008000;">;</span>
            <span style="color: #000000;">&#125;</span>
&nbsp;
            <span style="color: #0600FF;">return</span> true<span style="color: #008000;">;</span>
        <span style="color: #000000;">&#125;</span>
    <span style="color: #000000;">&#125;</span>
<span style="color: #000000;">&#125;</span></pre></td></tr></table></div>


</div>

<h2>Keeping the type &#038; member dropdown bars in sync with the cursor</h2>

<p>The default LanguageService implementation calls SynchronizeDropdowns sometimes, but not every time it's needed. To help with the overall feel of the dropdowns, we need to add two more pieces.</p>

<p>First, we need to call SynchronizeDropdowns after a parse is completed. We already have a property <tt>UpdateDropdowns</tt> inside the <tt>MyCLanguageService</tt> class that is checked inside <tt>OnIdle</tt>. We just need to add the following code in <tt>ParseSource</tt>, inside the <tt>switch ( req.Reason )</tt> under <tt>case ParseReason.Check</tt>:</p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
</pre></td><td class="code"><pre class="csharp" style="font-family:monospace;"><span style="color: #008080; font-style: italic;">// make sure the dropdowns are updated after a parse</span>
UpdateDropdowns <span style="color: #008000;">=</span> true<span style="color: #008000;">;</span></pre></td></tr></table></div>


<p>Second, we need to keep track of when our lists of DropDownMembers in the <tt>MyCSource</tt> class change:</p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
</pre></td><td class="code"><pre class="csharp" style="font-family:monospace;">IList<span style="color: #008000;">&lt;</span>DropDownMember<span style="color: #008000;">&gt;</span> _types<span style="color: #008000;">;</span>
IList<span style="color: #008000;">&lt;</span>DropDownMember<span style="color: #008000;">&gt;</span> _members<span style="color: #008000;">;</span>
&nbsp;
<span style="color: #0600FF;">public</span> <span style="color: #FF0000;">bool</span> TypesUpdated
<span style="color: #000000;">&#123;</span>
    get<span style="color: #008000;">;</span>
    set<span style="color: #008000;">;</span>
<span style="color: #000000;">&#125;</span>
<span style="color: #0600FF;">public</span> <span style="color: #FF0000;">bool</span> MembersUpdated
<span style="color: #000000;">&#123;</span>
    get<span style="color: #008000;">;</span>
    set<span style="color: #008000;">;</span>
<span style="color: #000000;">&#125;</span>
<span style="color: #0600FF;">public</span> IList<span style="color: #008000;">&lt;</span>DropDownMember<span style="color: #008000;">&gt;</span> Types
<span style="color: #000000;">&#123;</span>
    get
    <span style="color: #000000;">&#123;</span>
        <span style="color: #0600FF;">return</span> _types<span style="color: #008000;">;</span>
    <span style="color: #000000;">&#125;</span>
    set
    <span style="color: #000000;">&#123;</span>
        _types <span style="color: #008000;">=</span> value<span style="color: #008000;">;</span>
        TypesUpdated <span style="color: #008000;">=</span> true<span style="color: #008000;">;</span>
    <span style="color: #000000;">&#125;</span>
<span style="color: #000000;">&#125;</span>
<span style="color: #0600FF;">public</span> IList<span style="color: #008000;">&lt;</span>DropDownMember<span style="color: #008000;">&gt;</span> Members
<span style="color: #000000;">&#123;</span>
    get
    <span style="color: #000000;">&#123;</span>
        <span style="color: #0600FF;">return</span> _members<span style="color: #008000;">;</span>
    <span style="color: #000000;">&#125;</span>
    set
    <span style="color: #000000;">&#123;</span>
        _members <span style="color: #008000;">=</span> value<span style="color: #008000;">;</span>
        MembersUpdated <span style="color: #008000;">=</span> true<span style="color: #008000;">;</span>
    <span style="color: #000000;">&#125;</span>
<span style="color: #000000;">&#125;</span></pre></td></tr></table></div>


<h2>Source code for this article</h2>

<p>Here's the source code for the ManagedMyC sample at this point. Since I surely missed things, you can always <a href="http://blog.280z28.org/go.php?http://www.winmerge.org/" title="(72 hits)">diff this code</a> versus the original source from my <a href="http://blog.280z28.org/go.php?http://blog.280z28.org/archives/2008/10/21/" title="(162 hits)">first post on this subject</a>.</p>

<p>Once again, you’ll have to generate your own LanguageService and Package Guids and set them in <tt>MyCConstants.cs</tt> before building this project.</p>

<p>The file is compressed with <a href="http://blog.280z28.org/go.php?http://www.7-zip.org" title="(307 hits)">7-zip</a> because it’s free &amp; awesome.<br />
<a href="http://blog.280z28.org/go.php?http://www.280z28.org/downloads/AntlrVS/ManagedMyC-2.7z" title="(112 hits)">ManagedMyC-2.7z</a></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.280z28.org/archives/2008/10/24/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>ManagedMyC: Intro to building an AST</title>
		<link>http://blog.280z28.org/archives/2008/10/23/</link>
		<comments>http://blog.280z28.org/archives/2008/10/23/#comments</comments>
		<pubDate>Sat, 18 Oct 2008 21:23:53 +0000</pubDate>
		<dc:creator>280Z28</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Tutorials]]></category>

		<guid isPermaLink="false">http://blog.280z28.org/archives/2008/10/23/</guid>
		<description><![CDATA[This is part 3 of [many?] posts about creating an ANTLR-based language service for Visual Studio.

Sure a scanner and parser are cool, and syntax highlighting is nice. But the real power in the Visual Studio language services comes in their IntelliSense abilities, and supporting those effectively requires building and processing an AST. In this section, [...]]]></description>
			<content:encoded><![CDATA[<p>This is part 3 of [many?] posts about creating an ANTLR-based language service for Visual Studio.</p>

<p>Sure a scanner and parser are cool, and syntax highlighting is nice. But the real power in the Visual Studio language services comes in their IntelliSense abilities, and supporting those effectively requires building and processing an AST. In this section, I&#8217;ll show how to integrate the ANTLR automatic AST features, including a tree parser, into the ManagedMyC language service. Among other things, I&#8217;ll assume the reader is already familiar with ANTLR syntax for parsers, rewrites, and tree parsers.</p>

<p>There are plenty of other places to learn about those separately; my goal is to show how to start incorporating the existing knowledge into a usable language service. This article only discusses adding the tree grammar to your language service and using it to process a bare-bones tree created in the parser. For this article, there are no new UI/language service features supported. In the next article, I&#8217;ll show how to use the tree parser output implement a <i>solid</i> TypeAndMemberDropdownBars implementation.</p>

<p><span id="more-23"></span></p>

<h2>Building an AST in the parser</h2>

<p>At this point, we&#8217;ll focus on a minimal AST needed to support a limited number of features. We want to know:</p>

<ul>
<li>The type and name of declared global variables</li>
<li>The signature and location (span) of functions defined at global scope</li>
</ul>

<p>In the grammar MyC.g3, add options indicating we intend to build an AST.</p>

<div style="border:1px dashed"><pre>options
{
    language=CSharp2;
    <span style="background-color:yellow">output=AST;</span>
    <span style="background-color:yellow">ASTLabelType=CommonTree;</span>
}</pre></div>

<p>Then build the minimal AST. Pseudo-tokens are used as the root of some trees for both identification and to keep the tree parser LL(1) for speed. Only the parser rules are included here, and I left out most of the tokens to save space.</p>

<div style="border:1px dashed"><pre>tokens
{
    // all our previous tokens still go here
    END_BLOCK_COMMENT = '*/';

    <span style="background-color:yellow">AST_FUNCDEF;</span>
    <span style="background-color:yellow">AST_PARAMS;</span>
    <span style="background-color:yellow">AST_DECL;</span>
}

@lexer::namespace { ManagedMyC }
@parser::namespace { ManagedMyC }

program
    :   declarations
        EOF
    ;

declarations
    :   declaration*
    ;

declaration
    :   declaration_
    ;

declaration_
    :   class1? type? IDENTIFIER paren_params block
        { Region( $block.start, $block.stop ); }
        <span style="background-color:yellow">-> ^(AST_FUNCDEF class1? type? IDENTIFIER paren_params block)</span>
    |   simple_declaration
    ;

simple_declarations1
    :   simple_declaration+
    ;

simple_declaration
    :   semi_declaration ';'<span style="background-color:yellow">!</span>
    ;

semi_declaration
    :   class1? type IDENTIFIER
        (',' IDENTIFIER)*
        <span style="background-color:yellow">-> ^(AST_DECL class1? type IDENTIFIER+)</span>
    ;

params1
    :   parameter (','<span style="background-color:yellow">!</span> parameter)*
    ;

parameter
    :   type<span style="background-color:yellow">^</span> IDENTIFIER
    ;

paren_params
    :   l='(' params1? r=')'
        { Match($l, $r); }
        <span style="background-color:yellow">-> ^(AST_PARAMS params1?)</span>
    ;

class1
    :   'static'
    |   'auto'
    |   'extern'
    ;

type
    :   'int'
    |   'void'
    ;

<span style="background-color:yellow">// for now, we don't need to know the <i>contents</i> of a block, just where it starts and ends.</span>
block
    :   open_block <span style="background-color:yellow">(</span>block_content1<span style="background-color:yellow">!)</span>? close_block
        { Match($open_block.start, $close_block.start); }
    ;

open_block
    :   '{'
    ;

close_block
    :   '}'
    ;

<span style="background-color:lightseagreen">// From here on it's the same as in the first version of the grammar</span>
</pre></div>

<h2>Adding a tree grammar to the project</h2>

<p>We&#8217;ll name the tree grammar <tt>MyCWalker</tt>, so the grammar file is <tt>MyCWalker.g3</tt>, the generated class is <tt>MyCWalker.cs</tt>, and the user-created partial class we&#8217;ll call <tt>MyCWalkerHelper.cs</tt>. When I add a new grammar to a project, the first thing I do is create empty files with those names and place them in the project folder. Then I unload the project in Visual Studio, and right click > Edit ManagedMyC.csproj. Add the following items to the project:</p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
</pre></td><td class="code"><pre class="xml" style="font-family:monospace;">  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;ItemGroup<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;Antlr3</span> <span style="color: #000066;">Include</span>=<span style="color: #ff0000;">&quot;MyCWalker.g3&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
      <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;OutputFiles<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>MyCWalker.cs;MyCWalker.tokens<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/OutputFiles<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/Antlr3<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;Compile</span> <span style="color: #000066;">Include</span>=<span style="color: #ff0000;">&quot;MyCWalker.cs&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
      <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;AutoGen<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>True<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/AutoGen<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
      <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;DesignTime<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>True<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/DesignTime<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
      <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;DependentUpon<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>MyCWalker.g3<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/DependentUpon<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/Compile<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;Compile</span> <span style="color: #000066;">Include</span>=<span style="color: #ff0000;">&quot;MyCWalkerHelper.cs&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
      <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;DependentUpon<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>MyCWalker.g3<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/DependentUpon<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/Compile<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/ItemGroup<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre></td></tr></table></div>


<p>Save the modified project file, close it, and then right click on the project in Solution Explorer > Reload.</p>

<h2>Creating a tree grammar to match the parser&#8217;s generated AST</h2>

<div style="border:1px dashed"><pre>tree grammar MyCWalker;

options
{
    language=CSharp2;
    tokenVocab=MyC;
    ASTLabelType=CommonTree;
}

@namespace { ManagedMyC }

program
    :   declarations
    ;

declarations
    :   declaration*
    ;

declaration
    :   declaration_
    ;

declaration_
    :   ^(AST_FUNCDEF class1? type? IDENTIFIER parameters block)
    |   simple_declaration
    ;

simple_declarations1
    :   simple_declaration+
    ;

simple_declaration
    :   ^(AST_DECL class1? type IDENTIFIER+)
    ;

parameters
    :   ^(AST_PARAMS parameter*)
    ;

parameter
    :   ^(type IDENTIFIER)
    ;

class1
    :   'static'
    |   'auto'
    |   'extern'
    ;

type
    :   'int'
    |   'void'
    ;

// notice we excluded the block_content1 tree in the parser, so we skip it here too
block
    :   open_block /*block_content1?*/ close_block
    ;

open_block
    :   '{'
    ;

close_block
    :   '}'
    ;
</pre></div>

<h2>Calling the tree parser during parse operations</h2>

<p>First, we edit the <tt>MyCWalkerHelper.cs</tt> file to add a <tt>WalkAST</tt> function that the parser can use.</p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
</pre></td><td class="code"><pre class="csharp" style="font-family:monospace;"><span style="color: #0600FF;">using</span> <span style="color: #008080;">Antlr.Runtime.Tree</span><span style="color: #008000;">;</span>
&nbsp;
<span style="color: #0600FF;">namespace</span> ManagedMyC
<span style="color: #000000;">&#123;</span>
    <span style="color: #0600FF;">partial</span> <span style="color: #FF0000;">class</span> MyCWalker
    <span style="color: #000000;">&#123;</span>
        <span style="color: #0600FF;">public</span> MyCWalker<span style="color: #000000;">&#40;</span> MyCParser parser, CommonTree tree <span style="color: #000000;">&#41;</span>
            <span style="color: #008000;">:</span> <span style="color: #0600FF;">this</span><span style="color: #000000;">&#40;</span> <span style="color: #008000;">new</span> CommonTreeNodeStream<span style="color: #000000;">&#40;</span> tree <span style="color: #000000;">&#41;</span> <span style="color: #000000;">&#41;</span>
        <span style="color: #000000;">&#123;</span>
            <span style="color: #000000;">&#40;</span> <span style="color: #000000;">&#40;</span>CommonTreeNodeStream<span style="color: #000000;">&#41;</span>input <span style="color: #000000;">&#41;</span>.<span style="color: #0000FF;">TokenStream</span> <span style="color: #008000;">=</span> parser.<span style="color: #0000FF;">TokenStream</span><span style="color: #008000;">;</span>
        <span style="color: #000000;">&#125;</span>
&nbsp;
        <span style="color: #0600FF;">public</span> <span style="color: #0600FF;">void</span> WalkAST<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span>
        <span style="color: #000000;">&#123;</span>
            program<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
        <span style="color: #000000;">&#125;</span>
    <span style="color: #000000;">&#125;</span>
<span style="color: #000000;">&#125;</span></pre></td></tr></table></div>


<p>The main entry point to the parser is <tt>MyCParser.Parse()</tt> in <tt>MyCParserHelper.cs</tt>. We add code to that function to automatically process the tree after a parse:</p>

<pre>public bool Parse()
{
    <span style="background-color:yellow">program_return result =</span> program();

    <span style="background-color:yellow">MyCWalker walker = new MyCWalker( this, (CommonTree)result.Tree );</span>
    <span style="background-color:yellow">walker.WalkAST();</span>

    return true;
}
</pre>

<h2>What&#8217;s next</h2>

<p>I&#8217;m not including a new set of source code with this post because the next set of source already includes the TypeAndMemberDropdownBars implementation that I&#8217;ll be explaining in the next article.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.280z28.org/archives/2008/10/23/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>ManagedMyC: Code folding for functions</title>
		<link>http://blog.280z28.org/archives/2008/10/22/</link>
		<comments>http://blog.280z28.org/archives/2008/10/22/#comments</comments>
		<pubDate>Fri, 17 Oct 2008 06:03:41 +0000</pubDate>
		<dc:creator>280Z28</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Tutorials]]></category>

		<guid isPermaLink="false">http://blog.280z28.org/archives/2008/10/22/</guid>
		<description><![CDATA[This is part 2 of [many?] posts about creating an ANTLR-based language service for Visual Studio.

Since this is a near-trivial feature to add based on the code in my previous post, I&#8217;ll go ahead and get it in tonight. We want to fold from the opening { to the closing } of a function, so [...]]]></description>
			<content:encoded><![CDATA[<p>This is part 2 of [many?] posts about creating an ANTLR-based language service for Visual Studio.</p>

<p>Since this is a near-trivial feature to add based on the code in my previous post, I&#8217;ll go ahead and get it in tonight. We want to fold from the opening { to the closing } of a function, so the first thing to do is find that in the grammar.</p>

<div style="border:1px dashed"><pre style="color:darkblue">declaration_
    :   class1? type? IDENTIFIER paren_params block
    |   simple_declaration
    ;
</pre></div>

<p><span id="more-22"></span></p>

<p>The first alternative in the <tt>declaration_</tt> rule is a function: clearly you have return type, name, parameters, and then the definition block. Since the <tt>block</tt> rule starts with { and ends with }, it&#8217;s exactly what we want to fold. We&#8217;ll make this work just like the braces; change the rule to add an action to mark the folding region:</p>

<div style="border:1px dashed"><pre style="color:darkblue">declaration_
    :   class1? type? IDENTIFIER paren_params block
        { Region( $block.start, $block.stop ); }
    |   simple_declaration
    ;
</pre></div>

<p>Then open up your MyCParserHelper.cs file and add these two <tt>Region</tt> helper functions immediately above the <tt>DefineRegion</tt> function already there:</p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
</pre></td><td class="code"><pre class="csharp" style="font-family:monospace;"><span style="color: #0600FF;">public</span> <span style="color: #0600FF;">void</span> Region<span style="color: #000000;">&#40;</span> IToken lh, IToken rh <span style="color: #000000;">&#41;</span>
<span style="color: #000000;">&#123;</span>
    DefineRegion<span style="color: #000000;">&#40;</span> TextSpanHelper.<span style="color: #0000FF;">Merge</span><span style="color: #000000;">&#40;</span> ToTextSpan<span style="color: #000000;">&#40;</span> lh <span style="color: #000000;">&#41;</span>, ToTextSpan<span style="color: #000000;">&#40;</span> rh <span style="color: #000000;">&#41;</span> <span style="color: #000000;">&#41;</span> <span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
<span style="color: #000000;">&#125;</span>
<span style="color: #0600FF;">public</span> <span style="color: #0600FF;">void</span> Region<span style="color: #000000;">&#40;</span> IToken token <span style="color: #000000;">&#41;</span>
<span style="color: #000000;">&#123;</span>
    DefineRegion<span style="color: #000000;">&#40;</span> ToTextSpan<span style="color: #000000;">&#40;</span> token <span style="color: #000000;">&#41;</span> <span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
<span style="color: #000000;">&#125;</span></pre></td></tr></table></div>


<p>Finally, you need to make sure the AuthoringSink knows that you are making changes to the document&#8217;s hidden region markers by adding a line to <tt>DefineRegion</tt>:</p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
</pre></td><td class="code"><pre class="csharp" style="font-family:monospace;"><span style="color: #0600FF;">public</span> <span style="color: #0600FF;">void</span> DefineRegion<span style="color: #000000;">&#40;</span> TextSpan span <span style="color: #000000;">&#41;</span>
<span style="color: #000000;">&#123;</span>
    Sink.<span style="color: #0000FF;">ProcessHiddenRegions</span> <span style="color: #008000;">=</span> true<span style="color: #008000;">;</span>
    Sink.<span style="color: #0000FF;">AddHiddenRegion</span><span style="color: #000000;">&#40;</span> span <span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
<span style="color: #000000;">&#125;</span></pre></td></tr></table></div>

]]></content:encoded>
			<wfw:commentRss>http://blog.280z28.org/archives/2008/10/22/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Custom Visual Studio language services: ManagedMyC meets ANTLR</title>
		<link>http://blog.280z28.org/archives/2008/10/21/</link>
		<comments>http://blog.280z28.org/archives/2008/10/21/#comments</comments>
		<pubDate>Fri, 17 Oct 2008 03:25:35 +0000</pubDate>
		<dc:creator>280Z28</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Tutorials]]></category>

		<guid isPermaLink="false">http://blog.280z28.org/archives/2008/10/21/</guid>
		<description><![CDATA[As some of you know (ok probably not many of you), I&#8217;m the author behind Pixel Mine nFringe, a custom language service framework that we used to provide UnrealScript editing &#38; debugging features in Visual Studio 2005 and 2008. To date, I&#8217;ve written 2 full language services with it (UnrealScript and Antlr v3) and toyed [...]]]></description>
			<content:encoded><![CDATA[<p>As some of you know (ok probably not many of you), I&#8217;m the author behind <a href="http://blog.280z28.org/go.php?http://wiki.pixelminegames.com/index.php?title=Tools:nFringe:Features" title="(253 hits)">Pixel Mine nFringe</a>, a custom language service framework that we used to provide UnrealScript editing &amp; debugging features in Visual Studio 2005 and 2008. To date, I&#8217;ve written 2 full language services with it (UnrealScript and Antlr v3) and toyed with several others (INI files, C/C++, StringTemplate, and a scripting language used in another game). Several people have asked how to get started on a language service using ANTLR grammars for the backend features.</p>

<p>Just to get started, I&#8217;ve made a near direct port of the ManagedMyC sample from the Visual Studio SDK, which uses MPLEX/MPPG, to one that uses <a href="http://blog.280z28.org/go.php?http://www.antlr.org" title="(167 hits)">ANTLR</a>. The most important thing to note at this point: many parts of this sample are inefficient, clumsy, and/or just done the wrong way. None of the features from earlier posts here are implemented in this sample [yet]. Over the next several weeks, I plan to make blog entries covering individual tasks required to make ManagedMyC a solid example of how someone could make a custom language service.</p>

<p><span id="more-21"></span></p>

<p>The source code for this post is linked at the end of this article. I&#8217;ve divided this post into the two major items involved in creating an ANTLR-based language service: setting up the grammar compiler with MSBuild, and creating a scanner-friendly lexer.</p>

<h2>Setting up ANTLR grammars to compile with your language service</h2>

<p>Antlr generates .cs files that must be included in the project build. Visual Studio&#8217;s build system has a problem identifying files generated in the middle of a build, so you normally have to build your project twice for a grammar change to take effect. To stop Visual Studio from caching the timestamps of the generated files so the build always works, add the following before the <tt>Import</tt> elements near the end of the project file:</p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
</pre></td><td class="code"><pre class="xml" style="font-family:monospace;"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;PropertyGroup<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;UseHostCompilerIfAvailable<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>False<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/UseHostCompilerIfAvailable<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/PropertyGroup<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre></td></tr></table></div>


<p>You also need to add rules to have the grammars build with MSBuild. Add the following immediately after the <tt>Import</tt> elements:</p>

<div style="overflow:auto">


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
</pre></td><td class="code"><pre class="xml" style="font-family:monospace;"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;PropertyGroup<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;Antlr3ToolPath<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>$(MSBuildProjectDirectory)\..\Antlr<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/Antlr3ToolPath<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;CoreCompileDependsOn<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>$(CoreCompileDependsOn);GenerateAntlrCode<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/CoreCompileDependsOn<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;CoreCleanDependsOn<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>$(CoreCleanDependsOn);CleanAntlrCode<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/CoreCleanDependsOn<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/PropertyGroup<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;Target</span> <span style="color: #000066;">Name</span>=<span style="color: #ff0000;">&quot;GenerateAntlrCode&quot;</span> <span style="color: #000066;">Inputs</span>=<span style="color: #ff0000;">&quot;@(Antlr3)&quot;</span> <span style="color: #000066;">Outputs</span>=<span style="color: #ff0000;">&quot;%(OutputFiles)&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;Message</span> <span style="color: #000066;">Importance</span>=<span style="color: #ff0000;">&quot;normal&quot;</span> <span style="color: #000066;">Text</span>=<span style="color: #ff0000;">&quot;Antlr: Transforming '@(Antlr3)' to '%(Antlr3.OutputFiles)'&quot;</span> <span style="color: #000000; font-weight: bold;">/&gt;</span></span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;Exec</span> <span style="color: #000066;">Command</span>=<span style="color: #ff0000;">&quot;java -cp %22$(Antlr3ToolPath)\antlr3.jar;$(Antlr3ToolPath)\antlr-2.7.7.jar;$(Antlr3ToolPath)\stringtemplate-3.1b1.jar%22 org.antlr.Tool -lib %22%(RootDir)%(Directory).%22 -message-format vs2005 @(Antlr3)&quot;</span> <span style="color: #000066;">Outputs</span>=<span style="color: #ff0000;">&quot;%(OutputFiles)&quot;</span> <span style="color: #000000; font-weight: bold;">/&gt;</span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/Target<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;Target</span> <span style="color: #000066;">Name</span>=<span style="color: #ff0000;">&quot;CleanAntlrCode&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;ItemGroup<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;_CleanAntlrFileWrites</span> <span style="color: #000066;">Include</span>=<span style="color: #ff0000;">&quot;@(Antlr3-&gt;</span></span>'%(RelativeDir)%(Filename).tokens')&quot; /&gt;
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/ItemGroup<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;Message</span> <span style="color: #000066;">Importance</span>=<span style="color: #ff0000;">&quot;normal&quot;</span> <span style="color: #000066;">Text</span>=<span style="color: #ff0000;">&quot;Antlr: Deleting output files '@(_CleanAntlrFileWrites)'&quot;</span> <span style="color: #000000; font-weight: bold;">/&gt;</span></span>
  <span style="color: #808080; font-style: italic;">&lt;!-- Uncomment the following line if you want the &quot;Rebuild Solution&quot; command to rebuild your grammars --&gt;</span>
  <span style="color: #808080; font-style: italic;">&lt;!--&lt;Delete Files=&quot;@(_CleanAntlrFileWrites)&quot; /&gt;--&gt;</span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/Target<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre></td></tr></table></div>


</div>

<h2><tt>IScanner</tt>-friendly lexers</h2>

<p>The biggest difference between traditional parsing and the code highlighter in Visual Studio is in the amount of text they process at a time. For regular parsing, generally started by a call to <tt>LanguageService.ParseSource</tt>, you have access to and can parse the entire source file as a single block of text. The syntax highlighter, exposed by a class that implements the <tt>IScanner</tt> interface, only has access to one line at a time, so it must be resumable (better word?) from any point in the file. ANTLR generated lexers are not trivial to use one line at a time, but with a bit of thought up front, it&#8217;s not bad either.</p>

<p>The primary problem lies in single lexical tokens, such as block comments, that span more than one line. To work in a Visual Studio colorizer, your lexer needs to be able to start in the middle of any multi-line token. ManagedMyC has 2 tokens that can span multiple lines: white space and block comments.</p>

<h3>White space, the not-so-multiline multiline token</h3>

<p>First, handling white space. If you have a whitespace rule like the following, simply break it in two so it doesn&#8217;t span multiple lines.</p>

<p>Before:</p>

<div style="border:1px dashed"><pre style="color:darkblue">WS
    :   (' '|'\t'|'\r'|'\n')+
        { $channel=HIDDEN; }
    ;
</pre></div>

<p>After:</p>

<div style="border:1px dashed"><pre style="color:darkblue">NEWLINE
    :   '\r'? '\n'
        { $channel = HIDDEN; }
    ;

WS
    :   (' '|'\t')+
        { $channel=HIDDEN; }
    ;
</pre></div>

<h3>Multi-line tokens: block comments</h3>

<p><span style="color:red">Edit 4/15/09: I have a new method for handling this type of token that is more reliable, faster, and cleaner than this method. I&#8217;ll be making a new blog post soon to revisit the issue.</span></p>

<p>Next is the big one: handling C-style block comments. The following is the simplest form of C-style comment represented in an ANTLR lexer rule:</p>

<div style="border:1px dashed"><pre style="color:darkblue">COMMENT
    :   '/*' .* '*/'
        { $channel=HIDDEN; }
    ;
</pre></div>

<p>First, you don&#8217;t want your lexer to throw exceptions when a block comment doesn&#8217;t end before the end of a line, so we modify the rule to continue to the end of the text or until the comment ends, whichever comes first:</p>

<div style="border:1px dashed"><pre style="color:darkblue">COMMENT
    :   '/*'
        (   ~('*')
            |   ('*' ~'/') => '*'
        )*
        ('*/')?
        { $channel=HIDDEN; }
    ;
</pre></div>

<p>Making the lexer able to resume parsing in the middle of a comment is a bit more difficult. We do this by forcing everything to be a comment until we reach the end of the block comment, and then continue like normal. This takes several steps.</p>

<p>First, we need to be able to detect the end of a block comment. Since <tt>*/</tt> is only valid in C as the end of a block comment, we simply add it in the <tt>tokens{}</tt> section of the grammar:</p>

<div style="border:1px dashed"><pre style="color:darkblue">tokens
{
    // ...
    END_BLOCK_COMMENT = '*/';
    // ...
}</pre></div>

<p>Next, we need to make sure no character bombs the lexer (NoViableAltException), so we add the following as the last rule in the file:</p>

<div style="border:1px dashed"><pre style="color:darkblue">ANYCHAR
    :   .
    ;
</pre></div>

<p>Next, we need to have a property in the lexer class to get/set the current state. In the MyCLexerHelper.cs file (the user-edited file for the <tt>partial</tt> class), we add the following:</p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
</pre></td><td class="code"><pre class="csharp" style="font-family:monospace;"><span style="color: #0600FF;">using</span> <span style="color: #008080;">Antlr.Runtime</span><span style="color: #008000;">;</span>
&nbsp;
<span style="color: #0600FF;">namespace</span> ManagedMyC
<span style="color: #000000;">&#123;</span>
    <span style="color: #0600FF;">partial</span> <span style="color: #FF0000;">class</span> MyCLexer
    <span style="color: #000000;">&#123;</span>
        <span style="color: #0600FF;">public</span> <span style="color: #FF0000;">bool</span> InBlockComment
        <span style="color: #000000;">&#123;</span>
            get<span style="color: #008000;">;</span>
            set<span style="color: #008000;">;</span>
        <span style="color: #000000;">&#125;</span>
    <span style="color: #000000;">&#125;</span>
<span style="color: #000000;">&#125;</span></pre></td></tr></table></div>


<p>which we manipulate inside the COMMENT rule:</p>

<div style="border:1px dashed"><pre style="color:darkblue">COMMENT
    :   '/*'
        {
            InBlockComment = true;
            $channel = HIDDEN;
        }
        (   ~('*')
            |   ('*' ~'/') => '*'
        )*
        ('*/' {InBlockComment = false;})?
    ;
</pre></div>

<p>The final step is to override the <tt>NextToken()</tt> function to handle cases where the lexer started in a comment state:</p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
</pre></td><td class="code"><pre class="csharp" style="font-family:monospace;"><span style="color: #0600FF;">using</span> <span style="color: #008080;">Antlr.Runtime</span><span style="color: #008000;">;</span>
&nbsp;
<span style="color: #0600FF;">namespace</span> ManagedMyC
<span style="color: #000000;">&#123;</span>
    <span style="color: #0600FF;">partial</span> <span style="color: #FF0000;">class</span> MyCLexer
    <span style="color: #000000;">&#123;</span>
        <span style="color: #0600FF;">public</span> <span style="color: #FF0000;">bool</span> InBlockComment
        <span style="color: #000000;">&#123;</span>
            get<span style="color: #008000;">;</span>
            set<span style="color: #008000;">;</span>
        <span style="color: #000000;">&#125;</span>
&nbsp;
        <span style="color: #0600FF;">public</span> <span style="color: #0600FF;">override</span> IToken NextToken<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span>
        <span style="color: #000000;">&#123;</span>
            IToken next <span style="color: #008000;">=</span> <span style="color: #0600FF;">base</span>.<span style="color: #0000FF;">NextToken</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
&nbsp;
            <span style="color: #0600FF;">if</span> <span style="color: #000000;">&#40;</span> next.<span style="color: #0000FF;">Type</span> <span style="color: #008000;">!=</span> EOF <span style="color: #008000;">&amp;&amp;</span> InBlockComment <span style="color: #008000;">&amp;&amp;</span> next.<span style="color: #0000FF;">Type</span> <span style="color: #008000;">!=</span> COMMENT <span style="color: #000000;">&#41;</span>
            <span style="color: #000000;">&#123;</span>
                <span style="color: #0600FF;">if</span> <span style="color: #000000;">&#40;</span> next.<span style="color: #0000FF;">Type</span> <span style="color: #008000;">==</span> END_BLOCK_COMMENT <span style="color: #000000;">&#41;</span>
                    InBlockComment <span style="color: #008000;">=</span> false<span style="color: #008000;">;</span>
&nbsp;
                next.<span style="color: #0000FF;">Type</span> <span style="color: #008000;">=</span> COMMENT<span style="color: #008000;">;</span>
                next.<span style="color: #0000FF;">Channel</span> <span style="color: #008000;">=</span> HIDDEN<span style="color: #008000;">;</span>
            <span style="color: #000000;">&#125;</span>
&nbsp;
            <span style="color: #0600FF;">return</span> next<span style="color: #008000;">;</span>
        <span style="color: #000000;">&#125;</span>
    <span style="color: #000000;">&#125;</span>
<span style="color: #000000;">&#125;</span></pre></td></tr></table></div>


<h2>Source code for this sample</h2>

<p>You&#8217;ll have to generate your own LanguageService and Package Guids and set them in <tt>MyCConstants.cs</tt> before building this project.</p>

<p>The file is compressed with <a href="http://blog.280z28.org/go.php?http://www.7-zip.org/" title="(80 hits)">7-zip</a> because it&#8217;s awesome.&lt;br/>
<a href="http://blog.280z28.org/go.php?http://www.280z28.org/downloads/AntlrVS/ManagedMyC-1.7z" title="(194 hits)">ManagedMyC-1.7z</a></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.280z28.org/archives/2008/10/21/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Custom Visual Studio language services: Tracking recently used items in autocompletion lists</title>
		<link>http://blog.280z28.org/archives/2008/10/20/</link>
		<comments>http://blog.280z28.org/archives/2008/10/20/#comments</comments>
		<pubDate>Tue, 07 Oct 2008 20:34:04 +0000</pubDate>
		<dc:creator>280Z28</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Tutorials]]></category>

		<guid isPermaLink="false">http://blog.280z28.org/archives/2008/10/20/</guid>
		<description><![CDATA[The C# language service has the great feature of remembering recently used items in the completion lists (auto-complete, complete word, member select, etc.). You can add a similar ability to your language service by deriving your Declarations-derived class from MruDeclarations instead of Declarations.




1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
public abstract class MruDeclarations : Declarations
&#123;
    static List&#60;string&#62; _recentCompletions = [...]]]></description>
			<content:encoded><![CDATA[<p>The C# language service has the great feature of remembering recently used items in the completion lists (auto-complete, complete word, member select, etc.). You can add a similar ability to your language service by deriving your Declarations-derived class from MruDeclarations instead of Declarations.<span id="more-20"></span></p>

<div style="overflow:auto">


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
</pre></td><td class="code"><pre class="csharp" style="font-family:monospace;"><span style="color: #0600FF;">public</span> abstract <span style="color: #FF0000;">class</span> MruDeclarations <span style="color: #008000;">:</span> Declarations
<span style="color: #000000;">&#123;</span>
    <span style="color: #0600FF;">static</span> List<span style="color: #008000;">&lt;</span><span style="color: #FF0000;">string</span><span style="color: #008000;">&gt;</span> _recentCompletions <span style="color: #008000;">=</span> <span style="color: #008000;">new</span> List<span style="color: #008000;">&lt;</span><span style="color: #FF0000;">string</span><span style="color: #008000;">&gt;</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
    <span style="color: #0600FF;">static</span> <span style="color: #0600FF;">void</span> InsertUsedItem<span style="color: #000000;">&#40;</span> <span style="color: #FF0000;">string</span> name <span style="color: #000000;">&#41;</span>
    <span style="color: #000000;">&#123;</span>
        <span style="color: #0600FF;">if</span> <span style="color: #000000;">&#40;</span> <span style="color: #FF0000;">string</span>.<span style="color: #0000FF;">IsNullOrEmpty</span><span style="color: #000000;">&#40;</span> name <span style="color: #000000;">&#41;</span> <span style="color: #000000;">&#41;</span>
            return<span style="color: #008000;">;</span>
&nbsp;
        <span style="color: #0600FF;">if</span> <span style="color: #000000;">&#40;</span> _recentCompletions.<span style="color: #0000FF;">Count</span> <span style="color: #008000;">&gt;=</span> <span style="color: #FF0000;">20</span> <span style="color: #000000;">&#41;</span>
            _recentCompletions.<span style="color: #0000FF;">RemoveAt</span><span style="color: #000000;">&#40;</span> <span style="color: #FF0000;">0</span> <span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
        _recentCompletions.<span style="color: #0000FF;">Remove</span><span style="color: #000000;">&#40;</span> name <span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
        _recentCompletions.<span style="color: #0000FF;">Add</span><span style="color: #000000;">&#40;</span> name <span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
    <span style="color: #000000;">&#125;</span>
&nbsp;
    <span style="color: #0600FF;">public</span> <span style="color: #0600FF;">override</span> <span style="color: #0600FF;">void</span> GetBestMatch<span style="color: #000000;">&#40;</span> <span style="color: #FF0000;">string</span> value, <span style="color: #0600FF;">out</span> <span style="color: #FF0000;">int</span> index, <span style="color: #0600FF;">out</span> <span style="color: #FF0000;">bool</span> uniqueMatch <span style="color: #000000;">&#41;</span>
    <span style="color: #000000;">&#123;</span>
        <span style="color: #0600FF;">base</span>.<span style="color: #0000FF;">GetBestMatch</span><span style="color: #000000;">&#40;</span> value, <span style="color: #0600FF;">out</span> index, <span style="color: #0600FF;">out</span> uniqueMatch <span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
&nbsp;
        <span style="color: #0600FF;">if</span> <span style="color: #000000;">&#40;</span> <span style="color: #008000;">!</span>uniqueMatch <span style="color: #000000;">&#41;</span>
        <span style="color: #000000;">&#123;</span>
            List<span style="color: #008000;">&lt;</span><span style="color: #FF0000;">string</span><span style="color: #008000;">&gt;</span> relevantRecentItems <span style="color: #008000;">=</span> _recentCompletions.<span style="color: #0000FF;">Where</span><span style="color: #000000;">&#40;</span> item <span style="color: #008000;">=&gt;</span> item.<span style="color: #0000FF;">StartsWith</span><span style="color: #000000;">&#40;</span> value, StringComparison.<span style="color: #0000FF;">OrdinalIgnoreCase</span> <span style="color: #000000;">&#41;</span> <span style="color: #000000;">&#41;</span>.<span style="color: #0000FF;">ToList</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
            <span style="color: #0600FF;">if</span> <span style="color: #000000;">&#40;</span> relevantRecentItems.<span style="color: #0000FF;">Count</span> <span style="color: #008000;">==</span> <span style="color: #FF0000;">0</span> <span style="color: #000000;">&#41;</span>
                return<span style="color: #008000;">;</span>
&nbsp;
            <span style="color: #FF0000;">string</span> last <span style="color: #008000;">=</span> relevantRecentItems.<span style="color: #0000FF;">OrderBy</span><span style="color: #000000;">&#40;</span> i <span style="color: #008000;">=&gt;</span> i, StringComparer.<span style="color: #0000FF;">OrdinalIgnoreCase</span> <span style="color: #000000;">&#41;</span>.<span style="color: #0000FF;">Last</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
&nbsp;
            var declaration <span style="color: #008000;">=</span>
                <span style="color: #008080; font-style: italic;">// start at index to ignore items that fall before the first item that starts with the text typed so-far (case-insensitive)</span>
                Enumerable.<span style="color: #0000FF;">Range</span><span style="color: #000000;">&#40;</span> index, GetCount<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">-</span><span style="color: #FF0000;">1</span> <span style="color: #000000;">&#41;</span>
                <span style="color: #008080; font-style: italic;">// anonymous type to cache the DisplayText</span>
                .<span style="color: #0000FF;">Select</span><span style="color: #000000;">&#40;</span> i <span style="color: #008000;">=&gt;</span> <span style="color: #008000;">new</span>
                <span style="color: #000000;">&#123;</span>
                    DisplayText <span style="color: #008000;">=</span> GetDisplayText<span style="color: #000000;">&#40;</span> i <span style="color: #000000;">&#41;</span>,
                    Index <span style="color: #008000;">=</span> i
                <span style="color: #000000;">&#125;</span> <span style="color: #000000;">&#41;</span>
                <span style="color: #008080; font-style: italic;">// stop taking items when we reach the last relevant recent completion in alphabetical order (case-insensitive)</span>
                .<span style="color: #0000FF;">TakeWhile</span><span style="color: #000000;">&#40;</span> item <span style="color: #008000;">=&gt;</span> <span style="color: #FF0000;">string</span>.<span style="color: #0000FF;">Compare</span><span style="color: #000000;">&#40;</span> item.<span style="color: #0000FF;">DisplayText</span>, last, StringComparison.<span style="color: #0000FF;">OrdinalIgnoreCase</span> <span style="color: #000000;">&#41;</span> <span style="color: #008000;">&lt;=</span> <span style="color: #FF0000;">0</span> <span style="color: #000000;">&#41;</span>
                <span style="color: #008080; font-style: italic;">// filter on whether the recent completions list contains the item (case-insensitive)</span>
                .<span style="color: #0000FF;">Where</span><span style="color: #000000;">&#40;</span> item <span style="color: #008000;">=&gt;</span> relevantRecentItems.<span style="color: #0000FF;">Contains</span><span style="color: #000000;">&#40;</span> item.<span style="color: #0000FF;">DisplayText</span>, StringComparer.<span style="color: #0000FF;">OrdinalIgnoreCase</span> <span style="color: #000000;">&#41;</span> <span style="color: #000000;">&#41;</span>
                <span style="color: #008080; font-style: italic;">// rank the items that match a recent completion</span>
                <span style="color: #008080; font-style: italic;">//  - give preference to items that were more recently typed</span>
                <span style="color: #008080; font-style: italic;">//  - give preference to case-sensitive matches</span>
                <span style="color: #008080; font-style: italic;">//  =&gt; higher rank values indicate better matches</span>
                .<span style="color: #0000FF;">OrderByDescending</span><span style="color: #000000;">&#40;</span> item <span style="color: #008000;">=&gt;</span>
                <span style="color: #000000;">&#123;</span>
                    <span style="color: #FF0000;">int</span> withCase <span style="color: #008000;">=</span> relevantRecentItems.<span style="color: #0000FF;">LastIndexOf</span><span style="color: #000000;">&#40;</span> item.<span style="color: #0000FF;">DisplayText</span> <span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
                    <span style="color: #008080; font-style: italic;">// bias case-insensitive matches to case-sensitive matches have higher rank</span>
                    <span style="color: #FF0000;">int</span> withoutCase <span style="color: #008000;">=</span> relevantRecentItems.<span style="color: #0000FF;">FindLastIndex</span><span style="color: #000000;">&#40;</span> i <span style="color: #008000;">=&gt;</span> i.<span style="color: #0000FF;">Equals</span><span style="color: #000000;">&#40;</span> item.<span style="color: #0000FF;">DisplayText</span>, StringComparison.<span style="color: #0000FF;">OrdinalIgnoreCase</span> <span style="color: #000000;">&#41;</span> <span style="color: #000000;">&#41;</span> <span style="color: #008000;">-</span> <span style="color: #FF0000;">1</span><span style="color: #008000;">;</span>
                    <span style="color: #008080; font-style: italic;">// Give preference to the more recent match. Note that LastIndexOf() returns -1 if the item wasn't found,</span>
                    <span style="color: #008080; font-style: italic;">// so if the item doesn't have a case-sensitive match, withoutCase always has the higher value.</span>
                    <span style="color: #0600FF;">return</span> Math.<span style="color: #0000FF;">Max</span><span style="color: #000000;">&#40;</span> withCase, withoutCase <span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
                <span style="color: #000000;">&#125;</span> <span style="color: #000000;">&#41;</span>
                .<span style="color: #0000FF;">FirstOrDefault</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
&nbsp;
            <span style="color: #0600FF;">if</span> <span style="color: #000000;">&#40;</span> declaration <span style="color: #008000;">!=</span> <span style="color: #0600FF;">null</span> <span style="color: #000000;">&#41;</span>
            <span style="color: #000000;">&#123;</span>
                index <span style="color: #008000;">=</span> declaration.<span style="color: #0000FF;">Index</span><span style="color: #008000;">;</span>
            <span style="color: #000000;">&#125;</span>
        <span style="color: #000000;">&#125;</span>
    <span style="color: #000000;">&#125;</span>
    <span style="color: #0600FF;">public</span> <span style="color: #0600FF;">override</span> <span style="color: #FF0000;">string</span> OnCommit<span style="color: #000000;">&#40;</span> IVsTextView textView, <span style="color: #FF0000;">string</span> textSoFar, <span style="color: #FF0000;">char</span> commitCharacter, <span style="color: #FF0000;">int</span> index, <span style="color: #0600FF;">ref</span> TextSpan initialExtent <span style="color: #000000;">&#41;</span>
    <span style="color: #000000;">&#123;</span>
        <span style="color: #FF0000;">string</span> committed <span style="color: #008000;">=</span> <span style="color: #0600FF;">base</span>.<span style="color: #0000FF;">OnCommit</span><span style="color: #000000;">&#40;</span> textView, textSoFar, commitCharacter, index, <span style="color: #0600FF;">ref</span> initialExtent <span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
        InsertUsedItem<span style="color: #000000;">&#40;</span> committed <span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
        <span style="color: #0600FF;">return</span> committed<span style="color: #008000;">;</span>
    <span style="color: #000000;">&#125;</span>
<span style="color: #000000;">&#125;</span></pre></td></tr></table></div>


</div>
]]></content:encoded>
			<wfw:commentRss>http://blog.280z28.org/archives/2008/10/20/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
