Wenn über das Grundsätzliche keine Einigkeit besteht, ist es sinnlos, miteinander Pläne zu machen.
Konfuzius
Was ist eine EditorConfig?
EditorConfig hilft dabei konstante Quellcode Konventionen über mehrere Entwickler, IDEs und Projekte beizubehalten.
Das Projekt besteht aus einem Dateiformat zur Definition von Quellcode Konventionen und einer Sammlung von Texteditor-Plugins, die es verschiedenen Editoren und IDEs ermöglicht das Dateiformat zu lesen und die festgelegten Konventionen anzuwenden.
Plugin-frei ist Visual Studio.
Plugin-gebunden ist unter anderem Visual Studio Code.
Mehr Informationen über die EditorConfig findest du hier.
Weshalb nutzen wir eine EditorConfig?
Wir verwenden die EditorConfig, damit wir effizient arbeiten können und unser Fokus auf der Logik der Applikation liegt. Dieses Vorgehen bewahrt uns davor ständig unseren Quellcode auf Einheitlichkeit kontrollieren zu müssen. So sparen wir Zeit und fördern das gemeinsame Verständnis.
Das Item Template wird von uns als weitere Grundlage benutzt. Ziel dieses Projekt ist es, eine eigene EditorConfig Datei zu erstellen und diese in jedem kommenden Projekt zu verwenden. Dabei sparen wir Zeit bei der Analyse des Quellcodes ein und implementieren diesen einheitlich.
Vorgehen – Wie erstelle ich eine EditorConfig Datei?
Die EditorConfig Datei wird in einem NuGet-Paket verpackt. NuGet ist der empfehlenswerteste Ansatz für dieses Projekt, dank des einfachen Erstellens der Pakete, der Verfügbarkeit sowie der einfachen Installation. Ein anderer Ansatz für das Projekt wäre ein Visual Studio Template zu erstellen, dazu mehr in einem nächsten Blogbeitrag.
Der ganze Prozess vom Packen der nuspec-Datei bis zum Hochladen auf Nuget.org, wird von einer Azure Build Pipeline übernommen, welche wir implementiert haben.
Umsetzung
Anlegen des Projekts
Zuerst erstellen wir eine C# Klassenbibliothek und entfernen die Standarddateien. Anschliessend legen wir folgende Projektstruktur an:
In der .editorconfig Datei sind die Konventionen definiert.
Referenzen (Dependencies) werden hier nicht benötigt.
Inhalte template.json
Innerhalb des .template.config Verzeichnis liegt die Datei template.json, welche die Konventionen der .NET CLI Vorlagen beinhaltet. Diese ist für den Fall da, dass wir ein Visual Studio Item Template erstellen. Ausserdem die Datei dotnetcli.host.json, die als Erinnerung an die Parameter für den Visual Studio Dialog ist.
Hier ein Ausschnitt der template.json:
Konventionen definieren
Die Konventionen generieren wir mit der Extension ReSharper und definieren noch weitere Konventionen, wie zum Beispiel spezielle Tabs für YAML Dateien.
Unten ein kleiner Ausschnitt der .editorconfig Datei.
`root = true` gibt an, dass der Editor nicht nach weiteren .editorconfig Dateien suchen soll.
Danach kommen Standardkonventionen, die von allen IDEs und Editoren unterstützt werden.
Um alle Verstösse der Konventionen in der Error List von Visual Studio anzuzeigen, sind die letzten Einstellungen da. Sie definieren den Schweregrad mit welcher jede Kategorie von Konvention angezeigt werden soll.
NuGet-Paket erstellen
Um das Item Template auf NuGet als Paket bereitzustellen, muss eine nuspec-Datei mit folgendem Inhalt erstellt werden:
<?xml version="1.0" encoding="utf-8"?>
<package xmlns="http://schemas.microsoft.com/packaging/2012/06/nuspec.xsd">
<metadata>
<readme>docs/README.md</readme>
<icon>content\databinding-default-editorconfig\icon.png</icon>
<id>databinding.editorconfig</id>
<version>$version$</version>
<description>
Databinding EditorConfig Standard
Blogpost: coming soon...
</description>
<authors>Simon Müller</authors>
<license type="expression">MIT</license>
<packageTypes>
<packageType name="Template" />
</packageTypes>
</metadata>
<files>
<file src="Template_EditorConfig\Template_EditorConfig\templates\"
exclude="Template_EditorConfig\Template_EditorConfig\templates\**\bin\**;
Template_EditorConfig\Template_EditorConfig\templates\**\obj\**"
target="content"/>
<file src="..\README.md" target="docs/README.md"/>
</files>
</package>
Alternativ ist das auch in der .csproj Datei möglich. Wir haben uns für die nuspec-Datei entschieden, da es eine klare Trennung zeigt zwischen Projekt und NuGet Einstellungen.
Die definierten Dateien in <file> werden in das Content Verzeichnis im NuGet-Paket gepackt.
Speziell daran ist die Versionsnummer ($version$), welche von der Pipeline mit einem PowerShell-Skript automatisch hochgezählt und ersetzt wird.
Kontrollierung
Ein guter Weg, um ein NuGet-Paket zu kontrollieren, ist der nuget Package Explorer.
Das NuGet-Paket steht jetzt zum Herunterladen bereit.
Probleme mit der .editorconfig Datei
Beim Kontrollieren mit dem Package Explorer ist uns schnell aufgefallen, dass die .editorconfig Datei immer gefehlt hat und so die Installation fehlgeschlagen ist.
Nach unserer Recherche wurde klar, dass alle mit einem Punkt beginnenden Dateien automatisch ausgeschlossen werden. Auch mit explizitem Angeben in der nuspec-Datei. Mit dem Argument `-NoDefaultExcludes`, beim Packen der nuspec-Datei, konnten wir dies umgehen:
`nuget pack src/databinding.editorconfig.nuspec -NoDefaultExcludes -Properties version=$(Build.BuildNumber) -OutputDirectory $(Build.ArtifactStagingDirectory)`
Version zur Datei hinzufügen
Um zu Erkennen mit welcher .editorconfig Datei gearbeitet wird, haben wir mit einem PowerShell-Skript die Version am Anfang hinzugefügt:
...
scriptType: 'inlineScript'
inlineScript: |
$editorconfig = 'src/Template_EditorConfig/Template_EditorConfig/templates/databinding-default-editorconfig/Default/.editorconfig'
$content = Get-Content -Path $editorconfig -Raw
New-Item -ItemType "file" -Path $editorconfig -Force
Set-Content -Path $editorconfig -Value "###`n# Version: $(Build.BuildNumber)`n###`n"
Add-Content -Path $editorconfig -Value $content
PowerShell kann nur Inhalt am Ende einer Datei anfügen. In vier Schritten haben wir eine Lösung gefunden:
- Die Datei wird ausgelesen und der Inhalt gespeichert.
- Die Datei wird mit einer leeren Datei (gleicher Dateiname) ersetzt.
- Die neue Datei bekommt die Version.
- Der Inhalt der alten Datei wird angehängt.
README Bilder Sourcen
Die Bilder in der README.md Datei wurden auf NuGet.org nicht angezeigt.
Wie sich herausgestellt hat, braucht NuGet.org eine vertrauenswürdige Source der Bilder, um sie anzuzeigen. Dazu haben wir ein öffentliches GitHub Repository angelegt, welches alle Bilder beinhaltet. Die Source der Bilder muss direkt (raw.githubusercontent…) auf das Bild gelegt werden.
Nur ein Bild aus einer nicht vertrauenswürdigen Source führt dazu, dass die anderen auch nicht geladen werden.
Verwendung im Projekt
Installation über nuget
Über nuget.org oder direkt über die Kommandozentrale lässt sich das Paket installieren:
dotnet tool install --global databinding.editorconfig --version <Versions Nummer>
Um die Installation zu verifizieren, kann folgender Befehl ausgeführt werden:
dotnet new --list
Das Template wird jetzt in der Liste angezeigt:
Zur Deinstallation:
dotnet new -u databinding.editorconfig
Hinzufügen über Terminal
Um das Template einer Solution oder einem Projekt hinzuzufügen, muss das Projekt/Solution-Verzeichnis in der Kommandozentrale geöffnet werden. Beispiel:
Folgender Befehl erstellt die .editorconfig Datei in dem Projekt/Solution Verzeichnis:
dotnet new db-editorconfig
Danach mit dem Dialog «Add Existing Item» die Datei hinzufügen, sonst werden die Konventionen nicht übernommen.
Analyse laufen lassen
Mit einem Rechtsklick auf das Projekt/Solution oder Alt+F11 (Visual Studio), kann eine Analyse des bestehenden Quellcodes gemacht werden.
Verstösse gegen die Konventionen werden danach mit dem eingestellten Schweregrad in der Error List angezeigt.
Build Error auslösen
Konventionsverstösse können auf Wunsch einen Build Error auslösen. Hierfür muss die rot umrandete Zeile in der Projekt-Datei unter <PropertyGroup> hinzugefügt werden:
Widersprüche
Widersprüche zwischen den Code-Analysen treten öfters auf, je mehr Extension, Analyser usw. installiert sind.
Beispiel für einen Widerspruch war die Konvention für Csharp:
csharp_style_var_for_built_in_types = true
Und die Konvention von ReSharper:
resharper_for_built_in_types = use_var_when_evident
Die Lösung war die ReSharper Convention auf `use_var` zu stellen, damit der Wiederspruch gelöst wird.
Visual Studio Item Template
Die Überlegung
Geplant war, dass die .editorconfig Datei als Item Template über den Visual Studio Dialog „Add New Item“ hinzugefügt werden kann:
Ein Projekt Template, welches wir erstellt haben, wurde automatisch nach der Installation angezeigt. Wir nahmen an, dass dies bei dem Item Template genau gleich funktionieren würde.
Probleme
Das Item Template wurde nicht angezeigt nach der Installation über die Konsole.
Weitere Recherchen haben ergeben, dass das Item Template im Verzeichnis `%USERPROFILE%\Documents\Visual Studio 2022\Templates\ItemTemplates` gespeichert werden muss. Ausserdem in einem ZIP Ordner mit einer .vstemplate Datei:
Inhalt der .vstemplate Datei:
<VSTemplate Version="3.0.0" xmlns="http://schemas.microsoft.com/developer/vstemplate/2005" Type="Item">
<TemplateData>
<DefaultName>db-editorconfig.png</DefaultName>
<Name>db-editorconfig</Name>
<Description><No description available></Description>
<ProjectType>CSharp</ProjectType>
<SortOrder>10</SortOrder>
<Icon>__TemplateIcon.png</Icon>
<PreviewImage>__PreviewImage.png</PreviewImage>
</TemplateData>
<TemplateContent>
<References />
<ProjectItem SubType="" TargetFileName=".editorconfig" ReplaceParameters="false">.editorconfig</ProjectItem>
</TemplateContent>
</VSTemplate>
Weshalb wurde es nicht umgesetzt?
Es ist eine einfache Art das Template zu einem Projekt oder zu einer Solution hinzuzufügen. Jedoch ist es den Aufwand aus folgenden Gründen nicht wert:
- Zusätzliche Dateien müssen erstellt und ins NuGet-Paket gepackt werden.
- Der Benutzer muss aus dem NuGet-Paket die Dateien zusammensuchen und sie als ZIP Ordner im oben genannten Verzeichnis speichern.
- Es ist nur für Visual Studio.
- Das Item Template lässt sich nicht für alle Projekttypen auslegen. Das hat zur Folge, dass bei vielen Projekten das Template nicht angezeigt wird.
Fazit
Die EditorConfig lässt sich einfach zu einem Projekt oder einer Solution hinzufügen. Es hilft Entwickler, die gemeinsam an einem Projekt arbeiten, die Quellcode Konventionen einzuhalten.
Die grosse Mehrheit der Konventionen wird allerdings nur von Visual Studio in Zusammenhang mit der ReSharper Extension unterstützt. Es können andere Editoren und IDEs verwendet werden, welche aber nicht so viele Verstösse gegen die Konventionen anzeigen.
Wiederum kann der persönlich bevorzugte Editor zum Implementieren verwendet werden und zum Schluss die Analyse in Visual Studio durchgeführt werden.
Für die databinding GmbH stellen diese Konventionen einen grossen Mehrwert da, weil Visual Studio und ReSharper oft zum Einsatz kommen.
Mein persönliches Fazit zu EditorConfig
Für mich war dies ein gutes Startprojekt, um die Methoden und Tools, die bei der databinding GmbH eingesetzt werden, kennenzulernen. Bei der Umsetzung dieses Projekts sind mir oft Fehler unterlaufen, z.B. das Problem mit dem NoDefaultExclude beim Packen der nuspec-Datei. Durch Verwendung der Pipeline werden mir diese Fehler nicht mehr passieren, weil diese automatisiert sind.
Das EditorConfig Projekt findet sich auf GitHub.