如何确定部分方法没有实现

时间:2014-04-12 06:20:00

标签: c# roslyn

鉴于此案:

partial class Test
{
    partial void FooBar();
}

partial class Test
{
    public void Foo()
    {
        FooBar();
    }
}

现在从SymbolInfo调用中获取FooBar()会给我IMethodSymbol PartialDefinitionPart == nullPartialImplementationPart == null。有没有办法确定没有部分实施?

3 个答案:

答案 0 :(得分:3)

PartialDefinitionPart的XML文档说:

  

如果这是部分方法实现部分,则返回相应的       定义部分。否则为null。

PartialImplementationPart

  

如果这是没有正文的部分方法声明,则方法是       用body实现,返回实现定义。除此以外       空。

这意味着如果您正在调用具有实现的部分方法,则其符号将具有非null PartialImplementationPart。有趣的是,似乎没有一种简单的方法来确定方法是否是部分方法。

答案 1 :(得分:0)

方法声明必须

  1. 拥有partial修饰符(MethodDeclarationSyntax.Modifiers
  2. 和(基于svicks答案)既没有IMethodSymbol.PartialDefinitionPart
  3. 也不是IMethodSymbol.PartialImplementationPart部分没有实施。
  4. 下面的代码演示了如何在给定解决方案中找不到实现的所有部分方法:

    foreach (var project in solution.Projects)
    {
        foreach (var document in project.Documents)
        {
            var methods = document
                .GetSyntaxRootAsync().Result
                .DescendantNodes()
                .OfType<MethodDeclarationSyntax>()
                .ToList();
    
            var semanticModel = document.GetSemanticModelAsync().Result;
            foreach (var method in methods)
            {
                if (method.Modifiers.All(m => m.ValueText != "partial"))
                    continue;
    
                var methodSymbol = semanticModel.GetDeclaredSymbol(method);
                if (methodSymbol.PartialDefinitionPart == null 
                    && methodSymbol.PartialImplementationPart == null)
                {
                    // found partial method without an implementation!
                }
            }
        }
    }
    

    因为你已经有一个方法符号,并且知道你的方法是偏的,这当然有点过分,但我想展示如何找到未实现部分方法而不用

答案 2 :(得分:0)

当我试图寻找方法并在roslyn github问题[1]中找到实现时,我自己使用对IMethodSymbol中语法的引用对方法进行编码。该版本对我不起作用,因为我发现DeclaringSyntaxReferences仅包含一项,即使部分方法有正文也是如此。我以这种方式解决了这个问题:

    public static bool IsPartialMethod(this IMethodSymbol method, out bool hasEmptyBody)
    {
        if (method.IsDefinedInMetadata())
        {
            hasEmptyBody = false;
            return false;
        }

        foreach (var reference in method.DeclaringSyntaxReferences)
        {
            var syntax = reference.GetSyntax();
            if (syntax.Kind() != SyntaxKind.MethodDeclaration)
                continue;

            var node = syntax as MethodDeclarationSyntax;
            if (!node.Modifiers.Any(SyntaxKind.PartialKeyword))
            {
                hasEmptyBody = false;
                return false;
            }
        }

        hasEmptyBody = method.PartialImplementationPart == null || method.PartialDefinitionPart != null;
        return true;
    }

    /// <returns>False if it's not defined in source</returns>
    public static bool IsDefinedInMetadata(this ISymbol symbol)
    {
        return symbol.Locations.Any(loc => loc.IsInMetadata);
    }

[1] https://github.com/dotnet/roslyn/issues/48#issuecomment-75641847