कस्टम कंपाइलर चेतावनी


115

जब .net अप्रत्यक्ष रूप से .Net का उपयोग करते हुए यह आपको संकलक चेतावनी देता है, तो आपको बताता है कि ऑब्जेक्ट / विधि / संपत्ति अप्रचलित है और अन्य चीजों का उपयोग किया जाना चाहिए। मैं वर्तमान में एक ऐसी परियोजना पर काम कर रहा हूं जिसमें पूर्व-कर्मचारी कोड को फिर से भरने की बहुत आवश्यकता है। मैं एक कस्टम विशेषता लिखना चाहता हूं जिसका उपयोग मैं उन विधियों या गुणों को चिह्नित करने के लिए कर सकता हूं जो संकलक चेतावनी उत्पन्न करेंगे जो संदेश लिखते हैं। कुछ इस तरह

[MyAttribute("This code sux and should be looked at")]
public void DoEverything()
{
}
<MyAttribute("This code sux and should be looked at")>
Public Sub DoEverything()
End Sub

मैं चाहता हूं कि यह एक संकलक चेतावनी उत्पन्न करे, जो कहती है, "यह कोड sux और इसे देखा जाना चाहिए"। मुझे पता है कि एक कस्टम विशेषता कैसे बनाई जाती है, सवाल यह है कि मैं इसे कैसे दृश्य स्टूडियो में संकलक चेतावनी उत्पन्न करने का कारण बनता हूं।


क्या यह C # है? मैं संभवतः इस पर C # (नहीं C) के रूप में प्रतिशोध लेने जा रहा हूं जो कि मूल पोस्टर को चुनने का मतलब है।
ओनोरियो कैटेनेशिएक

13
यह मान्य VB या C # नहीं है ... तो यह क्या है ...?
17

5
पुराना सवाल है, लेकिन आप अब रोसलिन का उपयोग करके कस्टम कंपाइलर चेतावनी को परिभाषित कर सकते हैं।
आरजे कुथबर्टन

4
@jrummell इन रोसलिन बोलते हैं, कोड एनालाइजर: johnkoerner.com/csharp/creating-your-first-code-analyzer
RJ Cuthbertson

2
@RJCuthbertson मैंने आपकी टिप्पणी को स्वीकार किए गए उत्तर में स्थानांतरित कर दिया, यह ध्यान देने योग्य है।
jpaugh

जवाबों:


27

अपडेट करें

अब रोजलिन (विजुअल स्टूडियो 2015) के साथ यह संभव है। आप कर सकते हैं का निर्माण एक कोड विश्लेषक कस्टम विशेषता के लिए जाँच करने के लिए


मुझे विश्वास नहीं होता कि यह संभव है। अप्रचलित को विशेष रूप से संकलक द्वारा व्यवहार किया जाता है और सी # मानक में परिभाषित किया जाता है। पृथ्वी पर क्यों अप्रत्यक्ष रूप से स्वीकार्य नहीं है? यह मेरे लिए ऐसा लगता है कि यह ठीक उसी स्थिति में है जिसके लिए इसे तैयार किया गया था, और ठीक वही हासिल होता है जिसकी आपको आवश्यकता होती है!

यह भी ध्यान दें कि विज़ुअल स्टूडियो ने फ्लाई पर भी अप्रत्यक्ष रूप से वितरित चेतावनियों को उठाया है, जो बहुत उपयोगी है।

अनहेल्दी होने का मतलब यह नहीं है, बस आप सोच रहे हैं कि आप इसे इस्तेमाल करने के लिए उत्सुक क्यों नहीं हैं ...

दुर्भाग्य से अप्रत्यक्ष रूप से सीलबंद है (शायद आंशिक रूप से विशेष उपचार के कारण) इसलिए आप अपनी खुद की विशेषता को इसमें से नहीं हटा सकते।

C # मानक से: -

विशेषता अप्रचलित का उपयोग उन प्रकारों और प्रकारों के सदस्यों को चिह्नित करने के लिए किया जाता है जिन्हें अब उपयोग नहीं किया जाना चाहिए।

यदि कोई प्रोग्राम एक प्रकार या सदस्य का उपयोग करता है जिसे अप्रचलित विशेषता के साथ सजाया गया है, तो संकलक एक चेतावनी या एक त्रुटि जारी करता है। विशेष रूप से, कंपाइलर चेतावनी जारी करता है यदि कोई त्रुटि पैरामीटर प्रदान नहीं किया जाता है, या यदि त्रुटि पैरामीटर प्रदान किया गया है और मूल्य गलत है। कंपाइलर त्रुटि जारी करता है यदि त्रुटि पैरामीटर निर्दिष्ट किया गया है और इसमें मूल्य सही है।

क्या यह आपकी आवश्यकताओं को पूरा नहीं करता है? ... आप इससे बेहतर नहीं करने जा रहे हैं जो मुझे नहीं लगता।


14
मैं उसी चीज की तलाश में हूं। अप्रचलित 'काम करता है' लेकिन कोड वास्तव में अप्रचलित नहीं है क्योंकि रिफैक्टरिंग के कारण यह अधूरा है।
जी।

11
मैं @ जी, और शायद मूल लेखक से सहमत हूं। अप्रचलित का अर्थ है अप्रचलित, उपयोग न करें। मैं कुछ को "इस संकलन के रूप में चिह्नित करना चाहता हूं, लेकिन हमें वास्तव में या तो) कार्यक्षमता या बी) रिफैक्टर को पूरा करने की आवश्यकता है।" यह एक विकास समय विशेषता का अधिक होगा। इसके अलावा कार्य कार्य, जैसे // TODO:, लेकिन मैं उन का उपयोग नहीं करता हूं, जैसा कि मैं अनुमान लगा रहा हूं कि बहुत से लोग नहीं करते हैं, लेकिन संकलक की नियमित रूप से समीक्षा करते हैं।
माइकजेनसेन

8
[Obsolete]टैग का उपयोग न करने का एक अन्य कारण यह है कि यदि आपको संपत्ति के साथ XmlSerialization करने की आवश्यकता हो तो समस्या हो सकती है। [Obsolete]टैग जोड़ने से [XmlIgnore]पर्दे के पीछे की विशेषता भी जुड़ जाती है ।
burnttoast11

6
अप्रचलित अलग है। अप्रचलित आपको उस पद्धति को कॉल करने वाले कोड की प्रत्येक पंक्ति पर एक चेतावनी देगा। मुझे नहीं लगता कि पोस्टर यही चाहता है (कम से कम वह नहीं है जो मैं चाहता हूं जब मैंने खोज की और यह सवाल पाया)। मैंने सोचा कि प्रश्न क्या देख रहा था, फ़ंक्शन की परिभाषा को दिखाने के लिए एक चेतावनी के लिए था, कभी भी जगह नहीं है कि इसका उपयोग किया जा रहा है।
निक

सबसे बड़ा जवाब नहीं। -1 अपनी असमर्थता के बारे में सोचने के लिए इसका उपयोग न करने के कारण आलोचना की योग्यता है। यह रवैया प्रामाणिकता को हतोत्साहित करता है।
माइक सोखा तृतीय

96

यह एक कोशिश के काबिल है।

आप अप्रचलित का विस्तार नहीं कर सकते, क्योंकि यह अंतिम है, लेकिन शायद आप अपनी विशेषता बना सकते हैं, और उस वर्ग को इस तरह अप्रचलित कर सकते हैं:

[Obsolete("Should be refactored")]
public class MustRefactor: System.Attribute{}

फिर जब आप "MustRefactor" विशेषता के साथ अपने तरीकों को चिह्नित करते हैं, तो संकलन चेतावनी दिखाएगी। यह एक संकलन समय चेतावनी उत्पन्न करता है, लेकिन त्रुटि संदेश अजीब लगता है, आपको इसे अपने लिए देखना चाहिए और चुनना चाहिए। यह वह चीज है जो आप हासिल करना चाहते थे।

अद्यतन: इस कोड के साथ यह एक चेतावनी उत्पन्न करता है (बहुत अच्छा नहीं है, लेकिन मुझे नहीं लगता कि कुछ बेहतर है)।

public class User
{
    private String userName;

    [TooManyArgs] // Will show warning: Try removing some arguments
    public User(String userName)
    {
        this.userName = userName;   
    }

    public String UserName
    {
        get { return userName; }
    }
    [MustRefactor] // will show warning: Refactor is needed Here
    public override string ToString()
    {
        return "User: " + userName;
    }
}
[Obsolete("Refactor is needed Here")]
public class MustRefactor : System.Attribute
{

}
[Obsolete("Try removing some arguments")]
public class TooManyArgs : System.Attribute
{

}

क्या आप इसे उत्पन्न कर सकते हैं? मैं उत्सुक हूँ।
मीका

1
संपत्ति / विधि नहीं कहे जाने पर भी संकलित चेतावनी शुरू हो जाती है।
रॉल्फ क्रिस्टेंसेन

1
यहाँ अच्छे सुझाव हैं। मैं एक ही काम करना चाह रहा था, और NotImplementedException को फेंकना समाप्त कर दिया। सबसे अच्छा समाधान नहीं है क्योंकि वे संकलन समय पर नहीं दिखाते हैं, केवल रनटाइम पर यदि कोड निष्पादित होता है। मैं इसे एक कोशिश खुद दूँगा।
मंकीवेंच

1
क्या यह बहुत अच्छा नहीं होगा यदि ऑब्बोल्टएटरब्यूट डिबगरडिजप्ले एट्रिब्यूट की तरह अभिव्यक्ति का समर्थन कर सकता है, तो हम वास्तव में कुछ अच्छा सामान कर सकते हैं। visualstudio.uservoice.com/forums/121579-visual-studio/...
jpierson

यदि आप IDisposableउन अप्रचलित वर्गों पर लागू करते हैं, तो इसका मतलब है कि आप अपने डोडी परीक्षण कोड को एक usingब्लॉक में लपेट सकते हैं । इस तरह using(new MustRefactor()){DodgyCode();}:। फिर आप जब भी काम पूरा कर सकते हैं, तब आपको सभी सहायता मिल सकती हैं। मैं अभी Sleepइस धागे का उपयोग कर रहा हूँ लूप के लिए थ्रेड के लिए मुझे डिबगिंग उद्देश्यों के लिए कृत्रिम रूप से धीमा करना होगा।
फ्रेजर

48

कुछ संकलक में आप चेतावनी जारी करने के लिए #warning का उपयोग कर सकते हैं:

#warning "Do not use ABC, which is deprecated. Use XYZ instead."

Microsoft कंपाइलर्स में, आप आमतौर पर संदेश प्रागमा का उपयोग कर सकते हैं:

#pragma message ( "text" )

आपने .Net का उल्लेख किया है, लेकिन यह निर्दिष्ट नहीं किया है कि आप C / C ++ या C # के साथ प्रोग्रामिंग कर रहे थे या नहीं। यदि आप C # में प्रोग्रामिंग कर रहे हैं, तो आपको पता होना चाहिए कि C # #warning प्रारूप का समर्थन करता है


1
#warning या #pragma पूर्व-प्रोसेसर निर्देश हैं और इस प्रकार मीका के पूर्व सहयोगियों के किसी भी कोड की उपस्थिति की परवाह किए बिना चलेगा, और यह बिल्कुल भी विशेषता के साथ बातचीत नहीं करता है। बहुत कुछ निश्चित अप्रचलित यह हासिल करने का एकमात्र साधन है ...
18

39

वर्तमान में हम बहुत सारे रिफैक्टिंग के बीच में हैं जहाँ हम सब कुछ ठीक नहीं कर सकते। हम सिर्फ #warning preproc कमांड का उपयोग करते हैं जहाँ हमें वापस जाकर कोड को देखना होगा। यह संकलक आउटपुट में दिखाता है। मुझे नहीं लगता कि आप इसे किसी विधि पर रख सकते हैं, लेकिन आप इसे विधि के अंदर रख सकते हैं, और इसे ढूंढना अभी भी आसान है।

public void DoEverything() {
   #warning "This code sucks"
}

7

VS 2008 (+ sp1) में #warings क्लीन सोल्युशन एंड रिबिल्ड सॉल्यूशन के बाद एरर लिस्ट में ठीक से दिखाई नहीं देते हैं। कुछ चेतावनियाँ त्रुटि सूची में तब दिखाई जाती हैं जब मैं विशेष वर्ग फ़ाइल खोलता हूँ। इसलिए मुझे कस्टम विशेषता का उपयोग करने के लिए मजबूर किया गया:

[Obsolete("Mapping ToDo")]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property)]
public class MappingToDo : System.Attribute
{
    public string Comment = "";

    public MappingToDo(string comment)
    {
        Comment = comment;
    }

    public MappingToDo()
    {}
}

इसलिए जब मैं इसके साथ कुछ कोड फ्लैग करता हूं

[MappingToDo("Some comment")]
public class MembershipHour : Entity
{
    // .....
}

यह इस तरह चेतावनी देता है:

Namespace.MappingToDo अप्रचलित है: 'मैपिंग टुडे'।

मैं चेतावनी का पाठ नहीं बदल सकता, 'कुछ टिप्पणी' में इसे त्रुटि सूची नहीं दिखाया गया है। लेकिन यह फ़ाइल में उचित स्थान पर कूद जाएगा। इसलिए यदि आपको ऐसे चेतावनी संदेशों को अलग-अलग करने की आवश्यकता है, तो विभिन्न विशेषताओं का निर्माण करें।


6

आप जो करने की कोशिश कर रहे हैं वह विशेषताओं का दुरुपयोग है। इसके बजाय Visual Studio कार्य सूची का उपयोग करें। आप इस तरह से अपने कोड में एक टिप्पणी दर्ज कर सकते हैं:

//TODO:  This code sux and should be looked at
public class SuckyClass(){
  //TODO:  Do something really sucky here!
}

फिर मेनू से दृश्य / कार्य सूची खोलें। कार्य सूची में दो श्रेणियां हैं, उपयोगकर्ता कार्य और टिप्पणियाँ। टिप्पणियों पर स्विच करें और आप अपने सभी // टोडो को देखेंगे: वहाँ। TODO पर डबल क्लिक करने से आपके कोड में टिप्पणी आ जाएगी।

अल


1
मुझे यह एक अधिक बेहतर समाधान लगता है
शमूएल

1
क्या होगा यदि आप किसी फ़ंक्शन को "उत्पादन कोड में नहीं बुलाया जाना" या इसी तरह के रूप में चिह्नित करना चाहते हैं। इसलिए आप चाहते हैं कि अगर कोई फंक्शन या क्लास बुलाया जाए या उसे इंस्टेंट किया जाए, लेकिन अगर यह सिर्फ संकलित है, तो इसे फायर करें।
जेसी काली मिर्च

2

मुझे नहीं लगता कि आप कर सकते हैं। जहाँ तक मुझे पता है कि अप्रत्यक्ष सहायता के लिए समर्थन अनिवार्य रूप से सी # संकलक में हार्डकोड किया गया है; आप सीधे कुछ भी ऐसा नहीं कर सकते।

आप जो करने में सक्षम हो सकते हैं वह एक MSBuild कार्य (या एक पोस्ट-बिल्ड ईवेंट) का उपयोग करना है जो न्यायपूर्ण संकलित असेंबली के खिलाफ एक कस्टम टूल निष्पादित करता है। कस्टम टूल असेंबली में सभी प्रकार / विधियों को दर्शाता है और आपके कस्टम विशेषता का उपभोग करता है, जिस बिंदु पर वह System.Console के डिफ़ॉल्ट या त्रुटि TextWriters पर प्रिंट कर सकता है।


2

अप्रचलित एट्रिब्यूट के स्रोत को देखते हुए , ऐसा नहीं लगता है कि यह कंपाइलर चेतावनी उत्पन्न करने के लिए कुछ विशेष कर रहा है, इसलिए मैं @ टेक्नोफाइल के साथ जाना चाहूंगा और कहूंगा कि यह कंपाइलर में हार्ड-कोडेड है। क्या कोई कारण है जो आप अपने चेतावनी संदेशों को उत्पन्न करने के लिए केवल अप्रत्यक्ष रूप से उपयोग नहीं करना चाहते हैं ?


कोड के अलावा कोई विशेष कारण अनिवार्य रूप से अप्रचलित नहीं है।
मीका

1
यह सी # विनिर्देश में निर्दिष्ट है क्योंकि संकलक द्वारा विशेष रूप से व्यवहार किया जा रहा है, मेरे उत्तर को देखें :-)। मीका - 'विशेषता अप्रचलित का उपयोग उन प्रकारों और प्रकारों के सदस्यों को चिह्नित करने के लिए किया जाता है जिन्हें अब उपयोग नहीं किया जाना चाहिए।' विनिर्देशन से। क्या यह लागू नहीं है? ...
ljs

बस अगर किसी को आश्चर्य हुआ, ऐसा करने के लिए स्रोत कोड में कोई C # कोड नहीं है। referenceource.microsoft.com/#mscorlib/system/…
Paweł Mach

1

कई टिप्पणियां हैं जो चेतावनी या प्रज्ञा को सम्मिलित करने का सुझाव देती हैं। अप्रचलित काम बहुत अलग तरीके से होता है! लाइब्रेरी L के किसी फ़ंक्शन को अप्रचलित चिह्नित करना, अप्रचलित संदेश तब उठता है जब कोई प्रोग्राम फ़ंक्शन को कॉल करता है, भले ही कॉलर प्रोग्राम लाइब्रेरी L में न हो। चेतावनी केवल L को संकलित करने पर संदेश को उठाती है।


1

यहां रोसलिन इम्प्लीमेंटेशन है, इसलिए आप अपनी विशेषताओं को बना सकते हैं जो मक्खी पर चेतावनी या त्रुटियां देते हैं।

मैंने एक विशेषता टाइप कॉल की है, IdeMessageजो चेतावनी उत्पन्न करने वाली विशेषता होगी:

[AttributeUsage(AttributeTargets.Method, AllowMultiple = true, Inherited = true)]
public class IDEMessageAttribute : Attribute
{
    public string Message;

    public IDEMessageAttribute(string message);
}

ऐसा करने के लिए आपको पहले रोसलिन एसडीके को स्थापित करना होगा और विश्लेषक के साथ एक नया वीएसआईएक्स प्रोजेक्ट शुरू करना होगा। मैंने संदेशों की तरह कुछ कम प्रासंगिक टुकड़े को छोड़ दिया है, आप यह पता लगा सकते हैं कि यह कैसे करना है। अपने विश्लेषक में आप ऐसा करते हैं

public override void Initialize(AnalysisContext context)
{
    context.RegisterSyntaxNodeAction(AnalyzerInvocation, SyntaxKind.InvocationExpression);
}

private static void AnalyzerInvocation(SyntaxNodeAnalysisContext context)
{
    var invocation = (InvocationExpressionSyntax)context.Node;

    var methodDeclaration = (context.SemanticModel.GetSymbolInfo(invocation, context.CancellationToken).Symbol as IMethodSymbol);

    //There are several reason why this may be null e.g invoking a delegate
    if (null == methodDeclaration)
    {
        return;
    }

    var methodAttributes = methodDeclaration.GetAttributes();
    var attributeData = methodAttributes.FirstOrDefault(attr => IsIDEMessageAttribute(context.SemanticModel, attr, typeof(IDEMessageAttribute)));
    if(null == attributeData)
    {
        return;
    }

    var message = GetMessage(attributeData); 
    var diagnostic = Diagnostic.Create(Rule, invocation.GetLocation(), methodDeclaration.Name, message);
    context.ReportDiagnostic(diagnostic);
}

static bool IsIDEMessageAttribute(SemanticModel semanticModel, AttributeData attribute, Type desiredAttributeType)
{
    var desiredTypeNamedSymbol = semanticModel.Compilation.GetTypeByMetadataName(desiredAttributeType.FullName);

    var result = attribute.AttributeClass.Equals(desiredTypeNamedSymbol);
    return result;
}

static string GetMessage(AttributeData attribute)
{
    if (attribute.ConstructorArguments.Length < 1)
    {
        return "This method is obsolete";
    }

    return (attribute.ConstructorArguments[0].Value as string);
}

इसके लिए कोई CodeFixProvider नहीं है आप इसे समाधान से निकाल सकते हैं।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.