08 April 2009

ReSharper 4.5 Released

We just released ReSharper 4.5, minor version aimed at performance, stability, compatibility and less memory usage. All the same great features plus some nice additions, free for owners of ReSharper 4.x licenses. You can read more about what we were doing to improve quality of our product for your pleasure.

Download ReSharper 4.5 and enjoy your productivity boost!

From now on, we are going to focus on ReSharper 5 with the main goal to support Visual Studio 2010 and C# 4. But that is not the whole story about next major version! I will be blogging about ReSharper 5 cool new features during our way to the next release.

Develop with pleasure!

06 April 2009

Mortal Kode -- Quite Simple Generics

It is very important for a tool to understand correctly what is written in the code. You just can't underestimate the importance of this ability. If the code is not correctly parsed, resolved, analyzed and understood by the tool's core, any other feature of the tool can easily fail. Nobody wants Rename refactoring to miss changes, code completion to insert unavailable symbols and code navigation to put the caret in a wrong position. Actually, the most annoying thing would be wrong code analysis, when code is incorrectly flagged with error, when in fact it compiles just fine. This all can easily happen if underlying code model is wrong.

That's why here at JetBrains, we put a lot of effort into our code model, language understanding and work hard to handle even most complex cases -- after all, they can easily be found in real applications.

Today we will look at complexity of code involving generics in C#. Consider the following example (thanks to Vladimir for this one):

  abstract class A<T>
  {
    public abstract void Foo(T x);
    public abstract class B<S> : A<B<S>>
    {
      public class C<U> : B<C<U>> 
      {
 
      }
    }
  }

I think not too many people out there can easily say what would be the correct signature for the implementation of method Foo in the nested class C<U>. As for me, I can't. Doing it manually is simply too much.

First, we try Visual Studio "override" helper and we get the following:

  public override void Foo(A<B<S>>.B<C<U>> x)
  {
    throw new NotImplementedException();
  }

Complex enough, and not quite correct:
error CS0115: 'A<T>.B<S>.C<U>.Foo(A<A<A<A<T>.B<S>>.B<A<T>.B<S>.C<U>>>.B<S>>.B<A<A<T>.B<S>>.B<A<T>.B<S>.C<U>>.C<U>>)': no suitable method found to override 
error CS0534: 'A<T>.B<S>.C<U>' does not implement inherited abstract member 'A<A<A<T>.B<S>>.B<A<T>.B<S>.C<U>>>.Foo(A<A<T>.B<S>>.B<A<T>.B<S>.C<U>>)'

Let's see what ReSharper 4.5 inserts when developer uses "Implement missing members" action from the "Generate" menu:

  public override void Foo(A<A<T>.B<S>>.B<A<T>.B<S>.C<U>> x)
  {
  }

You can see that parameter type is exactly the same as expected by compiler. Needless to say the signature is correct, and you don't have to compile it first.

Does your tool understand non-trivial code?

Next time, we'll take a look at some lambda fun.