Force a switch block to implement all cases (using FxCop)

19 בדצמבר 2008

8 תגובות


זה מבאס אבל ממש מבאס, ולמי שזה לא קרה עדיין שיצביע, אני מדבר כמובן על המצב שבו אתם יושבים וכותבים במשך שעה ארוכה פוסט מושקע עם דוגמאות, ואז כשהכול מוכן ל Publish, בלחיצת כפתור הכל נמחק.


אבל כמובן שנהיה חזקים ונשקיע עוד שעה מהחיים עבור הקהילה, ונכתוב את הכל מחדש.


אז אחרי שהתבכיינתי, נגש לעניין.


 


באחד הפוסטים הראשונים כתבתי על דרך להכריח את המתכנתים כשעושים switch על enum, לעשות case על כל האפשריות, ו Arielr כתב בתגובה "לא יהיה יותר קל לכתוב חוק של FXCOP ולסגור עניין?" אז חשבתי לעצמי, קדימה בוא נממש את זה, אז נכנסתי לעולם של FxCop, וממשתי את זה.


אז לפני שנראה מה זה בכלל FxCop ואיך מממשים את מה שאנחנו מדברים עליו, נראה קודם איך יראה הקוד שלנו.


נסתכל על הקוד הבא:


 




    1 [ForceSwitch]


    2 public enum MyEnum


    3 {


    4     A, B, C, D, E


    5 }


    6 


    7 public class Class1


    8 {


    9     public Class1(MyEnum myEnum)


   10     {


   11         switch (myEnum)


   12         {


   13             case MyEnum.C:


   14                 Console.WriteLine("");


   15                 break;


   16             case MyEnum.B:


   17                 Console.WriteLine("");


   18                 break;


   19             default:


   20                 Console.WriteLine("");


   21                 break;


   22         }


   23     }


   24 }


 

אנחנו רואים enum שיש עליו attribute בשם ForceSwitch ויש class שב ctor שלו אנחנו עושים switch על ה enum,

כשנקמפל, נקבל את השגיאה הבאה:

 

Switch

 

הקוד שלנו יעבור קומפילציה, רק אם נממש case עבור כל אחד מהאפשרויות.

 

 

לפני שנראה את המימוש הספציפי, נעשה מעבר קטן על FxCop,

למעשה זה נותן לנו את היכולת לשלוט על איך יראה הקוד שלנו, החל משליטה על סגנון שמות של מאפיינים (שכולם יתחילו באות גדולה) עד להגדרות של Code Security, למעשה יחד עם Visual Studio מגיע סט מכובד של חוקים שיכולים לעזור לנו לכתוב יותר נכון.

לחיצה ימנית על הפרויקט, לחיצה על מאפיינים, ובחירה בטאב של Code Analysis יביא אותנו למסך הבא:

 

Code Analysis

 

כמו שאחנו רואים בתמונה יש לנו מבחר של חוקים שאנחנו יכולים לבחור בהם, כדי להכריח את המפתחים לכתוב נכון, ואנחנו יכולים להוסיף חוקים משלנו, כמו זה שאחנו רואים בתמונה שמסומן (הקידומת של SG, ראשי תיבות של שמי)

 

אפשר כמובן להגדיר האם זה שגיאה או אזהרה, על ידי סימון האפשרות מצד ימין של כל חוק, ואפשר להגדיר האם זה ירוץ אוטומטי בכל קומפילציה, על ידי סימון האפשרות Enable Code Analysus on Build, במדה וזה לא יהיה מוגדר, כשנרצה להריץ את הבדיקות, לחיצה ימנית על הפרויקט, ואז Run Code Analysis.

 

כעת נראה כיצד אנחנו יכולים להוסיף חוקים בעצמנו.

אז בשלב ראשון אנחנו נירש מ class שנקרא BaseIntrospectionRule ונצטרך להוסיף reference לשני ה dll הבאים:



  • C:\Program Files\Microsoft Visual Studio 9.0\Team Tools\Static Analysis Tools\FxCop\FxCopSdk.dll


  • C:\Program Files\Microsoft Visual Studio 9.0\Team Tools\Static Analysis Tools\FxCop\Microsoft.Cci.dll

כעת נראה את הקוד:

 



    1 internal class ForceSwitch : BaseIntrospectionRule


    2 {


    3     public ForceSwitch()


    4         : base("ForceSwitch",


    5                 "SGFxCopRules.SGFxCopRules.xml",


    6                 typeof(ForceSwitch).Assembly)


    7     { }


    8 


    9     public override ProblemCollection Check(Member member)


   10     {


   11         Method method = member as Method;


   12         if (method != null)


   13         {


   14             VisitMethod(method);


   15         }


   16 


   17         if (Problems.Count == 0)


   18         {


   19             return base.Check(member);


   20         }


   21 


   22         return Problems;


   23     }


   24 


   25     public override void VisitSwitchInstruction(SwitchInstruction switchInstruction)


   26     {


   27         TypeNode enumType = switchInstruction.Expression.Type;


   28         foreach (var item in enumType.Attributes)


   29         {


   30             if (item.Type.Name.Name == "ForceSwitchAttribute")


   31             {


   32                 if (switchInstruction.Targets.Count != enumType.Members.Count – 1)


   33                 {


   34                     Resolution resolution =


   35                         GetResolution(new string[]


   36             {


   37                 enumType.Name.Name


   38             });


   39 


   40                     Problems.Add(


   41                         new Problem(resolution,


   42                                     switchInstruction.SourceContext));


   43                 }


   44             }


   45         }


   46     }


   47 }


 

 

 

הקוד הוא מאוד פשוט:

הוא מורכב מ:

Ctor: שקורא לאבא שלו, ושולח לו את הפרמטרים הבאים: השם שלו, היכן ממוקם ה xml (נראה אותו בהמשך) שמגדיר את החוק, וחייב להיות מוגדר כ Embedded Resource.

override Check : אנחנו נבדוק האם אותו member הוא מתודה, במידה וכן נפעיל את Visit, שבמדה והוא ימצא בלוק של switch, הוא יפעיל אוטומטית את ה –

VisitSwitchInstruction : שבודק האם יש על ה enum הזה attribute בשם ForceSwitch, במדה וכן הוא יבדוק האם לא מימשו את כל ה cases האפשריים, ובמדה וכן, הוא יוסיף Problem למאגר,

ה – Problem מורכב מ Resolution שיש לו מחרוזת שתכנס בהודעת השגיאה כמו שמוגדר ב xml (שכבר נראה אותו) ומ – SourceContext שיודע איפה בדיוק (שורה, וכדומה) התרחשה השגיאה.

 

ה xml נראה כך:

 



    1 <Rules FriendlyName="SGFxCopRules">


    2   <Rule TypeName="ForceSwitch" Category="SGRules" CheckId="SGR1000">


    3     <Name>ForceSwitch</Name>


    4     <Description>You must implement all cases in the enum</Description>


    5     <LongDescription></LongDescription>


    6     <Owner/>


    7     <Url>/ForceSwitch</Url>


    8     <Resolution>Not all enum '{0}' cases were implented</Resolution>


    9     <Email/>


   10     <MessageLevel Certainty="99">Error</MessageLevel>


   11     <FixCategories>NonBreaking</FixCategories>


   12   </Rule>


   13 </Rules>


 

בשורה 1 מגדירים מה יהיה כתוב בחלון של Code Analysis על הקטוגריה שלנו.

אחרי זה אנחנו מגדירים סט של מאפיינים עבור ה rule, ובשורה מספר 8 אנחנו מגדירים את הודעת השגיאה, וכמובן ה 0 יוחלף עם הפרמטרים שאנחנו שולחים מהקוד.

 

וכמובן כך נראה ה attribute

 



    1     public class ForceSwitchAttribute : Attribute


    2     {


    3 


    4     }


 

כמובן שהוא לא צריך לעשות כלום, הוא בסך הכל צריך לסמן את ה enum, אפשר לקרוא לזה MarkedAttribute.

 

 את הקוד המקומפל צריך לזרוק ל

:C:\Program Files\Microsoft Visual Studio 9.0\Team Tools\Static Analysis Tools\FxCop\Rules

 

 

אני מצרף את הקוד יחד עם קוד לבדיקה, להורדה מכאן.

 

והנה מספר לינקים:

 


 


 


 

ומצגת נחמדה שמסבירהה בצורה פשוטה על FxCop (אני התחלתי בזה)

 

תהנו

 

בפוסט הבא, אני אספר לכם, איך אפשר לדבג את הקוד של ה Code Analisys.

 


 

הוסף תגובה
facebook linkedin twitter email

להגיב על Moshe לבטל

האימייל לא יוצג באתר. שדות החובה מסומנים *

8 תגובות

  1. Baruch Frei19 בדצמבר 2008 ב 14:32

    כל הכבוד על ההשקעה. באמת התפלאתי למה לקח כ"כ הרבה זמן…
    אבל היה שוה לחכות.

    הגב
  2. Rotem Bloom19 בדצמבר 2008 ב 20:09

    לגבי העניין שכתבת בהתחלה שה-PUBLISH נמחק לך. פשוט תשתמש ב-LIVE WRITER במקום להשתמש ב-IE שאתה כותב פוסט.
    http://get.live.com/writer/overview
    הרבה יותר נוח יעיל ואפשר לשמור הכל על המחשב שלך.

    הגב
  3. Maor David-Pur19 בדצמבר 2008 ב 20:16

    שלמה, פוסט מעולה!!!
    זה אמור להיות אחד הפוסטים הבאים שלי כי הבטחתי לקהל אצלי בהרצאה ב DEV ACADEMY שאפרסם כזה פוסט.
    כל הכבוד על ההשקעה והשיתוף.

    מאור

    הגב
  4. Avi Pinto19 בדצמבר 2008 ב 22:52

    שימושי ביותר, תודה

    הגב
  5. Shlomo20 בדצמבר 2008 ב 20:46

    רותם, תודה על ה Live Writer, זה מאוד עוזר

    הגב
  6. Moshe21 בדצמבר 2008 ב 11:16

    באיזו גרסה אתה משתמש (VS?)
    משום מה אצלי גם לאחר התקנת FxCop אין לשונית "Code Analisis"

    הגב
  7. Shlomo21 בדצמבר 2008 ב 11:44

    זה קיים כבר ב Visual Studio 2005
    זה יותר משנה, איזה סוג פרויקט יש לך, אם יש לך פרויקט מסוע Web Site, אז אין באמת טאב של Code Analysis
    רק אם תבחר ב
    Propery Page->Build->Enable Code Analysis

    הגב