In the previous two posts, we have seen how Rider‘s code analysis works: it continuously validates our code, analyzing it with over 2400 inspections coming from ReSharper and from IntelliJ-based IDEs. In this post, we’ll look at how we can make use of Rider’s code analysis to spot errors before compiling and running our application – saving time and getting feedback earlier in the development process.
In this series: (table of contents will be updated as we progress)
- Introduction to code analysis in Rider
- Solution-wide analysis in Rider
- Using Rider to spot errors before our application runs
- Learning best practices and language features using Rider code inspections
- Consistent code bases using Rider code analysis
Compiler warnings and errors
We all know XKCD’s “My code’s compiling” comic. As developers, we like early feedback on what we are doing so we can keep doing what we were doing, without having to wait on things like compiling our code. Instead of having to compile, wait, then navigate to compiler errors, Rider will let us know upfront if something will break during compilation.
The most basic example would be invalid syntax: Rider will complain when something is wrong in our code – from a missing semicolon to a missing method and more:
Rider’s code analysis also detects missing references. When a specific type or method cannot be found and compilation would fail, Rider will tell us and provide quick fixes to add import statements or add a reference (Alt+Enter):
Rider’s code analysis also provides warnings. It’s perfectly fine to have code that does not have XMLdoc comments. However, they help ensure other developers get proper information about the public API we’re exposing. Rider lets us know and provides a quick fix to automatically add XMLdoc comments for the current public type or type member:
Writing code using the async/await pattern? Rider knows about it and will inform us when we’re calling an awaitable method without awaiting – ensuring our code behaves as expected and executes the async method at the correct moment. A quick fix can help us resolve the issue automatically.
For those who’ve seen us at conferences, we used to have JetBrains T-shirts stating “I see dead code”. Rider is no exception: it also sees dead code! Rider detects symbols and private members that are declared but not used, such as fields and local variables. Using namespace imports that are not required? Rider sees those, too. We can easily spot and remove code that is not being used with a quick fix, cleaning up our code and making it compile more efficiently:
Of course we can also search our entire project or solution for unused code. Use Shift+Ctrl+Alt+I to run an inspection by name (e.g. “non-accessed local variable”) or search for the current issue in the whole solution:
Potential runtime errors
Being able to detect compiler warnings and errors without compiling sure is nice, but what if we told you Rider can also detect potential runtime errors without even running the applications? Several code inspections can help us detect issues that may potentially occur at runtime – saving us the tedious task of having to sift through error logs and investigating strange runtime behaviour.
Checking for null values is a very common operation in .NET development. Rider helps us by detecting when a potential
NullReferenceException can occur, and suggests adding a null check – which we can do with a quick fix:
Another good example would be exception rethrowing. In many cases we want to log when an exception occurs, and then rethrow it. Unfortunately in many code bases, we see this:
catch (Exception ex)
Nothing is really wrong here, except for the dubious
throw ex;. In this example, we are not rethrowing our exception and instead are creating a new stack trace for our exception, losing the original source of the exception. Since the stack trace information is crucial to identifying the root cause of a problem, we want to keep it. Good thing Rider detects this for us and provides a quick fix (Alt+Enter) to solve it!
More exceptions! Even though it’s tempting to add an empty general catch clause, it’s not recommended to do so. If we don’t log the exception somewhere (or properly handle the exception), there will be no trace of it ever having happened. Code analysis in Rider detects this, and suggests adding a comment to clarify why we are not handling the exception properly. We can optionally increase the inspection severity to make it a bit more visible across our solution, too.
The following code also has a runtime issue. Instead of printing
counter as numbers 1 through 100, there is a good chance it would print the value 100 for each iteration in our loop. The tasks we spawn are possibly executed after the enumeration happens, which will result in each of them pointing to the last element in our list. What we have to do here is capture the current value in a variable, and use that one in our task instead. Rider informs us about this potential issue, and knows how to fix it:
Rider spots various issues in other programming languages and frameworks, too. Why wait until someone runs a web application in the browser, if Rider can already determine we’re making use of an unknown CSS class? Best of all, the IDE also comes with a quick fix to create the CSS class definition for us!
What else is there?
When we introduced code analysis in the first post of this series, we saw that in the settings under Editor | Inspection Settings | Inspection Severity there are several categories of inspections – grouped by language and framework. To explore further, make sure to check these categories for more inspections related to spotting errors before compiling/running the application:
- Potential Code Quality issues, such as members that cannot be resolved or writing functions that never return.
- Common Practices and Code Improvements, such as merging two if statements with an “or”, inverting conditions, …
- Compiler Warnings, such as invalid syntax, unused fields, … – the things that the compiler will warn us about later.
Of course other categories are interesting too – we’ll cover more of them in upcoming posts.
In this post, we’ve seen how Rider’s code analysis can help us work more efficiently and write better code by spotting (and fixing) code issues before compiling and running the application. In our next post, we’ll see how we can use code analysis to learn best practices and new language features. Stay tuned!
Download Rider and give it a try! We’d love to hear your feedback.