Background
Ken Sykes and Juan Carlos Arevalo Baeza (JCAB) are both Principal Software Engineers who work on Time Travel Debugging at Microsoft. They are part of the team that maintains and develops the Windows Debugger (WinDbg) and related technologies. Their codebase is developed with C++ and CMake and they primarily use VS Code for day-to-day development of their code.
They have been integrating GitHub Copilot and GitHub Copilot Chat into their C++ development in VS Code and have found many useful workflows for the AI pair programming tool.
Download GitHub Copilot
To access GitHub Copilot and Copilot Chat, you will need an active subscription to GitHub Copilot. If you’re just getting started, please check out the VS Code documentation.
This blog post series has been written in partnership with Ken and JCAB to highlight their workflows with Copilot and Copilot Chat respectively and inspire other C++ developers on potential use cases to integrate with their code.
How we use Copilot for C++
Copilot provides AI-generated autocomplete-style suggestions as we code. Copilot has greatly helped our team with reaching new levels of productivity when interacting with our large codebases.
For example, it has been good at following our coding styles for repetitive tasks. We highly recommend Copilot to save you some time with repetitive typing.
This has been widely applicable to many areas of our C++ workflows, from writing test code to implementing classes. Two specific examples that have been greatly impactful in that we will expand upon below are adding additional methods to a class and generating classes after migrating library dependencies.
You can follow along with the examples in this sample repo: KenSykes/ExampleLibraryConversion: Demonstration of Copilot code completion (github.com). Please note that Copilot suggestions are probabilistic, not deterministic, and you may not see the exact same suggestions as you follow along.
Adding additional methods to a class
Reference code: Branch: main, file: ExampleLibraryConversion.cpp
One of our favorite ways to use Copilot is to have it follow existing coding patterns to save typing. For example, we have a class that interacts with dbghelp.dll
through function pointers (GetProcAddress-based delay loading). Recently we needed to add some additional dbghelp methods to this class, such as SymInitializeW
. All we need to do is go to the places that define existing structs, press enter and start to type, and Copilot will dynamically update to fill in the rest. Then, we can edit down the results to get to the desired outcome.
After adding this new class member, we can scroll up to the constructor and notice that Copilot is able to offer a valid initialization suggestion for us.
Then, add the prototype for the wrapper and Copilot can offer a reasonable implementation.
A more complex example of Copilot helping with initializations can be viewed below for now a new Load Module object.
In this example, Copilot can generate the implementation of the method with great default options. These default options are also commented by Copilot to document what the zeros and nullptrs mean.
Generating code when migrating libraries
Reference code: Branch: convert_to_nlohmann, file:ExampleLibraryConversion.cpp
We have found Copilot helpful with managing libraries in our repository and refactoring code. Specifically, we previously used the rapidJSON library, managed through a vcpkg.json
file, to serialize our structs into JSON.
An example of such a struct of information can be viewed here:
The original rapidJSON code was hand-written and took hours to do (including time to become familiar with the library). While producing this blog, we found that Copilot could generate much of the code correctly once some rapidJSON boilerplate code is provided. See how easily Copilot can generate the JSON object using pre-determined o and s objects for rapidJSON:
We recently had a desire to update this library dependency from rapidJSON to nlohmann-json, since the nlohmann-json library is better-maintained. To start updating the code, all we needed to do was update our vcpkg.json
dependencies to have a nlohmann-json entry and include this new dependency in our cpp file per official library documentation.
From there, Copilot was able to produce 80% of the code for this process with the proper formatting for nlohmann-json, letting the team focus on reviewing the generated code rather than implementing the fixes in applicable areas.
Generating code based on input data
Reference code: Branch: convert_to_nlohmann, File: ExampleParser.cpp
Copilot can also save you time writing parsing code. Given some sample input data pasted in a comment, Copilot can generate C++ structures and parsing code for you. To demonstrate this, we started with the nlohmann JSON parser, added a conversion for std::string
, and then pasted some sample JSON from openweathermap.org in a comment.
Now, watch Copilot go to work. Move cursor below the comment and hit Enter. You will start to get suggestions for code. Keep pressing Tab and Enter as Copilot writes out all the structures to represent the data and the nlohmann to_json()
/ from_json()
methods, culminating in a ParseWeatherData()
method that can fully parse the sample text.
The full Copilot-generated code can be found here.
If you look closely that the Weather field of WeatherData is a single element but the JSON is an array, so a std::vector<>
would have been a better choice. Things like this are easy to fix up on your own, or perhaps add more representative JSON samples to the comment to give Copilot more context.
Wrap up
A big thanks to Ken and JCAB from the Time Travel Debugging Team for collaborating with us on this blog post!
Copilot can provide you with AI-powered assistance at many points in your C++ development, such as migrating libraries and initializing new methods. Download Copilot and try out utilizing it in your areas of repetitive coding! Please note that responses are generated by AI, so we recommend reviewing any responses provided and iterating when necessary.
Our team is working hard on improving C++ integrations, so please let us know any improvements you’d like to see to your C++ workflows. Additionally, let us know what other types of content you’d like to see regarding use cases or additional information about Copilot.
We welcome all types of feedback on your experience with the product. The comments below are open, or you can find us via email at visualcpp@microsoft.com or via Twitter at @VisualC.
How one can enable header file visibility in Copilot?
Or let Copilot to see entire workspace files to be aware of the whole context…
Hi,
We recommend opening any relevant header files or workspace files to improve quality of Copilot completions results. Copilot will take these opened files into context to improve relevant completions results.
Hi,
Thanks for the answer, still it looks like Copilot in VSCode completely ignores all the stuff like #editor, #selection, #file, for example:
Me: please find any problems in #selection
Copilot: I'm sorry for any confusion, but as an AI, I can't directly access your local system or files. You need to paste the code you want me to analyze into the conversation. Once you've done that, I'll be able to help you find any potential...