Formatowanie kodu dotnetowego

Przyjemnie się pracuje z kodem gdy jest on czytelny. Między innymi oznacza to spójność formatowania. Istnieje wiele szkół i gorących debat na temat tego jak organizować pliki z kodem. Czy używamy spacji, czy tabulacji do robienia wcięć? Czy otwieramy klamry na końcu tej samej linii, czy w nowej?

Do jakiegokolwiek wniosku nie dojdziemy, ważne jest aby w danym projekcie kod był spójny. W tym celu powstają narzędzia do formatowania kodu.

Okazuje się jednak, że pracując z technologią .NET, bardzo mało ludzi nie korzysta z Visual Studio. VS oferuje funkcję formatowania kodu i pracując w nim często jej używam. Jednak od pewnego czasu pracuję pod Linuxem i zacząłem szukać innego rozwiązania.

CodeFormatter

Po chwili szukania natrafiłem na utworzony w 2014 projekt zespołu rozwijającego .NET o nazwie CodeFormatter. Możecie go znaleźć na Githubie.

Ten program będzie formatował kod dotnetowy zgodnie z regułami jakie stosuje się do dotnet/corefx, czyli BCLu w .NET Core. Dodatkowo, edytując kod źródłowy można dopisać swoje własne reguły, bądź zmodyfikować istniejące.

Pobieranie

Ostatni release został wypuszczony w styczniu 2016, podczas gdy ostatni commit, pozwalający by uruchomić to narzędzie pod Mono (a więc na Linuxie), wyszedł w listopadzie 2016.

Więc trzeba pobrać kod żródłowy i samemu zbudować najnowszą wersję.

Mój skrypt instalujący

Stwierdziłem, że można nieco zautomatyzować proces pobrania, budowania i instalacji tego jakże przydatnego narzędzia, więc napisałem skrypt, który automatycznie sklonuje repozytorium z githuba, pobierze paczki NuGet, zbuduje projekt, przekopiuje niezbędne pliki do folderu /opt/code-formatter i utworzy plik wykonywalny w miejscu należącym do PATH, aby można było korzystać z tego narzędzia w dowolnym miejscu.

Mój skrypt możecie znaleźć tu: manio143/CodeFormatter-Installer. Jeśli z niego skorzystacie i będziecie zadowoleni, prosiłbym o gwiazdkę, wtedy pojawi się wyżej w wynikach wyszukiwania na GitHubie.

Używanie

No więc mamy zainstalowane to narzędzie (jeśli nie, to po prostu zastąp code-formatter mono path/to/CodeFormatter.exe), czas na sformatowanie jakiegoś kodu.

Pierwsza uwaga jest taka, że to narzędzie wymaga do działania projektu, solucji lub pliku rsp (response file). Więc jeśli mamy pojedyńczy plik .cs to go tym nie sformatujemy. Ale wtedy wystarczy otworzyć go w VS lub VS Code i tam go sformatować.

Więc żeby sformatować nasz projekt wystarczy odpalić

code-formatter MyProject.csproj

Teraz przejdziemy przez kilka opcji:

  • /nocopyright - nie auktualizuj informacji copyright
  • /copyright:copyfile - dodaj zawartość z pliku copyfile jako komentarz na górze każdego pliku z kodem
  • /lang:<lang> - wskazanie języka (‘C#’ lub ‘Visual Basic’)
  • /nounicode - nie konwertuj stringów ze znakami unicode do ecape sequences
  • /rule+:<rule> i /rule-:<rule> - dodaj usuń regułę (jakie reguły są dostępne dowiesz się uruchamiając program z flagą /rules)

Więc w moim przypadku użyłem opcji /nounicode i /rule-:FieldNames, żeby moje prywatne pola nie zaczynały się od _.

Formatowanie przed commitem

Fajnym pomysłem jest podpiąć się pod “haczyk” w repozytorium git, tak aby przed każdym commitem uruchamiane było reformatowanie kodu.

Istnieje wiele git hooków zarówno dla operacji klienta jak i serwera, a poczytać o tym można tu: Git Hooks.

Najprościej jest umieścić plik pre-commit w folderze .git/hooks/ z prawami uruchamiania (chmod +x) o takiej zawartości

#!/bin/bash
code-formatter <our options> MyProject.csproj
# apparently solution file does not work

Niestety, testując to rozwiązanie znalzłem poważny problem. Otóż formatowanie zachodzi niezależnie od tego co mamy w stage’u, więc musielibyśmy po sformatowaniu ponownie dodać zmodyfikowane pliki.

Inną opcją jest podpiąć się jakoś pod MSBuild i formatować nasz kod przed zbudowaniem oraz nigdy nie commitować nie budującego się kodu.