Hello, I’m Mitchell Slep, a developer on the Visual C++ compiler team. I’m very excited to tell you about a new feature in Visual Studio 2010 – C++ IntelliSense can now display compiler-quality syntax and semantic errors as you browse and edit your code!
We display a wavy underline or “squiggle” in your code at the location of the error. Hovering over the squiggle will show you the error message. We also show the error in the Error List window. The squiggles are great for showing you errors in the code you are currently viewing or editing, whereas the Error List window can help you find problems elsewhere in the translation unit, all without doing a build.
Designing the feature
We had two scenarios in mind when designing this feature. One is of course productivity – it’s very convenient to be able to fix errors as they happen instead of waiting to discover them after a build, which can save you a lot of time. We also wanted to improve the experience when IntelliSense doesn’t work. IntelliSense has always been a black box – it often worked well, but if it didn’t, you had no idea why. Now IntelliSense has a powerful feedback mechanism that allows you take corrective action – either by fixing errors in your code or making sure your project is configured correctly.
One decision we had to make when designing this feature was how often to update the errors as you edit your code. If we don’t do it often enough, the errors quickly become out of date and irrelevant. But doing it too often can also lead to irrelevant results, like a squiggle under ‘vect’ while you’re in the middle of typing ‘vector’! We also don’t want to hog your CPU with constant background parsing.
We found that a good balance was to wait for 1 second of idle time after you edit or navigate to a new part of the code before beginning to update the errors. In this case ‘idle’ means that you haven’t typed anything and you haven’t navigated to a different part of the code.
We also experimented with some different designs for what to do with existing errors during the short window of time between when you make an edit and when the newly updated errors are available. For instance, one design we tried was to clear all squiggles on the screen immediately after an edit, and then redraw the new errors when they are available. We also considered a variant of this where we only clear the squiggles on the lines below the location of your edit (since making an edit can generally only affect code appearing after it). These designs have the advantage that you never see a stale squiggle, but in usability studies we found that this produced an annoying flickering affect, and also some confusion as to whether a squiggle disappeared because it was fixed or because it was just temporarily being updated. The design we went with was to leave existing squiggles in place after an edit, and then swap them with the new errors when they are available. This works well since the updates are very fast.
One of the technical challenges with this feature was making it fast. As many of you know, large C++ projects can often take several hours to build. One of the ways we get around this is by having IntelliSense focus on a single translation unit at a time (a translation unit is a .cpp file plus all of its included headers). However, even that didn’t give us the kind of responsiveness we wanted for a live-compilation feature like squiggles.
To get even better performance, we’ve developed some innovate incremental parsing techniques that minimize the amount of code we need to parse. This allows IntelliSense to parse your code much faster than the time it would take to do an actual build (or even the time it would take to compile a single .cpp file). The ideas are simple, but are challenging to implement in a complex, context-sensitive language like C++.
When you first open a file, we parse just enough code to build up a global symbol table, skipping over a lot of code (like function-bodies) that only introduces local symbols. Once we’ve built up the symbol table, we lazily parse the code that we skipped “on-demand”. For instance, we only parse the inside of a function body when you actually view it on the screen. If you make changes inside a function body, we are able to reparse just that function body. Of course, all of this only happens during idle time, as described above. These parsing techniques allow us to show you fast, relevant errors even as you edit large, complex code bases.
External build systems
If your solution already builds with Visual Studio, you will immediately benefit from having accurate syntax and semantic errors reported by IntelliSense as you browse and edit your code. But this feature is also good news for those of you with external build systems. The IntelliSense errors in the Error List window can guide you towards setting up a solution with accurate IntelliSense. For instance, if you load up a solution configured for an external build system, you might see something like this:
Now you know that you need to adjust your Include Path. Making these tweaks to your solution will dramatically improve the quality of IntelliSense you get with an external build system.
It’s been a lot of fun working on this feature and especially dogfooding it – it’s great not to have to do builds all the time! You can preview this feature in Beta 1 and I look forward to hearing your feedback in the comments.