{"id":374429,"date":"2023-07-27T16:13:57","date_gmt":"2023-07-27T15:13:57","guid":{"rendered":"https:\/\/blog.jetbrains.com\/?post_type=dotnet&#038;p=374429"},"modified":"2023-07-28T14:12:47","modified_gmt":"2023-07-28T13:12:47","slug":"introducing-predictive-debugging-a-game-changing-look-into-the-future","status":"publish","type":"dotnet","link":"https:\/\/blog.jetbrains.com\/en\/dotnet\/2023\/07\/27\/introducing-predictive-debugging-a-game-changing-look-into-the-future","title":{"rendered":"Introducing Predictive Debugging: A Game-Changing Look into the Future"},"content":{"rendered":"\n<p>With the introduction of debugging tools, software developers were empowered to<strong> interactively investigate the control flow of software programs<\/strong> to find bugs in live environments. At JetBrains, we&#8217;ve always strived to improve the art of debugging. Besides the more <a href=\"https:\/\/blog.jetbrains.com\/en\/dotnet\/2017\/08\/21\/running-debugging-net-project-rider\">standard things you expect from a debugger<\/a>, we also introduced features like:<\/p>\n\n\n\n<ul>\n<li><a href=\"https:\/\/blog.jetbrains.com\/en\/dotnet\/2017\/11\/21\/resharper-2017-3-brings-debugger-editor\">Inline local variables, current line expressions and function returns<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/blog.jetbrains.com\/en\/dotnet\/2019\/08\/13\/debugger-additions-rider-2019-2-pin-top-floating-actions-redesigned-stack-frames\">Floating execution actions and Pin-to-top (Rider)<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/blog.jetbrains.com\/en\/dotnet\/2020\/10\/15\/immediate-window-interact-with-your-code-while-debugging-in-rider\">Immediate window with code completion (Rider)<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/blog.jetbrains.com\/en\/dotnet\/2019\/04\/16\/edit-continue-just-time-debugging-debugger-improvements-rider-2019-1\">Edit &amp; Continue and Tooltip Evaluation (Rider)<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/blog.jetbrains.com\/en\/dotnet\/2020\/04\/30\/smart-step-enabled-default-debugger-updates-rider-2020-1\">Smart Step-Into behavior (Rider)<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/blog.jetbrains.com\/en\/dotnet\/2017\/08\/28\/rider-advanced-debugging-breakpoints\">Advanced Breakpoints (dependent, temporary, and more) (Rider)<\/a><\/li>\n<\/ul>\n\n\n\n<p><em>Check out&nbsp;<a href=\"https:\/\/youtu.be\/KM27QGVwgas\" target=\"_blank\" rel=\"noreferrer noopener nofollow\">Joseph Guadagno\u2019s talk on Debugging Tips and Tricks with JetBrains Rider<\/a>&nbsp;to see these features live and in action!<\/em><\/p>\n\n\n\n<p>As a seasoned developer, you may have heard a few <a href=\"https:\/\/lemire.me\/blog\/2016\/06\/21\/i-do-not-use-a-debugger\/\" target=\"_blank\" rel=\"noreferrer noopener nofollow\"><strong>criticisms of using debuggers<\/strong><\/a>. Debugging critics usually advise putting more thought into the issue at hand, instrumenting unit tests, or adding good old log output.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full is-resized\"><img decoding=\"async\" loading=\"lazy\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2023\/07\/got-here.png\" alt=\"IDE: Has proper debugging tools -- Programmer: console.log(&quot;I got here&quot;)\" class=\"wp-image-374538\" width=\"510\" height=\"510\"\/><\/figure>\n\n\n\n<p>Every software project is different, but we can probably agree that <strong>software development has become more complex<\/strong> over the years. We write code that runs on remote machines (including Docker), incorporates more and more third-party libraries, and must scale for millions of operations per second. These scenarios can be hard or impossible to troubleshoot with just logs or unit tests. However, our first-class debugging tools give you great options to handle these with ease:<\/p>\n\n\n\n<ul>\n<li><a href=\"https:\/\/blog.jetbrains.com\/en\/dotnet\/2017\/12\/20\/debugging-third-party-code-rider\">Debugging into NuGet packages<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/blog.jetbrains.com\/en\/dotnet\/2018\/04\/03\/memory-view-exploring-net-memory-debugging-rider-2018-1\">Exploring Memory usages (Rider)<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/blog.jetbrains.com\/en\/dotnet\/2018\/11\/29\/remote-debugging-comes-rider-2018-3\">Debugging Remote Processes over SSH (Rider)<\/a><\/li>\n<\/ul>\n\n\n\n<p>Nevertheless,&nbsp;although JetBrains tools provide a rich debugging experience,&nbsp;developers often find themselves in a situation of step-by-step debugging with lots of restarts and scattered breakpoints:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full is-resized\"><img decoding=\"async\" loading=\"lazy\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2023\/07\/step-by-step.png\" alt=\"MonkeyUser: Step-By-Step Debugging\" class=\"wp-image-374571\" width=\"600\" height=\"375\"\/><\/figure>\n\n\n\n<p>It comes as no surprise that we want to <strong>take your debugging experience to the next level<\/strong>. My fellow .NET developers, <strong>meet the predictive debugger in ReSharper 2023.2<\/strong>!<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"getting-started-with-the-predictive-debugger\">Getting Started with the Predictive Debugger<\/h2>\n\n\n\n<p>The predictive debugger is currently in beta and only available in ReSharper (Rider will come later). If you want to try it out, head over to the options page under <b>Tools | Debugger | Editor Integration | Predictive Debugger<\/b> and enable <b>Show predicted values (beta)<\/b>:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" loading=\"lazy\" width=\"1554\" height=\"1164\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2023\/07\/options-page-1.png\" alt=\"\" class=\"wp-image-376635\"\/><\/figure>\n\n\n\n<p><em>For minimal effort, you can also enable the <b>Start predictive debugger automatically<\/b> option, but be aware that this might affect performance.<\/em><\/p>\n\n\n\n<p>Once enabled, you can start debugging into the future! Let&#8217;s begin with an easy-to-follow example:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" loading=\"lazy\" width=\"2114\" height=\"582\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2023\/07\/example1.png\" alt=\"Easy Example for Predictive Debugging\" class=\"wp-image-374483\"\/><\/figure>\n\n\n\n<p>Hopefully, the colors give you a good idea of what&#8217;s happening, but of course, we will walk through them anyway:<\/p>\n\n\n\n<ul>\n<li>Expressions&nbsp;<strong>highlighted in green or red<\/strong>&nbsp;indicate that the expression was evaluated to&nbsp;<code>true<\/code>&nbsp;or&nbsp;<code>false<\/code>, respectively.<\/li>\n\n\n\n<li>Statements that are <strong>grayed-out<\/strong> indicate that the code path won&#8217;t execute, similar to <a href=\"https:\/\/www.jetbrains.com\/help\/resharper\/Find_dead_code.html\" target=\"_blank\" rel=\"noreferrer noopener nofollow\">dead code<\/a>.<\/li>\n\n\n\n<li><a href=\"https:\/\/www.jetbrains.com\/help\/resharper\/Debugging_Assistance.html#inline-debugging\" target=\"_blank\" rel=\"noreferrer noopener nofollow\">Inline values<\/a> <strong>highlighted in blue<\/strong>&nbsp;show the predicted values after executing the corresponding statement.<\/li>\n\n\n\n<li><strong>Yellow or red inlay hints<\/strong> show where the prediction ends; for example, when a method returns, an exception is thrown (caught vs. uncaught), or the program halts (<code>Environment.Exit<\/code>).<\/li>\n<\/ul>\n\n\n\n<p>A prediction can also end at a function call the debugger is cautious about evaluating. That is for your own (or your software&#8217;s) well-being. Since code is executed during debugging, the debugger has to be sure that it&#8217;s not causing any mutations. When running the above example, we must confirm the evaluation of the <code>int.TryParse<\/code> method (more about that later):<\/p>\n\n\n\n<figure class=\"wp-block-image size-full is-resized\"><img decoding=\"async\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2023\/07\/example2.png\" data-gif-src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2023\/07\/example2.gif\" alt=\"Evaluating Possibly Impure Functions\" \/><\/figure>\n\n\n\n<p>Are you ready for peak productivity? Watch this next example, where the predictive debugger allows our team to <strong>perform live edits<\/strong> (<a rel=\"noreferrer noopener nofollow\" href=\"https:\/\/learn.microsoft.com\/en-us\/visualstudio\/debugger\/edit-and-continue-visual-csharp?view=vs-2022\" target=\"_blank\">Edit &amp; Continue<\/a>) and eventually fix a bug within the Roslyn codebase!<\/p>\n\n\n\n<figure class=\"wp-block-image size-full is-resized\"><img decoding=\"async\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2023\/07\/example3.png\" data-gif-src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2023\/07\/example3.gif\" alt=\"Live Debugging with Edit &amp; Continue\" \/><\/figure>\n\n\n\n<p>As you can imagine, the C# analysis implementation is rather complex, with many test cases and notable starting times. Predictive debugging makes these tasks a lot easier.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"enhancing-predictions-with-annotations\">Enhancing Predictions with Annotations<\/h2>\n\n\n\n<p>As mentioned in the previous section, the <strong>predictive debugger won&#8217;t evaluate possibly impure functions to avoid side effects<\/strong>. As a human developer, you most certainly have more knowledge about the code, which is why we give you the possibility to forcefully evaluate a call by clicking the hint:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" loading=\"lazy\" width=\"2500\" height=\"946\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2023\/07\/not-annotated.png\" alt=\"Debugging Code without Annotations\" class=\"wp-image-374549\"\/><\/figure>\n\n\n\n<p>Of course, it would be technically possible to <em>always evaluate this function<\/em> with the click of a button. However, if you are a long-term friend and lover of our tools, you&#8217;ll know that <strong>our .NET products are even smarter when you <a href=\"https:\/\/blog.jetbrains.com\/en\/dotnet\/2018\/05\/02\/improving-rider-resharper-code-analysis-using-jetbrains-annotations\">enhance your code with annotations<\/a><\/strong>. In contrast to a local &#8220;allow list of functions to execute&#8221;, annotations benefit from being code-centric and available to the whole team.<\/p>\n\n\n\n<p>The <code>PureAttribute<\/code> (either from <code>JetBrains.Annotations<\/code> or <code>System.Diagnostics.Contracts<\/code>) was previously used to indicate that <a href=\"https:\/\/www.jetbrains.com\/help\/resharper\/Reference__Code_Annotation_Attributes.html#PureAttribute\" target=\"_blank\" rel=\"noreferrer noopener nofollow\">a method does not make any observable state changes<\/a> and that its return value is not used. For the predictive debugger, this attribute comes in handy because the attribution <strong>informs the debugger that the method is safe to evaluate<\/strong>. Once we put the <code>PureAttribute<\/code> on all our qualified functions (i.e., the <code>\/<\/code> division operator, <code>FileExists<\/code>, and <code>ReadAllLines<\/code>), the debugger can tell us right away about the outcome of the method:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" loading=\"lazy\" width=\"2500\" height=\"946\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2023\/07\/all-annotated.png\" alt=\"Debugging Code with Annotations\" class=\"wp-image-374461\"\/><\/figure>\n\n\n\n<p>Debugger predictions also consider&nbsp;<a href=\"https:\/\/www.jetbrains.com\/help\/resharper\/Contract_Annotations.html\" target=\"_blank\" rel=\"noreferrer noopener nofollow\">contract annotations<\/a>,&nbsp;which allow to formulate program halts and null\/not-null return values based on the function&#8217;s input.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"future-work-and-limitations\">Future Work and Limitations<\/h2>\n\n\n\n<p>We will use <a href=\"https:\/\/www.jetbrains.com\/help\/resharper\/Code_Analysis__External_Annotations.html\" target=\"_blank\" rel=\"noreferrer noopener nofollow\">external annotations<\/a> to mark code we cannot control to reduce possibly impure evaluations.&nbsp;For example, to declare <code>File.Exists<\/code>&nbsp;or&nbsp;<code>int.TryParse<\/code> as pure functions.<\/p>\n\n\n\n<p>Unfortunately,&nbsp;async\/await code is unsupported because the debugger doesn&#8217;t allow multithreaded evaluations.<\/p>\n\n\n\n<p>As already noted, the predictive debugger is currently in beta, meaning that your feedback is crucial for it to reach its full potential. Please report any bugs you encounter to <a href=\"https:\/\/youtrack.jetbrains.com\/issues\/RSRP\" target=\"_blank\" rel=\"noreferrer noopener nofollow\">our issue tracker<\/a>, along with any suggestions or requests you may have.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"conclusion\">Conclusion<\/h2>\n\n\n\n<p>For our conclusion, let&#8217;s come back to one of the debugger criticisms:<\/p>\n\n\n\n<blockquote class=\"wp-block-quote\">\n<p>Debuggers don\u2019t remove bugs. They only show them in slow motion.<\/p>\n<\/blockquote>\n\n\n\n<p>There&#8217;s no doubt that debuggers on their own do not remove any bugs. It is rather important to treat the predictive debugger as another tool in our toolbox. A tool that <em>can<\/em> help understand so-called &#8220;impossible situations&#8221; (see&nbsp;<a href=\"https:\/\/www.reddit.com\/r\/ProgrammerHumor\/comments\/97o4pp\/six_stages_of_debugging\/\" target=\"_blank\" rel=\"noreferrer noopener nofollow\">6 stages of debugging<\/a>) more quickly and without any code modifications, allowing us to <em>then<\/em> write covering tests more efficiently.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" loading=\"lazy\" width=\"504\" height=\"500\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2023\/07\/chicken3.jpeg\" alt=\"Meme: Chicken that doesn't want to try the debugger. Actually trying predictive debugger. Ending up liking it.\" class=\"wp-image-374472\"\/><\/figure>\n\n\n\n<p><strong>Give it a go with the latest <\/strong><a href=\"https:\/\/www.jetbrains.com\/resharper\/nextversion\/\" target=\"_blank\" rel=\"noreferrer noopener nofollow\"><strong>ReSharper 2023.2 EAP<\/strong><\/a>, and let us know if you have any questions or suggestions in the comments section below. Thanks for reading!<\/p>\n\n\n\n<p><sub><em>Image credit: <a href=\"https:\/\/unsplash.com\/photos\/41NsEMAB1Ps\" target=\"_blank\" rel=\"noreferrer noopener nofollow\">Hasnain Sikora<\/a><\/em><\/sub><\/p>\n","protected":false},"author":553,"featured_media":376654,"comment_status":"closed","ping_status":"closed","template":"","categories":[4992,1401],"tags":[264,46],"cross-post-tag":[],"acf":[],"_links":{"self":[{"href":"https:\/\/blog.jetbrains.com\/en\/wp-json\/wp\/v2\/dotnet\/374429"}],"collection":[{"href":"https:\/\/blog.jetbrains.com\/en\/wp-json\/wp\/v2\/dotnet"}],"about":[{"href":"https:\/\/blog.jetbrains.com\/en\/wp-json\/wp\/v2\/types\/dotnet"}],"author":[{"embeddable":true,"href":"https:\/\/blog.jetbrains.com\/en\/wp-json\/wp\/v2\/users\/553"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.jetbrains.com\/en\/wp-json\/wp\/v2\/comments?post=374429"}],"version-history":[{"count":10,"href":"https:\/\/blog.jetbrains.com\/en\/wp-json\/wp\/v2\/dotnet\/374429\/revisions"}],"predecessor-version":[{"id":456588,"href":"https:\/\/blog.jetbrains.com\/en\/wp-json\/wp\/v2\/dotnet\/374429\/revisions\/456588"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/blog.jetbrains.com\/en\/wp-json\/wp\/v2\/media\/376654"}],"wp:attachment":[{"href":"https:\/\/blog.jetbrains.com\/en\/wp-json\/wp\/v2\/media?parent=374429"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.jetbrains.com\/en\/wp-json\/wp\/v2\/categories?post=374429"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.jetbrains.com\/en\/wp-json\/wp\/v2\/tags?post=374429"},{"taxonomy":"cross-post-tag","embeddable":true,"href":"https:\/\/blog.jetbrains.com\/en\/wp-json\/wp\/v2\/cross-post-tag?post=374429"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}