清理 roslyn 成员声明语法标识符
Sanitize roslyn memberdeclarationsyntax identifier
在构建 synxtaxtrees 时,roslyn 中是否有任何现有的方法或机制来清理 memberdeclarationsynxtax 节点的标识符名称?
例如带有空格、点、破折号或使用保留字的名称,如 class、void、string
[编辑]
需要澄清的是,将生成代码,因此您事先不知道或无法控制输入,目的是净化输入。我指的是等同于 Path.GetInvalidFileNameChars() 的语法树,您可以使用它来清理用于创建目录和文件的输入。我在问 roslyn 是否有任何此类机制。
我认为这个答案有两个部分。首先,在语法级别上,您永远不会有一个带有保留关键字值的 IdentifierNameSyntax
。我知道你在谈论方法声明,但同样的想法适用于命名空间,(它的语法树更浅)。
考虑:
namespace class
{
}
对应的语法树(用Roslyn Syntax Visualizer生成):
请注意,在上图中 IdentifierName
旁边有一个闪电。这表明它完全丢失了。解析器不会将 class
误认为标识符。它知道每次它看到关键字 class
时都是 ClassDeclarationSyntax
的开头。
您的语法树完全被破坏,甚至 Visual Studio 都没有意识到您正试图使用值为 "class" 的标识符。它指示三个错误:
- 需要标识符
- { 预计
- } 预计
如果您正在生成标识符并希望检测您生成的字符串是否可以用作有效标识符,则此答案的第二部分适用。我简单地搜索了代码库,没有注意到任何可以检测标识符中无效字符和关键字的方法。但是,我们可以结合两种方法来实现您想要的:
SyntaxFacts.IsValidIdentifier()
and IsCSharpKeyword()
(不幸的是,这是内部的,必须复制到您的程序中)。
string myIdentifier = "test&";
bool validIdentifier = SyntaxFacts.IsValidIdentifier(myIdentifier); //false
string myOtherIdentifier = "class";
bool isKeyword = myOtherIdentifier.IsCSharpKeyword(); //true
请注意,IsCSharpKeyword()
不会检查 Contextual Keywords
,它们可能出现在标识符中。但是,将您的 class 命名为 var
可能会引入语义错误,因此您可能还想添加这些上下文关键字。
在跟进接受的答案时,我在 SyntaxFacts 上发现了一些可以在这里使用的其他方法。
GetKeywordKind(string)
returns 表示关键字的 SyntaxKind
,如果传递的字符串不是 C# 关键字,则为 SyntaxKind.None
。 GetContextualKeywordKind(string)
对上下文关键字做同样的事情。这应该可以轻松地执行以下操作:
string identifier = "double";
bool isAnyKeyword = SyntaxFacts.GetKeywordKind(identifier) != SyntaxKind.None
|| SyntaxFacts.GetContextualKeywordKind(identifier) != SyntaxKind.None;
在构建 synxtaxtrees 时,roslyn 中是否有任何现有的方法或机制来清理 memberdeclarationsynxtax 节点的标识符名称?
例如带有空格、点、破折号或使用保留字的名称,如 class、void、string
[编辑] 需要澄清的是,将生成代码,因此您事先不知道或无法控制输入,目的是净化输入。我指的是等同于 Path.GetInvalidFileNameChars() 的语法树,您可以使用它来清理用于创建目录和文件的输入。我在问 roslyn 是否有任何此类机制。
我认为这个答案有两个部分。首先,在语法级别上,您永远不会有一个带有保留关键字值的 IdentifierNameSyntax
。我知道你在谈论方法声明,但同样的想法适用于命名空间,(它的语法树更浅)。
考虑:
namespace class
{
}
对应的语法树(用Roslyn Syntax Visualizer生成):
请注意,在上图中 IdentifierName
旁边有一个闪电。这表明它完全丢失了。解析器不会将 class
误认为标识符。它知道每次它看到关键字 class
时都是 ClassDeclarationSyntax
的开头。
您的语法树完全被破坏,甚至 Visual Studio 都没有意识到您正试图使用值为 "class" 的标识符。它指示三个错误:
- 需要标识符
- { 预计
- } 预计
如果您正在生成标识符并希望检测您生成的字符串是否可以用作有效标识符,则此答案的第二部分适用。我简单地搜索了代码库,没有注意到任何可以检测标识符中无效字符和关键字的方法。但是,我们可以结合两种方法来实现您想要的:
SyntaxFacts.IsValidIdentifier()
and IsCSharpKeyword()
(不幸的是,这是内部的,必须复制到您的程序中)。
string myIdentifier = "test&";
bool validIdentifier = SyntaxFacts.IsValidIdentifier(myIdentifier); //false
string myOtherIdentifier = "class";
bool isKeyword = myOtherIdentifier.IsCSharpKeyword(); //true
请注意,IsCSharpKeyword()
不会检查 Contextual Keywords
,它们可能出现在标识符中。但是,将您的 class 命名为 var
可能会引入语义错误,因此您可能还想添加这些上下文关键字。
在跟进接受的答案时,我在 SyntaxFacts 上发现了一些可以在这里使用的其他方法。
GetKeywordKind(string)
returns 表示关键字的 SyntaxKind
,如果传递的字符串不是 C# 关键字,则为 SyntaxKind.None
。 GetContextualKeywordKind(string)
对上下文关键字做同样的事情。这应该可以轻松地执行以下操作:
string identifier = "double";
bool isAnyKeyword = SyntaxFacts.GetKeywordKind(identifier) != SyntaxKind.None
|| SyntaxFacts.GetContextualKeywordKind(identifier) != SyntaxKind.None;