我正在编写一个 Roslyn 分析器来执行一些文档规则。规则规定只有在程序集外部可见的字段和类型才需要记录。这让我遇到了一个问题,即查明一个字段或类型是否有效可见并且可以在声明程序集之外使用。
鉴于此声明:
namespace TestApp {
internal class InternalClass {
public class InnerClass {
public int PublicFieldInInternal;
}
}
}
我想知道 PublicFieldInInternal
在声明程序集之外是否可见。我使用下面的代码来确定可访问性:
private bool IsNonPrivateMemberDeclaration(SyntaxNodeAnalysisContext context, SyntaxNode node)
{
if (node is BaseFieldDeclarationSyntax fieldDeclaration)
{
var firstField = fieldDeclaration.Declaration.Variables.First();
var fieldAccessibility = context.SemanticModel.GetDeclaredSymbol(firstField).DeclaredAccessibility;
return ConstructVisibleFromOtherAssemblies(fieldAccessibility);
}
var accessibility = context.SemanticModel.GetDeclaredSymbol(node)?.DeclaredAccessibility;
if (accessibility != null)
{
return ConstructVisibleFromOtherAssemblies(accessibility.Value);
}
Debug.Assert(true, "This code should be unreachable as one of the two cases above will catch all calls");
return false;
}
private static bool ConstructVisibleFromOtherAssemblies(Accessibility accessibility) =>
accessibility == Accessibility.Public ||
accessibility == Accessibility.Protected ||
accessibility == Accessibility.ProtectedOrInternal;
但是,它没有考虑父类型的可访问性,因此对应于 PublicFieldInInternal
的符号的 DeclaredAccessibility
属性返回 Accessibility.Public
。有没有办法直接查询语义模型以获得有效的可访问性,或者我是否需要递归地查看包含类型?
最佳答案
我最终采用了这种方法,它通过了所有单元测试:
private bool IsVisibleFromOtherAssemblies(SyntaxNodeAnalysisContext context, SyntaxNode node)
{
ISymbol declaredSymbol = GetDeclaredSymbol(context, node);
var accessibility = declaredSymbol.DeclaredAccessibility;
var visibility = ConstructVisibleFromOtherAssemblies(accessibility);
var containingType = declaredSymbol.ContainingType;
return IsSymbolAndContainingTypeVisible(visibility, containingType);
}
private static ISymbol GetDeclaredSymbol(SyntaxNodeAnalysisContext context, SyntaxNode node)
{
if (node is BaseFieldDeclarationSyntax fieldDeclaration)
{
var firstField = fieldDeclaration.Declaration.Variables.First();
return context.SemanticModel.GetDeclaredSymbol(firstField);
}
return context.SemanticModel.GetDeclaredSymbol(node);
}
private bool IsSymbolAndContainingTypeVisible(bool visibility, INamedTypeSymbol containingType)
{
if (containingType == null)
{
return visibility;
}
return visibility && IsSymbolAndContainingTypeVisible(
ConstructVisibleFromOtherAssemblies(containingType.DeclaredAccessibility),
containingType.ContainingType);
}
private static bool ConstructVisibleFromOtherAssemblies(Accessibility accessibility) =>
accessibility == Accessibility.Public ||
accessibility == Accessibility.Protected ||
accessibility == Accessibility.ProtectedOrInternal;
关于c# - 在 Roslyn 分析器中查找字段和类型的有效可访问性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54480727/