2016-09-28 54 views
6

鑑於下面的代碼段,例如:確定如果兩個SyntaxTokens是相同

public class Thing 
{ 
    public int Item { get; } 

    public Thing(int item) 
    { 
     Item = Item; // note incorrect assignment: rhs should be item, the passed-in arg, hence analyzer should warn 
    } 

    public Thing(Thing other) 
    { 
     Item = other.Item; // correct assignment, should NOT trigger analyzer 
    } 
} 

我正在寫一個羅斯林分析器至低於檢測和報告可能誤認爲自賦值的這些情況下,相關部分:

public override void Initialize(AnalysisContext context) 
{ 
    context.RegisterSyntaxNodeAction(MistakenSelfAssignment, SyntaxKind.SimpleAssignmentExpression); 
} 

private static void MistakenSelfAssignment(SyntaxNodeAnalysisContext context) 
{ 
    var assignment = context.Node as AssignmentExpressionSyntax; 
    if (assignment == null) 
    { 
     return; 
    } 

    var leftToken = GetIdentifierToken(assignment.Left); 
    var rightToken = GetIdentifierToken(assignment.Right); 

    if (leftToken != null && leftToken.IsEquivalentTo(rightToken)) // this never works 
    { 
     var diagnostic = Diagnostic.Create(Rule, assignment.GetLocation()); 
     context.ReportDiagnostic(diagnostic); 
    } 
} 

private static SyntaxToken GetIdentifierToken(ExpressionSyntax syntax) 
{ 
    var identifierName = syntax as IdentifierNameSyntax; 
    if (identifierName != null) 
    { 
     return identifierName.Identifier; 
    } 

    var identifierAccess = syntax as MemberAccessExpressionSyntax; 
    if (identifierAccess != null) 
    { 
     return identifierAccess.Name.Identifier; 
    } 

    return default(SyntaxToken); 
} 

但我無法弄清楚如何確定轉讓的LHS和RHS是同樣的道理 - SyntaxToken.IsEquivalentTo似乎是我想要的方法,但它始終返回false,因爲這樣做SyntaxToken.Equals==

確定令牌是否指向自身的正確方法是什麼?

+1

SyntaxFactory.AreEquivalent? – Marcus

+0

@馬庫斯那種工作,但它也認爲像'Item = other.Item'等等東西,這不是我想要的。我只關心變量或屬性被賦值爲自己的值的情況。 –

+0

你能發表需要分析的整個代碼嗎?或比較失敗的部分。通過查看實現,我無法看到「IsEquivalentTo」可能無法提供準確的結果。 – Marcus

回答

1

我不認爲你可以在SyntaxToken級別上做到這一點。起初,我認爲語義模型可以幫助你,但在這兩種情況下,符號都是指同一個東西,所以你不能用它來區分。

但是,你可以做的只是調查SimpleAssignmentExpression,檢查兩個操作數是否都是標識符,並通過與Marcus提到的相同的SyntaxFactory.AreEquivalent()檢查它們的等價性。我得到這個(見this gist全額LINQPad查詢):

比方說,你寫這個方法:

private static bool IsAssignmentBad(AssignmentExpressionSyntax assignmentNode) 
{ 
    if (!assignmentNode.IsKind(SyntaxKind.SimpleAssignmentExpression)) 
    { 
     return false; 
    } 

    var lhs = assignmentNode.Left; 
    if (!lhs.IsKind(SyntaxKind.IdentifierName)) 
    { 
     return false; 
    } 

    var rhs = assignmentNode.Right; 
    if (!rhs.IsKind(SyntaxKind.IdentifierName)) 
    { 
     return false; 
    } 

    return SyntaxFactory.AreEquivalent(lhs, rhs); 
} 

然後用這個運行它給你想要的東西,我想:

var tree = CSharpSyntaxTree.ParseText(
@"public class Thing 
{ 
    public int Item { get; } 

    public Thing(int item) 
    { 
     Item = Item; // note incorrect assignment: rhs should be item, the passed-in arg, hence analyzer should warn 
    } 

    public Thing(Thing other) 
    { 
     Item = other.Item; // correct assignment, should NOT trigger analyzer 
    } 
}"); 

var root = tree.GetRoot(); 

var incorrectAssignment = root.DescendantNodes().OfType<AssignmentExpressionSyntax>().First(); 
var correctAssignment = root.DescendantNodes().OfType<AssignmentExpressionSyntax>().Last(); 

var b1 = IsAssignmentBad(correctAssignment); // doesn't consider the assignment bad 
var b2 = IsAssignmentBad(incorrectAssignment); // this one does 
+0

'if(!lhs.IsKind(SyntaxKind.IdentifierName))'檢查可能太強大了。程序文本可能是'this.Item = Item',我想OP也想要這樣標記。 –

+0

沒錯,沒有想到那個。稍後我會更新答案(我現在在Mac上,因此無法測試代碼)。 – Ties

相關問題