Partager via


Better intellisense information

A couple of days ago I brought up the code definition window.  I mentioned what purpose it was trying to serve, how some of the developers were thinking about changing it and how I thought it could be improved. In response to that, a poster mentioned that Eclipse had a behavior that they really liked, specifically that when you held down ctrl and hovered over an identifier it would show a fragment of code showing the definition.

I can see an immediate benefit of that system over our current one in that it allows you to get similar information to the Code Definition View (CDV) without having to move your cursor from where you were working.  Thus you can easily hover over a ton of variables in the block of code where you're working and refresh your understanding of them.  I decided to spike that kind of feature to see if it could be done.  In order to do this I just tried to leverage our existing architecture as much as possible in order to make the amount of coding effort extremely small and so that I could get some quick results to run by you and the rest of the team as to how good a feature this was.

In order to do that I started with the fact that we already support the concept of giving you information about an identifier when you hover over it through the form of a tooltip.  Normally this is pretty basic information.  For a field/method we'll show the name of the type it's defined in and it's signature.  For a local variable we'll show it's type and name.  For a type we'll show if it's a class/interface/enum/delegate.  And for all of the above we'll also show the doc comment along with it.

I couldn't think of really relevant information to show when hovering over the name of a class (although maybe seeing the base and interface list would be useful).  I also couldn't' think of anything useful for a property/method declaration since we already show their entire signature (although it might be useful to know if a property has a getter/setter or not).  So that left me with fields, enums, and local variables.  For all of those it seemed useful to show not only the type and name of the field when you hovered over it, but also and code that might have initialized it.

I.e. normally when you hover over an enum value you see something pretty basic.  Given the following enum:

        enum Colors

        {

            Red,

            Green,

            Blue,

            Yellow = Red | Green

            ...

        }

When you select (or hover over) the use of Yellow you would see

hovering!

but now you see

hovering!

This initializer expression can be arbitrarily complex, and it works just fine even with multiple variable declarations.  All in all, i think it could be pretty useful like in the following case:

Before: hovering!

After: hovering!

There are of course many ways we could improve on this.  For one, i think it would be far more useful to show you the definition in context.  So rather than just see the declaration and initialization, you see a few statements above and below that one.  There's a good chance that that auxiliary information will help you understand that member better.  That could be a bit confusing, so it would probably be necessary to bold out the actual definition line in the tooltip so you could identify it in the ~5+'ish lines we'd be showing you (this is also something I'd like to spike).  IMO, the ideal thing to do would be to pop up a tooltip which contained a perfectly rendered snippet of your code with the appropriate definition highlighted somehow (maybe by slightly adjusting the background color behind it).

The current implementation has some issues with it that would need to be addressed.  Firstly, it rather blasé about how much memory it uses.  For every item that you have it stores this additional initialization information so that it can be displayed as necessary.  As you can imagine, the amount of these items one might have in their solution could be enormous and we need to be conscious of how much memory we use and not go overboard. If the amount of memory this consumed was a problem (on say 250 project solutions) then I'd probably move to a delayed computation mode where the initialization expression was determined when it was needed for the tooltip. But, this implementation was by far the simplest that could work and so I did it that way :-)   If we were to move to a model where we displayed the context around the definition I'm fairly certain this would have to change as every definition we learned about would suddenly be storing a large amount of duplicated data along with it.

Also, the new display has the potential to be quite confusing in debugger related scenarios.  Imagine the following code:

Now, when you're debugging you hover and you see that text and you go "what?!  How is the value 0??  Waitaminute, the watch window shows it as 5. wtfomgnojuo!!!"  Other systems, like the class designer and the object browser might then call into this code to get things to display to heir user and this information might not be relevant, and might be completely nonsensical to them.  Each of these issues is pretty easily solvable, but the worry is that there might be more out there that we could be unaware of.

The issue of consistency also comes into play.   If we added this, it's not clear that VB/C++/J# would as well.  They might not consider it a useful feature "too much clutter", or they might not be able to do it efficiently and don't want it affecting their user experience.

Anyways, I'd love to hear your thoughts on this.  If you like just the spiked version and would consider that a significant benefit; if you like it but really think it needs more; if you like it but think we're going down a completely wrong path and we should be doing something else; or if you just plain don't like it.

Comments

  • Anonymous
    July 30, 2004
    I might be off my rocker but....

    I thought that VB.NET had a lot of cool Intellisense features at the cost of a background compiler. And the background compiler is what hindered the language from being used in HUGE projects.

    Is there background compiling going on here?
  • Anonymous
    July 30, 2004
    The comment has been removed
  • Anonymous
    July 30, 2004
    This genre of questions have one universal answer: MAKE IT CONFIGURABLE. Now the question becomes what should the default behavior be, and I would say: disabled while the application is running (ie debug mode), otherwise enabled.
  • Anonymous
    July 30, 2004
    I've no idea how hard it would be, but for local variables, how about making it show the last assignment to it, rather than the initilialization? (of course, ideally, the last assignment would always be the initialisation... </functional zealot>
  • Anonymous
    August 01, 2004
    Addy: I'm not sure if I agree. Making it configurable is not necessarily the right choice in all circumstances. If there is a "right" think to do, then pick that over a choice. It's also not right if you're forcing hte user to change the choice over and over depending on what they're doing.
  • Anonymous
    August 01, 2004
    Ahrha: Why would that be idea? :-)
  • Anonymous
    August 02, 2004
    What about making this behaviour configurable via macros or something like the keyboard mapping dialog? It's better not to have too many options in the options dialog, but it would be nice to expose these commands to the user somewhere. For instance, I might want to call the "Show defintion" function with ctrl-d so I don't have to take my hands from the keyboard. Similarly, in debug mode, I could display variable values when hovering but variable definitions when ctrl-hovering.
  • Anonymous
    August 02, 2004
    David: These behaviors are always available through the keyboard. Specifically this would fall under the command:

    Edit.QuickInfo

    which you can bind to any keystroke.
  • Anonymous
    June 12, 2009
    PingBack from http://insomniacuresite.info/story.php?id=4139