Viasfora v1.6 Released

Today I published a new update to my Viasfora extension for Visual Studio 2010-2013. One of the new features in this build is a text editor margin that could be useful to other fellow developers working on extending the Visual Studio Text Editor.

Developer Margin

Developer Margin

One of the reasons why I implemented this was that I when I needed to extend Viasfora to support new file formats and other document types, I always had to resort to setting breakpoints in the debugger to figure out things such as the content type and how the editor worked, and this gets tiresome real quick!

In this first iteration, the margin exposes the following information:

  • What buffers compose the buffer graph: Complex editors in VS often require layering multiple buffers with different content types on top of each other, and this will let you easily see what those buffers are. For example, an ASP.NET MVC Razor editor might contain several buffers, such as the main Razor document, one containing the underlying CSharp code generated for the document, another containing the JavaScript code, plus a few other projection/elision buffers.
    Because the content type is the key to extending the text editor, it is very useful to be able to examine how the buffer graph is made up and making sure you don’t have multiple instances of your extension on multiple buffers interacting poorly with one another.
  • Exploring individual buffers: Besides visualizing the buffer graph, you can also explore the contents of the each of the buffers in a separate editor window. One side benefit of this is that it makes it easy to check out what the generated code for many text editors is like :) .
  • Exploring Content Types: In Visual Studio, content types can inherit from one another. For example, the “RazorCSharp” content type inherits from “Razor”, which in turn inherits from “htmlx”, and so on. With Viasfora, you can now easily inspect the content type tree.
  • Keeping track of the caret position: Visual Studio does a nice job of telling you where you’re located in the document at any given time with the line/column slots in the status bar. However, if you’re implementing text editor extensions such as classifiers, you often will be tracking things based on the actual position in the text buffer, rather than as line/column pairs. The margin adds such a counter on the bottom right.

Eventually, I hope to add other useful features to the margin, but suggestions are always welcome. Enjoy!

Pretty QuickInfo Tooltips and VS Themes

A Visual Studio Extension can extend quick info tooltips by implementing the IQuickInfoSource interface (and a few other things).

Most of the samples implement the AugmentQuickInfoSession() method by adding string values into the quickInfoContent collection. However, you can also add UIElement objects when you want to present tooltips that have complex content.

I implemented this for Viasfora as part of the XmlQuickInfoSource class, in order to present a much nicer tooltip for XML namespace prefixes. The end result was this:

Tooltip on Light Theme

Tooltip on Light Theme

It looked great. That is, until I tried it on Visual Studio 2012/2013 using the Dark Theme, which turned out to be unreadable:

Tooltip on Dark Theme

Tooltip on Dark Theme

After a lot of researching, I ran into the answer: There is an EnvironmentColors class included in the Microsoft.VisualStudio.Shell.(11|12).0.dll assembly, which will contains styles you can use to theme your WPF elements to properly match the selected theme.

For my needs, I could just use the ToolTipBrushKey, ToolTipTextBrushKey and PanelHyperlinkBrushKey properties to style my controls. However, I ran into a snag: The EnvironmentColors class is not available on the Visual Studio 2010 assemblies, which was a problem for me in order to support VS2010/2012/2013 with a single assembly.

While not a very pretty solution, I resorted to using Reflection coupled with the major Visual Studio version number in order to support this feature. The relevant pieces of code are:

private UIElement CreateInfoText(String xmlns, String url) {
  var textBlock = new TextBlock();
  Hyperlink hl = new Hyperlink(new Run(url));
  textBlock.Inlines.AddRange(new Inline[] {
    new Bold(new Run("Prefix: ")),
    new Run(xmlns),
    new LineBreak(),
    new Bold(new Run("Namespace: ")),
    hl
  });
  // set styles in order to support other 
  // visual studio themes on 2012/2013
  object tooltipBrushKey = VsfPackage.Instance.FindColorResource("ToolTipBrushKey");
  if ( tooltipBrushKey != null  ) {
    textBlock.SetResourceReference(TextBlock.BackgroundProperty, tooltipBrushKey);
  }
  object tooltipTextBrushKey = VsfPackage.Instance.FindColorResource("ToolTipTextBrushKey");
  if ( tooltipTextBrushKey != null ) {
    textBlock.SetResourceReference(TextBlock.ForegroundProperty, tooltipTextBrushKey);
  }
  object hlBrushKey = VsfPackage.Instance.FindColorResource("PanelHyperlinkBrushKey");
  if ( hlBrushKey != null ) {
    hl.SetResourceReference(Hyperlink.ForegroundProperty, hlBrushKey);
  }
  return textBlock;
}
private Version vsVersion;

public object FindColorResource(String name) {
  if ( vsVersion.Major <= 10 ) {
    return null;
  }
  Assembly assembly = Assembly.Load(String.Format(
    "Microsoft.VisualStudio.Shell.{0}.0, Version={0}.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a",
    vsVersion.Major
    ));
  if ( assembly != null ) {
    Type type = assembly.GetType("Microsoft.VisualStudio.PlatformUI.EnvironmentColors");
    var prop = type.GetProperty(name);
    return prop.GetValue(null, null);
  }
  return null;
}

Hope someone else finds this useful. Enjoy!

IClassifier and IDisposable

I’ve been troubleshooting some issues with Viasfora and noticed something that I definitely was not expecting:

It appears that if you implement an IClassifier extension, and also implement IDisposable, it will not be called by Visual Studio once the text buffer is released.

I have noticed this on Visual Studio 2013, but so far, I haven’t fully verified if this is indeed the expected behavior, or if it is caused by something else I am doing. I do know of many other Visual Studio extensions that combine IClassifier with IDisposable, so if this turns out to be the default behavior, it could signal other extensions may be leaking resources.

Viasfora v1.2 Released

Viasfora version 1.2 has been released! Most of the work on this released went into significantly improving the performance of the extension, particularly around Rainbow Parentheses and the Keyword Classifier.

One of the issues that I ran into was that when both features were enabled, they could interact in ways that would easily kill performance, particularly causing the C# editor to blink the highlight on some words, which was not a good thing. Another big challenge was the JavaScript editor, which, because of how it parses JS (in VS2010, in particular), it becomes very sensitive on anything that forces tag updates.

Much of the extra performance work went into improving the lexing code to extract braces when the document changes. I’m still not terribly happy with the current code, but it seems to be holding up for now. Two of the things that improved this the most are keeping a list of all the braces found and then only doing partial invalidation when the document changes, and also providing a quick way to look up ranges of braces based on the document lines. Still lots of room for improvement here!

As for new features? Rainbow parentheses is now supported on VB (often asked about!). Initial support for F# is also provided, but I am sure the default set of F# keywords I chose for this version could use some improvement. If you’re an F# fan, let me know of any suggestions!.

Viasfora v1.1 Published

Tonight I pushed a new version of my Viasfora extension for Visual Studio. In this version, I fixed some features that were not working on Visual Studio 2013 due to the introduction of a new HTML editor, particularly highlighting closing HTML tags.

What’s exiting to me, however, is the new feature: Rainbow Parentheses:

Rainbow Parentheses

Rainbow Parentheses

This is a Visual Studio version inspired by one of my favorite Vim plugins. Features:

  • Supported for C#, C/C++ and JavaScript files.
  • Highlights {}, [] and () braces.
  • Supports 4 different nesting levels, format for each one can be customized through the Tools -> Options dialog (Rainbow Parentheses 1-4).

Comments, bug reports and feature requests are always welcome. Enjoy!

Introducing Viasfora

A couple of days ago, I unveiled Viasfora, my latest attempt at building a decently packaged extension for Visual Studio 2010, 2012, and 2013. I had already published a few VS Extensions before (Keyword Classifier, BetterXml, Line Adornments, and Xaml Classifier Fix), but it was not overly successful. The reasons for this were several:

  • I originally published those extensions not really as something useful in their own right, but rather as samples on how to implement VS extensions. They were successful in that regard, but none were ever very widely used.
  • While useful in their own right, the extensions weren’t very polished. They were not very easy to customize and the code needed some cleanup to be easier to maintain.
  • The names, frankly, sucked.
  • I’m terrible at promoting stuff, so I never did much about them other than a few posts on this blog. I even was so absentminded that I uploaded BetterXml to the Visual Studio Gallery, only to forget to publish it. No wonder no one used it!

What is Viasfora?

Viasfora is a combination of my 3 most significant previous extensions. Keyword Classifier, BetterXml and Line Adornments. It puts them all in a single, nice package that includes full customizability through the Tools -> Options dialog in Visual Studio, including the ability to turn individual features on/off.

So what does Viasfora offer? Check the website for the full details, but here are some highlights:

  • Current Line Highlighting, a native feature in VS2013, but supported on VS2010 and VS2012.
  • Custom highlighting of Control Flow keywords, LINQ-related Keywords and Visibility keywords for C#, C/C++, JavaScript and Visual Basic (new!).
  • Highlighting of character escape sequences in C# strings, which makes it real easy to spot them!
  • Custom highlighting of XML namespace prefixes in XML/XAML/HTML documents.
  • Highlighting closing element tags in XML/XAML/HTML documents in a different color as the opening element tag. This is one of my favorite features and one I often miss from Vim.
  • Matching (through highlight) of opening/closing element tags in XML documents (new!).
  • Tooltips for easy lookup of XML namespace prefixes.

Hopefully having a nice (if simple) website for the extension with all the information makes it easier for people to find and get interested in it. As with my previous extensions, complete source is available on the < a href='https://github.com/tomasr/viasfora/'>github repository.

Where does the name come from?

Sorry, I still suck at naming :) . The name Viasfora comes from my attempt of mixing the greek word "Diáfora" and, well, obviously VS for Visual Studio. It sounds catchy, I think!

Please let me know if anyone runs into any problems, bugs or feature requests.

Updating Visual Studio Extensions

I spent some time this week researching what would be needed to update some of my Visual Studio 2010 extensions to support Visual Studio 2012. I’ve now managed to do so, and would like to share what I found in case anyone else finds it useful.

Warning: This post was written and tested with the Visual Studio 2012 release candidate and I have no clue how well it will work on the final release. I’ll update it or post again once it comes out if needed.

The first thing to try was, of course, to take the existing code, migrate it into a VS2012 project, and update all references to Visual Studio assemblies. That worked, as far as building goes, but the extensions would still not work. It is not that they would cause any errors; they just didn’t do anything.

In this particular case, I focused on two of my extensions: KeywordClassifier and BetterXml. Both of them rely on the same mechanism, which was layering an ITagger<ClassificationTag> on top of the tags produced by the original provider. This was done through the use of an ITagAggregator<ClassificationTag>.

After a bit of debugging, I discovered the reason the original code was no longer working was because the ITagAggregator<ClassificationTag> instance returned by Visual Studio would simply return an empty list when GetTags() was called.

With some experimentation, I realized that while asking for an ITagAggregator<ClassificationTag> no longer worked, asking for an ITagAggregator<IClassificationTag> (that is, use the interface instead of the specific type) would indeed work. Plus, the same code would work just as well in VS2010!

return new KeywordTagger(
  ClassificationRegistry,
  Aggregator.CreateTagAggregator<IClassificationTag>(buffer)
) as ITagger<T>;

I was still not terribly thrilled about having to keep separate branches of the extensions with different project files and manifests to support both Visual Studio versions, so I started digging a bit more to see what other options there were. After a bunch of tests, I came up with something that works and allows me to keep a single VSIX file that works across both versions:

  • Modify the extension manifest to make it installable under VS2012. I did this modifying the <SupportedProducts> tag in the .vsixmanifest file to add an entry for VS2012, like this:
    <VisualStudio Version="11.0">
      <Edition>Ultimate</Edition>
      <Edition>Premium</Edition>
      <Edition>Pro</Edition>
      <Edition>IntegratedShell</Edition>
      <Edition>VST_All</Edition>
    </VisualStudio>
    

    Now, I do not know if these are the correct edition strings, though, but they work with the VS2012 release candidate ultimate edition that is in MSDN. If anyone knows what the right strings should be, let me know and I’ll fix it.

  • I changed the MaxVersion attribute of the SupportedFrameworkRuntimeEdition tag to specify .NET 4.5. I don’t know if that is needed (or useful), but probably wouldn’t hurt :)
    <SupportedFrameworkRuntimeEdition MinVersion="4.0" MaxVersion="4.5" />
    
  • Build the extension and package using VS2010, without changing the existing (and VS2010-specific) assembly references.

After trying this, the two extensions would load and run just fine in both VS2010 and VS2012, even if just one of them had been installed. I guess that VS2012 might be doing some assembly redirection when the extension is loaded, to ensure references are loaded correctly despite the fact that they have changed versions for 2012.

I’ve updated the code of KeywordClassifier and BetterXml on GitHub with the necessary changes. A big ‘Thank you!’ goes out to Oren Novotny for the help.

On the plus side, I discovered that my XAML Classifier Fix extension is no longer needed in Visual Studio 2012, now that the team introduced an explicit XAML Text classification.

BetterXml

BetterXml is a Visual Studio 2010 extension I’ve been working on recently in an attempt to improve the experience of the built-in XML editor in VS. Right now it’s only on its early stages, so it doesn’t add much, but I hope to improve it as I find new things I’d like to add.

What does it do? BetterXml has two main features right now: Syntax highlighting extension and namespace tooltips.

Syntax Highlighting

BetterXml provides two new classification format definitions: XML Prefix and XML Closing Tag.

  • XML Prefix will change the color/format used to highlight prefixes in XML names (the ‘x’ in x:name).
  • XML Closing Tag will change the color/format used to highlight closing element tags. This is one feature that some color schemes use in Vim that I always missed in VS, and it’s pretty cool that the extensibility model in VS2010 allows me to provide this; it makes reading long documents a lot easier.

Here’s a screenshot showing both of these:

syntax highlighting

This is supported on regular XML documents (including XSD) as well as XAML and HTML documents.

Namespace Tooltips

If you hover the mouse pointer over a prefix in an XML document, BetterXml will try to figure out the URI of the namespace that prefix maps to, and present a tooltip with that information:

tooltips

I haven’t done much tweaking of this feature yet so it will probably be a bit slow on large documents, since it requires partially parsing the document. This feature is only supported on XML and XAML documents.

Other Plans

I’ve been looking into other improvements I’d like to add to BetterXml. One I really wanted to provide was extending Intellisense completion based on previously used element/attribute names, which would be pretty useful for XML documents without schema.

VS2010 does provide ways to extend completion, and while it requires a lot of boilerplate code, it works. Unfortunately, after much trial and error I’ve been unable to make it work correctly, and certainly could never get it to behave the same way the built-in completion works.

While VS does seem to support multiple concurrent completion providers on the same buffer and will display the completion sets for all of them, I could not figure out the magic incantations to make it work reliably and in ways that behavior was predictable. Probably my own fault, but without clear documentation on how they are supposed to work together (if it’s even supported at all), it’s not trivial to do.

Source

Source code for BetterXml is available as usual on github.

Trying out Resharper 5.0

There are many .NET developers that can’t live without Jetbrain’s R# product. I’m not really one of them. Don’t get me wrong, I like the idea of R# and some of the features it offers, it’s just that it could be so much better if it didn’t keep getting in my way!

Let’s get something out of the way before I dive into what I’d like to see improved in R#: I bought my own R# license out of my own money. I do think it’s a fairly reasonably priced product for all the features it offers.

Improvements I’d like to see

  • More modularity: I work in a fairly specific environment where some of the tools R# provides don’t help at all, and in fact, I don’t need them or want them in my way.
    Hence, I’d love to see top-level options to turn off broad features. Right now pretty much only two features have this: IntelliSense and Code Analysis. I’d love to see the same for things like code formatting and the like.
  • Better options for saving/sharing settings: It’s a pain in the neck to configure R# after installing it (or keeping it configured after that). The Options dialog is a mess, and there are way too many settings and no easy way (that I can find) to export your settings to a file I can save and keep around for later installations.
    Yes, I’m aware that R# saves its settings in an external XML file you can save, but it’s stored some place I can never remember, gets overwritten and messed up all the time when running multiple VS options at the same time and I always forget to fish it out before dumping a VM or something, so it’s as if it was never there.
    Just give me a way to export/import settings; that’s a lot easier to live with.
  • Unit Testing: I’m rather happy using the test runner in R#, use it all the time. However, it would be really nice if there was a way to set it up so that the Debug option worked for mixed managed/unmanaged solutions.
    Right now, the Debug option only enables the managed debugger, but I also work with lots of code that includes managed tests over a mixture of managed and unmanaged C++ code and to debug that I always have to use the NUnit test runner instead.

Things that just piss me off

There are a few things that I can’t stand when using R#, however; to the point where I have to disable it just to get any work done without losing my mind:

  • Crashes: R# 4.5 was notoriously unstable. It would crash all the freaking time for me. R# 5.0 seems better on VS2010, but not on VS2008 to the point where the simplest reproducible crash that R# 4.5 would cause is still present in 5.0. Here’s just an example: Launch a new, empty VS2008 instance (with no auto-project opening or anything), then drag a C# file from explorer to VS. Watch VS crash and burn.
  • Stop messing with ViEmu: I’m a long time user of ViEmu, absolutely love it. However, R# often messes with ViEmu on VS2008, in particularly with the keyboard handling. The one that always causes me trouble is firing a new empty VS2008 instance and loading a solution that contains only unmanaged C++ projects, where R# shouldn’t even get involved, and watch the keyboard go all crazy on you.
    Only way to work when this happens is to disable the R# add-in temporarily, which is really annoying. I know people love R#, but for me ViEmu >>> R#. Mess with ViEmu and it’s you that’s getting canned.
  • Smarter Settings: Given my concerns about making it easier to export/import my R# settings, and my desire to disable code formatting, it’s not surprising this is an issue for me.
    See, I already have all my VS code formatting rules properly configured and persisted in my .VSSETTINGS file. Install VS again and in seconds its there. Install R# and instead of defaulting its own code formatting rules to my existing VS settings, it applies its own coding conventions. That’s just disrespectful and annoying, to be honest.

Anyway, let’s see how life with R# 5.0 goes. So far, the VS2010 integration seems nice, but I will still be primarily a VS2008 user for a long time, so it sucks a lot that stability there hasn’t improved.

VS2010 RC Weirdness Around Custom Format Definitions

I’ve been noticing some oddities in how Visual Studio 2010 RC handles Custom ClassificationFormatDefinitions when multiple extensions are interacting together. It it hasn’t been fixed already, then I guess it’s already too late for it to matter, but I still wanted to bring it up just to know if it’s just me that’s been noticing this.

As some readers are aware, I’ve written a couple of VS2010 extensions for myself which I always install as soon as I setup a new VS2010 installation, and so far I’ve been very happy with the results and VS2010 extensibility in general. Both of these extensions define custom ClassificationFormatDefinition, whose format I then tweak on my current VS color scheme.

And this generally works great. That is, until I install another extension created by someone else. The first time I noticed this was when I installed the Visual Studio Color Theme Editor extension by Matthew Johnson. Everything worked fine, except that after using it a bit I realized that every time I changed the color theme for the whole IDE using Matthew’s extension, my custom ClassificationFormatDefinitions would revert back to the default formats specified in the original definitions in code, instead of the values I had assigned to them in my customized VS color scheme.

Re-importing the .vssettings file with my saved VS color scheme would get colors and formats right again, so, to be honest, I didn’t give it much thought at the moment.

Yesterday, however, I ran into this again while trying VsVim by Jared Parsons. As soon as I fired up VS2010 after installing VsVim, I noticed that custom formats for my own definitions reverted once again to the default values. I ran into a couple of issues with VsVim so decided to disable it for now while until I had time to look into it closer and imagine my surprise when right after restarting VS2010 my customized format definitions came up right away instead of the default values!

So my impression is that something (but not sure what) causes VS to ignore customized custom definition formats configuration (confusing, I know, sorry) when multiple VS extensions are running. Has anyone else run into this before?