Blue Orange Green Pink Purple

Posts Tagged ‘Continuous Integration’

You can use the search form below to go through the content and find a specific post or page:

Jun 11

HowTo: Eigene Regeln für Microsoft StyleCop erstellen

Im ersten Teil der Serie habe ich erklärt, wie man StyleCop grundsätzlich in Verbindung mit MSBuild und Visual Studio verwenden kann. Heute möchte ich kurz erklären, wie man eigene Regeln für StyleCop definiert und diese mit dem Setup vom ersten Teil verwenden kann. Da ich selber ein verfechter davon bin, private Member (Properties, Klassen, Methoden, etc.) mit einem _ (Unterstrich) als Präfix zu versehen, möchte ich heute eine StyleCop Regel implementieren, die genau diesen Standard überprüft.

Eigene Regeln implementieren!
Um eigene Regeln für StyleCop zu implementieren, müssen wir zuerst einmal StyleCop herunterladen bzw. installieren, weil wir dabei 2 wichtige Assemblies bekommen, die wir für die Entwicklung benötigen. Als nächstes erstellen wir uns in Visual Studio eine leere Klassenbibliothek und referenzieren die 2 Assemblies

  • Microsoft.StyleCop.dll
  • Microsoft.StyleCop.CSharp.dll

Haben wir das, erstellen wir uns eine neue Klasse und leiten diese von Microsoft.StyleCop.SourceAnalyzer ab. Das ist die Basisklasse für alle Regeln, die in StyleCop verfügbar sein sollen. Zusätzlich definieren wir über der Klasse noch ein Attribut, das angibt, für welche Sprache die Regel verwendet werden kann: [SourceAnalyzer(typeof(CsParser))].

Die Basisklasse implementiert eine Methode namens AnalyzeDocument(…), die wir in unserer eigenen Klasse nun überschreiben sollten, um auch wirklich auf den Quellcode der einzelnen Dateien, die später von unserer Regel evaluiert werden sollen, Zugriff zu haben:


public override void AnalyzeDocument(CodeDocument document)
{
   CsDocument csdocument = document as CsDocument;
   if (csdocument == null) return;

   csdocument.WalkDocument(new CodeWalkerElementVisitor<object>(this._VisitElement));
}

Die Methode hat einen Parameter vom Type CodeDocument. Dieses Dokument können wir anschließend auf ein CsDocument casten, da wir ja wissen, dass unsere Regel nur für CSharp Dokumente verwendet werden kann. Um jetzt das Dokument durchlaufen zu können, bietet das SDK hierfür verschiedene Klassen an, mit den denen unterschiedliche Typen evaluiert werden können. Wir verwenden hier die Klasse CodeWalkerElementVisitor, weil wir nur an Elementen (Klassen, Properites, usw.) interessiert sind. Diese Klassen verwenden das Visitor Design Pattern. Das heißt, dass der Visitor das Quelldokument durchparst und sobald er auf ein (in unserem Falle) Element trifft, die Methode _VisitElement aufruft:

private bool _VisitElement(CsElement element, CsElement parentElement, object context)
{
   if (element.Generated) return true;

   if (element.AccessModifier == AccessModifierType.Public ||
       element.AccessModifier == AccessModifierType.Internal) return true;

   if (element.ElementType == ElementType.Field ||
       element.ElementType == ElementType.Accessor ||
       element.ElementType == ElementType.Constructor ||
       element.ElementType == ElementType.ConstructorInitializer ||
       element.ElementType == ElementType.Destructor ||
       element.ElementType == ElementType.EmptyElement ||
       element.ElementType == ElementType.EnumItem ||
       element.ElementType == ElementType.ExternAliasDirective ||
       element.ElementType == ElementType.File ||
       element.ElementType == ElementType.Indexer ||
       element.ElementType == ElementType.Namespace ||
       element.ElementType == ElementType.Root ||
       element.ElementType == ElementType.UsingDirective) return true;

   if (element.Declaration.Name.Trim().StartsWith("_")) return true;

   this.AddViolation(element, element.LineNumber, "NonPublicMemberUnderscorePrefix");

   return true;
}

Die Methode überprüft, ob es sich bei dem Element um einen Typ handelt, der für uns auch von Interesse ist. Falls ja, muss der Name des Elements mit einem Unterstrich beginnen. Tut es das nicht, verwenden wir die Methode AddViolation der Basisklasse, um StyleCop mitzuteilen, dass wir auf eine Regelverletzung gestossen sind. Der 3. Parameter “NonPublicMemberUnderscorePrefix” ist wichtig: Um diese Regel nun tatsächlich verwenden zu können, müssen wir sie noch mit einigen Metainformationen ausstatten:

MetaInfos für StyleCop Regeln
StyleCop verwendet für jede Regel ein XML File, das die notwendigen Metainformationen für jede Regel beinhaltet. Wir müssen daher für unsere eigene Regel noch ein XML File erstellen, dass genau diese Metainformationen beinhaltet. Zuerst fügen wir zu unserem VS Projekt ein neues XML File hinzu und ändern in den Properties die Eigenschaft Build Action auf Embedded Resource. Anschließend können wir im XML File die Metainformationen befüllen:

<?xml version="1.0" encoding="utf-8" ?>

<SourceAnalyzer Name="My Rules">
 <Description>
  My custom StyleCop rules.
 </Description>
 <Rules>
  <RuleGroup Name="Naming Rules">
   <Rule Name="NonPublicMemberUnderscorePrefix" CheckId="MY1001">
    <Context>
     NonPublic members must start with an underscore
     followed by an upper-case letter.
    </Context>
    <Description>
     NonPublic members must start with an
     underscore followed by an upper-case letter.
    </Description>
   </Rule>
  </RuleGroup>
 </Rules>
</SourceAnalyzer>

Der Aufbau dieses XMLs ist relativ einfach. Zuerst definieren wir einen neuen SourceAnalyser und geben ihm einen Namen und eine Beschreibung. Dann definieren wir eine neue Gruppe für unsere Regel (RuleGroup, wir könnten auf diese Gruppe auch verzichten). Und jetzt kommt der wirklich interessante Teil. Wir definieren unsere eigene Regel und geben ihr einen Namen: NonPublicMemberUnderscorePrefix. Dieser Name muss exakt mit dem übereinstimmen, den wir vorher bei der Methode AddViolation(…) im Sourcecode als 3. Parameter angegeben haben. Sind diese Namen unterschiedlich, kann StyleCop die Metainformationen nicht eindeutig zuordnen. WICHTIG: Der Name der XML Datei muss exakt der gleiche wie der Name der Sourcecode Datei sein. Also heißt die *.cs Datei MyRules.cs muss die XML auch MyRules.xml heißen.

Um diese Regel jetzt auch tatsächlich in StyleCop verwenden zu können, kopieren wir sie in das Installationsverzeichnis von StyleCop. Starten wir jetzt den StyleCopSettingsEditor, sollten wir unsere neue Regel bereits in der Liste sehen können:

Integration mit MSBuild
Um solche eigenen Regeln auch mit dem Setup aus dem ersten Teil verwenden zu können, müssen wir am *.targets File von StyleCop etwas verändern. Bei diesem Setup haben wir alle Dateien (*.dll und *.targets), die für StyleCop notwendig sind, in einem relativen Verzeichnispfad abgelegt. In das selbe Verzeichnis kopieren wir nun unsere soeben erstellte StyleCop-Assembly. Im selben Verzeichnis sollte eigentlich eine Datei namens Microsoft.StyleCop.Targets liegen. Die öffnen wir uns suchen nach der Zeile AdditionalAddinPaths=”…”. Der Pfad, der dort eingetragen ist, gibt an, wo zusätzliche Assemblies gespeichert sind, in denen eigene StyleCop Regeln definiert sind. Nun, da wir gerade unsere Assembly in das selbe Verzeichnis kopiert haben, können wir mit den VS Macros direkt relativ auf dieses Verzeichnis verweisen:

<StyleCopTask
   ProjectFullPath="$(MSBuildProjectFile)"
   SourceFiles="@(StyleCopFiles)"
   AdditionalAddinPaths="$(ProjectDir)\Integration\"
   ForceFullAnalysis="$(StyleCopForceFullAnalysis)"
   DefineConstants="$(DefineConstants)"
   TreatErrorsAsWarnings="$(StyleCopTreatErrorsAsWarnings)"
   CacheResults="$(StyleCopCacheResults)"
   OverrideSettingsFile="$(StyleCopOverrideSettingsFile)"
   OutputFile="$(StyleCopOutputFile)"
   MaxViolationCount="$(StyleCopMaxViolationCount)" />

Das wars. Der Sourcecode (den ich etwas erweitert habe) kann wie immer unter http://downloads.juergenoberngruber.at/blog/CustomStyleCopRules.zip herunter geladen werden.

In diesem Sinne.

Jan 05

Auflösen von VSS Abhängigkeiten bei Continuous Integration mit Teamcity

Wer hat schon mal eine Visual Studio Solution erstellt und darin ein oder mehrere Projekte aus einer anderen VSS Location dazugehängt? Das Ganze ist ziemlich praktisch, weil man so erreichen kann, gewisse Funktionalität auszulagern und in einer eigenen Bibiliothek zusammen zu fassen (ich denk da an firmeninterne Bibiliotheken) – die man zentral im VSS ablegen kann und später bei jedem neuen Projekt einfach aus VSS heraus laden und verwenden kann.

Wo gibts jetzt ein Problem?

Problematisch wirds, sobald man das Projekt als CI laufen hat und dort unter anderem einen Build (Release || Debug) des Projektes erzeugen will.

Warum: Der Build Runner (Nant) ist nicht in der Lage, die logischen Abhängigkeiten, die im *.sln File angegeben sind, richtig aufzulösen. MSBuild geht beim Kompilieren davon aus, das auf einer gewissen Filelocation eigentlich eine VS Projekt Datei liegt, die das Tool aber dann nicht findet — klar, weil es nicht aus dem VSS geladen wurde (Visual Studio würde solche Abhängigkeiten erkennen und den Benutzer darüber informieren, dass er die Abhängigkeiten nachladen muss). Somit schlägt der Kompilier-Versuch fehl und der Build Runner beendet den Build mit irgendeinem Fehler.

Nicht gut, was tun?
Um diese Abhängigkeiten trotzdem aufzulösen gibts im Contrib-Projekt (http://nantcontrib.sourceforge.net/) für NAnt einen paar gute Tasks, die sich mit VSS beschäftigen:

  • vssadd
  • vsscheckin
  • vsscheckout
  • vssdelete
  • vssget
  • vsshistory
  • vsslabel
  • vssundocheckout

Für unser Problem verwenden wir “vssget”, da wir mit dem Task im die aktuelle Version einer Datei oder eines ganzen VS Projekts laden können. Konfiguration ist ziemlich einfach:

</p>
<property name="vss.user" value="tiger"/>
<property name="vss.password" value="woods"/>
<property name="vss.dbpath" value="\\servername\srcsafe.ini"/>

<vssget username="${vss.user}" password="${vss.user}" dbpath="${vss.dbpath}"
        recursive="true" replace="true" writable="false"
        localpath="Relative_LocalPath_On_BuildServer"
        path="$/Path_In_Source/" /><br />

Was erreichen wir damit: Wir laden ein Projekt aus dem VSS und legen es lokal auf dem Build Server ab, damit beim Kompilieren über den MSBuild Task (http://nantcontrib.sourceforge.net/release/latest/help/tasks/msbuild.html) alle Abhängigkeiten, die ja in der VS Solution bestehen, gefunden und aufgelöst werden können.

Ziemlich einfach — nur sollte man es wissen.
In diesem Sinne.

  • Recent Posts
    • HowTo: Eigene Regeln für Microsoft StyleCop erstellen
    • HowTo: Microsoft StyleCop Integration mit Visual Studio und MSBuild
    • HowTo: Eigene Templates für Visual Studio 2008 erstellen, Teil 2
    • HowTo: Eigene Templates für Visual Studio 2008 erstellen, Teil 1
    • Performance des Cassini Webservers in Kombination mit Firefox
  • Archives
    • June 2010 (2)
    • May 2010 (3)
    • March 2010 (3)
    • February 2010 (4)
    • January 2010 (3)
    • December 2009 (1)
    • November 2009 (9)
  • Tags
    .net AOP ASP.NET ASP.NET MVC blend Bootmanager C# ci Codequality Configuration Continuous Integration css Cursor DateTime DDD Deployment dynamisch emit Exrpession Extensibility Fluent HowTo Microsoft MVVM Pattern PostSharp Reflection Repository ruby silverlight Software Design StyleCop System teamcity Templates VHD Virtual Images Visual Studio Vorlagen web Windows 7 Windows Mobile WinForms WPF XAML
  • About

    Jürgen Oberngruber is a project manager and software architect living in Wels, Austria and currently working at ecomplexx Austria, Wels. During his study at the University of Applied Sciences in Hagenberg, Austria he gained a deep knowledge in the field of software engineering using a lot of different programming languages. Since a few years he's focusing on the Microsofts .NET platform including all relevant technologies. One of his passion is to explore, to test and to evaluate new technologies and programming languages (mostly in the field of Microsofts .NET platform). Checkout more information on www.juergenoberngruber.at

  • Meta
    • Log in
    • Entries RSS
    • Comments RSS
    • WordPress.org
  • Archives
    • June 2010
    • May 2010
    • March 2010
    • February 2010
    • January 2010
    • December 2009
    • November 2009
  • Search






  • Home

© Copyright Jürgen Oberngruber's Blog. All rights reserved.
Designed by FTL WordPress Themes brought to you by DT Web Template

Back to Top