Entries Tagged 'Visual Studio' ↓
October 19th, 2008 — .Net, Code, Visual Studio
I said previously in my Brace Matching post that I want to try to document some of my findings while working on BooLangStudio. Well this is my second post on the subject.
When you’re implementing a custom language in Visual Studio, there’s a very good chance that you’re going to want to handle indentation slightly differently to the defaults. Every language has it’s own rules, after all.
Most of the resources I found online we’re pretty poor for how to get this working. Most people we’re pointing to overriding OnCommand in your derived Source class, or implementing some interop interface (i.e. IVsLanguageLineIndent). I could get none of these working. OnCommand never got raised, and the interfaces we’re useless.
I tried a few different methods for handling indentation, but none of them worked very well. I tried capturing the enter key press, but that didn’t work. Then I tried capturing alterations to the document, but those also got fired for navigating the document, so you’d press the up key and add a new line!
It ended up being pretty simple to implement, once I finally found the correct way to do it. I’ll cover how I did this for BooLangStudio below.
In your LanguageService, there’s a method you can override called CreateViewFilter which sets everything in motion.
Create yourself a class that derives from ViewFilter, and then return an instance of it from the overridden CreateViewFilter method in your language service.
Note: You need to make sure your project is configured to use Smart Indentation. If your project is complete enough to allow the user to customise this, then you’re fine. However, if not you can hard code this value yourself. In your language service there’s a GetLanguagePreferences method that returns all the preferences for your project. In that method you can set languagePreferences.IndentStyle = IdentingStyle.Smart, which is what I’ve done in BooLangStudio.
You’ll kick yourself for how easy this is. Now override the HandleSmartIndent method in your derived ViewFilter. That’s it really, in there you can access the Source object and do as you wish with smart indentation.
Taking BooLangStudio as an example, you can see in our BooViewFilter.cs that I delegate the work to a HandleSmartIndentAction. This is to make testing easier by having as little dependencies on Visual Studio as possible.
The Execute method of our HandleSmartIndentAction.cs class gets the caret location and passes it to an instance of a LineIndenter class, which determines (based on the previous line to the caret) whether the next line should be indented, or outdented.
So that’s how to implement Smart Indentation in your Visual Studio Extensibility project, and a little bit of implementation details of BooLangStudio.
September 2nd, 2008 — .Net, Boo, Code, Hobby Projects, Visual Studio
I’ve been meaning to write up some of my experiences developing for Visual Studio while I’ve been working on BooLangStudio, but I can never seem to find the time; either that, or when I can I’m not confident enough in what I’m doing to put it out here as a valid resource.
I’ll start small, here’s a quick guide to how I’ve implemented brace matching using the managed Visual Studio extensibility SDK.
What exactly is brace matching? Brace matching is where paired characters are highlighted when one or the other is selected in the editor.

There are a couple of things you need to consider when you implement brace matching.
Firstly, there are different types of braces that can be matched (depending on your language). Taking C# as an example, the brace matching works with parentheses (()), box brackets ([]), braces ({}), and chevrons (<>). These all need to be paired independently, as to avoid matching an open parenthesis with a closing brace.
Secondly, the matching has to work bi-directionally. The user can place their caret at either side of the bracket pair, and the highlighting should know where both sides are regardless.
LanguageService implementation
A lot of the legwork of implementing a language in Visual Studio is done in the LanguageService, and brace matching is no exception. You should already have a ParseSource method in your LanguageService; this is where we’re going to work.
The ParseSource method has a ParseRequest parameter, which exposes a Reason property. When this property is set to MatchBraces, that’s when we need to do our processing.
public override AuthoringScope ParseSource(ParseRequest request)
{
if (request.Reason == ParseReason.MatchBraces)
{
// match braces here
}
}
What needs to be done is pretty simple: Parse the open document and find the partner to the brace that the caret is on.
In BooLangStudio I’ve implemented this in the following fashion:
- Run the document through a
BracketPairFinder, which creates a list of bracket pairs in the document
- Get the index of the caret (baring in mind you have to translate between the Request’s Line and Column, and an actual string index)
- Find the pair that the caret is positioned at
- Get the opposite bracket from the pair
- Get the Line and Column of the opposite bracket
It’s upto you how you implement the above steps, as long as you end up with the opposite bracket to the one you started with. I’ll illustrate using the BooLangStudio source.
public override AuthoringScope ParseSource(ParseRequest request)
{
if (request.Reason == ParseReason.MatchBraces)
{
// find all pairs
var bracketFinder = new BracketPairFinder();
var bracketPairs = bracketFinder.FindPairs(request.Text);
// get index of caret from source text
Source source = languageService.GetSource(request.View);
int indexOfCaret = source.GetPositionOfLineIndex(request.Line, request.Col);
// find the partner to the bracket at the caret
int? partner = bracketPairs.FindPartnerIndex(indexOfCaret);
if (partner != null)
{
// tell Visual Studio about the pair
}
}
}
The Source class has a helpful GetPositionOfLineIndex method, which translates between a Line and Column to a single string index. Very handy!
Once you’ve got your indices, we need to inform Visual Studio of our findings. You do that by setting the request.Sink.FoundMatchingBrace to true, then calling the MatchPair method on the Sink. You need to pass two TextSpan instances to the MatchPair method; the first is the left brace, and the second the right.
public override AuthoringScope ParseSource(ParseRequest request)
{
if (request.Reason == ParseReason.MatchBraces)
{
...
if (partner != null)
{
// tell Visual Studio about the pair
request.Sink.FoundMatchingBrace = true;
int nextLine, nextCol;
source.GetLineIndexOfPosition(partner.Value, out nextLine, out nextCol);
request.Sink.MatchPair(
new TextSpan
{
iStartLine = request.Line,
iEndLine = request.Line,
iStartIndex = request.Col,
iEndIndex = request.Col
},
new TextSpan
{
iStartLine = nextLine,
iEndLine = nextLine,
iStartIndex = nextCol,
iEndIndex = nextCol + 1
}, 0);
}
return new AuthoringScope(); // replace with your implementation
}
}
The Source class has another helpful method: GetLineIndexOfPosition method, which translates back to Line and Column from a single string index.
Finally, just return an empty AuthoringScope, as it isn’t used as part of this parse request.
That’s it! You should have now successfully implemented brace matching. You may need to tweak the TextSpan indexes depending on your parser implementation, but it shouldn’t be far wrong.
BooLangStudio implementation
If you’re interested in seeing how I handle the brace parsing, I may cover that in a future post. However, you can find all the source in my github BooLangStudio fork. Some interesting one’s in particular are:
August 7th, 2008 — .Net, Boo, Hobby Projects, Visual Studio
It’s been a long time since I’ve written anything about BooLangStudio. Let me assure you that the development is still very much underway, and we’re steadily working towards our first release.
To fill you in a bit on what’s been going on. Jeffery Olson has completely rewritten the syntax highlighting to use the more flexible Boo.Pegs lexer, which allows us to overcome some of the obstacles we were facing with the traditional Boo lexer. There were limitations to what we could do with the traditional lexer, without modifying the Boo source. This was leading us down a road we weren’t keen on, one of maintaining a fork of the Boo source that contained our specific changes. With the move to the Boo.Pegs lexer, we’re free of this scenario!

Justin Chase has been tackling various issues all over the place. Several related to the build process, specifically how the Boo binaries are located on your machine, which has been a bit of a problem when there’s multiple developers working on a project whom both have Boo installed in a different location. He’s also been spiffing up the interface by adding some much needed icons to the projects.

Torkel Ödegaard has been working various issues throughout the project. He’s created a properties dialog for the project which allows you to alter the usual settings for your project, assembly name, default namespace etc… He also managed to get debugging working, which is awesome.
Then there’s me, I’ve been working on the intellisense capabilities. We’ve had intellisense support from day one, but it’s never been very extensive. For a long time it only worked on the current file you had open.
The entire solution is now processed behind-the-scenes to provide intellisense. Import statements are now recognised and imported types appear in the local scope intellisense. Any assemblies or projects that are referenced have their top-level types and namespaces included in the intellisense too.
Additionally I’ve been working on improving the method suggestion logic, which was initially very flakey. It boils down to being able to transform the current line into the desired type, which can be difficult in certain cases (StringBuilder().Append("Hello world").ToString(). for example).


I believe that about covers what we’ve been upto lately. Our biggest problem currently is that most of these features are implemented in separate branches, and haven’t yet been merged into our central repository. We’re working on this, and I reckon once we’ve done that we’ll be looking at doing a release.
May 25th, 2008 — .Net, Boo, Visual Studio
Quick update on the Boo plugin I mentioned previously. Jeff Olson announced the BooLangStudio project a couple of days after I announced mine, and we’ve decided to join forces. I’ve begun merging our codebases, and we’re looking to get a release out in the not too distant future.
Our combined code-bases have now got syntax highlighting, intellisense, single file and project support. Not bad going.
We’ve now got a nice little team going as well, which is a big improvement from what was the one man band of my self. One of the contributors, Torkel Ödegaard, has written a nice overview of our progress and processes as-well.
May 18th, 2008 — .Net, Boo, Hobby Projects, Visual Studio
What do we want? A Boo plug-in for Visual Studio. When do we want it? Sooner, rather than later.
The initial aim of this plug-in is to provide a “good enough” experience when using Boo files within other projects. I’m not currently focussing on doing full-scale development with Boo; so the target is DSLs and Binsor. There won’t be any assemblies created, or anything else that would affect your project. The only difference between how you work now would be that you could write Boo using Visual Studio, with syntax highlighting and intellisense.
That’s for the initial version anyway.
I’ve found that creating a plugin for Visual Studio isn’t that difficult, in-fact that’s an understatement, it’s stupidly easy. Most of the plugin architecture is successfully created using the project wizard, so there’s very little I needed to do from that point of view. The tricky part is getting Boo and Visual Studio to communicate.
I started by spending some time looking at the IronPython Studio implementation, the Boo implementation, abstract syntax trees, antlr, and after getting my head around what I needed to do, I set out on my adventure.
So what’s the result? A very basic (and flakey) implementation of both syntax highlighting and intellisense.

The highlighter isn’t perfect yet. It suffers from slowdown when you’re writing an unclosed string, and it can’t handle multi-line statements yet (think comment blocks).

The intellisense is pretty basic, it allows namespace navigation, and type methods, but there isn’t much in the way of constraints (you can see instance methods against types, for example).
There’s a lot of work to be done, but it’s fun and interesting.
Targets
In the near future I’d like to get the following done:
- Make intellisense work with everything in the local scope
- Make intellisense parse import statements
- Make syntax-highlighting correctly handle multi-line blocks
- Make syntax-highlighting highlight types (like C# does)
Then at some point tackle these:
- Get Resharper involved
- Refactoring support
Hopefully I’ll progress on these and report back in a future post.
Code
The code is poor, it’s a mess and probably all wrong; however, you can get it in the usual place. However, I haven’t provided a direct download because it isn’t really in a state to be distributed yet.
The source is accessible from Subversion at: http://jagregory.googlecode.com/svn/trunk/BooPlugin/ (using user jagregory-read-only)