Unity-specific code analysis in Rider 2018.2

Perhaps the most powerful feature that Rider has is its code analysis, finding issues and providing quick fixes and context actions to help you improve the quality of your code. Rider’s Unity support is no exception, and in this post, we’ll take a look at what Rider 2018.2 brings in terms of Unity-specific code analysis and refactorings.

In this series:

FormerlySerializedAs

One of Rider’s most used refactorings is the rename refactoring, which renames code elements much more safely than a simple textual find and replace. However, there is a small issue when renaming Unity serialised fields – Unity’s serialisation is keyed on name, so if you rename a field, any existing serialised data will break!

Fortunately, Unity has a solution to this – the FormerlySerializedAs attribute. This attribute specifies a “fall back” name to use if Unity can’t find the current name of the field. So when a serialised field is renamed, the new name is used to save any new data, but Unity will still be able to read existing data, because it can look for the old name if the new name isn’t used.

Rider 2018.2 adds support for [FormerlySerializedAs] to the rename refactoring. Now, when renaming a field, Rider will ask you if you want to add the [FormerlySerializedAs] attribute, and add it to the field, populated with the old name.

Add FormerlySerializedAs attribute during rename

Toggling attributes

The Alt+Enter menu is mostly associated with fixing highlights such as warnings or suggestions, but it also provides context specific actions, which can quickly transform the code at the text caret, changing the meaning rather than trying to fix a specific issue.

Rider 2018.2 adds a couple of new context actions. The first will quickly toggle a field between serialised and non-serialised, by adding or removing the [NonSerialized] and  [SerializeField] attributes. The action is smart enough to know that a public field without attributes is serialised, and will only add or remove attributes when necessary.

Context actions that toggle a field between serialised and non-serialised

The second action will add or remove the [HideInInspector] attribute, quickly letting you hide a serialised field from the Unity Inspector window.

Toggle HideInInspector attribute context action

Multiple field declarations

While we’re talking about fields, all of the quick fixes and context actions that work on fields have been updated to correctly handle multiple field declarations, where multiple fields are listed in one declaration.

For example, when using Alt+Enter on one field in a multiple field declaration, the “make serialised” context action will by default make that one field serialised, moving it out of the multiple field declaration and applying the attribute to the single field. But it also offers a sub-menu that will make all fields serialised.

Add FormerlySerializedAs attribute during rename

On top of that, Rider has added a new inspection that will warn if the [FormerlySerializedAs] attribute is applied to a multiple field declaration. When an attribute is applied to a multiple field declaration, it is actually applied to each field in that declaration. This means each field would be sharing the same previously serialised name, which would break the fallback serialisation!

Rider warns in this case, and adds a quick fix to split the single, multiple declaration into separate single declarations, allowing you to then decide which field should have the [FormerlySerializedAs] attribute applied.

Possible misapplication of FormerlySerializedAs attribute to multiple fields warning

Redundant attributes

While Rider 2018.2 has made it easy to add various attributes, such as [FormerlySerializedAs], [SerializeField] and [HideInInspector], it now also knows when these attributes are unnecessary and provides a quick fix to remove them. So if [FormerlySerializedAs] is applied to a field that isn’t serialised, or has the same name as the previously serialised value, it’s marked as redundant, and a quick Alt+Enter will remove it.

Similarly, [SerializeField] on a readonly field and [HideInInspector] on a non-serialised field will be marked as redundant.

Inefficient usage of Camera.main

We’ve added another inspection to try and help you stay on top of common performance mistakes. We already suggest you use CompareTag instead of comparing the tag property to a string literal (it avoids memory allocations – read more here), and Rider 2018.2 will now warn if you use Camera.main inside an Update method.

Internally, Camera.main calls FindObjectsWithTag each time it is accessed, which is very inefficient if it’s being used in frequently called methods such as Update, FixedUpdate or LateUpdate. You can read more about this issue at Unity’s support site.

Camera.main is inefficient warning

We’re already working on providing more inspections in this area for Rider 2018.3. Stay tuned!

Why is Rider suggesting this?

One really helpful feature that often gets overlooked is that many inspections have documentation explaining why Rider is showing a warning. All of the new inspections added in Rider 2018.2, such as using Camera.main in an Update method or applying the [FormerlySerializedAs] attribute to a multiple field declaration mentioned above, include such documentation. It’s available in the inspection options sub-menu in the Alt+Enter menu.

Why is Rider suggesting this? menu item

You can see a full list of the (Unity specific) documented inspections here, and a full list of Rider’s C# inspection descriptions here.

Mark possible event handlers as in use

Starting in 2018.1, Rider started to mark any public method as unused if it wasn’t explicitly used in code. Previously, this was only shown when Solution Wide Analysis was enabled. It’s a very useful feature to help find (and Alt+Enter remove) unused code. However, in Unity, it’s possible to wire up method calls inside the Unity editor, which Rider doesn’t know about. This means Rider might incorrectly tell you that a method is unused, when Unity is definitely using it!

To avoid these false reports, Rider will now mark all public static methods (and property setters) in Unity types as in use.

Custom serialisable classes

Rider offers nice support for serialised fields in Unity Object based classes, highlighting fields in the editor gutter, telling code analysis that a field is assigned a value implicitly to provide better warnings, and providing other features such as toggling serialised/non-serialised attributes. Rider 2018.2 extends this support to custom classes marked with the [Serializable] attribute.

Serializable class showing Unity support

And finally…

Eagle eyed users spotted that Unity specific warnings weren’t appearing in the Solution Wide Analysis tool window, when the option to show warnings was enabled. Oops! Fixed!

And we’ll wind up our code analysis coverage with one last inspection, or rather, without an inspection. That’s right, we’ve removed a highlight! Or more accurately, we’ve removed an incorrect warning.

Rider 2018.2 will no longer warn you that  if (this == null) will never be true for classes derived from UnityEngine.Object. Thanks to the way Unity overrides the equality operator, this can return true if the underlying native object has been destroyed. Rider no longer assumes this isn’t the case. No more false positives!

What’s left?

That brings us nearly to the end of our look at Unity support in Rider 2018.2. We’ve covered a lot of ground in this series, looking at adding Packages to the Unity Explorer, code completion and inspections in Assembly Definition Files, updated integration with the Unity Editor and new inspections, quick fixes and refactorings.

But there are one or two updates that don’t quite fit into any of the other posts. For example, we’ve updated our API support to include the latest APIs and documentation from Unity 2018.2. You can see the full list of changes in this GitHub milestone (and for Rider 2018.2.1 and 2018.2.2).

So that just leaves one last feature to squeeze in: two new Live Templates – sfield and sprop, for quickly creating a serialised field, or a property with a serialised field as a backing field. And of course, you can edit these in Rider’s new Live Templates editor.

Add FormerlySerializedAs attribute during rename

Download Rider 2018.2 today and give all of these new Unity specific features a go! And if you’d like to try the latest and greatest new features we’re working on, you can also check out the brand new Early Access Preview for Rider 2018.3.

This entry was posted in How-To's and tagged , , . Bookmark the permalink.

5 Responses to Unity-specific code analysis in Rider 2018.2

  1. Maciej Srokowski says:

    Love it! Rider already has no real competition when writing code for Unity. I wonder if there are any plans for some special code generation for the upcoming unity ECS? I know it is still in it’s early stages but plenty of people already use it in production. This is where rider unity support could truly shine. Most of it is done in the code (as opposite to setting things from editor) and plenty of it is very repetitive

    • Matt Ellis says:

      Yes, we absolutely have plans for ECS support. We won’t be adding anything specific in Rider 2018.3, but expect to add new features in Rider 2019.1. It would be great to hear any suggestions you might have, or even just knowing pain points. You can log them either in GitHub issues (the Unity plugin is open source) or at in YouTrack.

  2. Pingback: Dew Drop - October 19, 2018 (#2827) - Morning Dew

  3. Lior Tal says:

    Is it possible to create new analyzers and submit them as PRs to be included in Rider? I have my own analyzer (based on Mono.Cecil), and i’d like to develop the same rules for Rider so everybody can use them.

    • Matt Ellis says:

      Yes! The Unity support is open source at GitHub, and you can see some of the existing inspections here. We’re more than happy to take contributions, and you’ll need to sign a CLA first, details can be found in CONTRIBUTING.md.

      If you’d like to get started, I’d suggest getting in touch early – raise an issue and offer to implement it, or start a “work in progress” PR. This allows us to help with implementation – make suggestions before too much has been implemented, and to know what’s coming so we don’t accidentally duplicate work. You can also chat to us on the JetBrains/resharper-unity Gitter channel. And we have some “up for grabs” issues which are also a good place to get started.

      Looking forward to your contribution!

Leave a Reply

Your email address will not be published. Required fields are marked *