# Swift’te enum dizmece

Swift’ciler olarak ozellikle MVVM, Rx, Reducers gibi mimariler yaygınlaştıkça enum kullanımını artırdık. Objective C’den gelen kavimler olarak pek alışkın olmasak da Swift’teki kullanım kolaylığı ve yetenekleri bize `enum`’i sevdirdi. Dürüst olmak gerekirse Objective C’deki kullanımı daha samimiydi. Çünkü enum, enumeration’in kısaltılışı ve türkçede *numaralandırma* demek. Objective C’den gelen dedeler olarak biliyoruz ki her `case`’in bir numarası vardir. Ancak Swift’teki liberallik sonucu görüyoruz ki bu yaklaşımın pek bir numarası yokmuş. İstersen bir case’i `String` olarak ifade edebiliyorsun. İstersen direk kendisi ile de ifade edebilirsin.

Biz impossible state’leri, `mesaj`, `action` ve `effect`leri `enum`larla ifade ediyoruz dolayılısyla codebase’de `enum`lar baya birinci sınıf vatandaş.

Bir de bunun küçük kardeşi var: `switch`. `guard let` case, `if let` hayrani değilseniz `switch` ile `case`’leri yürüyeceksiniz, çare yok.

```swift
enum State<T, E: Error> {
    case loaded(Result<T, E>)
    case loading
}
```

Adı `State`, generic `T` parametresi aliyor ve iki case’i var, biri associated value’su olmayan `loading` durumu, digeri ise Success tipi `T`, hata tipi `Error` protokolu olan loaded adında bir `case`. Hem associated values’lu hem de generic parametreli.

Durum her zaman böyle olmuyor. Uygulamanız karmaşıksa çok özellikli ekranlarda genellikle [şunun](https://github.com/kickstarter/ios-oss/blob/master/Library/RefTag.swift) gibi `enum`’larla çalışırsınız.

Bu gibi uzun listeleri alfabetik dizmek gayet yararli, nereye bakacaginizi biliyorsunuz, case’leri hizlica bulabiliyorsunuz, ayni zamanda bizim gibi kalabalik bir ekibiniz varsa ortak bir dilde buluşmuş oluyorsunuz. Her case eşittir ama aralarında kavga çıkmasın diye alfabetik sıralıyoruz.
Bir de bu case’lerin uzerinde yuruyecek olan switch case’lerini hayal edin. Oradaki sikinti daha da büyük cunku her case’in altinda ilgili kod blogu da duruyor. Isler karmasiklasinca case’leri el ile sort etmek zorlaşıyor. Zaten çoğu zaman da hata yapıyoruz, PR çıkmışsak approval’lari kaybediyoruz, CI’i bekliyoruz vs.

Bu tip isleri yapmak icin SwiftFormat aracı var ancak henuz `sortedCases` adinda bir rule yok (güzel fırsat!). Ben de oturdum, SwiftFormat olmadan bu isi nasıl yaparım diye biraz kafa yordum. Size bu yolculugumu anlatacağım.
Ilk once bir Automator tool’u yazdım. Tek bir ogesi var, `Run Shell Script`. Orada da `sort` komut satırı aracını kullandım. En iyi sonucu `sort — ignore-leading-blanks -f` komutu verdi (Ayrıntılar icin `$ man sort`). Ancak bu aracın yeteneği çok sınırlı, körlemesine sıralıyor, ve case let ve case ayrımını anlayamadığı icin tum `case let`’leri grupluyor. Ayrıca `switch` kod bloklarinda iyice saçmalıyor.
Ardından farkettim ki, iyi bir alfabetik case siralayici yazabilmem icin biraz daha alt seviyeye, compiler seviyesine inmem gerekecek. Swift derleyicisi bizim kaynak kodumuzu alip AST’ye ceviriyor, yani kodu anlamlandirmadan onceki ilk adim, `tree` veri yapısına çevriliyor kaynak kodumuz. Şansıma da Apple SwiftSyntax adındaki aracı ile tam da bunu yapiyor ve bu arac GitHub’da acik kaynak kodlu olarak paylasiliyor. Bu araci kullanarak yapilmis su sitede ise canlı sekilde olusturulan AST’yi inceleyebilirsiniz.

Hemen yeni bir Swift paketi oluşturdum ve dependency olarak SwiftSyntax’i ekledim. Ardindan `import SwiftSyntax` diyerek `SwiftRewriter` class’ini inherit eden bir class actim, gerekli tokenlari manipule edecek olan metodlari override ettim. Boylece artik tokenize edilmis kaynak kodlari uzerinde modifikasyon yapabilir hale geldim.
SwiftSyntax öğrenirken, *iyi bir parser nasıl yazılır* konusu hakkında da gayet iyi iç görüler edindim, tavsiye ederim.

Kodu ne yazık ki paylasamayacagim ancak bahsetmemde bir kusur yok. Genel olarak kullandığım mantık su, amacım `enum` ve `switch case`’lerini alfabetik sıralamak olduğu icin case isimlerine ulaşmam gerekiyor (identifier token’i). Bunun icin `EnumDeclSyntax`, `SwitchStmtSyntax` gibi 4 adet token’in visit metodlarini override ettim ve ilgili `tree`’leri traverse edip case’lerin identifier’larini sort edip sonucu tekrar `standart output`’a yazdirdim.

Boylece Xcode içerisinde sort ettirmek istediğim kod blogunu seçip sag tıklayıp `Services`’ten ilgili automator scriptini çağırmam yeterli oluyor. Basitçe bu script, seçtiğim metni standard input bekleyen komut satiri aracıma gönderiyor, program islemleri yapıp sonucu output buffer’ına yazıyor ve kodum IDE uzerinde update oluyor.

### Referanslar

[Kickstarter open source app](https://github.com/kickstarter/ios-oss)

[SwiftSyntax — NSHipster]([Link](https://nshipster.com/swiftsyntax/))

[https://medium.com/@lucianoalmeida1/an-overview-of-swiftsyntax-cf1ae6d53494](Link)
