2016-09-28 5 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); 
} 

लेकिन मैं समझ नहीं लगा सकते हैं कि यदि एलएचएस और असाइनमेंट के आरएचएस इसी हैं - SyntaxToken.IsEquivalentTo विधि मैं चाहता हूँ हो गया लगता है, लेकिन यह हमेशा झूठे देता है, कर के रूप में SyntaxToken.Equals और ==

यह निर्धारित करने का सही तरीका क्या है कि टोकन स्वयं का जिक्र कर रहा है या नहीं?

+1

सिंटेक्स फैक्ट्री.एरक्वाइवलेंट? – Marcus

+0

@ मार्कस जो काम करता है, लेकिन यह 'आइटम = अन्य। इटिम' जैसी चीज़ों को समकक्ष समझा जाता है, जो मैं नहीं चाहता हूं। मुझे केवल उन मामलों में दिलचस्पी है जहां एक चर या संपत्ति को अपना मूल्य आवंटित किया जा रहा है। –

+0

क्या आप पूरे कोड को विश्लेषण के अधीन पोस्ट कर सकते हैं? या वह हिस्सा जहां तुलना विफल हो जाती है। कार्यान्वयन को देखकर मैं नहीं देख सकता कि 'IsEquivalentTo' संभवतः सटीक परिणाम देने में विफल कैसे हो सकता है। – Marcus

उत्तर

1

मुझे नहीं लगता कि आप इसे SyntaxToken स्तर पर कर सकते हैं। सबसे पहले, मैंने सोचा कि अर्थात् मॉडल आपको यहां मदद करेगा, लेकिन दोनों मामलों में, प्रतीक एक ही बात का संदर्भ लेते हैं, इसलिए आप इसे अलग करने के लिए उपयोग नहीं कर सकते हैं।

हालांकि, आप क्या कर सकते हैं, बस SimpleAssignmentExpression की जांच करें, जांचें कि दोनों ऑपरेंड पहचानकर्ता हैं या उसी SyntaxFactory.AreEquivalent() के माध्यम से उनकी समकक्षता की जांच करें जो मार्कस ने उल्लेख किया था।

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 

मान लीजिए कि आप इस विधि लिखते हैं: मैं इस (एक पूर्ण LINQPad क्वेरी के लिए this gist देखें) को मिला

+0

'if (! Lhs.IsKind (SyntaxKind.IdentifierName)) 'चेक शायद बहुत मजबूत है। प्रोग्राम टेक्स्ट 'this.Item = Item' हो सकता है, और मुझे लगता है कि ओपी भी ध्वजांकित करना चाहता है। –

+0

सच है, उस बारे में नहीं सोचा था। मैं बाद में जवाब अपडेट करूंगा (मैं अब मैक पर हूं, इसलिए कोड का परीक्षण नहीं कर सकता)। – Ties

संबंधित मुद्दे