ASP.NET tags and #if
Answered
The following code:
<% #if DEBUG %>
<%= ScriptsRepository.UrlsToScriptTags(Html, Url, ScriptsRepository.ScriptUrls) %>
<% #else %>
<%= ScriptsRepository.UrlToScriptTag(Html, Url, "Scripts/Site.js") %>
<% #endif %>
Gives an error in Resharper, "Expression expected" on the second line inside the else (highlighted in red). The ScriptsRespository.UrlToScriptTag method returns a string, I can only assume Resharper is getting confused about the intermingling of syntax? (Code works fine in practice).
If I change it to:
<% #if DEBUG Response.Write(ScriptsRepository.UrlsToScriptTags(Html, Url, ScriptsRepository.ScriptUrls)); #else Response.Write(ScriptsRepository.UrlToScriptTag(Html, Url, "Scripts/Site.js")); #endif %>
Or:
ScriptsRepository.UrlToScriptTag(Html, Url, "Scripts/Site.js")) %> <% #endif %>
Then the error goes away.
Is this a Resharper bug, or is the original code somehow invalid? I'm using R# 10.0.2 Ultimate on VS 2015 (12.0.24720.0
Thanks :)
Please sign in to leave a comment.
Oh. Nice bug. This looks like it's a quirk of the implementation of the C# islands, and the interaction with the ASP.NET directives and the preprocessor statements.
When working with .aspx files (or similar, like Razor), ReSharper creates an in-memory C# file that is very similar to what actually gets generated when the .aspx file is compiled - a method with a load of Response.Write method calls, passing in the ASP.NET directive contents. This allows ReSharper to map between the hidden C# file and the C# in the .aspx file - it shows any inspections that would be shown in the C# file, but mapped to the .aspx file. The same happens with code completion, etc.
ReSharper doesn't parse inside a disabled preprocessor section - the code is highly likely to be invalid, or at the least duplicate existing code. Supporting it has way too many edge cases. So in the generated code, the expression isn't parsed.
But the ASP.NET directive is expecting an expression. And when it maps to the underlying C# code, there is no valid expression - you've surrounded the expression in preprocessor directives, so it's essentially dead code. And so the ASP.NET directive flags it as an error.
Which means, when the code is generated and compiled, all will work as expected (as the ASP.NET directive becomes a call to Response.Write, which is already in the disabled preprocessor directive), but at edit time, ReSharper fails to see an expression when it's expecting one.
Basically, you've hit on a nice corner case of a leaky abstraction :)
One of my colleagues has just raised a bug you can vote on and follow - RSRP-453054. In the mean time, I would suggest using your first version that works - make sure that the start and end of a preprocessor statement are in the same ASP.NET directive, and use Response.Write. This way, the interaction between the preprocessor statements and ASP.NET directives is more predictable.
Hello Timothy,
I filed a new ticket to YouTrack https://youtrack.jetbrains.com/issue/RSRP-453054.
Thanks!