Invalidate highlightings on settings change

I have an IElementProblemAnalyzer, which emits highlightings based on different settings.

The problem now is that the highlightings aren't recalculated on a settings change and therefore stay out-of date till the file cache gets invalidated.

Is it possible to invalidate a specific IElementProblemAnalyzer?

9 comments

You can't invalidate a specific analyser, but you can tell the daemon to invalidate its caches, and it will intelligently update - which really means it will rescan all open, visible files, or cause solution wide analysis to rescan. You can do this by calling Daemon.Invalidate. You can do this manually when you change settings, but a better way of doing it is to look for changes in your setting and automatically invalidate. This works when you have multiple instances of VS open and change the settings in one - all instances are correctly updated and rescanned.

[SolutionComponent]
public class MySettingOnChange
{
  public MySettingOnChange(Lifetime lifetime, Daemon daemon, ISettingsStore settingsStore)
  {
    var entry = settingsStore.Schema.GetScalarEntry((MySettings s) => s.MySettingValue);
    settingsStore.AdviseChange(lifetime, entry, daemon.Invalidate);
  }
}

0

Hi,

Many thanks for you answer!

I changed the code a little bit, because the type Daemon doesn't exist in R# 9 anymore.

[SolutionComponent]
public class MySettingOnChange
{
  public MySettingOnChange(Lifetime lifetime, IDaemon daemon, ISettingsStore settingsStore)
  {
    var entry = settingsStore.Schema.GetScalarEntry((MySettings s) => s.MySetting);
    settingsStore.AdviseChange(lifetime, entry, () => daemon.Invalidate());
  }
}


Debugging this code shows that the AdviseChange delegate correctly gets called when I change the setting in the UI and for daemon a DaemonImpl instance gets injected.

The bad news: The Invalidate() call has no effect on the cached problem analyzer results. I still have to reopen a file / or invalidate the whole cache manually to recalculate the highlightings.

0

Ah, yes, sorry, I was looking at ReSharper 8 for Daemon. IDaemon is what you use for ReSharper 9. And yes, IDaemon.Invalidate only works on visible documents. If you're talking about results in Solution Wide Error Analysis, then you're going to have to cause a re-analysis there. I think the best way to do that would be to use SolutionAnalaysisManager.ReanalyzeAll(). This will drop all existing results and reanalyse everything, which is quite drastic. I don't think there's a nicer way of doing this - changing the settings might cause existing errors to not be errors any more, or they might cause new errors to be found. Which means reanalysing everything.

I'm not sure what ReSharper does in this situation - I can't think of any settings that cause a re-analysis, either of everything, or of existing errors. The only settings most inspections have is severity - whether something is treated as an error, warning, suggestion, etc. And as far as I can see, the SWEA manager has specific handling of this case - it keeps a track of all highlights, and updates the results if the severity changes (I think).

0

There is at least one setting in ReSharper, which has the same problem: ValueAnalysisMode (I created RSRP-434918 for this).

So, is it right that there is no more fine granulated option than calling SolutionAnalysisService.ReanalyzeAll()? What about invalidating all files containing specific tree node types (the same that my IElementProblemAnalyzer uses), or at least all files containing a specific PSI language?

If we don't want to automatically "reanalyze all" on settings changes due to performance reasons, could we at least place a manual trigger button in the "Inspection Results" / "Code Issues" window?

0

I've been speaking to the dev team, and there isn't really a perfect solution to this. It is possible to invalidate specific files, by calling SolutionAnalysisManager.ReanalyseFile. You could also potentially do something similar with file dependencies. ReSharper maintains a set of depdencies for a file - this can be another file, or a setting such as language level. When the files are changed, the dependencies are recalculated, and if anything has changed, all dependent files are also invalidated. This *might* help, but it doesn't seem likely, as it requires a file to be changed in order to recalculate the dependencies.

For example, the MVC support adds a dependency that is based on whether the MVC support is enabled or not. When the setting changes, the depdency is different, and affected files are reanalysed. However, I'm a little hazy on how this happens - as far as I can see, the dependency is added to the solution, and recalculated whenever a file is changed. This means that is the setting changes, the next time a file is changed, the solution dependency is now invalid, and everything is reanalysed again. But this is not really any different to just calling SolutionAnalysisManager.ReanalyzeAll.

You can see more about how MVC does this by looking at MvcDaemonStage, and MvcSpecificFileImageContributor.

0

Hi Matt,

many thanks for your research and your answer!

OK, if there is no good solution to this problem itself, what about the suggestion that we place the "reanalyze all files" more prominently (e.g. added it to the "Inspection Results" / "Code Issues" window toolbar) so that a user can at least trigger it (easily) manually?

Maybe, this could also be a solution / workaround for RSRP-434918.

0

There already is a Refresh button on the toolbar for inspection results. This should reanalyse.

0

Hi,

This "Refresh" button just checks the files of the currently listed highlightings and updates them, ... it doesn't "reanalyze all" files, i.e. does not find new highlightings in other files (due to settings changes).

BTW: The "Errors in Solution" window got such a toolbar button I think in R# 9.

0

Please sign in to leave a comment.