使用 Roslyn 有选择地删除预处理器指令
Selectively remove preprocessor directives using Roslyn
我想使用 Roslyn 清理一些旧的预处理器指令的代码。
例如,来自这段代码
#define TEST_1_0
#define TEST_1_1
namespace ConsoleApplication1
{
class TypeName
{
public static void Main(string[] args)
{
#if TEST_1_0
int TEST_1_0 = 1;
#if TEST_1_1
int TEST_1_1 = 1;
#else//TEST_1_1
int TEST_1_1 = 0;
#endif//TEST_1_1
#else//TEST_1_0
int TEST_1_0 = 0;
#endif//TEST_1_0
}
}
}
我想删除 else//TEST_1_0,但保留 else//TEST_1_1。我不能指望评论,所以我应该将 #if 与其对应的 #else 相关联,如果有的话。
找到#if 很容易,但找到相应的#else 就没那么容易了。
我尝试了两种策略:
- 在这里我在分析器中查找#else//TEST_1_0,并为该位置创建一个代码修复
- 这里我只是在analyzer中为#ifTEST_1_0创建一个codefix,并尝试从CodeFixprovider
中获取对应的else
两者都很快变得相当复杂,指令是琐事似乎有问题,它们分布在不同 SyntaxTokens 的 leadingTrivia 上。代码中的更改会在很大程度上影响位置指令,因此对所有情况进行编程看起来需要做很多工作..
我错过了什么吗?有没有更简单的方法来做到这一点而无需手动编程所有不同的情况?
你会选择策略 1 还是策略 2?
我的结论是roslyn不是去这里的路。
Roslyn 将预处理器指令建模为语法树中的琐事,琐事的位置根据实际代码的结构有很大差异。
因此,在语法树上工作会引入查找复杂性,这在基于文本的工作时不是问题,而更复杂意味着更多风险。二进制应该是一样的before/after处理!
所以我选择放弃 Roslyn 并简单地将 code/directive 混合解析为文本,使用正则表达式进行解析并使用老式堆栈来处理指令逻辑。
现在简单多了,小菜一碟..
还需要处理一些编码问题,那我就完成了! :)
解析愉快!
我同意 Arjan - Roslyn 不能用于该任务。为了解决类似的任务,我基于正则表达式和 Python sympy 库制作了自己的简单 C# 预处理器工具:undefine。我相信这会对你有所帮助。至于您描述的任务,请尝试以下命令:
>> python undefine apply -d TEST_1_0 YourFile.cs
我想使用 Roslyn 清理一些旧的预处理器指令的代码。
例如,来自这段代码
#define TEST_1_0
#define TEST_1_1
namespace ConsoleApplication1
{
class TypeName
{
public static void Main(string[] args)
{
#if TEST_1_0
int TEST_1_0 = 1;
#if TEST_1_1
int TEST_1_1 = 1;
#else//TEST_1_1
int TEST_1_1 = 0;
#endif//TEST_1_1
#else//TEST_1_0
int TEST_1_0 = 0;
#endif//TEST_1_0
}
}
}
我想删除 else//TEST_1_0,但保留 else//TEST_1_1。我不能指望评论,所以我应该将 #if 与其对应的 #else 相关联,如果有的话。
找到#if 很容易,但找到相应的#else 就没那么容易了。
我尝试了两种策略:
- 在这里我在分析器中查找#else//TEST_1_0,并为该位置创建一个代码修复
- 这里我只是在analyzer中为#ifTEST_1_0创建一个codefix,并尝试从CodeFixprovider 中获取对应的else
两者都很快变得相当复杂,指令是琐事似乎有问题,它们分布在不同 SyntaxTokens 的 leadingTrivia 上。代码中的更改会在很大程度上影响位置指令,因此对所有情况进行编程看起来需要做很多工作..
我错过了什么吗?有没有更简单的方法来做到这一点而无需手动编程所有不同的情况?
你会选择策略 1 还是策略 2?
我的结论是roslyn不是去这里的路。
Roslyn 将预处理器指令建模为语法树中的琐事,琐事的位置根据实际代码的结构有很大差异。
因此,在语法树上工作会引入查找复杂性,这在基于文本的工作时不是问题,而更复杂意味着更多风险。二进制应该是一样的before/after处理!
所以我选择放弃 Roslyn 并简单地将 code/directive 混合解析为文本,使用正则表达式进行解析并使用老式堆栈来处理指令逻辑。
现在简单多了,小菜一碟.. 还需要处理一些编码问题,那我就完成了! :) 解析愉快!
我同意 Arjan - Roslyn 不能用于该任务。为了解决类似的任务,我基于正则表达式和 Python sympy 库制作了自己的简单 C# 预处理器工具:undefine。我相信这会对你有所帮助。至于您描述的任务,请尝试以下命令:
>> python undefine apply -d TEST_1_0 YourFile.cs