Inclusion of using is put inside unrelated preprocessor directive
Version Used: VS 20017 Version 15.1 26403.7
Steps to Reproduce:
- Start with this program
#if DEBUG
using System.IO;
#endif
namespace ConsoleApplication2
{
class Foo
{
public void Bar()
{
Console.WriteLine();
}
}
}
-
Ctrl+.onConsole.WriteLine(); - Select "Using System"
- Observe how
using System;is put inside#if DEBUG, result:
#if DEBUG
using System;
using System.IO;
#endif
namespace ConsoleApplication2
{
class Foo
{
public void Bar()
{
Console.WriteLine();
}
}
}
Expected Behavior: using System; is put outside preprocessor directive.
Actual Behavior: using System; is put inside preprocessor directive making it incompilable in Release Mode.
💭 I would expect the feature to place the new directive inside a logically-equivalent guard. For example, if you were to start with the following code I would expect the result to behave as you observed:
#if DEBUG
using System.IO;
#endif
namespace ConsoleApplication2
{
class Foo
{
public void Bar()
{
#if DEBUG
Console.WriteLine(); // Ctrl+. on this line
#endif
}
}
}
Conceptually this isn't unreasonable, but there are a few cases that make it challenging:
- Nested directives
- Boolean equivalence (e.g.
#if !!DEBUGis equivalent to#if DEBUG, but has a different form)
PRs welcome.
I would expect the feature to place the new directive inside a logically-equivalent guard.
Currently we have no APIs to answer that question. From the perspective of everything consuming the SyntaxTree code there is only the code that active and the code that is disabled. We could certainly try to support this, but it would need a fair amount of plumbing/infrastructure to support. Given that we haven't heard about this issue in 15+ years, it would not be a high pri for me :)
I would expect the feature to place the new directive inside a logically-equivalent guard.
Unfortunately there might not be a single guard that covers it.
#if FOO
using System.IO;
#elif BAR
using System.IO;
#endif
namespace ConsoleApplication2
{
class Preprocessor2
{
public void Foo()
{
#if FOO || BAR
Console.WriteLine();
#endif
}
}
}
Given that we haven't heard about this issue in 15+ years...
I've had the issue two or three times recently in a class where I've used preprocessor directives to switch between alias.
#if DEBUG
using Dev___DataMember = System.Runtime.Serialization.DataMemberAttribute;
#else
using Dev___DataMember = System.Runtime.Serialization.IgnoreDataMemberAttribute;
#endif
There are properly cleaner ways to archive this, but it was a minor annoyance when my VS is in debug mode but the TFS server compiles in release mode and fails to build.
Unfortunately there might not be a single guard that covers it.
True, but one could be added. Again in theory. 😄
Would take a small community fix here.
Not planning on doing this.