Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ionic-framework/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何使用Roslyn查找变量的以前用法?_C#_Visual Studio 2015_Code Analysis_Roslyn - Fatal编程技术网

C# 如何使用Roslyn查找变量的以前用法?

C# 如何使用Roslyn查找变量的以前用法?,c#,visual-studio-2015,code-analysis,roslyn,C#,Visual Studio 2015,Code Analysis,Roslyn,我在写Rosyln分析仪。它检查以确保在访问类型上的另一个(潜在危险的)方法之前调用了一个方法。为了说明我的意思,这里有一些我想分析并失败的错误代码: private void myMethod() { var myThing = new MyThing(); myThing.Value = null; string value = myThing.GetValue(); // code blows up here as the internal value is nu

我在写Rosyln分析仪。它检查以确保在访问类型上的另一个(潜在危险的)方法之前调用了一个方法。为了说明我的意思,这里有一些我想分析并失败的错误代码:

private void myMethod()
{
    var myThing = new MyThing();
    myThing.Value = null;

    string value = myThing.GetValue(); // code blows up here as the internal value is null
}
这是一段可以的代码,因为它调用了一个说明它是否为null的方法:

private void myMethod()
{
    var myThing = new MyThing();
    myThing.Value = null;

    if(!myThing.HasValue)
    {
        return ;
    }

    string value = myThing.GetValue(); 
}
因此,它应该检查对
GetValue
的所有调用之前是否有对
HasValue
的调用

我刚从Roslyn开始,所以可能有一种比我最初(失败)尝试更优雅的方式:

1-声明我要检查调用表达式

context.RegisterSyntaxNodeAction(analyseMemberAccessNode, SyntaxKind.InvocationExpression);
2-在我的方法中,我得到方法名(
GetValue()

3-然后检查它是否为正确的“GetValue”

var memberSymbol = context.SemanticModel.GetSymbolInfo(memberAccess).Symbol as IMethodSymbol;

if (!memberSymbol?.OverriddenMethod.ToString().StartsWith("MyNamespace.MyThing.GetValue") ?? true)
    return;
到目前为止,一切都很好。所以我得到了变量的名称

5-现在我陷入困境-我的理论是:;获取包含方法,找到与
variableName
匹配的单变量声明,找到该声明的用法,并确保在
GetValue
之前调用
HasValue


简而言之,使用Roslyn分析器(源自
DiagnosticanAnalyzer
),如何确保在
GetValue
之前调用
HasValue

而不是为每次调用注册,最好注册整个方法声明。然后,您可以跟踪所有
MemberAccessExpressionSyntax
,并确保在
GetValue
之前调用给定变量
HasValue
。为此,我将从
MethodDeclaration
节点获取
MemberAccessExpressionSyntax
子体

context.RegisterSyntaxNodeAction((analysisContext) =>
{
    var invocations =
        analysisContext.Node.DescendantNodes().OfType<MemberAccessExpressionSyntax>();
    var hasValueCalls = new HashSet<string>();
    foreach (var invocation in invocations)
    {
        var e = invocation.Expression as IdentifierNameSyntax;

        if (e == null)
            continue;

        string variableName = e.Identifier.Text;

        if (invocation.Name.ToString() == "HasValue")
        {
            hasValueCalls.Add(variableName);
        }

        if (invocation.Name.ToString() == "GetValue")
        {
            if (!hasValueCalls.Contains(variableName))
            {
                analysisContext.ReportDiagnostic(Diagnostic.Create(Rule, e.GetLocation()));
            }
        }
    }
}, SyntaxKind.MethodDeclaration);
context.RegisterSyntaxNodeAction((analysisContext)=>
{
变量调用=
analysisContext.Node.DegenantNodes()。of type();
var hasValueCalls=newhashset();
foreach(调用中的var调用)
{
var e=invocation.Expression作为IdentifierNameSyntax;
如果(e==null)
继续;
字符串variableName=e.Identifier.Text;
if(invocation.Name.ToString()=“HasValue”)
{
hasValueCalls.Add(variableName);
}
if(invocation.Name.ToString()=“GetValue”)
{
如果(!hasValueCalls.Contains(variableName))
{
analysisContext.ReportDiagnostic(Diagnostic.Create(Rule,e.GetLocation());
}
}
}
},SyntaxKind.MethodDeclaration);

您正在查找
数据流
var e = memberAccess.Expression as IdentifierNameSyntax;

string variableName = e.Identifier.Text;
context.RegisterSyntaxNodeAction((analysisContext) =>
{
    var invocations =
        analysisContext.Node.DescendantNodes().OfType<MemberAccessExpressionSyntax>();
    var hasValueCalls = new HashSet<string>();
    foreach (var invocation in invocations)
    {
        var e = invocation.Expression as IdentifierNameSyntax;

        if (e == null)
            continue;

        string variableName = e.Identifier.Text;

        if (invocation.Name.ToString() == "HasValue")
        {
            hasValueCalls.Add(variableName);
        }

        if (invocation.Name.ToString() == "GetValue")
        {
            if (!hasValueCalls.Contains(variableName))
            {
                analysisContext.ReportDiagnostic(Diagnostic.Create(Rule, e.GetLocation()));
            }
        }
    }
}, SyntaxKind.MethodDeclaration);