Consolidating multiple ReSharper plugins

Developer
Apr 29 at 10:34 AM
Hi all. I've just gone to update my version of the ReSharper plugin to support ReSharper 2016.1, and I've seen that we've got another new version of StyleCop for ReSharper. I love the fact that StyleCop is moving forward and being maintained again, but I think we're setting ourselves up for pain by having multiple ReSharper plugins available.

So we now have:
  • StyleCop.StyleCop by me
  • ReSharper.StyleCop by kubiix
  • StyleCop.ReSharper920 + StyleCop.ReSharper1000 by csdahlberg, based on this repo
I'd love to reduce this down to just one version - it's not at all obvious which version I should use. I'd like to propose working together to get this sorted.

The problems I can see:
  • ReSharper.StyleCop by kubiix is not maintained and not open source.
  • My fork is out of sync with the StyleCop core changes in this repo
  • The ReSharper plugins for this project have issues that I've fixed in my fork (see below)
What I'd like to propose:
  • Unlist StyleCop.ReSharper920 and StyleCop.ReSharper1000, and make StyleCop.StyleCop the only supported version of the ReSharper plugin, taking on the recent changes to StyleCop core that have been made in this repo
    • There is no need for a separate ReSharper920 and ReSharper1000 - versions of ReSharper will use the last compatible version of the package. So, the current version of StyleCop.StyleCop supports 10.0, but an older version supports 9.2. ReSharper 9.2 will use this older version automatically.
    • I'd also like to see kubiix's ReSharper.StyleCop unlisted, too. I don't think this is going to happen, but the current version is pre-release, so most people won't see it. I think we can happily ignore it.
  • I'm more than happy to hand over the StyleCop GitHub org, if you'd like to migrate (I've also got the credentials for the @stylecop_dev twitter account, now I think of it)
  • If you do migrate to GitHub, I'd suggest moving the ReSharper plugin into a separate repo, where it could consume StyleCop.dll via nuget (my fork hasn't made any changes to StyleCop itself). Otherwise, merge my changes into this repo.
I'm going to update my fork to support ReSharper 2016.1, as I have a lot of support requests for it. I'm not going to update StyleCop core right now - I'd like to only merge changes once. I'll update it again as soon as we've decided how to move forward.

Thoughts?

Regards
Matt

PS: I mentioned above that my fork has a number of fixes for the ReSharper plugin. The changes I made are:
  • Fixed memory leaks in settings + engine usage
  • Much better (automatic) handling of throttling resources, rather than based on a slider
  • Bundled StyleCop into the plugin install, rather than requiring the VS plugin installed. They're strong named, so they can both be installed side-by-side
  • Updated settings to include new ReSharper 9/10 settings
  • High DPI support for the settings
  • Disable running StyleCop when StyleCopAnalysers is referenced (we don't need three C# parsers in a single process)
  • Removed the old versions of the plugin in the codebase - no more support for ReSharper 5.1.3! In fact, the codebase now only supports the current version of ReSharper
Coordinator
Apr 29 at 12:53 PM
Great to hear from you. I sent you a message here on CodePlex a while ago hoping to get this discussion started, but never heard back.

Most of what you said is also exactly what I'd like to do. I think the only thing I disagree with is having a single version of the ReSharper plugin. Assuming my understanding of the plugin in your fork is correct, each StyleCop version could only be compatible with a single ReSharper version. An example of what I want to avoid:
  1. StyleCop 4 is released with support only for ReSharper 9.2
  2. User has StyleCop 4 and ReSharper 9.2, and everything works
  3. StyleCop 5 is released with support only for ReSharper 10
  4. User wants to upgrade to StyleCop 5, but can't because it no longer supports ReSharper 9.2
Does that make sense and seem correct?


As a side note, not everything in 4.7.x is ideal. I first wanted to add support for VS 2015 and R# 9/10 as quickly and painlessly as possible, then for 5.x make some changes that really should be made but IMO are much more disruptive changes (like switching to SemVer, distributing via NuGet, upgrading to .NET 4, etc.).
Developer
Apr 29 at 1:56 PM
Ah, I didn't see any CodePlex messages, sorry.

What you say with versions is correct, yes, although it is possible to also release a 4.5 that would target StyleCop 5, but for ReSharper 9.2, if you wanted to.

I've spent plenty of time supporting multiple versions of ReSharper with a single plugin, and I do believe that targeting the most recently released version is the way to go. Supporting multiple versions adds a noticeable overhead, not least of which is installing and testing. But the biggest reason is that ReSharper is now licensed by subscription. As long as the user has a valid subscription, there's no reason for them not to be on the latest version - so you can happily assume that everyone with a license is on the latest version. And if they don't have a valid subscription, then they're going to be running a version of ReSharper that's 12 months old, and I don't think it's too unreasonable that you don't support versions this old with new features. And they'll still have the last version of the plugin that was compatible, so they're not stuck. Otherwise, you have to decide what version you want to support. 9.2 is reasonable, but now that 10.1 (2016.1) is out, should you support 10.0? If so, you've now got three versions to support, and we've already started work on 2016.2, which would bring you up to four. I don't think that maintenance overhead is worth it when the majority of people are going to upgrade anyway. You're spending your time chasing a minority of users.

That said, I'm trying to convince you, rather than refusing. What I really want is for users of ReSharper and StyleCop to not be confused as to what they need to install.
Coordinator
Apr 29 at 3:34 PM
I wonder if CodePlex actually delivers my messages. I have sent a few over the years to various people, and never gotten a response.

ReSharper is now licensed as a subscription, but people could still hold non-subscription-based licenses to previous versions. Especially in less-than-ideal corporate environments, teams could be stuck on versions of Visual Studio and/or ReSharper that are many versions old. That alone was frustrating enough for one team I worked on, but it would've been much, worse if a single StyleCop version didn't support all 4 versions of Visual Studio and 2 versions of ReSharper in use across the team.
As long as the user has a valid subscription, there's no reason for them not to be on the latest version
That's not necessarily true. Even with a subscription, management decisions could hold up adoption of a free upgrade for a long time. It took a while for us to get approval to use new versions of Visual Studio, even though all devs had MSDN Ultimate subscriptions.

Once support is added for a new version of Visual Studio or ReSharper, there should be very little additional dev work. It will add some testing and deployment work, but that seems very much worth it to me. Even the faster-moving ReSharper currently supports the last 6 years' worth (4 versions) of Visual Studio. It seems reasonable to me for StyleCop to support something similar with regards to ReSharper.
Coordinator
May 3 at 11:38 PM
As usual, I'm starting to doubt myself. I do think some devs (especially in the corporate world) would be impacted by dropping support for pre-10.x ReSharper versions, but as someone who doesn't even use ReSharper (other than to support StyleCop development), maybe I'm giving too much weight to maintaining backwards compatibility with previous ReSharper versions.

Does anyone else have any opinions on backwards compatibility? In particular, if nobody is needing support for StyleCop + ReSharper 9.2 + Visual Studio 2015, I'll probably defer to Matt on how to handle ReSharper plugins.
May 4 at 12:50 AM
Edited May 4 at 12:51 AM
I've been following the discussions threads for a while and really appreciate the work you've done so far csdahlberg! The only reason my team is still using 9.2 & vs2015 is because that used to be the only (latest) version that was supported with 2015 (we're still using 9.4.9 I believe which doesn't even have support for C#6 so we end up with a large exclusion list). We have a license for resharper 10 but stylecop was our blocker for not moving forward. So at least for our team, we'd happily move to the newest version given the chance (subscription model).

I was planning on moving us to the latest version of style cop (which supports C#6) until I saw this thread so I was going to wait until the verdict before convincing my team to prioritize upgrading stylecop.
May 4 at 4:55 AM
I'm also very happy to see that StyleCop development is picked up again, so a big thanks from me also!
I can confirm the position of eimakki: We are exactly in the same state and I believe that there is no real reason for resharper users to not upgrade to the latest version:

I think if someone seriously is using Resharper then he is convinced to benefit from Resharper that much that he always will stay up-to-date therefore no need to support StyleCop for older Resharper versions IMHO.
Developer
May 4 at 4:26 PM
Edited May 4 at 4:27 PM
I'm conflicted on this topic.

If we decided to support only R# 2016.1, my organization would be affected. We have around 70 engineers and purchasing licenses for all of them would be a big investment. Looking at the list of new features, there is nothing in there that would warrant an upgrade, at least, for us. One compelling reason we would upgrade is when we switch to a newer version of visual studio. Delaying the purchase has other benefits like access to newer versions of R#, from the time of purchase (if you time it right).

Other factors that prevented us with moving forward with R# upgrades in the past, was R# performance/bugs itself, and compatibility breaks with other R# extensions we use (Specflow had problems when R#9 was introduced, and I think this is still a problem).

If the plug-in support was limited only to latest R# version, we will be forced to maintain a fork. Which is OK, and is what we were used to already, but not ideal.

On the other hand, I dislike the fact that we need to copy code, reset namespaces and fix up releases, every time there is a new version of R# out (throw in 'Wave' in to mix of version numbers and subscriptions and visual studio release cycle, and it quickly gets out of hand). keeping up with R# release cycle should be much more simpler activity.

I understand Matt's intent, and supporting only the latest R# version is definitely an option, but maybe we could explore and see if there are any other options. Most of the problems stem from the fact that plugin take a hard dependency on R# binaries (when infact core stylcop and the plug-in code remains mostly the same). Maybe we could reach a better place if we had a better design for the plugin? I don't know/have an answer, I'll try to spend some time on this over the weekend.
May 4 at 5:04 PM

[The following comments are just thoughts for the rest of the group to discuss – our team has already moved to VS2015 and we have switched to the Rosyln based StyleCop, so these problems that have plagued us for years are now academic.]

We are another shop that has an R# subscription, so going with the latest version would have worked best for us. Our team abandoned integrated StyleCop installs years ago because getting the latest R# is deemed more important, and StyleCop is always holding us up. Our work-around has been to copy the StyleCop installation directory to our source tree and then uninstall it. This allows us to invoke it from post-build events without concern for R# compatibility. Sadly, this means we’ve had to do without any of the nice Visual Studio integration features.

That said, and knowing nothing about the internals of StyleCop, I’ve always wondered how necessary the integration with R# is in the first place. If there were some sort of “light” option on the install which could install in Visual Studio without interacting with R#, that might be a good option for those stuck on older R# versions. The R# release cycle just seems to be impossibly frequent for a team of volunteers to track effectively.

May 5 at 3:11 PM
Edited May 5 at 3:13 PM
I certainly see the value in supporting older versions especially for teams that aren't large corporations/teams that can afford or rather where the subscription model doesn't make any sense from a cost/utilization perspective. But as you pointed out Sanjay and some others, maybe the real solution isn't dropping older versions of R# altogether. I'm not familiar with the plugin code, but if the stylecop "core" is fairly independent from R# then is there a way to remove the dependency? Then (for the most part) it'll be plug and play? I know R# does release real often, even for our company (large corporation) we don't always get on the latest version if there isn't a compelling reason to do so (not sure how it works with subscriptions but we don't upgrade to the latest license server unless there's a compelling reason)..

Also R# has a high upgrade cadence so it's hard to keep up sometimes. While I can't speak for all the contributors, keeping up with R# and supporting all previous versions (at the very least you should consider supporting no more than 1 or two previous versions) seems to create a lot of overhead and work that quickly becomes daunting as the number of versions grows. If it's not possible to make the stylecop plugin independent of R# but still work with any/most versions, then a tradeoff to consider would be to only support up to vcurrent-N versions. I'll let you decide what N is :).

We do like the R# plugin though because we can apply a "code clean up" profile and we set all/most of our styling rules in stylecop rather than R# settings.
Coordinator
May 7 at 4:00 PM
eimakki wrote:
...if the stylecop "core" is fairly independent from R# then is there a way to remove the dependency? Then (for the most part) it'll be plug and play?
The core StyleCop functionality is completely independent from R#. The sole purpose of the R# plugins is to provide R#-specific extensions of the core StyleCop functionality, such as providing R# quick fixes for StyleCop violations and updating R# settings to be compatible with StyleCop. Since each wave of R# brings breaking changes, most functionality in each of the R# projects is tied to a single R# version and cannot be easily shared between the projects.

SanjayGuntur wrote:
I dislike the fact that we need to copy code, reset namespaces and fix up releases, every time there is a new version of R# out
I do, too, but it seems like that may be the least painful way to support more than a single R# version. Even if we added a layer of abstraction and were able to share 99% of the code across R# projects, we'd still have to copy/paste/renamespace the project that directly references the R# assemblies. Any changes to the new shared R# code would also increase the risk of breaking previous R# plugins.

Here are my current thoughts:
  1. Move core StyleCop functionality to github.com/StyleCop/StyleCop
  2. Create a NuGet package that contains everything needed by R# plugins
  3. Move R# plugins into version-specific repos and modify them to use the new core NuGet package
    1. I'm open to suggestions on naming schemes, but my first thoughts are github.com/StyleCop/ReSharper920 or github.com/StyleCop/ReSharperWave02
  4. Provide version-specific R# extensions in the R# gallery, which is pretty much required in order to support multiple R# versions
    1. The title of each package will not include the R# version (so "StyleCop" or "StyleCop for ReSharper" will be used for all versions, instead of "StyleCop for ReSharper 9.2", etc.
  5. Do the copy/paste/renamespace dance whenever a new R# version is released
  6. Automatically update R# plugins for the N most recent versions of R# whenever a new core StyleCop version is released
  7. Accept pull requests for anyone who wants to update R# plugins for older versions of R#
That would reduce the number of R# versions supported by core maintainers, but would allow others to keep updating R# plugins for older versions they care about without forcing them to use unofficial forks.
Coordinator
May 13 at 11:42 PM
Looks like no immediate objections?

There will need to be multiple add-in packages to support more than one version of ReSharper, which kind of implies that package IDs will be specific to a ReSharper version. I'm not particularly fond of the IDs of the packages I have already published (StyleCop.ReSharper920 and StyleCop.ReSharper1000). I think it would be better to mirror the version numbers of the Wave packages (StyleCop.ReSharper3 for Wave3 / ReSharper 9.2, StyleCop.Resharper4 for Wave4 / ReSharper10.0, etc.), but changing IDs would make upgrading more difficult (since the old package would need to be removed and the new one added). Unless anyone has a better suggestion, I think I'd like to leave StyleCop.ReSharper920 and StyleCop.ReSharper1000 as-is, but use StyleCop.Wave5, etc. going forward.
Developer
May 13 at 11:58 PM
Sorry for not replying sooner, and sorry I can't leave a proper reply now. I'm away from desk/work/laptop right now, but will be back on Monday, so I'll reply properly then - just wanted to make sure you knew I wasn't ignoring this thread :)
Developer
May 14 at 3:06 AM
Edited May 14 at 3:06 AM
Chris,

I wanted to investigate a few things around how the plugin code uses R# and core stylecop. The idea was to see if a boundary can be defined (on one or both sides) and what it would look like.
I understood your comment about creating another layer of abstraction, but still wanted to satisfy my curiosity. Work was hectic and I didn't get a chance to spend time on it.

I have no objection to your proposal. It will keep things the way they are, but allow us to move forward with core stylecop improvements. R# integration is important but not the primary use case for stylecop.

If we do find a way for the R# plugin to work with the 'installed' version of stylecop, rather than tying itself to a version or maintaining a copy for itself, we can always apply those improvements.

For the package id's, what you say makes sense. I'll do some research on what other R# extensions are doing.

This is also the time to think about ditching the MSI, and try out vs extension published to visual studio gallery.
Developer
May 17 at 7:24 PM
Right, catch up time :)

So, you already know my view on maintaining multiple versions of the ReSharper plugin, but just a couple of last comments.

Firstly, only supporting the latest version of ReSharper isn't as bad as it may seem - the previous versions of the plugin are still available, it's just that users of older versions don't get the latest, newest features.

Secondly, the big problem with maintaining multiple versions of the ReSharper plugin is testing - what's the plan for keeping on top of testing the changes across all supported versions?

Thirdly, if you are going to support multiple versions, I'd strongly suggest setting a policy of how far back you go. You're setting yourselves up for an uphill battle by just saying you'll support everything. I haven't had anyone ask for me to support an older version, either for StyleCop or for when I was maintaining multiple versions of the xunit plugin. I reckon this is something that doesn't actually have much demand. Perhaps support just the last 9.x, and the latest 10.x?

And finally, I'd definitely suggest keeping multiple versions in a single repo, and sharing files, if at all possible - copy and paste, and then updating every copy whenever there's a change or bug fix is a huge timesink, and very easy to get wrong, and that's exaggerated when they're in different repos.

Package IDs - I'd suggest keeping StyleCop.StyleCop, as it already has an install base, and people will get notified of updates, etc. (I'd suggest changing the title, though - "StyleCop by JetBrains" -> "Official StyleCop", or just "StyleCop"). And add any version specific ones you'd like alongside it.

As for an abstraction layer, the plugin is pretty much a client of the StyleCop.dll already. But we can't just drop a new version, it requires a recompile because it's strongly named, and tied to a specific version. This is because the ReSharper plugin needs to include StyleCop.dll in the install, or risk installing a broken plugin, or even worse, a plugin that causes all of ReSharper to break (ReSharper uses an IoC container, and if it can't satisfy dependencies, it can ripple all the way through the codebase and break, well, everything). Strong naming is also needed so that the Visual Studio plugin and the ReSharper plugin can both have a StyleCop.dll without breaking each other with updates.
Coordinator
May 19 at 3:03 AM
I'd be fine with only committing to support the latest version of ReSharper, but if anyone (for example, SanjayGuntur) wants plugin support for a previous version and is willing to update and test it, it seems like everything is made unnecessarily difficult (for both maintainers and users) by forcing them to use an unofficial fork and extension.

I think the reasons in favor of supporting only the latest version of ReSharper boil down to:
  1. Development and testing effort increases linearly with each additional supported version of ReSharper
    • It seems all-around beneficial (and a good example of how OSS can work) to accept pull requests for old versions if someone wants to do the dev work and testing.
  2. There should only be a single plugin for StyleCop in the ReSharper gallery (not StyleCop920, StyleCop1000, etc.)
    • Are there any practical reasons for this? It doesn't seem like there are any negatives from the perspective of a ReSharper user, since they would only see the single extension that is compatible with their version of ReSharper.
    • It seems reasonably likely to me that even if we only officially support the latest version of ReSharper, extensions from forks (such as the one by kubiix) will still find their way to the extension gallery. Having unofficial ReSharper-version-specific extensions seems worse to me than having official ReSharper-version-specific extensions.
If we do accommodate plugins for multiple versions of ReSharper, there would also be the question of having a single repository with shared code vs. separate repositories with the far-from-ideal copy/paste/rename routine every time a new version of ReSharper is added. With the majority of the files in the ReSharper projects directly referencing types from the ReSharper DLLs, it doesn't seem feasible to share the plugin code across multiple versions of ReSharper. Having separate repositories would also allow the plugin for a specific ReSharper version be updated/tested/released (or abandoned) completely independently of all other versions.