<?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>Mike Feingold&#039;s Adventures in programming &#187; vseditor</title>
	<atom:link href="http://www.hill30.com/MikeFeingoldBlog/index.php/category/vs-extensibility/vseditor/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.hill30.com/MikeFeingoldBlog</link>
	<description>In my journey through technologies Microsoft and otherwise I faced many wonders good and bad, useful and dangerous. For some time now I live with a growing feeling that some of my encounters can be of interest for people beyond the immediate circle of my friends. This blog is my attempt to share with you some of my stories.</description>
	<lastBuildDate>Thu, 12 Aug 2010 20:23:43 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.4</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>NDjango editor for VS2010 &#8211; 2 down 1 to go</title>
		<link>http://www.hill30.com/MikeFeingoldBlog/index.php/2010/03/15/ndjango-editor-for-vs2010-2-down-1-to-go/</link>
		<comments>http://www.hill30.com/MikeFeingoldBlog/index.php/2010/03/15/ndjango-editor-for-vs2010-2-down-1-to-go/#comments</comments>
		<pubDate>Mon, 15 Mar 2010 17:35:02 +0000</pubDate>
		<dc:creator>Michael Feingold</dc:creator>
				<category><![CDATA[VS Extensibility]]></category>
		<category><![CDATA[django]]></category>
		<category><![CDATA[vseditor]]></category>

		<guid isPermaLink="false">http://www.hill30.com/MikeFeingoldBlog/?p=333</guid>
		<description><![CDATA[From VS2010 Beta 1 to Beta 2 and now to RC. I will still need to port it (the editor) once more - from RC to the RTM, but for now enjoy the RC compatible version of the editor 
This post is about my experience with the port and it will be really short because [...]]]></description>
			<content:encoded><![CDATA[<p>From VS2010 Beta 1 to Beta 2 and now to RC. I will still need to port it (the editor) once more - from RC to the RTM, but for now enjoy the RC compatible version of the <a href="http://ndjango.org/index.php?title=Downloads" target="_blank">editor </a></p>
<p>This post is about my experience with the port and it will be really short because the port was pretty uneventful.</p>
<p>First of all the Intellisense Source interfaces (IQuickInfoSource, ICompletionSource) no longer have Get...Information methods. They have Augment...Session instead. Which for me makes more sense because now you can not only add completion sets from the source but also examine and even change existing elements in the completion set. These interfaces now also sport a Dispose method to help with the resource cleanup.</p>
<p>The changes were easy  - move the logic from GetCompletionInformation/GetToolTipContent method to the appropriate Augment method and add an empty Dispose method. Another small change is that there SquiggleTag is no longer which only made my life easier because now instead of deriving my own ErrorTag from SquiglleTag I can use the predefined ErrorTag.</p>
<p>And this is pretty much it.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.hill30.com/MikeFeingoldBlog/index.php/2010/03/15/ndjango-editor-for-vs2010-2-down-1-to-go/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Moving to VS2010 Beta 2</title>
		<link>http://www.hill30.com/MikeFeingoldBlog/index.php/2009/10/21/moving-to-vs2010-beta-2/</link>
		<comments>http://www.hill30.com/MikeFeingoldBlog/index.php/2009/10/21/moving-to-vs2010-beta-2/#comments</comments>
		<pubDate>Wed, 21 Oct 2009 21:57:07 +0000</pubDate>
		<dc:creator>Michael Feingold</dc:creator>
				<category><![CDATA[django]]></category>
		<category><![CDATA[vseditor]]></category>

		<guid isPermaLink="false">http://www.hill30.com/MikeFeingoldBlog/?p=253</guid>
		<description><![CDATA[First let me tell you that as much as I liked VS2010 Beta 1 I like the VS2010 Beta 2 much better. I will leave it to other guys to write  about the new UI, new features, much improved speed etc., so that in my post I can focus on what is closer to [...]]]></description>
			<content:encoded><![CDATA[<p>First let me tell you that as much as I liked VS2010 Beta 1 I like the VS2010 Beta 2 much better. I will leave it to other guys to write  about the new UI, new features, much improved speed etc., so that in my post I can focus on what is closer to me, VS Integration.</p>
<p>What I want to share with you here is a journal of what I did to port  my Django editor from Beta 1 to Beta 2 - I just got it running on Beta2. Let me start with telling you that I did not run into any major issues. Here is a list of what changes in the API affected Django editor and what I did to address the issues:</p>
<ul>
<li>Interface Microsoft.VisualStudio.ApplicationModel.Environments.IEnvironment is gone. As a matter of fact the entire Microsoft.VisualStudio.ApplicationModel namespace is no longer. This interface was used in a number of methods. In Beta 2 all these methods (at least the ones I used) are one parameter short. So the fix was easy - I just changed the signatures.</li>
<li>Microsoft.VisualStudio.Language.Intellisense.Completion constructor signature has changed. I need the insert value to be different from the display value, and the only constructor which gives a way to do that now also wants some information about icons. This is nothing too - gave it a null and an empty string to keep it happy</li>
<li>The Microsoft.VisualStudio.Text.ContentType.TypeName which used to be "text" now is "plaintext". This is a little more subtle - primarily because the compiler does not catch it, just need to be thorough to change it everywhere. Also I relied on context to skip certain buffers, in particular the buffers created to hold the tooltip text. I had to find a different way to do that.</li>
<li>The Microsoft.VisualStudio.Language.Intellisense.IQuickInfoSource.GetToolTipContent now returns ReadOnlyCollection&lt;object&gt; rather than an object - fine, I do not care about returning multiple, just wrapped my string into a collection and returned it</li>
<li>A few changes in the F# - namely due to rename rethrow() to reraise() and deprecation of the OverloadID attribute.</li>
<li>And finally the biggest change. Both Code Completion and Quick Info used to relay on broker map services, respectively ICompletionBrokerMapService andIQuickInfoBrokerMapService. These services maintained maps of brokers to textViews. No longer. Now Visual Studio maintains a single instance of ICompletionBroker as well as IQuickInfoBroker both to be accessed by directly importing them when necessary. An extra positive from this change was that  simplifying the code by throwing away the code related to mapping services showed me the path to streamline the way I work with projection buffers  in HTML editor and XML editor.</li>
</ul>
<p>And this is pretty much it. Of course I had to mess around with project settings, missing F# dlls, changed format for vsix manifest etc., but this is to be expected. Anyway now I have a version of the Django editor for Beta 2.  Right now I have it in the subversion. I will release it in binaries shortly.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.hill30.com/MikeFeingoldBlog/index.php/2009/10/21/moving-to-vs2010-beta-2/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Django Editor in VS2010 &#8211; more speed needed</title>
		<link>http://www.hill30.com/MikeFeingoldBlog/index.php/2009/09/22/django-editor-in-vs2010-more-speed-needed/</link>
		<comments>http://www.hill30.com/MikeFeingoldBlog/index.php/2009/09/22/django-editor-in-vs2010-more-speed-needed/#comments</comments>
		<pubDate>Tue, 22 Sep 2009 19:42:24 +0000</pubDate>
		<dc:creator>Michael Feingold</dc:creator>
				<category><![CDATA[django]]></category>
		<category><![CDATA[vseditor]]></category>

		<guid isPermaLink="false">http://www.hill30.com/MikeFeingoldBlog/?p=232</guid>
		<description><![CDATA[Last week I asked Alex to give the editor a 'real try' and try to break it. Guess what - he did it. All he did was he opened a template of a reasonable size and started typing. He types fast and as he typed the editor slowed to a crawl.
And understandably so. Here is [...]]]></description>
			<content:encoded><![CDATA[<p>Last week I asked Alex to give the editor a 'real try' and try to break it. Guess what - he did it. All he did was he opened a template of a reasonable size and started typing. He types fast and as he typed the editor slowed to a crawl.</p>
<p>And understandably so. Here is what's happening. Every keystroke is a change to the buffer with the template source code. It triggers the Change event on the buffer, which in turn initiates re-parsing of the template using updated template source. Yes, parsing is happening in a separate thread, and a single parsing request is something the parser can easily handle in the background without noticeable effect on the UI, but for bigger templates it can take some time for parsing to complete and with the typing speed of 10-15 keystrokes per second the requests start to pile up.</p>
<p>Thankfully there is no need to do it anew every time a key is hit - all we need is to parse the last one. Essentially when I type fast I do not really care for the parsing results, but when I pause in my typing I would like to see how good is what I've done so far.</p>
<p>I already discussed the parsing speed issue in the <a href="http://www.hill30.com/MikeFeingoldBlog/index.php/2009/08/02/django-editor-in-vs-2010-part-2-background-parsing/" target="_self">Part 2 Background Parsing </a>of the editor series. I listed there some things which can be done to address the speed issue. I implemented them all from the get go, except for the last one - the parsing requests queuing. And when Alex broke my beautiful editor, I realized that I am not getting away without implementing the queuing too.</p>
<p>Here is what I need: every time a parsing request comes in I schedule its execution for .5 sec in the future. If during the delay another request comes in, instead of creating a new request, I reschedule the active request so it is still set to run .5 sec after the last buffer modification. Once this delay is implemented parser will not run until there is a .5 sec pause in buffer modifications. In other words all requests with less then .5 sec time between them will be combined into one.</p>
<p>And here is the code to do this:</p>

<div class="wp_syntax"><div class="code"><pre class="csharp" style="font-family:monospace;">        <span style="color: #0600FF;color: #0000FF;">public</span> NodeProvider<span style="color: #000000;color: #000000;">&#40;</span>IVsOutputWindowPane djangoDiagnostics, IParser parser, ITextBuffer buffer<span style="color: #000000;color: #000000;">&#41;</span>
        <span style="color: #000000;color: #000000;">&#123;</span>
            <span style="color: #0600FF;color: #0000FF;">this</span>.<span style="color: #000000;">djangoDiagnostics</span> <span style="color: #008000;color: #000000;">=</span> djangoDiagnostics<span style="color: #008000;color: #000000;">;</span>
            <span style="color: #0600FF;color: #0000FF;">this</span>.<span style="color: #000000;">parser</span> <span style="color: #008000;color: #000000;">=</span> parser<span style="color: #008000;color: #000000;">;</span>
            <span style="color: #0600FF;color: #0000FF;">this</span>.<span style="color: #000000;">buffer</span> <span style="color: #008000;color: #000000;">=</span> buffer<span style="color: #008000;color: #000000;">;</span>
            filePath <span style="color: #008000;color: #000000;">=</span> <span style="color: #000000;color: #000000;">&#40;</span><span style="color: #000000;color: #000000;">&#40;</span>ITextDocument<span style="color: #000000;color: #000000;">&#41;</span>buffer.<span style="color: #000000;">Properties</span><span style="color: #000000;color: #000000;">&#91;</span><span style="color: #008000;color: #0000FF;">typeof</span><span style="color: #000000;color: #000000;">&#40;</span>ITextDocument<span style="color: #000000;color: #000000;">&#41;</span><span style="color: #000000;color: #000000;">&#93;</span><span style="color: #000000;color: #000000;">&#41;</span>.<span style="color: #000000;">FilePath</span><span style="color: #008000;color: #000000;">;</span>
            buffer.<span style="color: #000000;">Changed</span> <span style="color: #008000;color: #000000;">+=</span> <span style="color: #008000;color: #0000FF;">new</span> EventHandler<span style="color: #000000;color: #000000;">&#40;</span>buffer_Changed<span style="color: #000000;color: #000000;">&#41;</span><span style="color: #008000;color: #000000;">;</span>
            <span style="color: #008080; font-style: italic;color: #008000;">// we need to run rebuildNodes on a separate thread. Using timer</span>
            <span style="color: #008080; font-style: italic;color: #008000;">// for this seems to be an overkill, but we need the timer anyway so - why not</span>
            parserTimer <span style="color: #008000;color: #000000;">=</span>
                <span style="color: #008000;color: #0000FF;">new</span> Timer<span style="color: #000000;color: #000000;">&#40;</span>rebuildNodes, buffer.<span style="color: #000000;">CurrentSnapshot</span>, <span style="color: #FF0000;color: #000000;">0</span>, Timeout.<span style="color: #000000;">Infinite</span><span style="color: #000000;color: #000000;">&#41;</span><span style="color: #008000;color: #000000;">;</span>
        <span style="color: #000000;color: #000000;">&#125;</span>
&nbsp;
        <span style="color: #008080; font-style: italic;color: #008000;">/// Initiates the delayed parsing in response to the buffer changed event</span>
        <span style="color: #0600FF;color: #0000FF;">private</span> <span style="color: #0600FF;color: #0000FF;">void</span> buffer_Changed<span style="color: #000000;color: #000000;">&#40;</span><span style="color: #FF0000;color: #0000FF;">object</span> sender, TextContentChangedEventArgs e<span style="color: #000000;color: #000000;">&#41;</span>
        <span style="color: #000000;color: #000000;">&#123;</span>
            <span style="color: #008080; font-style: italic;color: #008000;">// shut down the old one</span>
            parserTimer.<span style="color: #000000;">Dispose</span><span style="color: #000000;color: #000000;">&#40;</span><span style="color: #000000;color: #000000;">&#41;</span><span style="color: #008000;color: #000000;">;</span>
&nbsp;
            <span style="color: #008080; font-style: italic;color: #008000;">// put the call to the rebuildNodes on timer</span>
            parserTimer <span style="color: #008000;color: #000000;">=</span>  <span style="color: #008000;color: #0000FF;">new</span> Timer<span style="color: #000000;color: #000000;">&#40;</span>rebuildNodes,  e.<span style="color: #000000;">After</span>,  PARSING_DELAY, Timeout.<span style="color: #000000;">Infinite</span><span style="color: #000000;color: #000000;">&#41;</span><span style="color: #008000;color: #000000;">;</span>
        <span style="color: #000000;color: #000000;">&#125;</span></pre></div></div>

]]></content:encoded>
			<wfw:commentRss>http://www.hill30.com/MikeFeingoldBlog/index.php/2009/09/22/django-editor-in-vs2010-more-speed-needed/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Visual Studio services and VS Editor extensions</title>
		<link>http://www.hill30.com/MikeFeingoldBlog/index.php/2009/09/08/visual-studio-services-and-vs-editor-extensions/</link>
		<comments>http://www.hill30.com/MikeFeingoldBlog/index.php/2009/09/08/visual-studio-services-and-vs-editor-extensions/#comments</comments>
		<pubDate>Tue, 08 Sep 2009 18:29:40 +0000</pubDate>
		<dc:creator>Michael Feingold</dc:creator>
				<category><![CDATA[VS Extensibility]]></category>
		<category><![CDATA[vseditor]]></category>

		<guid isPermaLink="false">http://www.hill30.com/MikeFeingoldBlog/?p=228</guid>
		<description><![CDATA[If you are familiar with Visual Studio Integration SDK you already know that "...Creating a VSPackage is a powerful way to extend Visual Studio...". You probably also know that VSPackages use Services to interact with each other and the core of the Visual Studio. Many components of the Visual Studio core are packages and can be [...]]]></description>
			<content:encoded><![CDATA[<p>If you are familiar with Visual Studio Integration SDK you already know that "...Creating a VSPackage is a powerful way to extend Visual Studio...". You probably also know that VSPackages use Services to interact with each other and the core of the Visual Studio. Many components of the Visual Studio core are packages and can be accessed as services. To access a service all you need is an appropriate service provider implementing the IServiceProvider interface. You also need to know the type of the service you want to access. Once you have both - call the GetService method on the provider and it will return the service you desire. All of this is good and handy when you are building your own VSPackage.</p>
<p>What about Visual Studio Editor extensions? What if all you are planning is an editor extension with just one small thing which goes beyond editor?</p>
<p>Guess what - all this wealth of the Visual Studio core services is still available to you without the formal frame of the VSPackage. It is available, that is, if you can get your hands on a service provider which is aware of the service you are after.</p>
<p>In my <a href="http://www.ndjango.com" target="_blank">NDjango designer</a> in addition to syntax colorization, code completion and other wonders of the Visual Studio Editor extensions I wanted to show the errors in both the Error List and a separate pane of the Output Window. There is a variety of ways to do it. </p>
<p>In NDjango designer it is done in NodeProviderBroker object by accessing the IVsOutputWindow service. Once I have the service I use its CreatePane method to create the Django Output pane (an IVsOutuptWindowPane object). And then, in the NodeSnapshot object I generate the messages using the OutpuTaskItemString method. You can find examples of how to use these services on the web and in the Visual Studio SDK, as well as in the source code of the <a href="http://ndjango.org/index.php?title=Future" target="_blank">NDjango designer</a></p>
<p>What is somewhat less obvious is how do you get to the starting point - the IVsOutputWindow service. It is promised that in the future it will be as easy as importing the ServiceProvider, and then calling the GetService method on the service provider. We are not there yet, so here is what I did to get by for now:</p>

<div class="wp_syntax"><div class="code"><pre class="csharp" style="font-family:monospace;">        <span style="color: #0600FF;color: #0000FF;">private</span> <span style="color: #FF0000;color: #0000FF;">object</span> GetService<span style="color: #000000;color: #000000;">&#40;</span>ITextBuffer textBuffer, Type type<span style="color: #000000;color: #000000;">&#41;</span>
        <span style="color: #000000;color: #000000;">&#123;</span>
            var vsBuffer <span style="color: #008000;color: #000000;">=</span> adaptersFactory.<span style="color: #000000;">GetBufferAdapter</span><span style="color: #000000;color: #000000;">&#40;</span>textBuffer<span style="color: #000000;color: #000000;">&#41;</span><span style="color: #008000;color: #000000;">;</span>
            <span style="color: #0600FF;color: #0000FF;">if</span> <span style="color: #000000;color: #000000;">&#40;</span>vsBuffer <span style="color: #008000;color: #000000;">==</span> <span style="color: #0600FF;color: #0000FF;">null</span><span style="color: #000000;color: #000000;">&#41;</span>
                <span style="color: #0600FF;color: #0000FF;">return</span> null<span style="color: #008000;color: #000000;">;</span>
&nbsp;
            Guid guidServiceProvider <span style="color: #008000;color: #000000;">=</span> VSConstants.<span style="color: #000000;">IID_IUnknown</span><span style="color: #008000;color: #000000;">;</span>
            IObjectWithSite objectWithSite <span style="color: #008000;color: #000000;">=</span> vsBuffer <span style="color: #0600FF;color: #0000FF;">as</span> IObjectWithSite<span style="color: #008000;color: #000000;">;</span>
            IntPtr ptrServiceProvider <span style="color: #008000;color: #000000;">=</span> IntPtr.<span style="color: #000000;">Zero</span><span style="color: #008000;color: #000000;">;</span>
            objectWithSite.<span style="color: #000000;">GetSite</span><span style="color: #000000;color: #000000;">&#40;</span><span style="color: #0600FF;color: #0000FF;">ref</span> guidServiceProvider, <span style="color: #0600FF;color: #0000FF;">out</span> ptrServiceProvider<span style="color: #000000;color: #000000;">&#41;</span><span style="color: #008000;color: #000000;">;</span>
            Microsoft.<span style="color: #000000;">VisualStudio</span>.<span style="color: #000000;">OLE</span>.<span style="color: #000000;">Interop</span>.<span style="color: #000000;">IServiceProvider</span> serviceProvider <span style="color: #008000;color: #000000;">=</span>
                <span style="color: #000000;color: #000000;">&#40;</span>Microsoft.<span style="color: #000000;">VisualStudio</span>.<span style="color: #000000;">OLE</span>.<span style="color: #000000;">Interop</span>.<span style="color: #000000;">IServiceProvider</span><span style="color: #000000;color: #000000;">&#41;</span>Marshal.<span style="color: #000000;">GetObjectForIUnknown</span><span style="color: #000000;color: #000000;">&#40;</span>ptrServiceProvider<span style="color: #000000;color: #000000;">&#41;</span><span style="color: #008000;color: #000000;">;</span>
&nbsp;
            Guid guidService <span style="color: #008000;color: #000000;">=</span> <span style="color: #008000;color: #0000FF;">typeof</span><span style="color: #000000;color: #000000;">&#40;</span>SVsOutputWindow<span style="color: #000000;color: #000000;">&#41;</span>.<span style="color: #000000;">GUID</span><span style="color: #008000;color: #000000;">;</span>
            Guid guidInterface <span style="color: #008000;color: #000000;">=</span> <span style="color: #008000;color: #0000FF;">typeof</span><span style="color: #000000;color: #000000;">&#40;</span>IVsOutputWindow<span style="color: #000000;color: #000000;">&#41;</span>.<span style="color: #000000;">GUID</span><span style="color: #008000;color: #000000;">;</span>
            IntPtr ptrObject <span style="color: #008000;color: #000000;">=</span> IntPtr.<span style="color: #000000;">Zero</span><span style="color: #008000;color: #000000;">;</span>
&nbsp;
            <span style="color: #FF0000;color: #0000FF;">int</span> hr <span style="color: #008000;color: #000000;">=</span> serviceProvider.<span style="color: #000000;">QueryService</span><span style="color: #000000;color: #000000;">&#40;</span><span style="color: #0600FF;color: #0000FF;">ref</span> guidService, <span style="color: #0600FF;color: #0000FF;">ref</span> guidInterface, <span style="color: #0600FF;color: #0000FF;">out</span> ptrObject<span style="color: #000000;color: #000000;">&#41;</span><span style="color: #008000;color: #000000;">;</span>
            <span style="color: #0600FF;color: #0000FF;">if</span> <span style="color: #000000;color: #000000;">&#40;</span>ErrorHandler.<span style="color: #000000;">Failed</span><span style="color: #000000;color: #000000;">&#40;</span>hr<span style="color: #000000;color: #000000;">&#41;</span> <span style="color: #008000;color: #000000;">||</span> ptrObject <span style="color: #008000;color: #000000;">==</span> IntPtr.<span style="color: #000000;">Zero</span><span style="color: #000000;color: #000000;">&#41;</span>
                <span style="color: #0600FF;color: #0000FF;">return</span> null<span style="color: #008000;color: #000000;">;</span>
&nbsp;
            IVsOutputWindow taskList <span style="color: #008000;color: #000000;">=</span> <span style="color: #000000;color: #000000;">&#40;</span>IVsOutputWindow<span style="color: #000000;color: #000000;">&#41;</span>Marshal.<span style="color: #000000;">GetObjectForIUnknown</span><span style="color: #000000;color: #000000;">&#40;</span>ptrObject<span style="color: #000000;color: #000000;">&#41;</span><span style="color: #008000;color: #000000;">;</span>
            Marshal.<span style="color: #000000;">Release</span><span style="color: #000000;color: #000000;">&#40;</span>ptrObject<span style="color: #000000;color: #000000;">&#41;</span><span style="color: #008000;color: #000000;">;</span>
&nbsp;
            <span style="color: #0600FF;color: #0000FF;">return</span> taskList<span style="color: #008000;color: #000000;">;</span>
        <span style="color: #000000;color: #000000;">&#125;</span></pre></div></div>

<p>This code is based on the code posted by <a href="http://github.com/NoahRic/GoToDef/blob/052b0a2c27bc215460231ab7c05266fea6791dfa/GoToDef/GoToDefMouseHandler.cs" target="_blank">Noah Richards</a> and it uses the text buffer (an object implementing IVsTextBuffer interface) as a gateway to access Visual Studio global services. Works for me.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.hill30.com/MikeFeingoldBlog/index.php/2009/09/08/visual-studio-services-and-vs-editor-extensions/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Django Editor in VS 2010 &#8211; Part 7 (Code Completion &#8211; Source)</title>
		<link>http://www.hill30.com/MikeFeingoldBlog/index.php/2009/09/05/django-editor-in-vs-2010-part-7-code-completion-source/</link>
		<comments>http://www.hill30.com/MikeFeingoldBlog/index.php/2009/09/05/django-editor-in-vs-2010-part-7-code-completion-source/#comments</comments>
		<pubDate>Sun, 06 Sep 2009 01:27:56 +0000</pubDate>
		<dc:creator>Michael Feingold</dc:creator>
				<category><![CDATA[django]]></category>
		<category><![CDATA[vseditor]]></category>

		<guid isPermaLink="false">http://www.hill30.com/MikeFeingoldBlog/?p=215</guid>
		<description><![CDATA[Look here for complete source
Ok. This post is the last and, I hope, the shortest and the simplest one in the Django Editor series. All what's left to cover is the source for the code completion part of the NDjango editor.
To continue line of reasoning from the previous post, the code completion source works in [...]]]></description>
			<content:encoded><![CDATA[<p align="right">Look <a href="http://ndjango.org/index.php?title=Future">here </a>for complete source</p>
<p>Ok. This post is the last and, I hope, the shortest and the simplest one in the Django Editor series. All what's left to cover is the source for the code completion part of the NDjango editor.</p>
<p>To continue line of reasoning from the previous post, the code completion source works in very much the same way as the quick info (see posts <a href="http://www.hill30.com/MikeFeingoldBlog/index.php/2009/08/09/django-editor-in-vs-2010-part-4-quick-info-controller" target="_self">4 </a>and <a href="http://www.hill30.com/MikeFeingoldBlog/index.php/2009/08/13/django-editor-in-vs-2010-part-5-quick-info-source" target="_self">5 </a>of the series). The source provider is registered as an MEF component and creates source objects for text buffers as necessary. Here is the code:</p>

<div class="wp_syntax"><div class="code"><pre class="csharp" style="font-family:monospace;">    <span style="color: #000000;color: #000000;">&#91;</span>Export<span style="color: #000000;color: #000000;">&#40;</span><span style="color: #008000;color: #0000FF;">typeof</span><span style="color: #000000;color: #000000;">&#40;</span>ICompletionSourceProvider<span style="color: #000000;color: #000000;">&#41;</span><span style="color: #000000;color: #000000;">&#41;</span><span style="color: #000000;color: #000000;">&#93;</span>
    <span style="color: #000000;color: #000000;">&#91;</span>Name<span style="color: #000000;color: #000000;">&#40;</span><span style="color: #666666;color: #993300;">&quot;NDjango Completion Source&quot;</span><span style="color: #000000;color: #000000;">&#41;</span><span style="color: #000000;color: #000000;">&#93;</span>
    <span style="color: #000000;color: #000000;">&#91;</span>Order<span style="color: #000000;color: #000000;">&#40;</span>Before <span style="color: #008000;color: #000000;">=</span> <span style="color: #666666;color: #993300;">&quot;default&quot;</span><span style="color: #000000;color: #000000;">&#41;</span><span style="color: #000000;color: #000000;">&#93;</span>
    <span style="color: #000000;color: #000000;">&#91;</span>ContentType<span style="color: #000000;color: #000000;">&#40;</span>Constants.<span style="color: #000000;">NDJANGO</span><span style="color: #000000;color: #000000;">&#41;</span><span style="color: #000000;color: #000000;">&#93;</span>
    <span style="color: #0600FF;color: #0000FF;">internal</span> <span style="color: #FF0000;color: #0000FF;">class</span> SourceProvider <span style="color: #008000;color: #000000;">:</span> ICompletionSourceProvider
    <span style="color: #000000;color: #000000;">&#123;</span>
        <span style="color: #000000;color: #000000;">&#91;</span>Import<span style="color: #000000;color: #000000;">&#93;</span>
        <span style="color: #0600FF;color: #0000FF;">internal</span> INodeProviderBroker nodeProviderBroker <span style="color: #000000;color: #000000;">&#123;</span> get<span style="color: #008000;color: #000000;">;</span> set<span style="color: #008000;color: #000000;">;</span> <span style="color: #000000;color: #000000;">&#125;</span>
&nbsp;
        <span style="color: #0600FF;color: #0000FF;">public</span> ICompletionSource TryCreateCompletionSource<span style="color: #000000;color: #000000;">&#40;</span>ITextBuffer textBuffer, IEnvironment environment<span style="color: #000000;color: #000000;">&#41;</span>
        <span style="color: #000000;color: #000000;">&#123;</span>
            <span style="color: #0600FF;color: #0000FF;">if</span> <span style="color: #000000;color: #000000;">&#40;</span>nodeProviderBroker.<span style="color: #000000;">IsNDjango</span><span style="color: #000000;color: #000000;">&#40;</span>textBuffer, environment<span style="color: #000000;color: #000000;">&#41;</span><span style="color: #000000;color: #000000;">&#41;</span>
                <span style="color: #0600FF;color: #0000FF;">return</span> <span style="color: #008000;color: #0000FF;">new</span> Source<span style="color: #000000;color: #000000;">&#40;</span><span style="color: #000000;color: #000000;">&#41;</span><span style="color: #008000;color: #000000;">;</span>
            <span style="color: #0600FF;color: #0000FF;">return</span> null<span style="color: #008000;color: #000000;">;</span>
        <span style="color: #000000;color: #000000;">&#125;</span>
    <span style="color: #000000;color: #000000;">&#125;</span></pre></div></div>

<p>And the source itself is responsible for providing the code completion data:</p>

<div class="wp_syntax"><div class="code"><pre class="csharp" style="font-family:monospace;">    <span style="color: #0600FF;color: #0000FF;">internal</span> <span style="color: #FF0000;color: #0000FF;">class</span> Source <span style="color: #008000;color: #000000;">:</span> ICompletionSource
    <span style="color: #000000;color: #000000;">&#123;</span>
        <span style="color: #0600FF;color: #0000FF;">public</span> ReadOnlyCollection GetCompletionInformation<span style="color: #000000;color: #000000;">&#40;</span>ICompletionSession session<span style="color: #000000;color: #000000;">&#41;</span>
        <span style="color: #000000;color: #000000;">&#123;</span>
            List completionNodes <span style="color: #008000;color: #000000;">=</span> session.<span style="color: #000000;">Properties</span><span style="color: #000000;color: #000000;">&#91;</span><span style="color: #008000;color: #0000FF;">typeof</span><span style="color: #000000;color: #000000;">&#40;</span>Source<span style="color: #000000;color: #000000;">&#41;</span><span style="color: #000000;color: #000000;">&#93;</span> <span style="color: #0600FF;color: #0000FF;">as</span> List<span style="color: #008000;color: #000000;">;</span>
            <span style="color: #0600FF;color: #0000FF;">if</span> <span style="color: #000000;color: #000000;">&#40;</span>completionNodes <span style="color: #008000;color: #000000;">!=</span> <span style="color: #0600FF;color: #0000FF;">null</span><span style="color: #000000;color: #000000;">&#41;</span>
            <span style="color: #000000;color: #000000;">&#123;</span>
                <span style="color: #008080; font-style: italic;color: #008000;">// Calculate the location of the textspan to be replaced with</span>
                <span style="color: #008080; font-style: italic;color: #008000;">// the selection. We always want to replace the entire word</span>
                ITextSnapshot snapshot <span style="color: #008000;color: #000000;">=</span> session.<span style="color: #000000;">SubjectBuffer</span>.<span style="color: #000000;">CurrentSnapshot</span><span style="color: #008000;color: #000000;">;</span>
                <span style="color: #FF0000;color: #0000FF;">int</span> triggerPoint <span style="color: #008000;color: #000000;">=</span> session.<span style="color: #000000;">TriggerPoint</span>.<span style="color: #000000;">GetPosition</span><span style="color: #000000;color: #000000;">&#40;</span>snapshot<span style="color: #000000;color: #000000;">&#41;</span><span style="color: #008000;color: #000000;">;</span>
                ITextSnapshotLine line <span style="color: #008000;color: #000000;">=</span> snapshot.<span style="color: #000000;">GetLineFromPosition</span><span style="color: #000000;color: #000000;">&#40;</span>triggerPoint<span style="color: #000000;color: #000000;">&#41;</span><span style="color: #008000;color: #000000;">;</span>
                <span style="color: #FF0000;color: #0000FF;">string</span> lineString <span style="color: #008000;color: #000000;">=</span> line.<span style="color: #000000;">GetText</span><span style="color: #000000;color: #000000;">&#40;</span><span style="color: #000000;color: #000000;">&#41;</span><span style="color: #008000;color: #000000;">;</span>
                <span style="color: #008080; font-style: italic;color: #008000;">// position of the first non-space character before the tag name</span>
                <span style="color: #FF0000;color: #0000FF;">int</span> start <span style="color: #008000;color: #000000;">=</span> lineString.<span style="color: #000000;">Substring</span><span style="color: #000000;color: #000000;">&#40;</span><span style="color: #FF0000;color: #000000;">0</span>, triggerPoint <span style="color: #008000;color: #000000;">-</span> line.<span style="color: #000000;">Start</span>.<span style="color: #000000;">Position</span><span style="color: #000000;color: #000000;">&#41;</span>.
                    <span style="color: #000000;">LastIndexOfAny</span><span style="color: #000000;color: #000000;">&#40;</span><span style="color: #008000;color: #0000FF;">new</span> <span style="color: #FF0000;color: #0000FF;">char</span><span style="color: #000000;color: #000000;">&#91;</span><span style="color: #000000;color: #000000;">&#93;</span> <span style="color: #000000;color: #000000;">&#123;</span><span style="color: #666666;color: #993300;">' '</span>, <span style="color: #666666;color: #993300;">'<span style="color: #008080; font-weight: bold;color: #808080;">\t</span>'</span>, <span style="color: #666666;color: #993300;">'%'</span><span style="color: #000000;color: #000000;">&#125;</span><span style="color: #000000;color: #000000;">&#41;</span>
                    <span style="color: #008000;color: #000000;">+</span> line.<span style="color: #000000;">Start</span>.<span style="color: #000000;">Position</span> <span style="color: #008000;color: #000000;">+</span> <span style="color: #FF0000;color: #000000;">1</span><span style="color: #008000;color: #000000;">;</span>
                <span style="color: #008080; font-style: italic;color: #008000;">// length of the word currently in the tag name position in the tag</span>
                <span style="color: #FF0000;color: #0000FF;">int</span> length <span style="color: #008000;color: #000000;">=</span> lineString.<span style="color: #000000;">Substring</span><span style="color: #000000;color: #000000;">&#40;</span>triggerPoint <span style="color: #008000;color: #000000;">-</span> line.<span style="color: #000000;">Start</span>.<span style="color: #000000;">Position</span><span style="color: #000000;color: #000000;">&#41;</span>.
                    <span style="color: #000000;">IndexOfAny</span><span style="color: #000000;color: #000000;">&#40;</span><span style="color: #008000;color: #0000FF;">new</span> <span style="color: #FF0000;color: #0000FF;">char</span><span style="color: #000000;color: #000000;">&#91;</span><span style="color: #000000;color: #000000;">&#93;</span> <span style="color: #000000;color: #000000;">&#123;</span><span style="color: #666666;color: #993300;">' '</span>, <span style="color: #666666;color: #993300;">'<span style="color: #008080; font-weight: bold;color: #808080;">\t</span>'</span>, <span style="color: #666666;color: #993300;">'%'</span><span style="color: #000000;color: #000000;">&#125;</span> <span style="color: #000000;color: #000000;">&#41;</span>
                    <span style="color: #008000;color: #000000;">+</span> triggerPoint <span style="color: #008000;color: #000000;">-</span> start<span style="color: #008000;color: #000000;">;</span>
&nbsp;
                CompletionSet completionSet <span style="color: #008000;color: #000000;">=</span> <span style="color: #008000;color: #0000FF;">new</span> CompletionSet<span style="color: #000000;color: #000000;">&#40;</span>
                    <span style="color: #666666;color: #993300;">&quot;ndjango.completions&quot;</span>,
                    session.<span style="color: #000000;">SubjectBuffer</span>.<span style="color: #000000;">CurrentSnapshot</span>.<span style="color: #000000;">CreateTrackingSpan</span><span style="color: #000000;color: #000000;">&#40;</span>
                    start, length, SpanTrackingMode.<span style="color: #000000;">EdgeInclusive</span><span style="color: #000000;color: #000000;">&#41;</span>,
                    CompletionsForNodes<span style="color: #000000;color: #000000;">&#40;</span>completionNodes<span style="color: #000000;color: #000000;">&#41;</span>,
                    <span style="color: #0600FF;color: #0000FF;">null</span><span style="color: #000000;color: #000000;">&#41;</span><span style="color: #008000;color: #000000;">;</span>
                <span style="color: #0600FF;color: #0000FF;">return</span> <span style="color: #008000;color: #0000FF;">new</span> ReadOnlyCollection<span style="color: #000000;color: #000000;">&#40;</span><span style="color: #008000;color: #0000FF;">new</span> List <span style="color: #000000;color: #000000;">&#123;</span> completionSet <span style="color: #000000;color: #000000;">&#125;</span><span style="color: #000000;color: #000000;">&#41;</span><span style="color: #008000;color: #000000;">;</span>
            <span style="color: #000000;color: #000000;">&#125;</span>
&nbsp;
            <span style="color: #0600FF;color: #0000FF;">return</span> null<span style="color: #008000;color: #000000;">;</span>
        <span style="color: #000000;color: #000000;">&#125;</span>
&nbsp;
        <span style="color: #0600FF;color: #0000FF;">private</span> IEnumerable CompletionsForNodes<span style="color: #000000;color: #000000;">&#40;</span>IEnumerable nodes<span style="color: #000000;color: #000000;">&#41;</span>
        <span style="color: #000000;color: #000000;">&#123;</span>
            <span style="color: #0600FF;color: #0000FF;">foreach</span> <span style="color: #000000;color: #000000;">&#40;</span>INode node <span style="color: #0600FF;color: #0000FF;">in</span> nodes<span style="color: #000000;color: #000000;">&#41;</span>
                <span style="color: #0600FF;color: #0000FF;">foreach</span> <span style="color: #000000;color: #000000;">&#40;</span><span style="color: #FF0000;color: #0000FF;">string</span> value <span style="color: #0600FF;color: #0000FF;">in</span> node.<span style="color: #000000;">Values</span><span style="color: #000000;color: #000000;">&#41;</span>
                    yield <span style="color: #0600FF;color: #0000FF;">return</span> <span style="color: #008000;color: #0000FF;">new</span> Completion<span style="color: #000000;color: #000000;">&#40;</span>value, value, value<span style="color: #000000;color: #000000;">&#41;</span><span style="color: #008000;color: #000000;">;</span>
        <span style="color: #000000;color: #000000;">&#125;</span>
    <span style="color: #000000;color: #000000;">&#125;</span></pre></div></div>

<p>Even though it is pretty easy to create a custom code completion presenter, I decided against creating my own presenter. And the only thing you need to do to make the standard one work is to feed it with a list of code completion sets in return value of the GetCompletionInformation method. One of the parameters you have to provide when creating your completion set is the tracking span. This tracking span determines what text will be replaced by the value selected by the user from the list of available values.</p>
<p>The rest of the voodoo in the code shown above has to do with calculation of this tracking span as well as building the list of values to show.</p>
<p>And this concludes our discussion of building django editor for Visual Studio 2010. As of the time of this writing I am getting ready to roll out a beta version of the django designer.</p>
<p>Looking back at as the project comes to completion, I can safely say that as planned the project consisted of two parts - extending the django parser for more detailed diagnostics and building the Visual Studio Editor capable of consuming the information. Of course, during the course of the project there were some design challenges. To my pleasant surprise almost all of them were related to the django parser rather than the actual editor code.</p>
<p>When I just started the project after the first look at the VSEditor I was saying that building custom editors in Visual Studio 2010 is a breeze. Now, when the project is at its completion, I still stand by my statement.</p>
<p>P.S. The project is open source, so feel free to browse the source code in the <a href="http://code.google.com/p/ndjango/source/browse/NDjango" target="_blank">subversion repository</a>. Currently the source code is in the development branch called VS2010Designer. The project is still in development, so there will be changes from the code published in the log. If you are want to look at the code matching exactly the code published in the posts look at the tag I created for this purpose. The tag name is Designer_blog_version. I hope you will find it helpful</p>
]]></content:encoded>
			<wfw:commentRss>http://www.hill30.com/MikeFeingoldBlog/index.php/2009/09/05/django-editor-in-vs-2010-part-7-code-completion-source/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Django Editor in VS 2010 &#8211; Part 6 (Code Completion &#8211; Controller)</title>
		<link>http://www.hill30.com/MikeFeingoldBlog/index.php/2009/09/03/django-editor-in-vs-2010-part-6-code-completion-controller/</link>
		<comments>http://www.hill30.com/MikeFeingoldBlog/index.php/2009/09/03/django-editor-in-vs-2010-part-6-code-completion-controller/#comments</comments>
		<pubDate>Thu, 03 Sep 2009 19:06:13 +0000</pubDate>
		<dc:creator>Michael Feingold</dc:creator>
				<category><![CDATA[django]]></category>
		<category><![CDATA[vseditor]]></category>

		<guid isPermaLink="false">http://www.hill30.com/MikeFeingoldBlog/?p=194</guid>
		<description><![CDATA[Look here for complete source
Code completion is the final piece of the NDjango designer. With code completion out of the way, the NDjango template editor all of us care so much about will be complete. OK. Let us get it over with.
The overall structure of the code completion code is very similar to the QuickInfo [...]]]></description>
			<content:encoded><![CDATA[<p align="right">Look <a href="http://ndjango.org/index.php?title=Future">here </a>for complete source</p>
<p>Code completion is the final piece of the NDjango designer. With code completion out of the way, the NDjango template editor all of us care so much about will be complete. OK. Let us get it over with.</p>
<p>The overall structure of the code completion code is very similar to the QuickInfo code I covered in two previous postings. As was the case with the QuickInfo, there are two classes, Controller and ControllerProvider controlling the session - in this case the Completion session and two more classes Source and SourceProvider providing the data to be displayed. As with the QuickInfo the Controller class instances are created by the Controller provider for all relevant TextViews and once attached to the buffers, Controllers create and dismiss the sessions.</p>
<p>Here is the code of my code completion controller provider:</p>

<div class="wp_syntax"><div class="code"><pre class="csharp" style="font-family:monospace;">    <span style="color: #000000;color: #000000;">&#91;</span>Export<span style="color: #000000;color: #000000;">&#40;</span><span style="color: #008000;color: #0000FF;">typeof</span><span style="color: #000000;color: #000000;">&#40;</span>IIntellisenseControllerProvider<span style="color: #000000;color: #000000;">&#41;</span><span style="color: #000000;color: #000000;">&#41;</span><span style="color: #000000;color: #000000;">&#93;</span>
    <span style="color: #000000;color: #000000;">&#91;</span>Name<span style="color: #000000;color: #000000;">&#40;</span><span style="color: #666666;color: #993300;">&quot;NDjango Completion Controller&quot;</span><span style="color: #000000;color: #000000;">&#41;</span><span style="color: #000000;color: #000000;">&#93;</span>
    <span style="color: #000000;color: #000000;">&#91;</span>Order<span style="color: #000000;color: #000000;">&#40;</span>Before <span style="color: #008000;color: #000000;">=</span> <span style="color: #666666;color: #993300;">&quot;Default Completion Controller&quot;</span><span style="color: #000000;color: #000000;">&#41;</span><span style="color: #000000;color: #000000;">&#93;</span>
    <span style="color: #000000;color: #000000;">&#91;</span>ContentType<span style="color: #000000;color: #000000;">&#40;</span>Constants.<span style="color: #000000;">NDJANGO</span><span style="color: #000000;color: #000000;">&#41;</span><span style="color: #000000;color: #000000;">&#93;</span>
    <span style="color: #0600FF;color: #0000FF;">internal</span> <span style="color: #FF0000;color: #0000FF;">class</span> ControllerProvider <span style="color: #008000;color: #000000;">:</span> IIntellisenseControllerProvider
    <span style="color: #000000;color: #000000;">&#123;</span>
        <span style="color: #000000;color: #000000;">&#91;</span>Import<span style="color: #000000;color: #000000;">&#93;</span>
        <span style="color: #0600FF;color: #0000FF;">internal</span> ICompletionBrokerMapService CompletionBrokerMapService <span style="color: #000000;color: #000000;">&#123;</span> get<span style="color: #008000;color: #000000;">;</span> set<span style="color: #008000;color: #000000;">;</span> <span style="color: #000000;color: #000000;">&#125;</span>
&nbsp;
        <span style="color: #000000;color: #000000;">&#91;</span>Import<span style="color: #000000;color: #000000;">&#93;</span>
        <span style="color: #0600FF;color: #0000FF;">internal</span> INodeProviderBroker nodeProviderBroker <span style="color: #000000;color: #000000;">&#123;</span> get<span style="color: #008000;color: #000000;">;</span> set<span style="color: #008000;color: #000000;">;</span> <span style="color: #000000;color: #000000;">&#125;</span>
&nbsp;
        <span style="color: #000000;color: #000000;">&#91;</span>Import<span style="color: #000000;color: #000000;">&#93;</span>
        <span style="color: #0600FF;color: #0000FF;">internal</span> IVsEditorAdaptersFactoryService adaptersFactory <span style="color: #000000;color: #000000;">&#123;</span> get<span style="color: #008000;color: #000000;">;</span> set<span style="color: #008000;color: #000000;">;</span> <span style="color: #000000;color: #000000;">&#125;</span>
&nbsp;
        <span style="color: #0600FF;color: #0000FF;">public</span> IIntellisenseController TryCreateIntellisenseController<span style="color: #000000;color: #000000;">&#40;</span>ITextView textView, IList subjectBuffers, IEnvironment context<span style="color: #000000;color: #000000;">&#41;</span>
        <span style="color: #000000;color: #000000;">&#123;</span>
            <span style="color: #FF0000;color: #0000FF;">bool</span> brokerCreated <span style="color: #008000;color: #000000;">=</span> false<span style="color: #008000;color: #000000;">;</span>
            <span style="color: #0600FF;color: #0000FF;">foreach</span> <span style="color: #000000;color: #000000;">&#40;</span>ITextBuffer subjectBuffer <span style="color: #0600FF;color: #0000FF;">in</span> subjectBuffers<span style="color: #000000;color: #000000;">&#41;</span>
                <span style="color: #0600FF;color: #0000FF;">if</span> <span style="color: #000000;color: #000000;">&#40;</span>nodeProviderBroker.<span style="color: #000000;">IsNDjango</span><span style="color: #000000;color: #000000;">&#40;</span>subjectBuffer, context<span style="color: #000000;color: #000000;">&#41;</span><span style="color: #000000;color: #000000;">&#41;</span>
                    brokerCreated <span style="color: #008000;color: #000000;">|=</span> <span style="color: #000000;color: #000000;">&#40;</span>CompletionBrokerMapService.<span style="color: #000000;">GetBrokerForTextView</span><span style="color: #000000;color: #000000;">&#40;</span>textView, subjectBuffer<span style="color: #000000;color: #000000;">&#41;</span> <span style="color: #008000;color: #000000;">!=</span> <span style="color: #0600FF;color: #0000FF;">null</span><span style="color: #000000;color: #000000;">&#41;</span><span style="color: #008000;color: #000000;">;</span>
&nbsp;
            <span style="color: #0600FF;color: #0000FF;">if</span> <span style="color: #000000;color: #000000;">&#40;</span>brokerCreated<span style="color: #000000;color: #000000;">&#41;</span>
                <span style="color: #0600FF;color: #0000FF;">return</span> <span style="color: #008000;color: #0000FF;">new</span> Controller<span style="color: #000000;color: #000000;">&#40;</span><span style="color: #0600FF;color: #0000FF;">this</span>, subjectBuffers, textView, context<span style="color: #000000;color: #000000;">&#41;</span><span style="color: #008000;color: #000000;">;</span>
&nbsp;
            <span style="color: #0600FF;color: #0000FF;">return</span> null<span style="color: #008000;color: #000000;">;</span>
        <span style="color: #000000;color: #000000;">&#125;</span>
    <span style="color: #000000;color: #000000;">&#125;</span></pre></div></div>

<p>Nothing really new or exciting here. The controller itself is somewhat longer. I still decided to include the complete source code for the class, but you are welcome to scroll all the way through the code to the notes down below:</p>

<div class="wp_syntax"><div class="code"><pre class="csharp" style="font-family:monospace;">    <span style="color: #FF0000;color: #0000FF;">class</span> Controller <span style="color: #008000;color: #000000;">:</span> IIntellisenseController, IOleCommandTarget
    <span style="color: #000000;color: #000000;">&#123;</span>
        <span style="color: #0600FF;color: #0000FF;">private</span> IList subjectBuffers<span style="color: #008000;color: #000000;">;</span>
        <span style="color: #0600FF;color: #0000FF;">private</span> ITextView subjectTextView<span style="color: #008000;color: #000000;">;</span>
        <span style="color: #0600FF;color: #0000FF;">private</span> IWpfTextView WpfTextView<span style="color: #008000;color: #000000;">;</span>
        <span style="color: #0600FF;color: #0000FF;">private</span> ICompletionSession activeSession<span style="color: #008000;color: #000000;">;</span>
        <span style="color: #0600FF;color: #0000FF;">private</span> IEnvironment context<span style="color: #008000;color: #000000;">;</span>
        <span style="color: #0600FF;color: #0000FF;">private</span> ControllerProvider provider<span style="color: #008000;color: #000000;">;</span>
&nbsp;
        <span style="color: #0600FF;color: #0000FF;">public</span> Controller<span style="color: #000000;color: #000000;">&#40;</span>ControllerProvider provider, IList subjectBuffers, ITextView subjectTextView, IEnvironment context<span style="color: #000000;color: #000000;">&#41;</span>
        <span style="color: #000000;color: #000000;">&#123;</span>
            <span style="color: #0600FF;color: #0000FF;">this</span>.<span style="color: #000000;">provider</span> <span style="color: #008000;color: #000000;">=</span> provider<span style="color: #008000;color: #000000;">;</span>
            <span style="color: #0600FF;color: #0000FF;">this</span>.<span style="color: #000000;">subjectBuffers</span> <span style="color: #008000;color: #000000;">=</span> subjectBuffers<span style="color: #008000;color: #000000;">;</span>
            <span style="color: #0600FF;color: #0000FF;">this</span>.<span style="color: #000000;">subjectTextView</span> <span style="color: #008000;color: #000000;">=</span> subjectTextView<span style="color: #008000;color: #000000;">;</span>
            <span style="color: #0600FF;color: #0000FF;">this</span>.<span style="color: #000000;">context</span> <span style="color: #008000;color: #000000;">=</span> context<span style="color: #008000;color: #000000;">;</span>
&nbsp;
            WpfTextView <span style="color: #008000;color: #000000;">=</span> subjectTextView <span style="color: #0600FF;color: #0000FF;">as</span> IWpfTextView<span style="color: #008000;color: #000000;">;</span>
            <span style="color: #0600FF;color: #0000FF;">if</span> <span style="color: #000000;color: #000000;">&#40;</span>WpfTextView <span style="color: #008000;color: #000000;">!=</span> <span style="color: #0600FF;color: #0000FF;">null</span><span style="color: #000000;color: #000000;">&#41;</span>
            <span style="color: #000000;color: #000000;">&#123;</span>
                WpfTextView.<span style="color: #000000;">VisualElement</span>.<span style="color: #000000;">KeyDown</span> <span style="color: #008000;color: #000000;">+=</span> <span style="color: #008000;color: #0000FF;">new</span> <span style="color: #000000;">System</span>.<span style="color: #000000;">Windows</span>.<span style="color: #000000;">Input</span>.<span style="color: #000000;">KeyEventHandler</span><span style="color: #000000;color: #000000;">&#40;</span>VisualElement_KeyDown<span style="color: #000000;color: #000000;">&#41;</span><span style="color: #008000;color: #000000;">;</span>
                WpfTextView.<span style="color: #000000;">VisualElement</span>.<span style="color: #000000;">KeyUp</span> <span style="color: #008000;color: #000000;">+=</span> <span style="color: #008000;color: #0000FF;">new</span> <span style="color: #000000;">System</span>.<span style="color: #000000;">Windows</span>.<span style="color: #000000;">Input</span>.<span style="color: #000000;">KeyEventHandler</span><span style="color: #000000;color: #000000;">&#40;</span>VisualElement_KeyUp<span style="color: #000000;color: #000000;">&#41;</span><span style="color: #008000;color: #000000;">;</span>
            <span style="color: #000000;color: #000000;">&#125;</span>
        <span style="color: #000000;color: #000000;">&#125;</span>
&nbsp;
        <span style="color: #0600FF;color: #0000FF;">void</span> VisualElement_KeyUp<span style="color: #000000;color: #000000;">&#40;</span><span style="color: #FF0000;color: #0000FF;">object</span> sender, <span style="color: #000000;">System</span>.<span style="color: #000000;">Windows</span>.<span style="color: #000000;">Input</span>.<span style="color: #000000;">KeyEventArgs</span> e<span style="color: #000000;color: #000000;">&#41;</span>
        <span style="color: #000000;color: #000000;">&#123;</span>
            <span style="color: #0600FF;color: #0000FF;">if</span> <span style="color: #000000;color: #000000;">&#40;</span>activeSession <span style="color: #008000;color: #000000;">!=</span> <span style="color: #0600FF;color: #0000FF;">null</span><span style="color: #000000;color: #000000;">&#41;</span>
            <span style="color: #000000;color: #000000;">&#123;</span>
                <span style="color: #0600FF;color: #0000FF;">if</span> <span style="color: #000000;color: #000000;">&#40;</span>e.<span style="color: #000000;">Key</span> <span style="color: #008000;color: #000000;">==</span> Key.<span style="color: #000000;">Escape</span><span style="color: #000000;color: #000000;">&#41;</span>
                <span style="color: #000000;color: #000000;">&#123;</span>
                    activeSession.<span style="color: #000000;">Dismiss</span><span style="color: #000000;color: #000000;">&#40;</span><span style="color: #000000;color: #000000;">&#41;</span><span style="color: #008000;color: #000000;">;</span>
                    e.<span style="color: #000000;">Handled</span> <span style="color: #008000;color: #000000;">=</span> true<span style="color: #008000;color: #000000;">;</span>
                <span style="color: #000000;color: #000000;">&#125;</span>
&nbsp;
                <span style="color: #0600FF;color: #0000FF;">if</span> <span style="color: #000000;color: #000000;">&#40;</span>e.<span style="color: #000000;">Key</span> <span style="color: #008000;color: #000000;">==</span> Key.<span style="color: #000000;">Enter</span><span style="color: #000000;color: #000000;">&#41;</span>
                <span style="color: #000000;color: #000000;">&#123;</span>
                    <span style="color: #0600FF;color: #0000FF;">if</span> <span style="color: #000000;color: #000000;">&#40;</span><span style="color: #0600FF;color: #0000FF;">this</span>.<span style="color: #000000;">activeSession</span>.<span style="color: #000000;">SelectedCompletionSet</span>.<span style="color: #000000;">SelectionStatus</span> <span style="color: #008000;color: #000000;">!=</span> <span style="color: #0600FF;color: #0000FF;">null</span> <span style="color: #000000;color: #000000;">&#41;</span>
                        activeSession.<span style="color: #000000;">Commit</span><span style="color: #000000;color: #000000;">&#40;</span><span style="color: #000000;color: #000000;">&#41;</span><span style="color: #008000;color: #000000;">;</span>
                    <span style="color: #0600FF;color: #0000FF;">else</span>
                        activeSession.<span style="color: #000000;">Dismiss</span><span style="color: #000000;color: #000000;">&#40;</span><span style="color: #000000;color: #000000;">&#41;</span><span style="color: #008000;color: #000000;">;</span>
                    e.<span style="color: #000000;">Handled</span> <span style="color: #008000;color: #000000;">=</span> true<span style="color: #008000;color: #000000;">;</span>
                <span style="color: #000000;color: #000000;">&#125;</span>
            <span style="color: #000000;color: #000000;">&#125;</span>
        <span style="color: #000000;color: #000000;">&#125;</span>
&nbsp;
        <span style="color: #0600FF;color: #0000FF;">void</span> VisualElement_KeyDown<span style="color: #000000;color: #000000;">&#40;</span><span style="color: #FF0000;color: #0000FF;">object</span> sender, <span style="color: #000000;">System</span>.<span style="color: #000000;">Windows</span>.<span style="color: #000000;">Input</span>.<span style="color: #000000;">KeyEventArgs</span> e<span style="color: #000000;color: #000000;">&#41;</span>
        <span style="color: #000000;color: #000000;">&#123;</span>
            ITextView textView <span style="color: #008000;color: #000000;">=</span> sender <span style="color: #0600FF;color: #0000FF;">as</span> ITextView<span style="color: #008000;color: #000000;">;</span>
            <span style="color: #0600FF;color: #0000FF;">if</span> <span style="color: #000000;color: #000000;">&#40;</span><span style="color: #0600FF;color: #0000FF;">this</span>.<span style="color: #000000;">subjectTextView</span> <span style="color: #008000;color: #000000;">!=</span> textView<span style="color: #000000;color: #000000;">&#41;</span>
                return<span style="color: #008000;color: #000000;">;</span>  <span style="color: #008080; font-style: italic;color: #008000;">// Make sure that this event happened on the same text view to which we're attached.</span>
&nbsp;
            <span style="color: #0600FF;color: #0000FF;">if</span> <span style="color: #000000;color: #000000;">&#40;</span><span style="color: #008000;color: #000000;">!</span><span style="color: #000000;color: #000000;">&#40;</span>e.<span style="color: #000000;">Key</span> <span style="color: #008000;color: #000000;">&gt;=</span> Key.<span style="color: #000000;">A</span> <span style="color: #008000;color: #000000;">&amp;&amp;</span> e.<span style="color: #000000;">Key</span> <span style="color: #008000;color: #000000;">&lt;=</span> Key.<span style="color: #000000;">Z</span><span style="color: #000000;color: #000000;">&#41;</span><span style="color: #000000;color: #000000;">&#41;</span>
               return<span style="color: #008000;color: #000000;">;</span>   <span style="color: #008080; font-style: italic;color: #008000;">// we only start the session when an alphanumeric key is pressed          </span>
&nbsp;
            <span style="color: #0600FF;color: #0000FF;">if</span> <span style="color: #000000;color: #000000;">&#40;</span>activeSession <span style="color: #008000;color: #000000;">!=</span> <span style="color: #0600FF;color: #0000FF;">null</span><span style="color: #000000;color: #000000;">&#41;</span>
                 return<span style="color: #008000;color: #000000;">;</span>  <span style="color: #008080; font-style: italic;color: #008000;">// if there is a session already leave it be</span>
&nbsp;
             <span style="color: #008080; font-style: italic;color: #008000;">// determine which subject buffer is affected by looking at the caret position</span>
             SnapshotPoint<span style="color: #008000;color: #000000;">?</span> caretPoint <span style="color: #008000;color: #000000;">=</span> textView.<span style="color: #000000;">Caret</span>.<span style="color: #000000;">Position</span>.<span style="color: #000000;">Point</span>.<span style="color: #000000;">GetPoint</span>
                 <span style="color: #000000;color: #000000;">&#40;</span>textBuffer <span style="color: #008000;color: #000000;">=&gt;</span>
                    <span style="color: #000000;color: #000000;">&#40;</span>
                        subjectBuffers.<span style="color: #000000;">Contains</span><span style="color: #000000;color: #000000;">&#40;</span>textBuffer<span style="color: #000000;color: #000000;">&#41;</span>
                        <span style="color: #008000;color: #000000;">&amp;&amp;</span> provider.<span style="color: #000000;">nodeProviderBroker</span>.<span style="color: #000000;">IsNDjango</span><span style="color: #000000;color: #000000;">&#40;</span>textBuffer, context<span style="color: #000000;color: #000000;">&#41;</span>
                        <span style="color: #008000;color: #000000;">&amp;&amp;</span> provider.<span style="color: #000000;">CompletionBrokerMapService</span>.<span style="color: #000000;">GetBrokerForTextView</span><span style="color: #000000;color: #000000;">&#40;</span>textView, textBuffer<span style="color: #000000;color: #000000;">&#41;</span> <span style="color: #008000;color: #000000;">!=</span> <span style="color: #0600FF;color: #0000FF;">null</span>
                    <span style="color: #000000;color: #000000;">&#41;</span>,  PositionAffinity.<span style="color: #000000;">Predecessor</span><span style="color: #000000;color: #000000;">&#41;</span><span style="color: #008000;color: #000000;">;</span>
&nbsp;
            <span style="color: #0600FF;color: #0000FF;">if</span> <span style="color: #000000;color: #000000;">&#40;</span><span style="color: #008000;color: #000000;">!</span>caretPoint.<span style="color: #000000;">HasValue</span><span style="color: #000000;color: #000000;">&#41;</span>
                return<span style="color: #008000;color: #000000;">;</span>   <span style="color: #008080; font-style: italic;color: #008000;">// return if no suitable buffer found</span>
&nbsp;
            List completionNodes <span style="color: #008000;color: #000000;">=</span>
                provider.<span style="color: #000000;">nodeProviderBroker</span>.<span style="color: #000000;">GetNodeProvider</span><span style="color: #000000;color: #000000;">&#40;</span>caretPoint.<span style="color: #000000;">Value</span>.<span style="color: #000000;">Snapshot</span>.<span style="color: #000000;">TextBuffer</span><span style="color: #000000;color: #000000;">&#41;</span>.<span style="color: #000000;">GetNodes</span><span style="color: #000000;color: #000000;">&#40;</span>caretPoint.<span style="color: #000000;">Value</span><span style="color: #000000;color: #000000;">&#41;</span>
                    .<span style="color: #000000;">FindAll</span><span style="color: #000000;color: #000000;">&#40;</span>node <span style="color: #008000;color: #000000;">=&gt;</span> node.<span style="color: #000000;">Values</span>.<span style="color: #000000;">Count</span><span style="color: #000000;color: #000000;">&#40;</span><span style="color: #000000;color: #000000;">&#41;</span> <span style="color: #008000;color: #000000;">&gt;</span> <span style="color: #FF0000;color: #000000;">0</span><span style="color: #000000;color: #000000;">&#41;</span><span style="color: #008000;color: #000000;">;</span>
&nbsp;
            <span style="color: #0600FF;color: #0000FF;">if</span> <span style="color: #000000;color: #000000;">&#40;</span>completionNodes.<span style="color: #000000;">Count</span> <span style="color: #008000;color: #000000;">==</span> <span style="color: #FF0000;color: #000000;">0</span><span style="color: #000000;color: #000000;">&#41;</span>
                return<span style="color: #008000;color: #000000;">;</span>  <span style="color: #008080; font-style: italic;color: #008000;">// return if there is no information to show</span>
&nbsp;
            attachKeyboardFilter<span style="color: #000000;color: #000000;">&#40;</span><span style="color: #000000;color: #000000;">&#41;</span><span style="color: #008000;color: #000000;">;</span>   <span style="color: #008080; font-style: italic;color: #008000;">// attach filter to intercept the Enter key</span>
&nbsp;
            ICompletionBroker broker <span style="color: #008000;color: #000000;">=</span> provider.<span style="color: #000000;">CompletionBrokerMapService</span>.<span style="color: #000000;">GetBrokerForTextView</span>
                  <span style="color: #000000;color: #000000;">&#40;</span>textView,caretPoint.<span style="color: #000000;">Value</span>.<span style="color: #000000;">Snapshot</span>.<span style="color: #000000;">TextBuffer</span><span style="color: #000000;color: #000000;">&#41;</span><span style="color: #008000;color: #000000;">;</span>
            ITrackingPoint triggerPoint <span style="color: #008000;color: #000000;">=</span> caretPoint.<span style="color: #000000;">Value</span>.<span style="color: #000000;">Snapshot</span>.<span style="color: #000000;">CreateTrackingPoint</span><span style="color: #000000;color: #000000;">&#40;</span>caretPoint.<span style="color: #000000;">Value</span>.<span style="color: #000000;">Position</span>, PointTrackingMode.<span style="color: #000000;">Positive</span><span style="color: #000000;color: #000000;">&#41;</span><span style="color: #008000;color: #000000;">;</span>
            activeSession <span style="color: #008000;color: #000000;">=</span> broker.<span style="color: #000000;">CreateCompletionSession</span><span style="color: #000000;color: #000000;">&#40;</span>triggerPoint, <span style="color: #0600FF;color: #0000FF;">true</span><span style="color: #000000;color: #000000;">&#41;</span><span style="color: #008000;color: #000000;">;</span>
            activeSession.<span style="color: #000000;">Properties</span>.<span style="color: #000000;">AddProperty</span><span style="color: #000000;color: #000000;">&#40;</span><span style="color: #008000;color: #0000FF;">typeof</span><span style="color: #000000;color: #000000;">&#40;</span>Source<span style="color: #000000;color: #000000;">&#41;</span>, completionNodes<span style="color: #000000;color: #000000;">&#41;</span><span style="color: #008000;color: #000000;">;</span>
            activeSession.<span style="color: #000000;">Dismissed</span> <span style="color: #008000;color: #000000;">+=</span> <span style="color: #008000;color: #0000FF;">new</span> <span style="color: #000000;">System</span>.<span style="color: #000000;">EventHandler</span><span style="color: #000000;color: #000000;">&#40;</span>OnActiveSessionDismissed<span style="color: #000000;color: #000000;">&#41;</span><span style="color: #008000;color: #000000;">;</span>
            activeSession.<span style="color: #000000;">Committed</span> <span style="color: #008000;color: #000000;">+=</span> <span style="color: #008000;color: #0000FF;">new</span> <span style="color: #000000;">System</span>.<span style="color: #000000;">EventHandler</span><span style="color: #000000;color: #000000;">&#40;</span>OnActiveSessionCommitted<span style="color: #000000;color: #000000;">&#41;</span><span style="color: #008000;color: #000000;">;</span>
            activeSession.<span style="color: #000000;">Start</span><span style="color: #000000;color: #000000;">&#40;</span><span style="color: #000000;color: #000000;">&#41;</span><span style="color: #008000;color: #000000;">;</span>
        <span style="color: #000000;color: #000000;">&#125;</span>
&nbsp;
        <span style="color: #0600FF;color: #0000FF;">void</span> OnActiveSessionDismissed<span style="color: #000000;color: #000000;">&#40;</span><span style="color: #FF0000;color: #0000FF;">object</span> sender, <span style="color: #000000;">System</span>.<span style="color: #000000;">EventArgs</span> e<span style="color: #000000;color: #000000;">&#41;</span>
        <span style="color: #000000;color: #000000;">&#123;</span>
            detachKeyboardFilter<span style="color: #000000;color: #000000;">&#40;</span><span style="color: #000000;color: #000000;">&#41;</span><span style="color: #008000;color: #000000;">;</span>
            activeSession <span style="color: #008000;color: #000000;">=</span> null<span style="color: #008000;color: #000000;">;</span>
        <span style="color: #000000;color: #000000;">&#125;</span>
&nbsp;
        <span style="color: #0600FF;color: #0000FF;">void</span> OnActiveSessionCommitted<span style="color: #000000;color: #000000;">&#40;</span><span style="color: #FF0000;color: #0000FF;">object</span> sender, <span style="color: #000000;">System</span>.<span style="color: #000000;">EventArgs</span> e<span style="color: #000000;color: #000000;">&#41;</span>
        <span style="color: #000000;color: #000000;">&#123;</span>
            detachKeyboardFilter<span style="color: #000000;color: #000000;">&#40;</span><span style="color: #000000;color: #000000;">&#41;</span><span style="color: #008000;color: #000000;">;</span>
            activeSession <span style="color: #008000;color: #000000;">=</span> null<span style="color: #008000;color: #000000;">;</span>
        <span style="color: #000000;color: #000000;">&#125;</span>
&nbsp;
        <span style="color: #0600FF;color: #0000FF;">public</span> <span style="color: #0600FF;color: #0000FF;">void</span> ConnectSubjectBuffer<span style="color: #000000;color: #000000;">&#40;</span>ITextBuffer subjectBuffer<span style="color: #000000;color: #000000;">&#41;</span> <span style="color: #000000;color: #000000;">&#123;</span> <span style="color: #000000;color: #000000;">&#125;</span>
&nbsp;
        <span style="color: #0600FF;color: #0000FF;">public</span> <span style="color: #0600FF;color: #0000FF;">void</span> Detach<span style="color: #000000;color: #000000;">&#40;</span>Microsoft.<span style="color: #000000;">VisualStudio</span>.<span style="color: #000000;">Text</span>.<span style="color: #000000;">Editor</span>.<span style="color: #000000;">ITextView</span> textView<span style="color: #000000;color: #000000;">&#41;</span>
        <span style="color: #000000;color: #000000;">&#123;</span>
            detachKeyboardFilter<span style="color: #000000;color: #000000;">&#40;</span><span style="color: #000000;color: #000000;">&#41;</span><span style="color: #008000;color: #000000;">;</span>
        <span style="color: #000000;color: #000000;">&#125;</span>
&nbsp;
        <span style="color: #0600FF;color: #0000FF;">public</span> <span style="color: #0600FF;color: #0000FF;">void</span> DisconnectSubjectBuffer<span style="color: #000000;color: #000000;">&#40;</span>ITextBuffer subjectBuffer<span style="color: #000000;color: #000000;">&#41;</span>
        <span style="color: #000000;color: #000000;">&#123;</span>
            WpfTextView <span style="color: #008000;color: #000000;">=</span> subjectTextView <span style="color: #0600FF;color: #0000FF;">as</span> IWpfTextView<span style="color: #008000;color: #000000;">;</span>
            <span style="color: #0600FF;color: #0000FF;">if</span> <span style="color: #000000;color: #000000;">&#40;</span>WpfTextView <span style="color: #008000;color: #000000;">!=</span> <span style="color: #0600FF;color: #0000FF;">null</span><span style="color: #000000;color: #000000;">&#41;</span>
            <span style="color: #000000;color: #000000;">&#123;</span>
                WpfTextView.<span style="color: #000000;">VisualElement</span>.<span style="color: #000000;">KeyDown</span> <span style="color: #008000;color: #000000;">-=</span> <span style="color: #008000;color: #0000FF;">new</span> <span style="color: #000000;">System</span>.<span style="color: #000000;">Windows</span>.<span style="color: #000000;">Input</span>.<span style="color: #000000;">KeyEventHandler</span><span style="color: #000000;color: #000000;">&#40;</span>VisualElement_KeyDown<span style="color: #000000;color: #000000;">&#41;</span><span style="color: #008000;color: #000000;">;</span>
                WpfTextView.<span style="color: #000000;">VisualElement</span>.<span style="color: #000000;">KeyUp</span> <span style="color: #008000;color: #000000;">-=</span> <span style="color: #008000;color: #0000FF;">new</span> <span style="color: #000000;">System</span>.<span style="color: #000000;">Windows</span>.<span style="color: #000000;">Input</span>.<span style="color: #000000;">KeyEventHandler</span><span style="color: #000000;color: #000000;">&#40;</span>VisualElement_KeyUp<span style="color: #000000;color: #000000;">&#41;</span><span style="color: #008000;color: #000000;">;</span>
                detachKeyboardFilter<span style="color: #000000;color: #000000;">&#40;</span><span style="color: #000000;color: #000000;">&#41;</span><span style="color: #008000;color: #000000;">;</span>
            <span style="color: #000000;color: #000000;">&#125;</span>
        <span style="color: #000000;color: #000000;">&#125;</span>
&nbsp;
        <span style="color: #0600FF;color: #0000FF;">private</span> <span style="color: #0600FF;color: #0000FF;">void</span> attachKeyboardFilter<span style="color: #000000;color: #000000;">&#40;</span><span style="color: #000000;color: #000000;">&#41;</span>
        <span style="color: #000000;color: #000000;">&#123;</span>
            ErrorHandler.<span style="color: #000000;">ThrowOnFailure</span><span style="color: #000000;color: #000000;">&#40;</span>provider.<span style="color: #000000;">adaptersFactory</span>.<span style="color: #000000;">GetViewAdapter</span><span style="color: #000000;color: #000000;">&#40;</span>subjectTextView<span style="color: #000000;color: #000000;">&#41;</span>.<span style="color: #000000;">AddCommandFilter</span><span style="color: #000000;color: #000000;">&#40;</span><span style="color: #0600FF;color: #0000FF;">this</span>, <span style="color: #0600FF;color: #0000FF;">out</span> oldFilter<span style="color: #000000;color: #000000;">&#41;</span><span style="color: #000000;color: #000000;">&#41;</span><span style="color: #008000;color: #000000;">;</span>
        <span style="color: #000000;color: #000000;">&#125;</span>
&nbsp;
        <span style="color: #0600FF;color: #0000FF;">private</span> <span style="color: #0600FF;color: #0000FF;">void</span> detachKeyboardFilter<span style="color: #000000;color: #000000;">&#40;</span><span style="color: #000000;color: #000000;">&#41;</span>
        <span style="color: #000000;color: #000000;">&#123;</span>
            ErrorHandler.<span style="color: #000000;">ThrowOnFailure</span><span style="color: #000000;color: #000000;">&#40;</span>provider.<span style="color: #000000;">adaptersFactory</span>.<span style="color: #000000;">GetViewAdapter</span><span style="color: #000000;color: #000000;">&#40;</span>subjectTextView<span style="color: #000000;color: #000000;">&#41;</span>.<span style="color: #000000;">RemoveCommandFilter</span><span style="color: #000000;color: #000000;">&#40;</span><span style="color: #0600FF;color: #0000FF;">this</span><span style="color: #000000;color: #000000;">&#41;</span><span style="color: #000000;color: #000000;">&#41;</span><span style="color: #008000;color: #000000;">;</span>
        <span style="color: #000000;color: #000000;">&#125;</span>
&nbsp;
        <span style="color: #008080; font-style: italic;color: #008000;">// The code below intercepts the ECMD_RETURN command before it is sent to the editor window.</span>
        <span style="color: #0600FF;color: #0000FF;">private</span> IOleCommandTarget oldFilter<span style="color: #008000;color: #000000;">;</span>
&nbsp;
        <span style="color: #0600FF;color: #0000FF;">private</span> <span style="color: #0600FF;color: #0000FF;">static</span> <span style="color: #0600FF;color: #0000FF;">readonly</span> Guid CMDSETID_StandardCommandSet2k <span style="color: #008000;color: #000000;">=</span> <span style="color: #008000;color: #0000FF;">new</span> Guid<span style="color: #000000;color: #000000;">&#40;</span><span style="color: #666666;color: #993300;">&quot;1496a755-94de-11d0-8c3f-00c04fc2aae2&quot;</span><span style="color: #000000;color: #000000;">&#41;</span><span style="color: #008000;color: #000000;">;</span>
        <span style="color: #0600FF;color: #0000FF;">private</span> <span style="color: #0600FF;color: #0000FF;">static</span> <span style="color: #0600FF;color: #0000FF;">readonly</span> <span style="color: #FF0000;color: #0000FF;">uint</span> ECMD_RETURN <span style="color: #008000;color: #000000;">=</span> <span style="color: #FF0000;color: #000000;">3</span><span style="color: #008000;color: #000000;">;</span>
&nbsp;
        <span style="color: #0600FF;color: #0000FF;">public</span> <span style="color: #FF0000;color: #0000FF;">int</span> Exec<span style="color: #000000;color: #000000;">&#40;</span><span style="color: #0600FF;color: #0000FF;">ref</span> Guid pguidCmdGroup, <span style="color: #FF0000;color: #0000FF;">uint</span> nCmdID, <span style="color: #FF0000;color: #0000FF;">uint</span> nCmdexecopt, IntPtr pvaIn, IntPtr pvaOut<span style="color: #000000;color: #000000;">&#41;</span>
        <span style="color: #000000;color: #000000;">&#123;</span>
            <span style="color: #0600FF;color: #0000FF;">if</span> <span style="color: #000000;color: #000000;">&#40;</span>pguidCmdGroup <span style="color: #008000;color: #000000;">==</span> CMDSETID_StandardCommandSet2k <span style="color: #008000;color: #000000;">&amp;&amp;</span> nCmdID <span style="color: #008000;color: #000000;">==</span> ECMD_RETURN<span style="color: #000000;color: #000000;">&#41;</span>
                <span style="color: #0600FF;color: #0000FF;">return</span> VSConstants.<span style="color: #000000;">S_OK</span><span style="color: #008000;color: #000000;">;</span>
            <span style="color: #0600FF;color: #0000FF;">return</span> oldFilter.<span style="color: #000000;">Exec</span><span style="color: #000000;color: #000000;">&#40;</span>pguidCmdGroup, nCmdID, nCmdexecopt, pvaIn, pvaOut<span style="color: #000000;color: #000000;">&#41;</span><span style="color: #008000;color: #000000;">;</span>
        <span style="color: #000000;color: #000000;">&#125;</span>
&nbsp;
        <span style="color: #0600FF;color: #0000FF;">public</span> <span style="color: #FF0000;color: #0000FF;">int</span> QueryStatus<span style="color: #000000;color: #000000;">&#40;</span><span style="color: #0600FF;color: #0000FF;">ref</span> Guid pguidCmdGroup, <span style="color: #FF0000;color: #0000FF;">uint</span> cCmds, OLECMD<span style="color: #000000;color: #000000;">&#91;</span><span style="color: #000000;color: #000000;">&#93;</span> prgCmds, IntPtr pCmdText<span style="color: #000000;color: #000000;">&#41;</span>
        <span style="color: #000000;color: #000000;">&#123;</span>
            <span style="color: #0600FF;color: #0000FF;">return</span> oldFilter.<span style="color: #000000;">QueryStatus</span><span style="color: #000000;color: #000000;">&#40;</span>pguidCmdGroup, cCmds, prgCmds, pCmdText<span style="color: #000000;color: #000000;">&#41;</span><span style="color: #008000;color: #000000;">;</span>
        <span style="color: #000000;color: #000000;">&#125;</span>
    <span style="color: #000000;color: #000000;">&#125;</span></pre></div></div>

<p>With this one even though the overall approach is the same as with the Quick Info, there are a few things deserving some explanation.</p>
<p>First the similarities: As with the Quick Info when the controller is created it hooks itself up to the view. It does so by subscribing to appropriate events on the view and in the event handlers it supplies the Intellisense sessions are created, started and dismissed as necessary. Also the information to be used by the source is attached to the session using session.Properties.</p>
<p>Now the differences: First of all the events here are different. In QuickInfo we relied on the OnMouseHover event to fire up the session and the session dismissal was handled automatically based on the mouse moves. With the Code completion we have to relay on the keyboard events for this purpose. See the implementation of the KeyUp and KeyDown events for more details.</p>
<p>The second and a little more unsettling difference is the games we have to play with the standard editor window. The problem is that when the user presses Enter, this keypress in addition to being sent to our KeyUp event is also sent to the editor window itself. As a result, the window gets updated which causes the update events to fire which in turn causes the current selection in the CompletionSet to be reset according to the matching rules. In other words, if the user selects something from the completion dropdown using arrows and presses enter, before the selection is applied to the code it is reset to whatever is considered to be a match to the letters keyed in before that. From the user standpoint, it causes the code completion code to ignore the selection with the arrow keys.</p>
<p>The attachKeyBoardFilter method above shows a way to suppress passing KeyUp event to the standard window. Also take a note of the detachKeyBoardFilter method, implementing the cleanup to be performed when the code completion session is completed one way or another.</p>
<p>And this is all I have to say about code completion controller. Bear with me - the only thing left is the code completion source, which is coming up next.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.hill30.com/MikeFeingoldBlog/index.php/2009/09/03/django-editor-in-vs-2010-part-6-code-completion-controller/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Django Editor in VS 2010 &#8211; Part 5 (Quick Info Source)</title>
		<link>http://www.hill30.com/MikeFeingoldBlog/index.php/2009/08/13/django-editor-in-vs-2010-part-5-quick-info-source/</link>
		<comments>http://www.hill30.com/MikeFeingoldBlog/index.php/2009/08/13/django-editor-in-vs-2010-part-5-quick-info-source/#comments</comments>
		<pubDate>Thu, 13 Aug 2009 16:59:55 +0000</pubDate>
		<dc:creator>Michael Feingold</dc:creator>
				<category><![CDATA[django]]></category>
		<category><![CDATA[vseditor]]></category>

		<guid isPermaLink="false">http://www.hill30.com/MikeFeingoldBlog/?p=184</guid>
		<description><![CDATA[Look here for complete source
In the previous post I explained the two components of the Quick Info implementation - the controller and the source. I also covered the Quick Info controller. Now, before diving into the source, let me tell you that you may not necessarily need the controller (or the source).
The thing is that [...]]]></description>
			<content:encoded><![CDATA[<p align="right">Look <a href="http://ndjango.org/index.php?title=Future">here </a>for complete source</p>
<p>In the previous post I explained the two components of the Quick Info implementation - the controller and the source. I also covered the Quick Info controller. Now, before diving into the source, let me tell you that you may not necessarily need the controller (or the source).</p>
<p>The thing is that these two are to certain degree independent of each other. The task of the controller is to manage the session, but it does not explicitly invoke the source - the system knows what source(s) to invoke based on the attributes you provide for the source. The controller also may (or may not) provide something to help source generate the tooltip, or the source can be smart enough to figure it out on its own. If the latter is true, and if some other Quick Info controller is already implemented, you do not need a new controller just to show tooltips from your new source - the existing one will do just fine. And vice versa - if you only need to change how the Quick Info session is triggered (or dismissed) you do not need to re-implement the source.</p>
<p>Alright, may be you are lucky, I am not, so let's get to it. Here it is, the QuickInfo source. Once more we have two objects a provider source and the actual provider. The provider source is decorated with the attributes the Visual Studio editor uses to determine when to invoke it. Here is the code:</p>

<div class="wp_syntax"><div class="code"><pre class="csharp" style="font-family:monospace;">    <span style="color: #000000;color: #000000;">&#91;</span>Export<span style="color: #000000;color: #000000;">&#40;</span><span style="color: #008000;color: #0000FF;">typeof</span><span style="color: #000000;color: #000000;">&#40;</span>IQuickInfoSourceProvider<span style="color: #000000;color: #000000;">&#41;</span><span style="color: #000000;color: #000000;">&#41;</span><span style="color: #000000;color: #000000;">&#93;</span>
    <span style="color: #000000;color: #000000;">&#91;</span>Name<span style="color: #000000;color: #000000;">&#40;</span><span style="color: #666666;color: #993300;">&quot;NDjango QuickInfo Source&quot;</span><span style="color: #000000;color: #000000;">&#41;</span><span style="color: #000000;color: #000000;">&#93;</span>
    <span style="color: #000000;color: #000000;">&#91;</span>Order<span style="color: #000000;color: #000000;">&#40;</span>Before <span style="color: #008000;color: #000000;">=</span> <span style="color: #666666;color: #993300;">&quot;default&quot;</span><span style="color: #000000;color: #000000;">&#41;</span><span style="color: #000000;color: #000000;">&#93;</span>
    <span style="color: #000000;color: #000000;">&#91;</span>ContentType<span style="color: #000000;color: #000000;">&#40;</span>Constants.<span style="color: #000000;">NDJANGO</span><span style="color: #000000;color: #000000;">&#41;</span><span style="color: #000000;color: #000000;">&#93;</span>
    <span style="color: #FF0000;color: #0000FF;">class</span> SourceProvider <span style="color: #008000;color: #000000;">:</span> IQuickInfoSourceProvider
    <span style="color: #000000;color: #000000;">&#123;</span>
        <span style="color: #000000;color: #000000;">&#91;</span>Import<span style="color: #000000;color: #000000;">&#93;</span>
        <span style="color: #0600FF;color: #0000FF;">internal</span> INodeProviderBroker nodeProviderBroker <span style="color: #000000;color: #000000;">&#123;</span> get<span style="color: #008000;color: #000000;">;</span> set<span style="color: #008000;color: #000000;">;</span> <span style="color: #000000;color: #000000;">&#125;</span>
&nbsp;
        <span style="color: #0600FF;color: #0000FF;">public</span> IQuickInfoSource TryCreateQuickInfoSource<span style="color: #000000;color: #000000;">&#40;</span>ITextBuffer textBuffer, IEnvironment environment<span style="color: #000000;color: #000000;">&#41;</span>
        <span style="color: #000000;color: #000000;">&#123;</span>
            <span style="color: #0600FF;color: #0000FF;">if</span> <span style="color: #000000;color: #000000;">&#40;</span>nodeProviderBroker.<span style="color: #000000;">IsNDjango</span><span style="color: #000000;color: #000000;">&#40;</span>textBuffer<span style="color: #000000;color: #000000;">&#41;</span><span style="color: #000000;color: #000000;">&#41;</span>
                <span style="color: #0600FF;color: #0000FF;">return</span> <span style="color: #008000;color: #0000FF;">new</span> Source<span style="color: #000000;color: #000000;">&#40;</span><span style="color: #000000;color: #000000;">&#41;</span><span style="color: #008000;color: #000000;">;</span>
            <span style="color: #0600FF;color: #0000FF;">return</span> null<span style="color: #008000;color: #000000;">;</span>
        <span style="color: #000000;color: #000000;">&#125;</span>
    <span style="color: #000000;color: #000000;">&#125;</span></pre></div></div>

<p>There is nothing to add to what's written in the code. The actual source is not this much more complex than the provider:</p>

<div class="wp_syntax"><div class="code"><pre class="csharp" style="font-family:monospace;">    <span style="color: #FF0000;color: #0000FF;">class</span> Source <span style="color: #008000;color: #000000;">:</span> IQuickInfoSource
    <span style="color: #000000;color: #000000;">&#123;</span>
&nbsp;
        <span style="color: #0600FF;color: #0000FF;">public</span> <span style="color: #FF0000;color: #0000FF;">object</span> GetToolTipContent<span style="color: #000000;color: #000000;">&#40;</span>IQuickInfoSession session, <span style="color: #0600FF;color: #0000FF;">out</span> Microsoft.<span style="color: #000000;">VisualStudio</span>.<span style="color: #000000;">Text</span>.<span style="color: #000000;">ITrackingSpan</span> applicableToSpan<span style="color: #000000;color: #000000;">&#41;</span>
        <span style="color: #000000;color: #000000;">&#123;</span>
            StringBuilder message <span style="color: #008000;color: #000000;">=</span> <span style="color: #008000;color: #0000FF;">new</span> StringBuilder<span style="color: #000000;color: #000000;">&#40;</span><span style="color: #000000;color: #000000;">&#41;</span><span style="color: #008000;color: #000000;">;</span>
            <span style="color: #FF0000;color: #0000FF;">int</span> position <span style="color: #008000;color: #000000;">=</span> session.<span style="color: #000000;">SubjectBuffer</span>.<span style="color: #000000;">CurrentSnapshot</span>.<span style="color: #000000;">Length</span><span style="color: #008000;color: #000000;">;</span>
            <span style="color: #FF0000;color: #0000FF;">int</span> length <span style="color: #008000;color: #000000;">=</span> <span style="color: #FF0000;color: #000000;">0</span><span style="color: #008000;color: #000000;">;</span>
            List nodes<span style="color: #008000;color: #000000;">;</span>
            <span style="color: #0600FF;color: #0000FF;">if</span> <span style="color: #000000;color: #000000;">&#40;</span>session.<span style="color: #000000;">Properties</span>.<span style="color: #000000;">TryGetProperty</span><span style="color: #008000;color: #000000;">&gt;</span><span style="color: #000000;color: #000000;">&#40;</span><span style="color: #008000;color: #0000FF;">typeof</span><span style="color: #000000;color: #000000;">&#40;</span>SourceProvider<span style="color: #000000;color: #000000;">&#41;</span>, <span style="color: #0600FF;color: #0000FF;">out</span> nodes<span style="color: #000000;color: #000000;">&#41;</span><span style="color: #000000;color: #000000;">&#41;</span>
            <span style="color: #000000;color: #000000;">&#123;</span>
                nodes.<span style="color: #0600FF;color: #0000FF;">ForEach</span><span style="color: #000000;color: #000000;">&#40;</span>
                    node <span style="color: #008000;color: #000000;">=&gt;</span>
                    <span style="color: #000000;color: #000000;">&#123;</span>
                        <span style="color: #0600FF;color: #0000FF;">if</span> <span style="color: #000000;color: #000000;">&#40;</span><span style="color: #008000;color: #000000;">!</span><span style="color: #FF0000;color: #0000FF;">String</span>.<span style="color: #000000;">IsNullOrEmpty</span><span style="color: #000000;color: #000000;">&#40;</span>node.<span style="color: #000000;">Description</span><span style="color: #000000;color: #000000;">&#41;</span><span style="color: #000000;color: #000000;">&#41;</span>
                            message.<span style="color: #000000;">Insert</span><span style="color: #000000;color: #000000;">&#40;</span><span style="color: #FF0000;color: #000000;">0</span>, node.<span style="color: #000000;">Description</span> <span style="color: #008000;color: #000000;">+</span> <span style="color: #666666;color: #993300;">&quot;<span style="color: #008080; font-weight: bold;color: #808080;">\n</span>&quot;</span><span style="color: #000000;color: #000000;">&#41;</span><span style="color: #008000;color: #000000;">;</span>
                        <span style="color: #0600FF;color: #0000FF;">if</span> <span style="color: #000000;color: #000000;">&#40;</span>node.<span style="color: #000000;">ErrorMessage</span>.<span style="color: #000000;">Severity</span> <span style="color: #008000;color: #000000;">&gt;=</span> <span style="color: #FF0000;color: #000000;">0</span><span style="color: #000000;color: #000000;">&#41;</span>
                            message.<span style="color: #000000;">Append</span><span style="color: #000000;color: #000000;">&#40;</span><span style="color: #666666;color: #993300;">&quot;<span style="color: #008080; font-weight: bold;color: #808080;">\n</span>&quot;</span> <span style="color: #008000;color: #000000;">+</span> node.<span style="color: #000000;">ErrorMessage</span>.<span style="color: #000000;">Message</span><span style="color: #000000;color: #000000;">&#41;</span><span style="color: #008000;color: #000000;">;</span>
                        <span style="color: #0600FF;color: #0000FF;">if</span> <span style="color: #000000;color: #000000;">&#40;</span>node.<span style="color: #000000;">Length</span> <span style="color: #008000;color: #000000;">&gt;</span> length<span style="color: #000000;color: #000000;">&#41;</span>
                            length <span style="color: #008000;color: #000000;">=</span> node.<span style="color: #000000;">Length</span><span style="color: #008000;color: #000000;">;</span>
                        <span style="color: #0600FF;color: #0000FF;">if</span> <span style="color: #000000;color: #000000;">&#40;</span>node.<span style="color: #000000;">Position</span> <span style="color: #008000;color: #000000;">&lt;</span> position<span style="color: #000000;color: #000000;">&#41;</span>
                            position <span style="color: #008000;color: #000000;">=</span> node.<span style="color: #000000;">Position</span><span style="color: #008000;color: #000000;">;</span>
                    <span style="color: #000000;color: #000000;">&#125;</span>
                        <span style="color: #000000;color: #000000;">&#41;</span><span style="color: #008000;color: #000000;">;</span>
            <span style="color: #000000;color: #000000;">&#125;</span>
&nbsp;
            applicableToSpan <span style="color: #008000;color: #000000;">=</span> session.<span style="color: #000000;">SubjectBuffer</span>.<span style="color: #000000;">CurrentSnapshot</span>.<span style="color: #000000;">CreateTrackingSpan</span><span style="color: #000000;color: #000000;">&#40;</span>
                position,
                length,
                Microsoft.<span style="color: #000000;">VisualStudio</span>.<span style="color: #000000;">Text</span>.<span style="color: #000000;">SpanTrackingMode</span>.<span style="color: #000000;">EdgeExclusive</span><span style="color: #000000;color: #000000;">&#41;</span><span style="color: #008000;color: #000000;">;</span>
&nbsp;
            <span style="color: #0600FF;color: #0000FF;">if</span> <span style="color: #000000;color: #000000;">&#40;</span>message.<span style="color: #000000;">Length</span> <span style="color: #008000;color: #000000;">&gt;</span> <span style="color: #FF0000;color: #000000;">0</span><span style="color: #000000;color: #000000;">&#41;</span>
                <span style="color: #0600FF;color: #0000FF;">return</span> message.<span style="color: #000000;">ToString</span><span style="color: #000000;color: #000000;">&#40;</span><span style="color: #000000;color: #000000;">&#41;</span><span style="color: #008000;color: #000000;">;</span>
            <span style="color: #0600FF;color: #0000FF;">else</span>
                <span style="color: #0600FF;color: #0000FF;">return</span> null<span style="color: #008000;color: #000000;">;</span>
        <span style="color: #000000;color: #000000;">&#125;</span>
   <span style="color: #000000;color: #000000;">&#125;</span></pre></div></div>

<p>As you can see the GetToolTipContent after some messing around with the node list returns the text message to be shown in the tooltip. Setting of the applicableToSpan forces dismissal of the QuickInfo session when the mouse cursor leaves the said span.</p>
<p>The next post will be about the final element - code completion</p>
]]></content:encoded>
			<wfw:commentRss>http://www.hill30.com/MikeFeingoldBlog/index.php/2009/08/13/django-editor-in-vs-2010-part-5-quick-info-source/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Django Editor in VS 2010 &#8211; Part 4 (Quick Info Controller)</title>
		<link>http://www.hill30.com/MikeFeingoldBlog/index.php/2009/08/09/django-editor-in-vs-2010-part-4-quick-info-controller/</link>
		<comments>http://www.hill30.com/MikeFeingoldBlog/index.php/2009/08/09/django-editor-in-vs-2010-part-4-quick-info-controller/#comments</comments>
		<pubDate>Sun, 09 Aug 2009 17:09:39 +0000</pubDate>
		<dc:creator>Michael Feingold</dc:creator>
				<category><![CDATA[django]]></category>
		<category><![CDATA[vseditor]]></category>

		<guid isPermaLink="false">http://www.hill30.com/MikeFeingoldBlog/?p=167</guid>
		<description><![CDATA[Look here for complete source
Welcome to the wonders of Intellisense. You can do so many things with intellisense and with the new MEF based architecture all of the wonders are actually acheivable by mere mortals without stretching your R&#38;D budget. OK almost all. Sometimes you still have to resort to the old ugly COM based [...]]]></description>
			<content:encoded><![CDATA[<p align="right">Look <a href="http://ndjango.org/index.php?title=Future">here </a>for complete source</p>
<p>Welcome to the wonders of Intellisense. You can do so many things with intellisense and with the new MEF based architecture all of the wonders are actually acheivable by mere mortals without stretching your R&amp;D budget. OK almost all. Sometimes you still have to resort to the old ugly COM based stuff, but the promise is out it's gonna get better in the final release.</p>
<p>QuickInfo is only one and, probably one of the simplest, of the many features available under Intellisense umbrella. The code I will present your here has nothing of the scary COM. Still, as with any of the Intellisense it has more moving parts than a classifier and/or tagger. The reason is pretty obvious - with taggers/classifiers you have only one dimension to worry about - the text itself. If the text is the same, the set of tags/classification types will not change either.</p>
<p>With Intellisense this is no longer true. The behavior of Intellisense, and QuickInfo in particular depends on the content as well as on what the user is doing - where is the caret, how did it move, where is the mouse cursor, etc. Because of this in addition to the Source supplying the content for the QuickInfo you have to deal with the Controller, which controls the QuickInfo session based on what the user is doing with mouse and keyboard.</p>
<p>The plumbing necessary for both the Source and the Controller is very similar to what you've seen in previous posts - there is a provider to be exported and the provider generates the actual class performing the function.</p>
<p>Here is my controller provider:</p>

<div class="wp_syntax"><div class="code"><pre class="csharp" style="font-family:monospace;">    <span style="color: #000000;color: #000000;">&#91;</span>Export<span style="color: #000000;color: #000000;">&#40;</span><span style="color: #008000;color: #0000FF;">typeof</span><span style="color: #000000;color: #000000;">&#40;</span>IIntellisenseControllerProvider<span style="color: #000000;color: #000000;">&#41;</span><span style="color: #000000;color: #000000;">&#41;</span><span style="color: #000000;color: #000000;">&#93;</span>
    <span style="color: #000000;color: #000000;">&#91;</span>Name<span style="color: #000000;color: #000000;">&#40;</span><span style="color: #666666;color: #993300;">&quot;NDjango Completion Controller&quot;</span><span style="color: #000000;color: #000000;">&#41;</span><span style="color: #000000;color: #000000;">&#93;</span>
    <span style="color: #000000;color: #000000;">&#91;</span>Order<span style="color: #000000;color: #000000;">&#93;</span>
    <span style="color: #000000;color: #000000;">&#91;</span>ContentType<span style="color: #000000;color: #000000;">&#40;</span>Constants.<span style="color: #000000;">NDJANGO</span><span style="color: #000000;color: #000000;">&#41;</span><span style="color: #000000;color: #000000;">&#93;</span>
    <span style="color: #0600FF;color: #0000FF;">internal</span> <span style="color: #FF0000;color: #0000FF;">class</span> CompletionControllerProvider <span style="color: #008000;color: #000000;">:</span> IIntellisenseControllerProvider
    <span style="color: #000000;color: #000000;">&#123;</span>
&nbsp;
        <span style="color: #000000;color: #000000;">&#91;</span>Import<span style="color: #000000;color: #000000;">&#40;</span><span style="color: #008000;color: #0000FF;">typeof</span><span style="color: #000000;color: #000000;">&#40;</span>IQuickInfoBrokerMapService<span style="color: #000000;color: #000000;">&#41;</span><span style="color: #000000;color: #000000;">&#41;</span><span style="color: #000000;color: #000000;">&#93;</span>
        <span style="color: #0600FF;color: #0000FF;">private</span> IQuickInfoBrokerMapService brokerMapService <span style="color: #000000;color: #000000;">&#123;</span> get<span style="color: #008000;color: #000000;">;</span> set<span style="color: #008000;color: #000000;">;</span> <span style="color: #000000;color: #000000;">&#125;</span>
&nbsp;
        <span style="color: #000000;color: #000000;">&#91;</span>Import<span style="color: #000000;color: #000000;">&#93;</span>
        <span style="color: #0600FF;color: #0000FF;">internal</span> INodeProviderBroker nodeProviderBroker <span style="color: #000000;color: #000000;">&#123;</span> get<span style="color: #008000;color: #000000;">;</span> set<span style="color: #008000;color: #000000;">;</span> <span style="color: #000000;color: #000000;">&#125;</span>
&nbsp;
        <span style="color: #0600FF;color: #0000FF;">public</span> IIntellisenseController TryCreateIntellisenseController<span style="color: #000000;color: #000000;">&#40;</span>ITextView textView, IList<span style="color: #008000;color: #000000;">&lt;</span>ITextBuffer<span style="color: #008000;color: #000000;">&gt;</span> subjectBuffers, IEnvironment context<span style="color: #000000;color: #000000;">&#41;</span>
        <span style="color: #000000;color: #000000;">&#123;</span>
&nbsp;
            <span style="color: #FF0000;color: #0000FF;">bool</span> brokerCreated <span style="color: #008000;color: #000000;">=</span> false<span style="color: #008000;color: #000000;">;</span>
            <span style="color: #0600FF;color: #0000FF;">foreach</span> <span style="color: #000000;color: #000000;">&#40;</span>ITextBuffer subjectBuffer <span style="color: #0600FF;color: #0000FF;">in</span> subjectBuffers<span style="color: #000000;color: #000000;">&#41;</span>
            <span style="color: #000000;color: #000000;">&#123;</span>
                <span style="color: #0600FF;color: #0000FF;">if</span> <span style="color: #000000;color: #000000;">&#40;</span>nodeProviderBroker.<span style="color: #000000;">IsNDjango</span><span style="color: #000000;color: #000000;">&#40;</span>subjectBuffer<span style="color: #000000;color: #000000;">&#41;</span><span style="color: #000000;color: #000000;">&#41;</span>
                    brokerCreated <span style="color: #008000;color: #000000;">|=</span> <span style="color: #000000;color: #000000;">&#40;</span>brokerMapService.<span style="color: #000000;">GetBrokerForTextView</span><span style="color: #000000;color: #000000;">&#40;</span>textView, subjectBuffer<span style="color: #000000;color: #000000;">&#41;</span> <span style="color: #008000;color: #000000;">!=</span> <span style="color: #0600FF;color: #0000FF;">null</span><span style="color: #000000;color: #000000;">&#41;</span><span style="color: #008000;color: #000000;">;</span>
            <span style="color: #000000;color: #000000;">&#125;</span>
&nbsp;
            <span style="color: #008080; font-style: italic;color: #008000;">// There may not be a broker for any of the subject buffers for this text view.  This can happen if there are no providers available.</span>
            <span style="color: #0600FF;color: #0000FF;">if</span> <span style="color: #000000;color: #000000;">&#40;</span>brokerCreated<span style="color: #000000;color: #000000;">&#41;</span>
            <span style="color: #000000;color: #000000;">&#123;</span>
                <span style="color: #0600FF;color: #0000FF;">return</span> <span style="color: #008000;color: #0000FF;">new</span> Controller<span style="color: #000000;color: #000000;">&#40;</span>nodeProviderBroker, subjectBuffers, textView, brokerMapService<span style="color: #000000;color: #000000;">&#41;</span><span style="color: #008000;color: #000000;">;</span>
            <span style="color: #000000;color: #000000;">&#125;</span>
&nbsp;
            <span style="color: #0600FF;color: #0000FF;">return</span> null<span style="color: #008000;color: #000000;">;</span>
        <span style="color: #000000;color: #000000;">&#125;</span>
    <span style="color: #000000;color: #000000;">&#125;</span></pre></div></div>

<p>It looks very much like a classifier provider or a tagger provider. The only noticeable difference is that tagger provider and classifier provider operate on text buffers (ITextBuffer), because they do not really care about mouse cursor movements and keyboard - only about buffer content. In here we have to worry about them, and the only way to do that is to deal with the text view (ITextView) and a text view can have multiple buffers it is showing. The rest of the code is pretty much the same. Similarly to the other providers, my QuickInfo controller provider tries to create a new QuickInfo controller for every django buffer. Here is the code for the QuickInfo controller:</p>

<div class="wp_syntax"><div class="code"><pre class="csharp" style="font-family:monospace;">    <span style="color: #FF0000;color: #0000FF;">class</span> Controller <span style="color: #008000;color: #000000;">:</span> IIntellisenseController
    <span style="color: #000000;color: #000000;">&#123;</span>
        <span style="color: #0600FF;color: #0000FF;">private</span> IList subjectBuffers<span style="color: #008000;color: #000000;">;</span>
        <span style="color: #0600FF;color: #0000FF;">private</span> ITextView textView<span style="color: #008000;color: #000000;">;</span>
        <span style="color: #0600FF;color: #0000FF;">private</span> IQuickInfoBrokerMapService brokerMapService<span style="color: #008000;color: #000000;">;</span>
        <span style="color: #0600FF;color: #0000FF;">private</span> IQuickInfoSession activeSession<span style="color: #008000;color: #000000;">;</span>
        <span style="color: #0600FF;color: #0000FF;">private</span> INodeProviderBroker nodeProviderBroker<span style="color: #008000;color: #000000;">;</span>
&nbsp;
        <span style="color: #0600FF;color: #0000FF;">public</span> Controller<span style="color: #000000;color: #000000;">&#40;</span>INodeProviderBroker nodeProviderBroker, IList subjectBuffers, ITextView textView, IQuickInfoBrokerMapService brokerMapService<span style="color: #000000;color: #000000;">&#41;</span>
        <span style="color: #000000;color: #000000;">&#123;</span>
            <span style="color: #0600FF;color: #0000FF;">this</span>.<span style="color: #000000;">nodeProviderBroker</span> <span style="color: #008000;color: #000000;">=</span> nodeProviderBroker<span style="color: #008000;color: #000000;">;</span>
            <span style="color: #0600FF;color: #0000FF;">this</span>.<span style="color: #000000;">subjectBuffers</span> <span style="color: #008000;color: #000000;">=</span> subjectBuffers<span style="color: #008000;color: #000000;">;</span>
            <span style="color: #0600FF;color: #0000FF;">this</span>.<span style="color: #000000;">textView</span> <span style="color: #008000;color: #000000;">=</span> textView<span style="color: #008000;color: #000000;">;</span>
            <span style="color: #0600FF;color: #0000FF;">this</span>.<span style="color: #000000;">brokerMapService</span> <span style="color: #008000;color: #000000;">=</span> brokerMapService<span style="color: #008000;color: #000000;">;</span>
&nbsp;
            textView.<span style="color: #000000;">MouseHover</span> <span style="color: #008000;color: #000000;">+=</span> <span style="color: #008000;color: #0000FF;">new</span> EventHandler<span style="color: #000000;color: #000000;">&#40;</span>textView_MouseHover<span style="color: #000000;color: #000000;">&#41;</span><span style="color: #008000;color: #000000;">;</span>
&nbsp;
        <span style="color: #000000;color: #000000;">&#125;</span>
&nbsp;
        <span style="color: #0600FF;color: #0000FF;">void</span> textView_MouseHover<span style="color: #000000;color: #000000;">&#40;</span><span style="color: #FF0000;color: #0000FF;">object</span> sender, MouseHoverEventArgs e<span style="color: #000000;color: #000000;">&#41;</span>
        <span style="color: #000000;color: #000000;">&#123;</span>
            <span style="color: #0600FF;color: #0000FF;">if</span> <span style="color: #000000;color: #000000;">&#40;</span>activeSession <span style="color: #008000;color: #000000;">!=</span> <span style="color: #0600FF;color: #0000FF;">null</span><span style="color: #000000;color: #000000;">&#41;</span>
                activeSession.<span style="color: #000000;">Dismiss</span><span style="color: #000000;color: #000000;">&#40;</span><span style="color: #000000;color: #000000;">&#41;</span><span style="color: #008000;color: #000000;">;</span>
&nbsp;
            SnapshotPoint<span style="color: #008000;color: #000000;">?</span> point <span style="color: #008000;color: #000000;">=</span> e.<span style="color: #000000;">TextPosition</span>.<span style="color: #000000;">GetPoint</span><span style="color: #000000;color: #000000;">&#40;</span>
                textBuffer <span style="color: #008000;color: #000000;">=&gt;</span>
                    <span style="color: #000000;color: #000000;">&#40;</span>
                        subjectBuffers.<span style="color: #000000;">Contains</span><span style="color: #000000;color: #000000;">&#40;</span>textBuffer<span style="color: #000000;color: #000000;">&#41;</span>
                        <span style="color: #008000;color: #000000;">&amp;&amp;</span> nodeProviderBroker.<span style="color: #000000;">IsNDjango</span><span style="color: #000000;color: #000000;">&#40;</span>textBuffer<span style="color: #000000;color: #000000;">&#41;</span>
                        <span style="color: #008000;color: #000000;">&amp;&amp;</span> brokerMapService.<span style="color: #000000;">GetBrokerForTextView</span><span style="color: #000000;color: #000000;">&#40;</span>textView, textBuffer<span style="color: #000000;color: #000000;">&#41;</span> <span style="color: #008000;color: #000000;">!=</span> <span style="color: #0600FF;color: #0000FF;">null</span>
                    <span style="color: #000000;color: #000000;">&#41;</span>
                ,PositionAffinity.<span style="color: #000000;">Predecessor</span><span style="color: #000000;color: #000000;">&#41;</span><span style="color: #008000;color: #000000;">;</span>
&nbsp;
            <span style="color: #0600FF;color: #0000FF;">if</span> <span style="color: #000000;color: #000000;">&#40;</span>point.<span style="color: #000000;">HasValue</span><span style="color: #000000;color: #000000;">&#41;</span>
            <span style="color: #000000;color: #000000;">&#123;</span>
                NodeProvider nodeProvider <span style="color: #008000;color: #000000;">=</span> nodeProviderBroker.<span style="color: #000000;">GetNodeProvider</span><span style="color: #000000;color: #000000;">&#40;</span>point.<span style="color: #000000;">Value</span>.<span style="color: #000000;">Snapshot</span>.<span style="color: #000000;">TextBuffer</span><span style="color: #000000;color: #000000;">&#41;</span><span style="color: #008000;color: #000000;">;</span>
                List quickInfoNodes <span style="color: #008000;color: #000000;">=</span> nodeProvider.<span style="color: #000000;">GetNodes</span><span style="color: #000000;color: #000000;">&#40;</span>point.<span style="color: #000000;">Value</span><span style="color: #000000;color: #000000;">&#41;</span><span style="color: #008000;color: #000000;">;</span>
                <span style="color: #0600FF;color: #0000FF;">if</span> <span style="color: #000000;color: #000000;">&#40;</span>quickInfoNodes <span style="color: #008000;color: #000000;">!=</span> <span style="color: #0600FF;color: #0000FF;">null</span><span style="color: #000000;color: #000000;">&#41;</span>
                <span style="color: #000000;color: #000000;">&#123;</span>
                    <span style="color: #008080; font-style: italic;color: #008000;">// the invocation occurred in a subject buffer of interest to us</span>
                    IQuickInfoBroker broker <span style="color: #008000;color: #000000;">=</span> brokerMapService.<span style="color: #000000;">GetBrokerForTextView</span><span style="color: #000000;color: #000000;">&#40;</span>textView, point.<span style="color: #000000;">Value</span>.<span style="color: #000000;">Snapshot</span>.<span style="color: #000000;">TextBuffer</span><span style="color: #000000;color: #000000;">&#41;</span><span style="color: #008000;color: #000000;">;</span>
                    ITrackingPoint triggerPoint <span style="color: #008000;color: #000000;">=</span> point.<span style="color: #000000;">Value</span>.<span style="color: #000000;">Snapshot</span>.<span style="color: #000000;">CreateTrackingPoint</span><span style="color: #000000;color: #000000;">&#40;</span>point.<span style="color: #000000;">Value</span>.<span style="color: #000000;">Position</span>, PointTrackingMode.<span style="color: #000000;">Positive</span><span style="color: #000000;color: #000000;">&#41;</span><span style="color: #008000;color: #000000;">;</span>
&nbsp;
                    activeSession <span style="color: #008000;color: #000000;">=</span> broker.<span style="color: #000000;">CreateQuickInfoSession</span><span style="color: #000000;color: #000000;">&#40;</span>triggerPoint, <span style="color: #0600FF;color: #0000FF;">true</span><span style="color: #000000;color: #000000;">&#41;</span><span style="color: #008000;color: #000000;">;</span>
                    activeSession.<span style="color: #000000;">Properties</span>.<span style="color: #000000;">AddProperty</span><span style="color: #000000;color: #000000;">&#40;</span><span style="color: #008000;color: #0000FF;">typeof</span><span style="color: #000000;color: #000000;">&#40;</span>SourceProvider<span style="color: #000000;color: #000000;">&#41;</span>, quickInfoNodes<span style="color: #000000;color: #000000;">&#41;</span><span style="color: #008000;color: #000000;">;</span>
                    activeSession.<span style="color: #000000;">Start</span><span style="color: #000000;color: #000000;">&#40;</span><span style="color: #000000;color: #000000;">&#41;</span><span style="color: #008000;color: #000000;">;</span>
                <span style="color: #000000;color: #000000;">&#125;</span>
            <span style="color: #000000;color: #000000;">&#125;</span>
        <span style="color: #000000;color: #000000;">&#125;</span>
&nbsp;
        <span style="color: #0600FF;color: #0000FF;">public</span> <span style="color: #0600FF;color: #0000FF;">void</span> ConnectSubjectBuffer<span style="color: #000000;color: #000000;">&#40;</span>ITextBuffer subjectBuffer<span style="color: #000000;color: #000000;">&#41;</span>
        <span style="color: #000000;color: #000000;">&#123;</span> <span style="color: #000000;color: #000000;">&#125;</span>
&nbsp;
        <span style="color: #0600FF;color: #0000FF;">public</span> <span style="color: #0600FF;color: #0000FF;">void</span> Detach<span style="color: #000000;color: #000000;">&#40;</span>ITextView textView<span style="color: #000000;color: #000000;">&#41;</span>
        <span style="color: #000000;color: #000000;">&#123;</span> <span style="color: #000000;color: #000000;">&#125;</span>
&nbsp;
        <span style="color: #0600FF;color: #0000FF;">public</span> <span style="color: #0600FF;color: #0000FF;">void</span> DisconnectSubjectBuffer<span style="color: #000000;color: #000000;">&#40;</span>ITextBuffer subjectBuffer<span style="color: #000000;color: #000000;">&#41;</span>
        <span style="color: #000000;color: #000000;">&#123;</span> <span style="color: #000000;color: #000000;">&#125;</span>
    <span style="color: #000000;color: #000000;">&#125;</span></pre></div></div>

<p>It is the responsibility of the controller to initiate the quick info session when the moment is right. For the NDjango designer I want to trigger the quick info session with the mouse hover event. So in the constructor I subscribe to the MouseHover event of the text view.</p>
<p>When this event is fired I am trying to acquire a point in the text buffer based on the current mouse position. I only want to consider points which satisfy the condition spelled out in the code. If a point (and a corresponding buffer) has been located, I request a node provider for the buffer and get a list of nodes from the provider based on the point. If the list is not empty, I initiate a new QuickInfo session. The list is placed on the session to be retrieved by the QuickInfo source when the content of the tooltip is requested.</p>
<p>So this is how the NDjango editor creates a QuickInfo session. So far the session even when triggered will not show anything. In the next post I will cover this with the code for NDjango editor Quick Info Source</p>
]]></content:encoded>
			<wfw:commentRss>http://www.hill30.com/MikeFeingoldBlog/index.php/2009/08/09/django-editor-in-vs-2010-part-4-quick-info-controller/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Django Editor in VS 2010 &#8211; Part 3 (Squiggles)</title>
		<link>http://www.hill30.com/MikeFeingoldBlog/index.php/2009/08/03/django-editor-in-vs-2010-part-3-squigglies/</link>
		<comments>http://www.hill30.com/MikeFeingoldBlog/index.php/2009/08/03/django-editor-in-vs-2010-part-3-squigglies/#comments</comments>
		<pubDate>Mon, 03 Aug 2009 18:10:27 +0000</pubDate>
		<dc:creator>Michael Feingold</dc:creator>
				<category><![CDATA[django]]></category>
		<category><![CDATA[vseditor]]></category>

		<guid isPermaLink="false">http://www.hill30.com/MikeFeingoldBlog/?p=125</guid>
		<description><![CDATA[Look here for complete source
Squiggles are wavy lines marking problematic areas. I would like to use them to indicate that there is a problem with certain django construct - tag and/or keyword. It also would be nice to give more specific diagnostic about what's wrong. For this purpose I will use the SquiggleTag class.
Creating a squiggle using SquiggleTag is very [...]]]></description>
			<content:encoded><![CDATA[<p align="right">Look <a href="http://ndjango.org/index.php?title=Future">here </a>for complete source</p>
<p>Squiggles are wavy lines marking problematic areas. I would like to use them to indicate that there is a problem with certain django construct - tag and/or keyword. It also would be nice to give more specific diagnostic about what's wrong. For this purpose I will use the SquiggleTag class.</p>
<p>Creating a squiggle using SquiggleTag is very similar to working with classifiers described in Part 1 of the series. As with the classifiers it takes 3 steps:</p>
<ul>
<li>create tag definition</li>
<li>create tagger</li>
<li>create tagger provider</li>
</ul>
<p>Because it is so similar, I think it is better just to show you the code and then give some brief explanation.</p>
<p>Error Tag definition:</p>

<div class="wp_syntax"><div class="code"><pre class="csharp" style="font-family:monospace;">        <span style="color: #0600FF;color: #0000FF;">internal</span> <span style="color: #FF0000;color: #0000FF;">class</span> ErrorTag <span style="color: #008000;color: #000000;">:</span> SquiggleTag
        <span style="color: #000000;color: #000000;">&#123;</span>
            <span style="color: #0600FF;color: #0000FF;">public</span> ErrorTag<span style="color: #000000;color: #000000;">&#40;</span><span style="color: #000000;color: #000000;">&#41;</span>
                <span style="color: #008000;color: #000000;">:</span> <span style="color: #0600FF;color: #0000FF;">base</span><span style="color: #000000;color: #000000;">&#40;</span><span style="color: #666666;color: #993300;">&quot;error&quot;</span><span style="color: #000000;color: #000000;">&#41;</span> <span style="color: #000000;color: #000000;">&#123;</span> <span style="color: #000000;color: #000000;">&#125;</span>
        <span style="color: #000000;color: #000000;">&#125;</span></pre></div></div>

<p>The lonely parameter of the SquiggleTag constructor controls the squiggle color. The SquiggleTag also has a property ToolTip and initially I thought of using it to show the diagnostic message, but it appears that this property is broken in Beta 1, so I decided to go the same route the VsEditor team is going and use the quick info for this purpose. I plan to cover quick info in the next post. Among other things using quick info gives you more flexibility - i.e. you can show in ToolTip both the error message as well as regular tips.</p>
<p>Now the provider:</p>

<div class="wp_syntax"><div class="code"><pre class="csharp" style="font-family:monospace;">    <span style="color: #000000;color: #000000;">&#91;</span>Export<span style="color: #000000;color: #000000;">&#40;</span><span style="color: #008000;color: #0000FF;">typeof</span><span style="color: #000000;color: #000000;">&#40;</span>ITaggerProvider<span style="color: #000000;color: #000000;">&#41;</span><span style="color: #000000;color: #000000;">&#41;</span><span style="color: #000000;color: #000000;">&#93;</span>
    <span style="color: #000000;color: #000000;">&#91;</span>ContentType<span style="color: #000000;color: #000000;">&#40;</span>Constants.<span style="color: #000000;">NDJANGO</span><span style="color: #000000;color: #000000;">&#41;</span><span style="color: #000000;color: #000000;">&#93;</span>
    <span style="color: #000000;color: #000000;">&#91;</span>TagType<span style="color: #000000;color: #000000;">&#40;</span><span style="color: #008000;color: #0000FF;">typeof</span><span style="color: #000000;color: #000000;">&#40;</span>SquiggleTag<span style="color: #000000;color: #000000;">&#41;</span><span style="color: #000000;color: #000000;">&#41;</span><span style="color: #000000;color: #000000;">&#93;</span>
    <span style="color: #FF0000;color: #0000FF;">class</span> TaggerProvider <span style="color: #008000;color: #000000;">:</span> ITaggerProvider
    <span style="color: #000000;color: #000000;">&#123;</span>
        <span style="color: #000000;color: #000000;">&#91;</span>Import<span style="color: #000000;color: #000000;">&#93;</span>
        <span style="color: #0600FF;color: #0000FF;">internal</span> INodeProviderBroker nodeProviderBroker <span style="color: #000000;color: #000000;">&#123;</span> get<span style="color: #008000;color: #000000;">;</span> set<span style="color: #008000;color: #000000;">;</span> <span style="color: #000000;color: #000000;">&#125;</span>
&nbsp;
        <span style="color: #0600FF;color: #0000FF;">public</span> ITagger<span style="color: #008000;color: #000000;">&lt;</span>T<span style="color: #008000;color: #000000;">&gt;</span> CreateTagger<span style="color: #008000;color: #000000;">&lt;</span>T<span style="color: #008000;color: #000000;">&gt;</span><span style="color: #000000;color: #000000;">&#40;</span>ITextBuffer buffer, IEnvironment context<span style="color: #000000;color: #000000;">&#41;</span> where T <span style="color: #008000;color: #000000;">:</span> ITag
        <span style="color: #000000;color: #000000;">&#123;</span>
            <span style="color: #0600FF;color: #0000FF;">if</span> <span style="color: #000000;color: #000000;">&#40;</span>nodeProviderBroker.<span style="color: #000000;">IsNDjango</span><span style="color: #000000;color: #000000;">&#40;</span>buffer<span style="color: #000000;color: #000000;">&#41;</span><span style="color: #000000;color: #000000;">&#41;</span>
                <span style="color: #0600FF;color: #0000FF;">return</span> <span style="color: #000000;color: #000000;">&#40;</span>ITagger<span style="color: #008000;color: #000000;">&lt;</span>T<span style="color: #008000;color: #000000;">&gt;</span><span style="color: #000000;color: #000000;">&#41;</span><span style="color: #008000;color: #0000FF;">new</span> Tagger<span style="color: #000000;color: #000000;">&#40;</span>nodeProviderBroker, buffer<span style="color: #000000;color: #000000;">&#41;</span><span style="color: #008000;color: #000000;">;</span>
            <span style="color: #0600FF;color: #0000FF;">else</span>
                <span style="color: #0600FF;color: #0000FF;">return</span> null<span style="color: #008000;color: #000000;">;</span>
        <span style="color: #000000;color: #000000;">&#125;</span>
    <span style="color: #000000;color: #000000;">&#125;</span></pre></div></div>

<p>No surprises here.</p>
<p>And finally the tagger:</p>

<div class="wp_syntax"><div class="code"><pre class="csharp" style="font-family:monospace;">    <span style="color: #FF0000;color: #0000FF;">class</span> Tagger <span style="color: #008000;color: #000000;">:</span> ITagger<span style="color: #008000;color: #000000;">&lt;</span>Constants.<span style="color: #000000;">ErrorTag</span><span style="color: #008000;color: #000000;">&gt;</span>
    <span style="color: #000000;color: #000000;">&#123;</span>
        <span style="color: #0600FF;color: #0000FF;">private</span> NodeProvider nodeProvider<span style="color: #008000;color: #000000;">;</span>
&nbsp;
        <span style="color: #0600FF;color: #0000FF;">public</span> Tagger<span style="color: #000000;color: #000000;">&#40;</span>INodeProviderBroker nodeProviderBroker, ITextBuffer buffer<span style="color: #000000;color: #000000;">&#41;</span>
        <span style="color: #000000;color: #000000;">&#123;</span>
            nodeProvider <span style="color: #008000;color: #000000;">=</span> nodeProviderBroker.<span style="color: #000000;">GetNodeProvider</span><span style="color: #000000;color: #000000;">&#40;</span>buffer<span style="color: #000000;color: #000000;">&#41;</span><span style="color: #008000;color: #000000;">;</span>
            nodeProvider.<span style="color: #000000;">NodesChanged</span> <span style="color: #008000;color: #000000;">+=</span> <span style="color: #008000;color: #0000FF;">new</span> NodeProvider.<span style="color: #000000;">SnapshotEvent</span><span style="color: #000000;color: #000000;">&#40;</span>provider_TagsChanged<span style="color: #000000;color: #000000;">&#41;</span><span style="color: #008000;color: #000000;">;</span>
        <span style="color: #000000;color: #000000;">&#125;</span>
&nbsp;
        <span style="color: #0600FF;color: #0000FF;">void</span> provider_TagsChanged<span style="color: #000000;color: #000000;">&#40;</span>SnapshotSpan snapshotSpan<span style="color: #000000;color: #000000;">&#41;</span>
        <span style="color: #000000;color: #000000;">&#123;</span>
            <span style="color: #0600FF;color: #0000FF;">if</span> <span style="color: #000000;color: #000000;">&#40;</span>TagsChanged <span style="color: #008000;color: #000000;">!=</span> <span style="color: #0600FF;color: #0000FF;">null</span><span style="color: #000000;color: #000000;">&#41;</span>
                TagsChanged<span style="color: #000000;color: #000000;">&#40;</span><span style="color: #0600FF;color: #0000FF;">this</span>, <span style="color: #008000;color: #0000FF;">new</span> SnapshotSpanEventArgs<span style="color: #000000;color: #000000;">&#40;</span>snapshotSpan<span style="color: #000000;color: #000000;">&#41;</span><span style="color: #000000;color: #000000;">&#41;</span><span style="color: #008000;color: #000000;">;</span>
        <span style="color: #000000;color: #000000;">&#125;</span>
&nbsp;
        <span style="color: #0600FF;color: #0000FF;">public</span> IEnumerable<span style="color: #008000;color: #000000;">&lt;</span>ITagSpan<span style="color: #008000;color: #000000;">&lt;</span>Constants.<span style="color: #000000;">ErrorTag</span><span style="color: #008000;color: #000000;">&gt;&gt;</span> GetTags<span style="color: #000000;color: #000000;">&#40;</span>Microsoft.<span style="color: #000000;">VisualStudio</span>.<span style="color: #000000;">Text</span>.<span style="color: #000000;">NormalizedSnapshotSpanCollection</span> spans<span style="color: #000000;color: #000000;">&#41;</span>
        <span style="color: #000000;color: #000000;">&#123;</span>
            <span style="color: #0600FF;color: #0000FF;">foreach</span> <span style="color: #000000;color: #000000;">&#40;</span>SnapshotSpan span <span style="color: #0600FF;color: #0000FF;">in</span> spans<span style="color: #000000;color: #000000;">&#41;</span>
            <span style="color: #000000;color: #000000;">&#123;</span>
                <span style="color: #0600FF;color: #0000FF;">foreach</span> <span style="color: #000000;color: #000000;">&#40;</span>NodeSnapshot node <span style="color: #0600FF;color: #0000FF;">in</span> nodeProvider.<span style="color: #000000;">GetNodes</span><span style="color: #000000;color: #000000;">&#40;</span>span<span style="color: #000000;color: #000000;">&#41;</span><span style="color: #000000;color: #000000;">&#41;</span>
                <span style="color: #000000;color: #000000;">&#123;</span>
                    <span style="color: #0600FF;color: #0000FF;">if</span> <span style="color: #000000;color: #000000;">&#40;</span>node.<span style="color: #000000;">SnapshotSpan</span>.<span style="color: #000000;">OverlapsWith</span><span style="color: #000000;color: #000000;">&#40;</span>span<span style="color: #000000;color: #000000;">&#41;</span> <span style="color: #008000;color: #000000;">&amp;&amp;</span> node.<span style="color: #000000;">Node</span>.<span style="color: #000000;">ErrorMessage</span>.<span style="color: #000000;">Severity</span> <span style="color: #008000;color: #000000;">&gt;</span> <span style="color: #FF0000;color: #000000;">0</span><span style="color: #000000;color: #000000;">&#41;</span>
                        yield <span style="color: #0600FF;color: #0000FF;">return</span> <span style="color: #008000;color: #0000FF;">new</span> TagSpan<span style="color: #008000;color: #000000;">&lt;</span>Constants.<span style="color: #000000;">ErrorTag</span><span style="color: #008000;color: #000000;">&gt;</span><span style="color: #000000;color: #000000;">&#40;</span>node.<span style="color: #000000;">SnapshotSpan</span>, <span style="color: #008000;color: #0000FF;">new</span> Constants.<span style="color: #000000;">ErrorTag</span><span style="color: #000000;color: #000000;">&#40;</span><span style="color: #000000;color: #000000;">&#41;</span><span style="color: #000000;color: #000000;">&#41;</span><span style="color: #008000;color: #000000;">;</span>
                <span style="color: #000000;color: #000000;">&#125;</span>
            <span style="color: #000000;color: #000000;">&#125;</span>
        <span style="color: #000000;color: #000000;">&#125;</span>
&nbsp;
        <span style="color: #0600FF;color: #0000FF;">public</span> <span style="color: #0600FF;color: #0000FF;">event</span> EventHandler<span style="color: #008000;color: #000000;">&lt;</span>SnapshotSpanEventArgs<span style="color: #008000;color: #000000;">&gt;</span> TagsChanged<span style="color: #008000;color: #000000;">;</span>
    <span style="color: #000000;color: #000000;">&#125;</span></pre></div></div>

<p>In the next post I will tackle something a little more complex - quick info</p>
]]></content:encoded>
			<wfw:commentRss>http://www.hill30.com/MikeFeingoldBlog/index.php/2009/08/03/django-editor-in-vs-2010-part-3-squigglies/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Django Editor in VS 2010 &#8211; Part 2 (Background Parsing)</title>
		<link>http://www.hill30.com/MikeFeingoldBlog/index.php/2009/08/02/django-editor-in-vs-2010-part-2-background-parsing/</link>
		<comments>http://www.hill30.com/MikeFeingoldBlog/index.php/2009/08/02/django-editor-in-vs-2010-part-2-background-parsing/#comments</comments>
		<pubDate>Sun, 02 Aug 2009 18:26:02 +0000</pubDate>
		<dc:creator>Michael Feingold</dc:creator>
				<category><![CDATA[django]]></category>
		<category><![CDATA[vseditor]]></category>

		<guid isPermaLink="false">http://www.hill30.com/MikeFeingoldBlog/?p=103</guid>
		<description><![CDATA[Look here for complete source
Every time the text in the editor window changes, all your classification, colorization, tagging etc. has to be re-evaluated. If you are lucky you can just take the text updates and run them through your parser. If it takes just a few statements to parse the updates, you do not need to [...]]]></description>
			<content:encoded><![CDATA[<p align="right">Look <a href="http://ndjango.org/index.php?title=Future">here </a>for complete source</p>
<p>Every time the text in the editor window changes, all your classification, colorization, tagging etc. has to be re-evaluated. If you are lucky you can just take the text updates and run them through your parser. If it takes just a few statements to parse the updates, you do not need to read the rest of this post. If your parser is really that simple (or smart) then all you need in your classifier, tagger and/or quickinfo controller is an event handler attached to the ITextBuffer's Changed event:</p>

<div class="wp_syntax"><div class="code"><pre class="csharp" style="font-family:monospace;">            buffer.<span style="color: #000000;">Changed</span> <span style="color: #008000;color: #000000;">+=</span> <span style="color: #008000;color: #0000FF;">new</span> EventHandler<span style="color: #000000;color: #000000;">&#40;</span>buffer_Changed<span style="color: #000000;color: #000000;">&#41;</span><span style="color: #008000;color: #000000;">;</span></pre></div></div>

<p>and then run the changes through your parser right in the event handler. You have to keep in mind though, that this code will be executed almost on each and every keystroke in your edit window.</p>
<p>So, if you are like the rest of us and have to worry about making the editor too sluggish to be useful, you might want to have a look at a few tricks which helped me to address this problem. Actually I have three:</p>
<ul>
<li>Make sure that no matter how many classifiers, taggers, whatever need results of parsing, all changes are ran through the parser only once</li>
<li>Make parsing asynchronous - do not make editor wait for the parser to finish parsing.</li>
<li>Queue the parsing - delay parsing for a second or so. This way if the update notifications are coming really fast you will still run the parser no more often than once a second</li>
</ul>
<p>At this time I do not have an implementation for the last one, but the overall structure of what I have lends itself well to parsing requests queuing.</p>
<p>To cover the first part I created my own interface INodeProviderBroker. I also wrote a class implementing the interface and exported it as a MEF component:</p>

<div class="wp_syntax"><div class="code"><pre class="csharp" style="font-family:monospace;">    <span style="color: #0600FF;color: #0000FF;">internal</span> <span style="color: #FF0000;color: #0000FF;">interface</span> INodeProviderBroker
    <span style="color: #000000;color: #000000;">&#123;</span>
        NodeProvider GetNodeProvider<span style="color: #000000;color: #000000;">&#40;</span>ITextBuffer buffer<span style="color: #000000;color: #000000;">&#41;</span><span style="color: #008000;color: #000000;">;</span>
        <span style="color: #FF0000;color: #0000FF;">bool</span> IsNDjango<span style="color: #000000;color: #000000;">&#40;</span>ITextBuffer buffer<span style="color: #000000;color: #000000;">&#41;</span><span style="color: #008000;color: #000000;">;</span>
    <span style="color: #000000;color: #000000;">&#125;</span>
&nbsp;
    <span style="color: #000000;color: #000000;">&#91;</span>Export<span style="color: #000000;color: #000000;">&#40;</span><span style="color: #008000;color: #0000FF;">typeof</span><span style="color: #000000;color: #000000;">&#40;</span>INodeProviderBroker<span style="color: #000000;color: #000000;">&#41;</span><span style="color: #000000;color: #000000;">&#41;</span><span style="color: #000000;color: #000000;">&#93;</span>
    <span style="color: #0600FF;color: #0000FF;">internal</span> <span style="color: #FF0000;color: #0000FF;">class</span> NodeProviderBroker <span style="color: #008000;color: #000000;">:</span> INodeProviderBroker
    <span style="color: #000000;color: #000000;">&#123;</span>
&nbsp;
        <span style="color: #008080; font-style: italic;color: #008000;">//the real parser</span>
        IParser parser <span style="color: #008000;color: #000000;">=</span> <span style="color: #008000;color: #0000FF;">new</span> Parser<span style="color: #000000;color: #000000;">&#40;</span><span style="color: #000000;color: #000000;">&#41;</span><span style="color: #008000;color: #000000;">;</span>
&nbsp;
        <span style="color: #0600FF;color: #0000FF;">public</span> <span style="color: #FF0000;color: #0000FF;">bool</span> IsNDjango<span style="color: #000000;color: #000000;">&#40;</span>ITextBuffer buffer<span style="color: #000000;color: #000000;">&#41;</span>
        <span style="color: #000000;color: #000000;">&#123;</span>
            <span style="color: #0600FF;color: #0000FF;">switch</span> <span style="color: #000000;color: #000000;">&#40;</span>buffer.<span style="color: #000000;">ContentType</span>.<span style="color: #000000;">TypeName</span><span style="color: #000000;color: #000000;">&#41;</span>
            <span style="color: #000000;color: #000000;">&#123;</span>
                <span style="color: #0600FF;color: #0000FF;">case</span> <span style="color: #666666;color: #993300;">&quot;text&quot;</span><span style="color: #008000;color: #000000;">:</span>
                <span style="color: #0600FF;color: #0000FF;">case</span> <span style="color: #666666;color: #993300;">&quot;HTML&quot;</span><span style="color: #008000;color: #000000;">:</span>
                    <span style="color: #0600FF;color: #0000FF;">return</span> true<span style="color: #008000;color: #000000;">;</span>
                <span style="color: #0600FF;color: #0000FF;">default</span><span style="color: #008000;color: #000000;">:</span> <span style="color: #0600FF;color: #0000FF;">return</span> false<span style="color: #008000;color: #000000;">;</span>
            <span style="color: #000000;color: #000000;">&#125;</span>
        <span style="color: #000000;color: #000000;">&#125;</span>
&nbsp;
        <span style="color: #0600FF;color: #0000FF;">public</span> NodeProvider GetNodeProvider<span style="color: #000000;color: #000000;">&#40;</span>ITextBuffer buffer<span style="color: #000000;color: #000000;">&#41;</span>
        <span style="color: #000000;color: #000000;">&#123;</span>
            NodeProvider provider<span style="color: #008000;color: #000000;">;</span>
            <span style="color: #0600FF;color: #0000FF;">if</span> <span style="color: #000000;color: #000000;">&#40;</span><span style="color: #008000;color: #000000;">!</span>buffer.<span style="color: #000000;">Properties</span>.<span style="color: #000000;">TryGetProperty</span><span style="color: #000000;color: #000000;">&#40;</span><span style="color: #008000;color: #0000FF;">typeof</span><span style="color: #000000;color: #000000;">&#40;</span>NodeProvider<span style="color: #000000;color: #000000;">&#41;</span>, <span style="color: #0600FF;color: #0000FF;">out</span> provider<span style="color: #000000;color: #000000;">&#41;</span><span style="color: #000000;color: #000000;">&#41;</span>
                buffer.<span style="color: #000000;">Properties</span>.<span style="color: #000000;">AddProperty</span><span style="color: #000000;color: #000000;">&#40;</span><span style="color: #008000;color: #0000FF;">typeof</span><span style="color: #000000;color: #000000;">&#40;</span>NodeProvider<span style="color: #000000;color: #000000;">&#41;</span>, provider <span style="color: #008000;color: #000000;">=</span> <span style="color: #008000;color: #0000FF;">new</span> NodeProvider<span style="color: #000000;color: #000000;">&#40;</span>parser, buffer<span style="color: #000000;color: #000000;">&#41;</span><span style="color: #000000;color: #000000;">&#41;</span><span style="color: #008000;color: #000000;">;</span>
            <span style="color: #0600FF;color: #0000FF;">return</span> provider<span style="color: #008000;color: #000000;">;</span>
        <span style="color: #000000;color: #000000;">&#125;</span>
&nbsp;
    <span style="color: #000000;color: #000000;">&#125;</span></pre></div></div>

<p>Each tagger, classifier what have you can import the provider broker and use the GetNodeProvider method to get a node provider for a given buffer. As you can see, the way GetNodeProvider works is it creates a new NodeProvider only once - upon first request for a given buffer. From this moment on, the GetNodeProvider will return the existing node provider taken from the buffer's property bag. Using MEF in this particular case might have been an overkill, but I decided to follow the lead of how this sort of things is done in VsEditor.</p>
<p>As to the second part, let me step you through the code for the node provider:</p>

<div class="wp_syntax"><div class="code"><pre class="csharp" style="font-family:monospace;">    <span style="color: #FF0000;color: #0000FF;">class</span> NodeProvider
    <span style="color: #000000;color: #000000;">&#123;</span>
        <span style="color: #0600FF;color: #0000FF;">private</span> List<span style="color: #008000;color: #000000;">&lt;</span>NodeSnapshot<span style="color: #008000;color: #000000;">&gt;</span> nodes <span style="color: #008000;color: #000000;">=</span> <span style="color: #008000;color: #0000FF;">new</span> List<span style="color: #008000;color: #000000;">&lt;</span>NodeSnapshot<span style="color: #008000;color: #000000;">&gt;</span><span style="color: #000000;color: #000000;">&#40;</span><span style="color: #000000;color: #000000;">&#41;</span><span style="color: #008000;color: #000000;">;</span>
        <span style="color: #0600FF;color: #0000FF;">private</span> <span style="color: #FF0000;color: #0000FF;">object</span> node_lock <span style="color: #008000;color: #000000;">=</span> <span style="color: #008000;color: #0000FF;">new</span> <span style="color: #FF0000;color: #0000FF;">object</span><span style="color: #000000;color: #000000;">&#40;</span><span style="color: #000000;color: #000000;">&#41;</span><span style="color: #008000;color: #000000;">;</span>
        <span style="color: #0600FF;color: #0000FF;">private</span> IParser parser<span style="color: #008000;color: #000000;">;</span>
        <span style="color: #0600FF;color: #0000FF;">private</span> ITextBuffer buffer<span style="color: #008000;color: #000000;">;</span>
&nbsp;
        <span style="color: #0600FF;color: #0000FF;">public</span> NodeProvider<span style="color: #000000;color: #000000;">&#40;</span>IParser parser, ITextBuffer buffer<span style="color: #000000;color: #000000;">&#41;</span>
        <span style="color: #000000;color: #000000;">&#123;</span>
            <span style="color: #0600FF;color: #0000FF;">this</span>.<span style="color: #000000;">parser</span> <span style="color: #008000;color: #000000;">=</span> parser<span style="color: #008000;color: #000000;">;</span>
            <span style="color: #0600FF;color: #0000FF;">this</span>.<span style="color: #000000;">buffer</span> <span style="color: #008000;color: #000000;">=</span> buffer<span style="color: #008000;color: #000000;">;</span>
            rebuildNodes<span style="color: #000000;color: #000000;">&#40;</span>buffer.<span style="color: #000000;">CurrentSnapshot</span><span style="color: #000000;color: #000000;">&#41;</span><span style="color: #008000;color: #000000;">;</span>
            buffer.<span style="color: #000000;">Changed</span> <span style="color: #008000;color: #000000;">+=</span> <span style="color: #008000;color: #0000FF;">new</span> EventHandler<span style="color: #000000;color: #000000;">&#40;</span>buffer_Changed<span style="color: #000000;color: #000000;">&#41;</span><span style="color: #008000;color: #000000;">;</span>
        <span style="color: #000000;color: #000000;">&#125;</span>
&nbsp;
        <span style="color: #0600FF;color: #0000FF;">public</span> <span style="color: #FF0000;color: #0000FF;">delegate</span> <span style="color: #0600FF;color: #0000FF;">void</span> SnapshotEvent <span style="color: #000000;color: #000000;">&#40;</span>SnapshotSpan snapshotSpan<span style="color: #000000;color: #000000;">&#41;</span><span style="color: #008000;color: #000000;">;</span>
&nbsp;
        <span style="color: #0600FF;color: #0000FF;">void</span> buffer_Changed<span style="color: #000000;color: #000000;">&#40;</span><span style="color: #FF0000;color: #0000FF;">object</span> sender, TextContentChangedEventArgs e<span style="color: #000000;color: #000000;">&#41;</span>
        <span style="color: #000000;color: #000000;">&#123;</span>
            rebuildNodes<span style="color: #000000;color: #000000;">&#40;</span>e.<span style="color: #000000;">After</span><span style="color: #000000;color: #000000;">&#41;</span><span style="color: #008000;color: #000000;">;</span>
        <span style="color: #000000;color: #000000;">&#125;</span>
&nbsp;
        <span style="color: #0600FF;color: #0000FF;">private</span> <span style="color: #0600FF;color: #0000FF;">void</span> rebuildNodes<span style="color: #000000;color: #000000;">&#40;</span>ITextSnapshot snapshot<span style="color: #000000;color: #000000;">&#41;</span>
        <span style="color: #000000;color: #000000;">&#123;</span>
            ThreadPool.<span style="color: #000000;">QueueUserWorkItem</span><span style="color: #000000;color: #000000;">&#40;</span>rebuildNodesAsynch, snapshot<span style="color: #000000;color: #000000;">&#41;</span><span style="color: #008000;color: #000000;">;</span>
        <span style="color: #000000;color: #000000;">&#125;</span>
&nbsp;
        <span style="color: #0600FF;color: #0000FF;">public</span> <span style="color: #0600FF;color: #0000FF;">event</span> SnapshotEvent NodesChanged<span style="color: #008000;color: #000000;">;</span>
&nbsp;
        <span style="color: #0600FF;color: #0000FF;">private</span> <span style="color: #0600FF;color: #0000FF;">void</span> rebuildNodesAsynch<span style="color: #000000;color: #000000;">&#40;</span><span style="color: #FF0000;color: #0000FF;">object</span> snapshotObject<span style="color: #000000;color: #000000;">&#41;</span>
        <span style="color: #000000;color: #000000;">&#123;</span>
            ITextSnapshot snapshot <span style="color: #008000;color: #000000;">=</span> <span style="color: #000000;color: #000000;">&#40;</span>ITextSnapshot<span style="color: #000000;color: #000000;">&#41;</span>snapshotObject<span style="color: #008000;color: #000000;">;</span>
            List<span style="color: #008000;color: #000000;">&lt;</span>NodeSnapshot<span style="color: #008000;color: #000000;">&gt;</span> nodes <span style="color: #008000;color: #000000;">=</span> parser.<span style="color: #000000;">Parse</span><span style="color: #000000;color: #000000;">&#40;</span>snapshot.<span style="color: #000000;">Lines</span>.<span style="color: #000000;">ToList</span><span style="color: #000000;color: #000000;">&#40;</span><span style="color: #000000;color: #000000;">&#41;</span>.<span style="color: #000000;">ConvertAll</span><span style="color: #000000;color: #000000;">&#40;</span>line <span style="color: #008000;color: #000000;">=&gt;</span> line.<span style="color: #000000;">GetTextIncludingLineBreak</span><span style="color: #000000;color: #000000;">&#40;</span><span style="color: #000000;color: #000000;">&#41;</span><span style="color: #000000;color: #000000;">&#41;</span><span style="color: #000000;color: #000000;">&#41;</span>
                .<span style="color: #000000;">ToList</span><span style="color: #000000;color: #000000;">&#40;</span><span style="color: #000000;color: #000000;">&#41;</span>
                    .<span style="color: #000000;">ConvertAll</span><span style="color: #008000;color: #000000;">&lt;</span>NodeSnapshot<span style="color: #008000;color: #000000;">&gt;</span>
                        <span style="color: #000000;color: #000000;">&#40;</span>node <span style="color: #008000;color: #000000;">=&gt;</span> <span style="color: #008000;color: #0000FF;">new</span> NodeSnapshot<span style="color: #000000;color: #000000;">&#40;</span>snapshot, node<span style="color: #000000;color: #000000;">&#41;</span><span style="color: #000000;color: #000000;">&#41;</span><span style="color: #008000;color: #000000;">;</span>
            <span style="color: #0600FF;color: #0000FF;">lock</span> <span style="color: #000000;color: #000000;">&#40;</span>node_lock<span style="color: #000000;color: #000000;">&#41;</span>
            <span style="color: #000000;color: #000000;">&#123;</span>
                <span style="color: #0600FF;color: #0000FF;">this</span>.<span style="color: #000000;">nodes</span> <span style="color: #008000;color: #000000;">=</span> nodes<span style="color: #008000;color: #000000;">;</span>
            <span style="color: #000000;color: #000000;">&#125;</span>
            <span style="color: #0600FF;color: #0000FF;">if</span> <span style="color: #000000;color: #000000;">&#40;</span>NodesChanged <span style="color: #008000;color: #000000;">!=</span> <span style="color: #0600FF;color: #0000FF;">null</span><span style="color: #000000;color: #000000;">&#41;</span>
                NodesChanged<span style="color: #000000;color: #000000;">&#40;</span><span style="color: #008000;color: #0000FF;">new</span> SnapshotSpan<span style="color: #000000;color: #000000;">&#40;</span>snapshot, <span style="color: #FF0000;color: #000000;">0</span>, snapshot.<span style="color: #000000;">Length</span><span style="color: #000000;color: #000000;">&#41;</span><span style="color: #000000;color: #000000;">&#41;</span><span style="color: #008000;color: #000000;">;</span>
        <span style="color: #000000;color: #000000;">&#125;</span>
&nbsp;
        <span style="color: #0600FF;color: #0000FF;">internal</span> List<span style="color: #008000;color: #000000;">&lt;</span>NodeSnapshot<span style="color: #008000;color: #000000;">&gt;</span> GetNodes<span style="color: #000000;color: #000000;">&#40;</span>SnapshotSpan snapshotSpan<span style="color: #000000;color: #000000;">&#41;</span>
        <span style="color: #000000;color: #000000;">&#123;</span>
            List<span style="color: #008000;color: #000000;">&lt;</span>NodeSnapshot<span style="color: #008000;color: #000000;">&gt;</span> nodes<span style="color: #008000;color: #000000;">;</span>
            <span style="color: #0600FF;color: #0000FF;">lock</span> <span style="color: #000000;color: #000000;">&#40;</span>node_lock<span style="color: #000000;color: #000000;">&#41;</span>
            <span style="color: #000000;color: #000000;">&#123;</span>
                nodes <span style="color: #008000;color: #000000;">=</span> <span style="color: #0600FF;color: #0000FF;">this</span>.<span style="color: #000000;">nodes</span><span style="color: #008000;color: #000000;">;</span>
            <span style="color: #000000;color: #000000;">&#125;</span>
            <span style="color: #0600FF;color: #0000FF;">if</span> <span style="color: #000000;color: #000000;">&#40;</span>nodes.<span style="color: #000000;">Count</span> <span style="color: #008000;color: #000000;">==</span> <span style="color: #FF0000;color: #000000;">0</span><span style="color: #000000;color: #000000;">&#41;</span>
                <span style="color: #0600FF;color: #0000FF;">return</span> nodes<span style="color: #008000;color: #000000;">;</span>
&nbsp;
            <span style="color: #008080; font-style: italic;color: #008000;">// just in case if while the tokens list was being rebuilt</span>
            <span style="color: #008080; font-style: italic;color: #008000;">// another modification was made</span>
            <span style="color: #0600FF;color: #0000FF;">if</span> <span style="color: #000000;color: #000000;">&#40;</span><span style="color: #0600FF;color: #0000FF;">this</span>.<span style="color: #000000;">nodes</span><span style="color: #000000;color: #000000;">&#91;</span><span style="color: #FF0000;color: #000000;">0</span><span style="color: #000000;color: #000000;">&#93;</span>.<span style="color: #000000;">SnapshotSpan</span>.<span style="color: #000000;">Snapshot</span> <span style="color: #008000;color: #000000;">!=</span> snapshotSpan.<span style="color: #000000;">Snapshot</span><span style="color: #000000;color: #000000;">&#41;</span>
                <span style="color: #0600FF;color: #0000FF;">this</span>.<span style="color: #000000;">nodes</span>.<span style="color: #0600FF;color: #0000FF;">ForEach</span><span style="color: #000000;color: #000000;">&#40;</span>node <span style="color: #008000;color: #000000;">=&gt;</span> node.<span style="color: #000000;">TranslateTo</span><span style="color: #000000;color: #000000;">&#40;</span>snapshotSpan.<span style="color: #000000;">Snapshot</span><span style="color: #000000;color: #000000;">&#41;</span><span style="color: #000000;color: #000000;">&#41;</span><span style="color: #008000;color: #000000;">;</span>
&nbsp;
            <span style="color: #0600FF;color: #0000FF;">return</span> nodes<span style="color: #008000;color: #000000;">;</span>
        <span style="color: #000000;color: #000000;">&#125;</span>
&nbsp;
        <span style="color: #0600FF;color: #0000FF;">internal</span> List<span style="color: #008000;color: #000000;">&lt;</span>INode<span style="color: #008000;color: #000000;">&gt;</span> GetNodes<span style="color: #000000;color: #000000;">&#40;</span>SnapshotPoint point<span style="color: #000000;color: #000000;">&#41;</span>
        <span style="color: #000000;color: #000000;">&#123;</span>
            List<span style="color: #008000;color: #000000;">&lt;</span>NodeSnapshot<span style="color: #008000;color: #000000;">&gt;</span>result <span style="color: #008000;color: #000000;">=</span> GetNodes<span style="color: #000000;color: #000000;">&#40;</span><span style="color: #008000;color: #0000FF;">new</span> SnapshotSpan<span style="color: #000000;color: #000000;">&#40;</span>point.<span style="color: #000000;">Snapshot</span>, point.<span style="color: #000000;">Position</span>, <span style="color: #FF0000;color: #000000;">0</span><span style="color: #000000;color: #000000;">&#41;</span><span style="color: #000000;color: #000000;">&#41;</span>
                            .<span style="color: #000000;">FindAll</span><span style="color: #000000;color: #000000;">&#40;</span>node <span style="color: #008000;color: #000000;">=&gt;</span> node.<span style="color: #000000;">SnapshotSpan</span>.<span style="color: #000000;">IntersectsWith</span><span style="color: #000000;color: #000000;">&#40;</span><span style="color: #008000;color: #0000FF;">new</span> SnapshotSpan<span style="color: #000000;color: #000000;">&#40;</span>point.<span style="color: #000000;">Snapshot</span>, point.<span style="color: #000000;">Position</span>, <span style="color: #FF0000;color: #000000;">0</span><span style="color: #000000;color: #000000;">&#41;</span><span style="color: #000000;color: #000000;">&#41;</span><span style="color: #000000;color: #000000;">&#41;</span><span style="color: #008000;color: #000000;">;</span>
            <span style="color: #0600FF;color: #0000FF;">if</span> <span style="color: #000000;color: #000000;">&#40;</span>result <span style="color: #008000;color: #000000;">==</span> <span style="color: #0600FF;color: #0000FF;">null</span><span style="color: #000000;color: #000000;">&#41;</span>
                <span style="color: #0600FF;color: #0000FF;">return</span> null<span style="color: #008000;color: #000000;">;</span>
            <span style="color: #0600FF;color: #0000FF;">return</span> result.<span style="color: #000000;">ConvertAll</span><span style="color: #000000;color: #000000;">&#40;</span>node <span style="color: #008000;color: #000000;">=&gt;</span> node.<span style="color: #000000;">Node</span><span style="color: #000000;color: #000000;">&#41;</span><span style="color: #008000;color: #000000;">;</span>
        <span style="color: #000000;color: #000000;">&#125;</span>
    <span style="color: #000000;color: #000000;">&#125;</span></pre></div></div>

<p>In the constructor (lines 8-14) the node provider submits a request to rebuild nodes with a call to the rebuildNodes method and subscribes to the buffer onChanged event. Within the event handler (line 20) it calls the same method. The rebuildNodes method uses thread pool to queue an asynchronous call to rebuildNodesAsynch. The rebuildNodesAsynch (lines 30 - 43) does the heavy lifting of the text parsing, but runs it on a separate thread. When parsing is completed it fires the NodesChanged event to inform the world that there is a fresh parsing result reflecting the latest updates.</p>
<p>Methods GetNode and GetNodes can be called at any moment. They will return the syntax node (list of syntax nodes) as of the last parsing completed by the moment the call was made regardless of whether there is a parsing  which is not completed yet.</p>
<p>BTW, this interaction between rebuildNodes and rebuildNodesAsynch is a good point to insert an implementation for trick #3 - parsing requests queuing. The rest of the code does not have to be changed.</p>
<p>If you go back now to Part 1 you will see how the node provider is used to retrieve parsing results. In the next post I will show how it is used with some other consumers.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.hill30.com/MikeFeingoldBlog/index.php/2009/08/02/django-editor-in-vs-2010-part-2-background-parsing/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>

