C++/CLI IntelliSense in Visual Studio vNext
Recently Mohsen & Craig talked about a Renaissance within C++ development and Tony talked rebuilding our developer communication around C++, both of these videos touched on the subject of providing a more real world pragmatic discussion around why we do things and what we’re planning. This post is the first in a series of posts we’re planning on making over the coming months where we’re asking for your thoughts about what you need in a C++ development tool and about our proposals for the next version of Visual C++. To set the stage for those discussions we’ll be providing some insight into how and why we made some particular decisions regarding product features. In the case of something new we’ll share how we saw the problem space and how we’re thinking of addressing it.
We’re looking forward to hearing your thoughts regarding these features and how best we can use the developer resources we have to give you the most value in the upcoming product (ideally we’d want to deliver on 100% of your needs but, as you know, sometimes you have to make trade-offs so we’re looking for your help to make the right ones).
The first feature area we’d like to hear from you about is C++/CLI IntelliSense. Let’s provide some background explanation and then discuss what we’re doing.
Why We Didn’t Include C++/CLI IntelliSense in Visual Studio 2010
As we are close to the final release of Visual Studio 2010 SP1, one of the top issues that came back is the absence of IntelliSense in C++/CLI projects. When we released the SP1 Beta last December, this issue topped the list of complaints as it was announced that it would not to be part of SP1. In this post we’ll explain a bit about the evolution of C++ IntelliSense support and one of the two questions everybody asks: why it’s not supported for C++/CLI projects in Visual Studio 2010?
A Brief Evolution of IntelliSense in C++ Languages
Those developers who have been using Visual Studio since its earliest editions know that IntelliSense has been featured for both native and managed C++. So why is it today only available for native? IntelliSense is a powerful feature that has to meet certain goals:
- Accuracy: all suggestions must fall within the context you are in, still encompassing the latest version of the complete related projects (i.e. a change in a header file).
- Speed: as fast as your fingertips. Thus the implementation must be based on a time-critical approach.
Our first implementation of C++ IntelliSense appeared in Visual C++ 6.0 and we did this through the creation of a supporting file, the infamous .NCB, that contained consolidated references and definitions generated by the compiler. IntelliSense was pretty limited but still considered an outstanding feature as no other IDE at the time offered anything similar. The .NCB file contained a rich set of information including class members, global variables, etc. but we didn’t have complete information for such constructs as namespaces and exceptions. This deficiency and the fact that these files grew so large, complex and occasionally corrupted (who doesn’t remember fixing an IntelliSense problem by deleting the .NCB file and having it rebuild), that we needed to change the underlying implementation.
With projects becoming more complex, additional issues emerged such as the one known as the “multi-mod” problem. This problem occurs when a header file is included into multiple translation units with different contexts (such as difference macros). With the NCB approach, we only remembered one context for a header file and you would see incorrect results for IntelliSense when in a different context. There was also the issue where we needed to recompile many files when a shared header was changed. This could cause the IDE to freeze in some cases (this also happened if a compile option was changed, like switching from DEBUG to RELEASE). To address this we needed to not only better understand the information contained in the source code but also store that data more efficiently and reliably. We also wanted to ensure that the IDE was as responsive as possible. Initially, we used techniques such as background compilation threads, idle time detection and priority queues to achieve this but eventually we realized that a complete IntelliSense re-architecture was required. For Visual Studio 2010 we started that work and decided to use a live model for IntelliSense, while changing the store (which is still used for “browsing” features) from an .NCB file to SQL Server Compact Edition. This helped increase the performance while also decreasing memory consumption. We also wanted to address the problem of differences between how we interpreted the code for IntelliSense and how we did it for the final compilation product. This problem manifested itself in things like the language features appearing in the IntelliSense engine but not in the compiler and vice versa.
The 2010 Dilemma
Prior to VS 2010, we used a modified version of our command-line compiler to implement IntelliSense. As we added new features to the language it was minimal work to enable them for IntelliSense. As part of our IntelliSense/IDE re-architecture in VS 2010 we decided to use a new compiler codebase for IntelliSense. This decision provided many benefits, but we simply underestimated the amount of work it would take to implement C++/CLI in this codebase, and we couldn’t change our plans by the time we realized it.
In addition to this unexpected amount of work, there were lots of new features that customers’ were asking for, such as:
- An improved IntelliSense error reporting.
- Faster compilation and more optimized code generation.
- #include auto-completion.
- The ability to target specific compilers and libraries.
- New MFC features like the class wizard or the restart manager.
- A build platform that provides better diagnostics, extensibility and integration.
- Improved C++ standards adherence.
- Support for parallel programming from both libraries and tooling (debugging, etc.)
- Standard Library improvements.
- Availability of Windows 7 technologies (like Direct3D 11, etc.)
Even with this constraint we really wanted to deliver IntelliSense for C++/CLI in VS 2010. We looked at several alternatives and mitigations, but nothing would fit our schedule and provide real value to our users. We considered trying to enable the old IntelliSense mechanism (i.e. NCB) for C++/CLI projects, but that would have been a huge amount of work as well. We also considered trying to hack something in, but we rejected that as well after investigation. We wouldn’t have been able to provide IntelliSense on any imported metadata, which would have made IntelliSense pretty useless for most people.
In the end it was one of those hard cuts you have to make when dealing with the real world resource and schedule constraints. It turned out that the work was also too much work to fit into SP1. As soon as we wrapped up VS 2010, we started work on C++/CLI IntelliSense, but it wasn’t ready in time for SP1. We realize this wasn’t what you wanted to happen and an explanation doesn’t help you get your work done if you are affected by this, but we want you to know the truth.
The good news, though, is that all these architectural changes made in Visual Studio 2010 have enabled us to deliver a better IntelliSense experience overall and will set us up to deliver a number of other features in the future.
C++/CLI IntelliSense in Visual Studio v.Next
Hopefully this gives you some insight into why we made the decisions we did.
The good news is that C++/CLI IntelliSense will be in the next version of Visual Studio. We’ve done a lot of work to get this in and, barring major unforeseen complications, you should expect to see it in the final product. As always, there is some risk, but we wanted to get this information out in front of you for your comments.
In our next post on this subject we’ll delve into more detail on our plans and ask you to comment on our thoughts. Stay tuned.