Better information in error cases


Dr. Pizza raised an interesting point in response to the previous post about method overload resolution, specifically:


“…but I would say that I hadn’t realized why it didn’t show completion information in some situations. Now it seems clear”


I thought this was pretty important to call out because it it exemplifies a problem that can arise when you work on a product for too long.  Namely, you start to recognize and accept the limitations of your current implementation and you don’t realize that from the end users perspective something will just seem broken and they won’t have any idea why.  What’s worse is that often times people end up confused, suprised or thinking that they’ve done something wrong.


With regards to the previous post, let’s look at completion lists.  A simple description of a completion list would be that is shows possible things that you would want to type given the current code context.  Note: we can’t say “show all valid things that could be written at this point” as you might be writing something like a method call to something that doesn’t exist.  There are also issues given the nature of code to be continuously broken as you’re in the middle of typing it, and for parse trees to often be in very confusing shapes, which can cause all sorts of fun disambiguating scenarios to arise.  And, for the most part if you’re typing complete gibberish we will probably to a pretty bad job of dealing with the situation.  (Just try typing your language of choice in an editor designed for another language and see how long it takes for it to get unhappy).  However, if you are writing reasonable C# code then it is certainly reasonable to expect this feature to “work” given the above intuitive definition.  And, given the extreme cases that cause completion lists to screw up, you might reasonably be unsure why things weren’t working when you were typing fairly normal code.


So the question I have is “is it necessary to try and convey that information to the user” and, if so, “how?”  C++ currently just says “Intellisense: ‘Type of expression to the left of the . has a type which could not be resolved’” in the status bar.  Would similar messages be useful to users, or just spam?  Something akin to “type of expression could not be evaluated because it contains an operator in it” or “unable to resolve method call to a single overload of Foo”?  I don’t like the latter because it seems to imply that you’ve done something wrong and that when you compile you’ll get a message about an ambiguous call to a method.  However, when it compiles correctly you’ll probably be asking yourself “what the heck was that message talking about!?”  Of course, it’s not pleasurable to think about announcing to the user: “sorry, couldn’t do that because it just isn’t supported”, but if it was valuable feedback and prevented users from thinking that their code was at fault, then it might be a reasonable thing to do. 


Comments (28)

  1. Dr Pizza says:

    Even though the C++ error is often wrong (as it oftentimes means that IntelliSense has just given up the ghost and needs its file deleted), and is often frustrating, it’s still preferable to the behaviour that C# seems to exhibit–doing nothing at all. If nothing else, it just lets me know that the computer "heard" me but can’t do anything to help me out.

    So, yes, I believe it would be useful.

  2. Daren says:

    I’ve often wondered why the current state of intellisense could not be communicated via the appearance of the caret – after all, that is where the coder’s attention is focused (or is that just me?).

  3. Daren: Could you give me an example of what you mean. How would you differentiate the cursor to convey the state of intellisense?

  4. damien morton says:

    Intellisense: confused

    in the status bar

  5. Timbo says:

    This is the first thing that popped into my head reading Daren’s post. You could use a superscript symbol to convey the state. If Intellisense has nothing to do, just leave it as the normal caret ‘|’. If Intellisense is confused, use ‘|<super>?</super>’. If Intellisense has good suggestions, use ‘|<super>!</super>’ — or just leave it normal, since the presence of suggestions is a good indicator by itself.

  6. damien morton says:

    Or we could have clippy wander onscreen and do a little confusion dance.

  7. Damien: Could you mock up some images of what that would look like?

    I’m getting a picture of "Filler Bunny" dancing around, but I don’t think many people would get the reference.

  8. damien morton says:

    Thats disgusting (I looked it up), but somehow aesthetically pleasing.

  9. j3 / Jeff Casimir says:

    I think the idea of augmenting the cursor is a good one, but I think it would be more inline with current MS functionality and more easily recognized to use sub script.

    Concept:

    The cursor is augmented with a symbol in a trailing subscript that reflects the current status of intellisense.

    Definitions:

    ! : Intellisense has detected an error (syntax, etc.)

    * : Intellisense has possible suggestions

    ? : Intellisense is confused on the current code

    Considerations:

    I would put the maniputlations on about a 3 second delay. If I am actively typing I don’t care what Intellisense is thinking; I am busy. If I think I’ve messed something up or need help, I am going to pause.

    Food for thought…

  10. Dr Pizza says:

    Another thing that I find annoying is that C++ and C# operate differently.

    I truly don’t understand why the text editors aren’t consistent across the different languages vs.net understands. I mean, I understand that there may be some differences; C++ is harder to parse than C# so sometimes its IntelliSense won’t be able to tell you what’s what; for example, its templates are generally unbounded (relying only on matching operations) so when writing a class or function template it can be hard to provide assistance.

    But I don’t understand why, for example, C++ should offer a warning when it can’t autocomplete but C# doesn’t. Shouldn’t these things be built to operate in the same way?

  11. Dr.Pizza: I would imagine the reasoning would be many fold.

    On one hand, each individual language team might have different ideas about what the best way is to interact with the user. There are a few options that can occur in this case. You can try to provide options to make each language emulate each other language. Or you can try to find some common middle ground. The first potentially has high cost as you try to mimic the behavior of every different system out there. The latter has the potential to end up with systems that aren’t as well targetted to the diffeerent developers that the different teams are targetting.

    Note: I’ve seen what you’ve said about Mort/Elvis/Einstein, and this isn’t a debate on that. It’s more about the fact that each team thinks very differently about what’s it’s trying to optimize, and it doesn’t seem to always consider the developer who moves from language to language. Part of this is that we don’t have a strong sense for how common this activity is.

    For example, take something as simple as the editing. experience. What should happen when someone presses enter in a completion list? VB being a line based langauge has strong roots that say that return means "go to the next line", whereas in other language we’ve seen that enter means to a person "select the current item in the list and that’s it".

    Another model would even be one where the editor wouldn’t allow you to leave your current line until you’d fixed all the mistakes on it. Maybe some people love that, maybe some people hate it. If those love/hates seem to fall on the boundry of the users who use one language over another, then maybe it makes sense to have separate behaviors in the editor for those languages. As I said before, sometimes the cost of having each language able to have all the different behaviors, and sometimes there isn’t really a middle ground.

    Ok, that’s a more higher level idea about why things can be different. In terms of actual specifics, sometimes it’s just because there isn’t a task force out there that verifies that all the languages behave the same way. When you have teams in different buildings, states and countries, you tend to allow a lot of autonomy because otherwise it can be a large burden with very little benefit. Also, going back to the original reasons, different teams think differently. So say VB feels it has a great idea for what to do with completion lists (filtering in this release for example). But we’re unconvinced it’s the right thing for our users. Or we have ideas that we think are great and we’d like to do a lot more than just filtering. So we might wait and see what the user feedback is on the features that other teams are doing (the blog serves as one way to get that feedback). Taking the status bar example again, what if C++ decides they have a better way of presenting this information (maybe like a tooltip that says "couldn’t determine intellisense because we are currently parsing the file", that way you wouldn’t have to watch the status bar, etc.) does everyone else have to then adopt that (potentially costly) new model?

    Then if we see that people really do want something in the editor (a behavior or feature) we then strongly consider it and also ask ourselves the question "is there a way to make this even better for C# users in the time we have". And, say we do come up with something awesome that we implement. The other language might say "that’s great, but it’ll take us 30 days to make our stuff work with it, and we consider other things more important"

    Ok, now to answer your specific question: "Shouldn’t these things be built to operate in the same way?"

    They are, in principle. However, teams have lots of flexibility and it’s not always clear that mimicing currently existing behavior is the best option.

    Note: I’m not arguing against consistency in the slightest. I just want to know if in this case consistency is the best choice or if there are better ways to do it.

    Also, there are people who are thinking about this. However, especially now when things are in beta it’s a time for lots of different teams and people to be experiementing with all teh different ways they think that the editor can be improved. Getting feedback during this time is what helps us determine what was/wasn’t a good idea and what we should try to have for everyone.

  12. Dr Pizza says:

    "does everyone else have to then adopt that (potentially costly) new model?"

    I rather suspect the answer should be yes. All or nothing. Make a decision. Or if it’s something where it’s easy to do in either case, but one group (or the other) just doesn’t like it, make it an option. Sometimes giving the user an option is just being lazy, but you know, I’m a software developer; I’m not going to be scared by an option. Pick a default (so don’t /force/ me to choose), and let me override it. Let me override it on a per-language basis, even.

    See, I could live with wildly different IDEs back in the VS 6 days because that’s what they were. Wildly different. Interdev was nothing like VC++ was nothing like VB. God alone knows what J++ was like. They made bugger all concession to consistency so their huge inconsistencies were tolerable.

    Then VS.NET came along. Off went VB, VC++, InterDev, and along came one IDE to rule them all.

    And in lots of ways, it’s pretty consistent. It all looks and feels more or less the same way across the board.

    But it’s not /completely/ consistent. And it’s this "mostly but not entirely" consistent feel that really grates. VS 6 wasn’t "inconsistent", it was just plain /different/. VS.NET acts like it’s meant to be the same /but it isn’t/.

    And frankly, that’s no good.

    Now maybe I’m unusual; I actually exploit VS.NET’s multi-language capabilities to some extent. It’s perfectly possible that most people don’t; they’re either /VB.NET guys/ or /C# guys/ or /C++ guys/. But I wouldn’t be so sure; at the very least, any ASP.NET guys are going to be mixed language (HTML plus C# or VB.NET, typically).

    Maybe I’m unusual in wanting these different languages to operate in about the same way; maybe people really do want C++ to warn them when it can’t IntelliSense but don’t mind when C# doesn’t.

    But I feel I should at least have the option. Much of the work at consolidating the interfaces into different languages has been done–I’d really like it to be finished off.

  13. Dr.Pizza: I don’t think this is unusal at all.

    I’d like to know more about your development practises involving the different languages. Fele free to send me a message through the contact link if you’d be interested in discussing this with me.

  14. Kavan says:

    I’m another cross language developer. It’s true, I prefer VB.NET, but I realize when doing things in another language will benefit me. So I usually end up writing some parts in C# or even in C++. I’ve already tried creating a single assembly out of netmodules produced with several languages in VS2005 and it’s great it’s possible at last. But it’s a pain not to be able to do it inside studio. Now I need several configurations: one that references projects as usual so that intellisense and everything is working for me and another for single assembly build. I hope there would be more support for this and even for cross references between projects (it is possible to do it in command line, take a look at System.dll and System.Xml.dll).

  15. Kavan: I thought you hated VB. It had all those things like optional parameters which you didn’t like!!

    🙂

    See my last post to Dr. Pizza. I’d also like to discuss this with you.

  16. DrPizza says:

    "I’d like to know more about your development practises involving the

    different languages. Fele free to send me a message through the contact link

    if you’d be interested in discussing this with me. "

    Principally when grafting C or C++ to .NET.

    MC++ is an abomination, but a nicer (easier) way of wrapping such code to

    make it .NETtable than using P/Invoke (mostly because it lets me do all the

    nice (or nasty, I suppose… I like ’em, anyway) things that C++ lets me do

    with pointers and such, and only wrap in CLR types at the very edges; using

    for example P/Invoke with C# and unsafe blocks just doesn’t seem to work as

    nicely for this kind of thing). C++ does things like easily let me read an

    unsigned integer out of a buffer; not so the .NET world (I don’t know why

    unsigned integers are not proper types, but goddammit, they should be.

    There are just too many network protocols and the like out there that depend

    on them. But I guess that’s beside the point here).

    But obviously, I wouldn’t want to actually write any "real" .NET code in

    MC++. C# is in most ways a much better alternative. I don’t know about

    anyone else, but I don’t much like writing __gc everywhere.

    So I’ll typically actually *use* my MC++ wrapper from a C# project.

  17. mikeb says:

    Cyrus:

    On a related note to this, I find myself often pressing Ctrl-J or Ctrl-Shift-Space to get Intellisense to do something when it doesn’t but I think it should.

    When it works, this is fine. However, I find that quite often it doesn’t do anything. After frantically repeating the hotkeys over, and over, I often figure out that Intellisense is not working because I don’t have an appropriate ‘using’ statement or assembly reference.

    After reading your blog, I now see why there are other situations where it doesn’t do anything.

    What I’d like is some sort of response to Ctrl-J or Ctrl-Shift-Space that indicates that Itellisense is working, but might not have any information for me because:

    – there is an overload that Intellisense can’t/won’t resolve

    – Intellisense doesn’t recognize the identifier – maybe because of a missing using statement or assembly reference.

    A 2 by 4 to the head like that would help me during those times when I just can’t get past pressing the hotkeys…

    Oh, and while I’m on the topic of ‘using’ statements, when I’m adding code that happens to use a new class that hasn’t been previously used in the source file, the editor should be able to take a new ‘using’ statement and automatically shove it in at the top of the source file, so I don’t have to jump to the top, add the ‘using’ then get back to where I was doing real work.

    That would be nice.

  18. MikeB: We’ve addressed many of these issues in VS2005 and I would really like to hear if they’re working for you.

    Specifically, we’ve added type colorization so that you can now tell instantly when intellisense cannot bind to something you’ve typed.

    Also, we’ve added a smart tag to automatically fully qualify the name or add ausing for it when this happens and its’ a type that we know about in the system.

    Could you try out the beta of the express sku and tell us what you think?

    Thanks!

  19. Kavan says:

    Cyrus: "See my last post to Dr. Pizza. I’d also like to discuss this with you."

    I use C# and C++ for performance reasons. I’m mostly developing game kind of things using managed directx where performance is of real concern. So things like unsafe code and c++ interop to create custom wrappers come handy. Now with C#2.0 another feature that I’m looking forward to is anonymous methods. I’m doing stuff like artificial intelligence and there I need a way to write code that is to be executed at a later time (something like that). Until now I’ve done things so that I manually created those helper classes that anonymous methods do out of the box. This is a good enough reason for me to use the feature.

    Is there any specific thing about development practises involving the different languages that you’re interested to hear about?

  20. I’m also using Visual Studio with multiple languages (C# and C++) and find it strange and unsettling that the editor behaves differently for different languages. For example, when commenting a block of code, why does the // appear just before the code in C++, but at the start of the line in C#? I think of the editor as being a uniform, cross-language component, and wouldn’t ever think to discuss the "C++ editor" or the "C# editor".

    It makes more sense to have these editors options configured on a per-user level, rather than a per-language one. Or perhaps the settings could be customized by language (similarly to some of the tab options), but default to being the same across languages.

    Also, I do think it would be nice if the Intellisense could indicate why it didn’t show any options. Perhaps the cursor could turn red if you had a syntax error (to match the underlining), and another color (or do nothing) if there were simply no completions available.

  21. Dr Pizza says:

    " and wouldn’t ever think to discuss the "C++ editor" or the "C# editor". "

    Indeed.

    From reading blogs it’s clear, however, that that’s how MS is approaching things.

    IMHO that attitude needs to be rethought. It’s not appropriate for a multi-language IDE.

  22. David, we are looking into changing the behavior of // to be consistent between C#/C++

    Dr.Pizza: We approach it that way because VS is a platform that one can ship editors in. It is mostly language neutral. I.e. when someone plugs in something like a scheme or dylan editor we cannot enforce other language constraints on it. So instead a command like "comment out this span of text" gets sent to the individual language, since it’s not safe to just insert //’s into the buffer. Each language then takes care of it according to it’s own rules.

    We don’t believe that it’s the case that there is one right answer to how should everything behave, and while we understand the argument for consistency, it’s not considered the most important thing when designing or implementing a feature.

    Also, in response to " maybe people really do want C++ to warn them when it can’t IntelliSense but don’t mind when C# doesn’t. "

    I dont’ think I ever stated that people didn’t mind. I think I was asking if the C++ model was helpful and if people had other suggestions (which they have) for a better way to present this to the user.

    Note: C# is it’s own product that ships seperately. It happens to be the case that it integrates within VS just like many other products out there (the exact number that do this is quite large). We coudl try to approach it as one single entity, but that would be incredibly dificult to coordinate with our ISVs with. But maybe our customers would like it more if we enforced consistency across everything.

  23. DrPizza says:

    "Dr.Pizza: We approach it that way because VS is a platform that one can ship editors in. It is mostly language neutral. I.e. when someone plugs in something like a scheme or dylan editor we cannot enforce other language constraints on it. So instead a command like "comment out this span of text" gets sent to the individual language, since it’s not safe to just insert //’s into the buffer. Each language then takes care of it according to it’s own rules."

    Sure, but there can still be a "VS way of doing things". So, for example, the behaviour of the comment tool should be to put the comments at the left margin for all languages where that’s possible (I mean, I can understand breaking the rules if one had a language where it just wasn’t possible to meet the rules, but that should be the exception, not the, er, rule. Apart from anything else, the deviation in behaviour in such cases is expected and understood, rather than being simple whim). Or IntelliSense should always warn if it can’t help you out. And if you make the warning mechanism more interesting (by messing with the cursor, for example) it should be done across the board. Maybe this’ll mean having an interface for cursor manipulation so that ISVs can tap into the same mechanism (so they all use a consistent "IntelliSense doesn’t recognize the type" or "IntelliSense is confused by what you’ve written" or whatever cursor/wiggle underline/etc.), but if that’s the price to pay, so be it.

    "We don’t believe that it’s the case that there is one right answer to how should everything behave, and while we understand the argument for consistency, it’s not considered the most important thing when designing or implementing a feature. "

    It should be. It’s surely the people spending hundreds of dollars on VS.NET that are getting the software entrenched, not the people spending $100 on Standard editions (or Express editions, as they now seem to be called).

    "Note: C# is it’s own product that ships seperately. It happens to be the case that it integrates within VS just like many other products out there"

    This is why it can’t be treated simply as its own product. If the only similarity between the products was that they were development environments–if they were as different as VB and VC++ 6 were–then it wouldn’t matter. But they’re just /not/.

    Eclipse has a similar approach, and IMO it *really* hurts it. It takes things further than VS.NET does (I don’t know that it’s actually any more /capable/ in this regard in VS.NET, rather it’s just that due to its development and distribution model these things are rather more in-your-face than in VS.NET) and it suffers because of it; there are loads of plugins but they don’t really work together. They don’t offer consistency because they were all developed with the mindset of independence. VS.NET has taken a few steps down that path already, and I personally don’t care to see it take any more. Eclipse is what I use in my day job, and I curse it every time I use it, because it feels too much like disjoint pieces of functionality, and not an integrated coherent environment.

    "(the exact number that do this is quite large). We coudl try to approach it as one single entity, but that would be incredibly dificult to coordinate with our ISVs with. But maybe our customers would like it more if we enforced consistency across everything. "

    I imagine the customers who use the single-language instantiations won’t mind one way or the other (because they won’t know). On the other hand, I suspect that every developer who uses multiple languages will be thankful (even if they’re not really cognizant of the fact) if you do go for more consistency. It’ll just feel that bit better.

  24. Dr. Pizza: I’ve added you as a vote for consistency between langauges as something we should do in the next version. Is that ok with you?

    Also, when you say "it should be", note that that’s a completely valid opinion, it’s just not hte opinion we hear from everybody. Nor is it something that people (so far) have tended to find as important as other work that is done. However, it’s not unimportant either. You’re not the first to state this, and there have been many passionate people sending this exact feedback to us.

    It is very much being considered and will be weighed against all the other work we want to do in the feature to see if it should be done.

  25. DrPizza says:

    "Is that ok with you? "

    Only /a/ vote?

    I feel more strongly about it than that.

    🙂

    "it’s just not hte opinion we hear from everybody"

    I’d be genuinely interested about those multilanguage users who don’t hold that opinion–to know their explanations and rationales.

    If they’re not users of multiple languages then their opinion on the issue counts for nothing, of course.