Roslyn Analyzer: How to handle a side effect of renaming classes

61 Views Asked by At

I'm writing a Roslyn analyzer that renames classes matching a certain pattern. The rename "fix" successfully renames the class, but in my unit test (which uses in-memory source which oddly enough results in a virtual file named '/0/Test0.cs'), whenever I specify "RenameFile: true" for the SymbolRenameOptions to rename the class "SomeTypeName" to "RenamedSomeTypeName", my test fails with the message:

Message:  Context: Iterative code fix application file name was expected to be '/0/Test0.cs' but was 'RenamedSomeTypeName.cs' Expected string length 11 but was 22. Strings differ at index 0. Expected: "/0/Test0.cs" But was: "RenamedSomeTypeName.cs"

I tried adding a new rule to my analyzer (although logically that seems like the wrong place to capture the problem since the issue occurs as a side effect of a fix which would typically happen after the analyze phase is complete).

I thought about trying to register a new code fix to my CodeFixProvider class, but that also seems futile since there would be no analyzer event to trigger a fix.

I've searched in vain for any hint as to how to handle this side effect failure message. Is there some sort of post-fix analyzer that can capture this issue so I can mark it as expected. That is, after all, what I really want to do.

1

There are 1 best solutions below

0
On BEST ANSWER

I traced this behavior down to the NUnitVerifier.Equal(T expected, T actual, string? message = null) method. I fixed the issue by overriding this method in a derived class and then checking if the specific string pair matched the expected behavior of the unit test. If so, return with no action, else invoke base method. As a bonus, this solution allows me to fail negative cases.

Note, I also had to override PushContext since the base class method looks like:

public virtual IVerifier PushContext(string context)
{
  Assert.AreEqual((object) typeof (NUnitVerifier), (object) this.GetType());
  return (IVerifier) new NUnitVerifier(this.Context.Push(context));
}

I simply switched out my type for NUnitVerifier in the assert and then returned a instance of my custom verifier class.