İlkay İlknur

just a developer...

C# 7.0 - Digit Separators

Bu makaleye Github üzerinden katkıda bulunabilirsiniz.

Not : Bu makaledeki örnekleri denemek için gereken ortam kurulum bilgisini buradan alabilirsiniz.

C# 7.0 ile beraber gelmesi planlanan ufak özelliklerden biri de digit separatorler. Digit separatorler ile numeric değer tanımlamaları sırasında istediğiniz bölümde basamakları ayırabiliyorsunuz. Böylece kod yazarken tanımlamış olduğunuz numeric değişkenlerin taşıdıkları değerler daha okunabilir olurken hem de siz tanımlama esnasında basamakları ayırabildiğiniz için hata yapma olasılığınız daha düşük oluyor. Digit separator olarak ise _ kullanıyoruz.

Örneğin,

int x = 1_000_000;
double y = 1_00.0_9;

Digit separatorlerin bir diğer kullanım alanı da binary literal'lar. Binary literal tanımlamaları esnasında da digit separatorleri kullanmamız mümkün.

Örneğin,

int x = 0b11_00_0_01;
double y = 0b1_00;

Bu ufak özellikle ilgili yazımızda bu kadar. Bir sonraki C# 7.0 özelliğinde görüşmek üzere...



C# 7.0 - Binary Literals

Bu makaleye Github üzerinden katkıda bulunabilirsiniz.

Not : Bu makaledeki örnekleri denemek için gereken ortam kurulum bilgisini buradan alabilirsiniz.

C# 7.0 ile beraber gelmesi muhtemel özelliklerden biride Binary Literals özelliği. Aslında C# design meetinglerini takip edenler için bu özellik süpriz bir özellik değil. Çünkü aslında aynı özellik C# 6.0'da da planlanıyordu ancak release döneminde bu özellik ne yazık ki C# 6.0'a dahil edilmedi.

İşin magazin tarafını bir kenara bırakırsak :) binary literals ile kod içerisinde binary olarak tanımlamalar yapabiliyorsunuz. Bunu yapmak için binary ifadenin başına 0b veya 0B yazmanız yeterli.

Örneğin,

static void Main(string[] args)
{
    int x = 0b1100001;
    double y = 0b100;
}

Gördüğünüz gibi kullanımı oldukça basit. Gelelim bu özellik nerelerde işimize yarayacak kısmına. Enumlara Flags attribute'ünü ekleyip 2'nin üssü bir biçimde değerler verdiğimizde enumlar üzerinde bitwise operasyonlar yapabiliyoruz. (Enumlar üzerinde bitwise operasyonlar ile ilgili yazmış olduğum yazıyı inceleyebilirsiniz. http://www.ilkayilknur.com/coklu-enum-degerleriyle-calismak) Burada 2'nin üssü değerleri verirken binary literalleri kullanabiliriz. Böylece hızlı bir şekilde ve daha az hata olasılığıyla hızlı bir şekilde kodumuzu yazabiliriz.

[Flags]
enum Colors
{
    Red = 0b1,
    Green = 0b10,
    Blue = 0b100
}

Gördüğünüz gibi binary literallerin bana göre en önemli kullanım alanı burası olacak. Bunun yanında C# ekibi binary ifadeleri öğrenen developerların da C# içerisinde eğitim amaçlı binary literalleri kullanacaklarını düşünüyorlar.

C# 7.0 binary literals özelliğiyle ilgili yazımız bu kadar. Zaten gördüğünüz gibi oldukça ufak bir özellik :) Bir sonraki yazıda görüşmek üzere...



C# 7.0 - Local Functions

Bu makaleye Github üzerinden katkıda bulunabilirsiniz.

Not : Bu makaledeki örnekleri denemek için gereken ortam kurulum bilgisini buradan alabilirsiniz.

C# 7.0 ile beraber gelmesi muhtemel en basit özelliklerden biride local functions özelliği. Hemen örnek yapmadan önce ilk olarak bu özelliğe ne gerek vardı sorusunun cevabını vermeye çalışalım.

Kod yazarken metotların çok fazla uzadığı ve bakımının zorlaştığı senaryolarda metot içerisindeki fonksiyonel bölümleri ayrı bir metot yaparız ve ilgili metot içerisinden de dışarıya aldığımız diğer metodu çağırırız. Bu ufak helper metotlarımız aslında baktığımızda sadece tek bir metot tarafından kullanılırlar ancak tanımlandıkları class'ın bir üyesi olurlar. Dolayısıyla bu helper metotları private olarak tanımlasak bile herhangi bir developer class içerisindeki başka bir metot içerisinden de istemememize rağmen bu metodu çağırabilir.

class Foo
{
    void Bar()
    {
        List<int> list = new List<int>();
        //Do something
        HelperMethod();
    }

    private void HelperMethod()
    {

    }
}

Örneğin yukarıdaki kodda HelperMethod isimli metot aynı class içerisindeki başka bir metottan da çağırılabilir.

class Foo
{
    void Bar()
    {
        List<int> list = new List<int>();
        //Do something
        HelperMethod();
    }

    private void HelperMethod()
    {

    }

    void Bar2()
    {
        HelperMethod();
    }
}

Bu aslında istenmeyen birşey olsa da bunun önüne geçmek pek mümkün değil. Tek kaçış yolu lambda ifadesi kullanarak Func veya Action tipinde bu helper metotları tanımlamak.

class Foo
{
    void Bar()
    {
        List<int> list = new List<int>();
        Action helper = () => { };
        //Do something
        helper();
    }
}

Bu durumda helper kısmı lambda ifadasi ile tanımladığımız için bu lambda ifadesi sadece Bar metodu içerisinden çağırılabilir ve erişilebilir. Böylece aslında en baştan amaçladığımız şeyi gerçekleştirmiş oluruz. Ancak Action ve Func olarak tanımlamanın bazı kısıtlamaları ile performans ve memory bakımından da bazı dezavantajları var.

Sahip oldukları kısıtlamalardan bazıları

  • Lambda ifadeleri generic olarak tanımlanamaz.
  • Lambda ifadeleri içerisinde ref, params ve out olarak parametre tanımlayamayız.
  • Lambda ifadelerini recursive olarak çağırmak için ufak bir trick yapmak gerekiyor. Tanımlama esnasında kendisini çağıramaz.

Tüm bu sıkıntılardan ötürü C# 7.0'da local functions özelliğinin getirilmesi planlanıyor. Şimdi gelelim local functions özelliğinin kullanımına.

class Foo
{
    void Bar()
    {
        List<int> list = new List<int>();
        void HelperMethod()
        {

        }

        HelperMethod();
    }
}

Yukarıda da gördüğünüz gibi metot içerisinde yeni bir metot tanımlamaktan başka birşey yapmıyoruz aslında. Dolayısıyla out, ref ve params parametrelerini de kullanabiliyoruz. Ayrıca bu metotların çağırımında da herhangi bir ekstra performans kaybı veya ekstra memory kullanımı da olmuyor. Local functionlar sadece tanımlı bulundukları metot içerisinden erişilebilir durumdalar. Yani başka bir metot içerisinden local function'ın çağırılması gibi bir durum söz konusu da değil. Yukarıdaki kodda da gördüğünüz gibi bir local functionı çağırmadan önce yukarıda o local function'ı tanımlamış olmak gerekiyor. Ayrıca local functionda, içerisinde bulunduğu metot içerisindeki her elemana da ulaşabilirsiniz.

class Foo
{
    void Bar()
    {
        List<int> list = new List<int>();
        void HelperMethod()
        {
            foreach (var item in list)
            {

            }
        }

        HelperMethod();
    }
}

C# 6.0 ve C# 7.0 Birarada

Yazıyı sonlandırmadan önce C# 6.0'da gelen expression-bodied function members özelliğini kullanarak local functions tanımlamadan bahsetmek istiyorum. Böylece tek satırlık bir local functionınız olduğunda hızlı bir şekilde bu özelliği kullanarak local functions tanımlayabilirsiniz.

class Foo
{
    void Bar()
    {
        List<int> list = new List<int>();
        void HelperMethod() => Console.WriteLine("Hello");

        HelperMethod();
    }
}

Evet, local functionsla ilgili bu yazıda bahsedeceklerimiz bu kadar. Gördüğünüz gibi ufak ama faydalı bir özellik gibi duruyor. Tabi C# developerların bu özelliği ne kadar benimseyeceklerini de merak etmiyor değilim.

Bir sonraki yazıda görüşmek üzere...



C# 7.0 Özelliklerini Nasıl Test Ederiz ?

Bu makaleye Github üzerinden katkıda bulunabilirsiniz.

Bir önceki blog yazısında C# 7.0 yeniliklerinden bahsettiğim videomu paylaşmıştım. Diyelim ki videoyu izlediniz veya başka yerlerden okuyup heyecanlandınız ve C# 7.0 özelliklerini test etmek istiyorsunuz :) Bu özellikleri test edebilmeniz için önünüzde 2 yol var. Biri kısmen kolay olan yol diğeri ise oldukça zorlu :) Önce kolay olandan başlayalım.

Visual Studio 15 Preview Üzerinde Test Etmek

Şu anda C# 7.0 özelliklerini test etmenin en kolay yolu Visual Studio 15 Preview kullanmak. Visual Studio 15 Preview sürümü adı üzerinde henüz preview olduğu için production makinanıza kurmanızı kesinlikle tavsiye etmiyorum. Bu yüzden bilgisayarınızda bir sanal makina yaratıp orada Visual Studio 15'i kurup testlerinizi yapabilirsiniz. Bir diğer alternatif ise Azure üzerinde Visual Studio 15 Preview imajlı bir VM yaratmak.

Visual Studio 15 Preview Installer Linki : http://aka.ms/vsnext

Visual Studio 15 Preview'ı kurdunuz ve hemen bir proje yaratıp özellikleri test etmek istiyorsunuz. Bir örnek yaptınız ama o da ne projeniz derlenmiyor ve hata veriyor.

Bu hatayı almamızın sebebi C# 7.0 özelliklerinin her birinin feature flagleri arkasına alınması. Yani ekip hızlı bir şekilde istediği özellikleri açıp kapatabiliyor gerekli olduğunda. Bu hatayı aşmanın yolu ise oldukça basit. Test yaptığımız projeye conditional compilation symbols olarak __DEMO__ ve __DEMO_EXPERIMENTAL__ 'ı eklemek.

Bu işlemi de yaptıktan sonra kodunuz başarılı olarak derlenecektir. Ancak her Visual Studio 15 Preview versiyonunda, duyurulan C# 7.0 özellikleri olmayabilir. Örneğin bu yazının yazıldığı dönemde bulunan Visual Studio 15 Preview içerisinde Tuple özellikleri henüz bulunmuyor.

Roslyn Source Code'unu Çalıştırıp Test Etmek

Gelelim diğer opsiyona. Github üzerinden Roslyn projesinin kodlarını indirip projeyi derleyip aynı şekilde özellikleri test edebilirsiniz. Daha önce bunu denemiş biri olarak uyarmam gerekir ki bu iş göründüğü kadar kolay değil. Kısaca yol göstermem gerekirse

Şimdiden bu opsiyonla uğraşacaklara kolaylıklar diliyorum :) Daha öncede bahsettiğim gibi en kolay opsiyon Visual Studio 15 Preview üzerinden testleri yapmak.

Bir sonraki yazıda görüşmek üzere.



C# 7.0'da Bizi Neler Bekliyor ?

Bu makaleye Github üzerinden katkıda bulunabilirsiniz.

C# 7.0'da Bizi Neler Bekliyor ?

C# 7.0 ile ilgili planlamalar daha C# 6.0 release olmadan önce başlasada bazı şeyler tam oturmadan herhangi bir paylaşımda bulunmak istememiştim. Artık Build konferansıyla beraber yavaş yavaş ana temaların belirginleşmesinden sonra C# 7.0 yazılarına başlamadan önce durumu özetleyen ve özelliklere kısaca değindiğim bir video çektim. Eğer C# 7.0 ile beraber neler gelecek diye merak ediyorsanız aşağıdaki videoyu izleyip bilgi sahibi olabilirsiniz.



Video Linki : https://www.youtube.com/watch?v=JPPWPtwXMFA



Visual Studio 2015 Update 2 İle Gelen Yenilikler

Bu makaleye Github üzerinden katkıda bulunabilirsiniz.

Build 2016'nın en önemli duyurularından biri de Visual Studio 2015 Update 2'nin release olmasıydı. Update 2 içerisinden bolca bug fix barındırsada bahsetmeye değer bazı yeni özellikler de barındırmakta.

Universal Platform Yenilikleri

Update 2 ile beraber Universal App'lerde kullandığımız Microsoft.NETCore.UniversalWindowsPlatform nuget paketininde 5.1.0 versiyonu release oldu. Visual Studio 2015 Update 2'yi yüklediğinizde bu nuget paketini update etmenizde fayda var.

Update 2 ile beraber gelen bir diğer özellik ise Universal App yaratma aşamasında karşımıza çıkan version seçim ekranı. Bu ekran ile uygulamanızın target edeceği ve minimum olarak destekleyeceği Windows 10 versiyonunu uygulama yaratırken seçebiliyorsunuz.

Update 2 ile beraber gelen en beğendiğim özellik ise basit ama zaman kazandıran bir özellik. Daha önceden Universal App'inizi store'a göndermek için paket yaratmak istediğinizde her seferinde live accountunuzla login olmak zorunda kalıyordunuz. Ancak Update 2 ile beraber bu sorunu çözmüşler ve Store'a bir kere login olduğunuzda Visual Studio artık bu account bilgilerini otomatik olarak hatırlıyor.

Interactive Window Yenilikleri

Visual Studio 2015 Update 1 ile beraber gelen en önemli yeniliklerden biri de Interactive Window'du. (Eğer daha önce Interactive Window'u duymadıysanız yazmış olduğum yazıyı okuyabilirsiniz.) Update 2 ile beraber Interactive Window tarafında da yenilikler mevcut. Bu yenilikler çalışmış olduğunuz proje içerisindeki kodları hızlı bir şekilde Interactive Window üzerinden çalıştırmanıza olanak sağlıyor. Bunun için Visual Studio içerisinde çalıştırmak istediğiniz kodu seçip sağ tıklayıp "Execute in Interactive"'i tıklamanız yeterli.

Editör Yenilikleri

Update 2 içerisinde güzel editör yenilikleri de bulunmakta. Bunlardan ilki using/import eklerken artık fuzzy matching yapılması. Yani eğer bir tipin adını yanlış yazarsanız Visual Studio tipin adından tahminde bulunuyor ve size uygun öneriyi sunup hem tipin adını düzeltiyor hem de ilgili using/import'u ekliyor.

Update 2 içerisinde ayrıca yeni refactoringler de bulunuyor. Bunlardan ilki delegate işletimlerinde null propagator operatörü kullanımını öneren refactoring.

Diğer refactoring ise make method synchronous refactoringi.

Bu yazıda değinmek istediğim yenilikler bunlar. Update 2 ile beraber gelen tüm yenilikleri https://www.visualstudio.com/en-us/news/vs2015-update2-vs.aspx adresinde bulabilirsiniz.



Visual Studio VNext - Visual Studio 15 Preview Yenilikleri

Bu makaleye Github üzerinden katkıda bulunabilirsiniz.

Bu seneki Build konferansının en önemli duyurularından biri de Visual Studio'nun bir sonraki major versiyonu olacak olan Visual Studio 15 Preview'dı. Daha ilk preview olmasına rağmen içerisinde güzel yenilikleri barındıran Visual Studio 15'e bu yazımızda kısaca bir gözatacağız.

Visual Studio 15 Preview adından da anlaşılacağı gibi henüz preview :). Dolayısıyla bilgisayarınıza yüklediğinizde eğer bir sorunla karşılaşırsanız bu sorunla ilgili Microsoft size destek vermeyecektir. Bu nedenle tavsiyem bilgisayarınızda yeni bir sanal makinada veya Azure üzerinde bir sanal makinada bu yenilikleri test etmeniz.

Yeni Installer

Bu yazıyı okuyorsanız tahmin ediyorum ki %90 ihtimalle hayatınızda en az bir kere makinanıza Visual Studio kurulumu yapmışsınızdır. Önce ufak bir setup dosyası download edilir sonra o setup dosyası arka planda 1-2 GB büyüklüğünde olan kurulum dosyalarını download eder ve sonrasında da 45dk-1 saate yakın Visual Studio'nun kurulmasını bekleriz. Kurulum zamanı setup sırasında nelerin kurulmasını istediğinize göre de değişir. Bazen developerlar yeniden kurulumla uğraşmamak için belki ileride lazım olur diye tüm opsiyonları seçerler. Bazen de default seçimle ilerlerler. Visual Studio ekibindeki kullanım datalarına bakarsak default seçenekle ilerleyen developerların %70'i default içerisindeki tüm functionalityleri ve tüm app tiplerini bile kullanmıyor.

Bu nedenlerden dolayı Visual Studio VNext'in en büyük temalarından biri bu kurulum aşamasını kolaylaştırmak ve hızlandırmak olacak. Hem setup dosyasının boyutunu ufaltma, hem kurulumu hızlandırma hem de Visual Studio'yu uygulama tipleri bazında modüler hale getirme şimdilik düşünülen yeniliklerden. Şimdi gelelim ilk preview'daki installer yeniliklerine.

http://aka.ms/vsnext adresine gidip sağdaki seçenekten yeni installerı download edip installer yeniliklerini test edebilirsiniz. Soldaki installer ise bildiğimiz klasik Visual Studio installerı.

Installerı download edip çalıştırdığımızda önceki versiyonların installerlarına nazaran farklı bir ekranla karşılaşıyoruz.

Ekrandan da görüleceği gibi artık Visual Studio çeşitli uygulama tiplerine uygun paketlerle geliyor. Yani eğer sadece .NET development yapacaksanız .NET Development paketini kurup hızlı bir şekilde kurulumu tamamlayabilirsiniz. Eğer sadece editör olarak kullanacağım diyorsanız core editörü seçip 300 MB'lık bir download yapıp Visual Studio'yu kurabiliyorsunuz. Şu anda sadece yukarıda resimde gördüğünüz kadar paket mevcut. Ancak zaman içerisinde Universal App paketi, Cloud App paketi gibi daha pek çok farklı paket installera eklenecektir.

Paket bazılı kurulumla beraber kurulum süreleri de gözle görülür bir şekilde düşüyor. Daha önce Visual Studio kurulumuyla 1-1.5 saatimizi harcarken artık çok daha kısa bir sürede kurulumu tamamlayabiliyoruz. Örneğin sadece core editör paketini yüklemek isterseniz max 10 dk içerisinde kurulum tamamlanıyor.(Paket downloadu yapıldığı için internet hızına göre değişiklik gösterebilir.)

Hızlandırılmış İlk Açılım

1-1.5 saat bekleyip Visual Studio kurulumunu tamamladıktan sonra ilk açtığımızda kullanacağımız dile göre seçim yaparız ve bir süre Visual Studio'nun ilk kullanıma hazırlanmasını bekleriz. Her ne kadar uyarıda bir kaç dakika sürebilir dese de bu süreç oldukça uzun sürebilmekte. Benim de şahsen Visual Studio kurulumunda en sinir olduğum şeylerden biridir bu :)

Visual Studio 15 ile beraber artık bu süre de oldukça kısalıyor ve 1 dakikayı bile bulmadan Visual Studio ilk kez bile olsa hızlıca açılıyor. Şahsen en sevdiğim özelliklerden biride bu Visual Studio 15 içerisindeki :D

Klasör Bazlı Çalışabilme

Yeni Visual Studio'nun en önemli özelliklerinden biri de klasör bazlı çalışabilme. Bundan önce Visual Studio'da bir projeyi açmak istediğimizde o projenin illa ki bir solution dosyası olması gerekiyordu. Ancak yeni Visual Studio ile beraber bu zorunluluk ortadan kalktı. Artık solution dosyası olmadan da doğrudan klasör bazlı olarak projeyi açıp çalışabiliyoruz. Böylece python, javascript gibi solution dosyası gerektirmeyen proje tipleriyle Visual Studio içerisinde çalışmak daha da kolay.

Solution Explorer içerisinde klasör görünümü

Code Style Rules

Roslyn projesiyle beraber custom analyzer yazabilmeye başlamamızla en çok sorulan sorulardan biri de proje içerisindeki code standartlarını korumak için bir analyzer yapabilmenin mümkün olup olmadıydı. Bununla ilgili 1-2 proje olsa da tam anlamıyla çözülemeyen bir sorundu bu. Artık Visual Studio 15'le beraber kodlama standartlarına uygun kurallar tanımlayabiliyoruz ve bu kuralların kontrolü projenin derleme aşamasında yapılıyor. Eğer kurala uygun olmayan kullanımlar varsa bunların fixleri için de Visual Studio size ilgili code fixi otomatik olarak sunuyor.

Code style kuralları şu anda Tools => Options ekranı içerisinde Text Editor => C# altında yer alıyor. Bu ekran içerisinde pek çok kural ayarlamak mümkün. Örneğin, projeler içerisinde this ve var keywordlerinin kullanımlarını belirleyebiliyorsunuz. Developerlar var keywordünü hiç kullanmamalı yada tipin belirgin olduğu durumlarda var keywordu kullanılabilir gibi kuralları ayarlayabiliyorsunuz.

Eğer isimlendirmelerle ilgili kurallar belirlemek isterseniz bu kuralları da yine aynı ekran üzerinden ayarlayabiliyorsunuz. Örneğin projede metot isimlendirmelerinde pascal casing kullanılsın diye ayarlarsanız Visual Studio derleme esnasında sizi isimlendirme kurallarına uymadığınız konusunda uyarıyor ve bunu düzeltmeniz için size code fix sunuyor.

Kuralları belirledikten sonra Visual Studio belirlediğimiz kurallara göre build esnasında ilgili uyarıları yapıyor.

"Show Potential Fixes"'a basarsak

Code style rule ekranı içerisinde yapılabilecek pek çok farklı ayar bulunmakta. Bununla ilgili daha detaylı bir şekilde başka bir blog yazısı yazmayı planlıyorum.

Diğer Özellikler

Build'deki sessionları izlerseniz Visual Studio 15 içerisinde yukarıda bahsettiklerime ek olarak gösterilen pek çok farklı özellik olduğunu göreceksiniz. Intellisense substring matching, intellisense filtering, "how do I" (en heyecanlanmadığım özellik :( ), code fix ile proje veya nuget paket referansı ekleme (en efsane özellik :) ) gibi özelliklerin hepsi private buildler üzerinden gösterildi. Bunun anlamı bu özellikle şu an için kullanıcılar tarafından test edilmek için hazır değiller. Tahmin ediyorum ki ilerleyen preview sürümlerinde bu özellikler de yavaş yavaş Visual Studio 15 içerisine eklenecektir.

Build'de Visual Studio 15 ile ilgili oturumlara aşağıda ulaşabilirsiniz.

Visual Studio 15 Preview yenilikleri şimdilik bu kadar. Yeni preview sürümleri çıktıkça içerisinde bulunan yeni özellikleri yine blogdan paylaşıyor olacağım.

Görüşmek üzere...



Roslyn - CSharpSyntaxWalker İle Syntax Tree Üzerinde Gezinme

Bu makaleye Github üzerinden katkıda bulunabilirsiniz.

Bir önceki roslyn makalemizde syntax tree yapısından ve syntax tree içerisinde bulunan yapılardan bahsetmiştik. Ayrıca syntax tree içerisinde istediğimiz yapıdaki elementleri bulmak için LINQ kullanmıştık. Bu yazıda ise syntax tree içerisinde gezinmenin farklı bir yolunu inceleyeceğiz. İlk olarak projemize yine Microsoft.CodeAnalysis nuget paketini ekliyoruz.

Install-Package Microsoft.CodeAnalysis 

Genelde syntax treeler ile çalışırken amacımız belirli bir tipte olan elementleri bulup bunlar üzerinde işlemler yapmak oluyor. Örneğin, tüm class tanımlamalarını bulup kontrol etmek veya değişken tanımlamalarını bulup kontrol etmek gibi... Bu nedenle aslında çoğunlukla ilk yaptığımız şey syntax tree içerisinde bulmayı amaçladığımız tanımlamalara gitmek. SyntaxWalker yapısı da otomatik olarak syntax tree üzerinde kolayca gezinmemizi ve istediğimiz tanımlamalara hızlıca ulaşmamızı sağlayan bir yapı. C# syntax tree'leri için bunun özelleşmiş hali de CSharpSyntaxWalker tipi. CSharpSyntaxWalker tipinin yapısına bakarsak bu tip abstract bir tip. Bu nedenle kendi SyntaxWalker tipimizi yazıp bu tipten türeteceğiz.

public class MethodWalker : CSharpSyntaxWalker
{

}

Diyelim ki çalıştığınız şirkette kullandığınız bir kodlama standardı var ve bu standarda göre yazdığınız metotların isimleri büyük harfle başlamalı. Bu nedenle syntax walker ile syntax tree içerisinde gezip metot tanımlamalarını bulup bu metotların isimlerini kontrol etmeliyiz.

Yukarıda gördüğünüz üzere CSharpSyntaxWalker içerisinde override edilebilecek çok sayıda metot var. Bu metotları override ettiğinizde syntax tree içerisinde metodun isminde yazan elementlere denk gelindiğinde override ettiğiniz metot çağırılıyor. Böylece sizde istediğiniz işlemleri burada yapabiliyorsunuz. En basitinden eğer tüm nodeları veya tokenları gezmek isterseniz Visit ve VisitToken metotlarını override edebilirsiniz. Böylece hızlı bir şekilde tree üzerinde istediğiniz elemanlara erişebilirsiniz.

public class MethodWalker : CSharpSyntaxWalker
{
    public override void VisitToken(SyntaxToken token)
    {
        base.VisitToken(token);
    }

    public override void Visit(SyntaxNode node)
    {
        base.Visit(node);
    }
}

Ancak daha spesifik tanımlamalara erişmekse amacınız daha özelleşmiş metotlar işinizi daha da kolaylaştırabilir. Bizim örneğinizde aslında biz sadece metot tanımlamalarına odaklanmak istiyoruz. Bu nedenle metot tanımlamalarına erişmek bizim için yeterli. Bu nedenle doğrudan VisitMethodDeclaration metodunu override ederek ilerliyoruz.

public class MethodWalker : CSharpSyntaxWalker
{
    public override void VisitMethodDeclaration(MethodDeclarationSyntax node)
    {
        base.VisitMethodDeclaration(node);
    }
}

Şimdi sıra geldi ilgili kontrolü yapma aşamasına. VisitMethodDeclaration metodunu override ettiğimizde bize artık MethodDeclarationSyntax node'u parametre olarak geliyor. Artık yapmamız gereken metot adının ilk harfini kontrol edip bir eğer illegal bir kullanım varsa ismini collection içerisine eklemek.

public class MethodWalker : CSharpSyntaxWalker
{
    public List<string> illegalMethodNames = new List<string>();
    public override void VisitMethodDeclaration(MethodDeclarationSyntax node)
    {
        if (char.IsLower(node.Identifier.ValueText, 0))
        {
            illegalMethodNames.Add(node.Identifier.ValueText);
        }
    }
}

Gördüğünüz gibi bu kadar basit. Şimdi sıra geldi bu yazdığımız syntax walker aracılığıyla kod üzerinde gezinmeye.

class Program
{
    static void Main(string[] args)
    {
        var tree = CSharpSyntaxTree.ParseText(@"class Foo
                {
                    void Bar()
                    {
                    }

                    void bar1()
                    {
                        //Illegal
                    }

                    void Bar2()
                    {
                    }

                    void m()
                    {
                        //Illegal
                    }

                    class InnerFoo
                    {
                        void innerM()
                        {
                            //Illegal
                        }
                    }
                }"
);

        MethodWalker methodWalker = new MethodWalker();
        methodWalker.Visit(tree.GetRoot());

        methodWalker.illegalMethodNames.ForEach(t => Console.WriteLine(t));
    }
}

Gördüğünüz gibi syntax tree yarattıktan sonra syntax walkerın visit metodunu syntax tree'nin rootunu göndererek çağırıyoruz ve ağaç üzerinde gezinmeye başlıyoruz. Uygulamayı çalıştırırsak çıktı olarak küçük harfle başlayan metotların isimlerinin ekrana yazıldığını görebiliriz.

Gördüğünüz üzere syntax tree üzerinde gezinmek roslyn API'ları sayesinde oldukça kolay. Siz de kod içerisinde belirli analizleri yapmak için hızlı bir şekilde ve oldukça az kod yazıp ilgili kontrolleri yapabilirsiniz. Peki analizleri yaptık ve hataları kısımları bulduk. Bunları nasıl temizleyeceğiz ? Örneğin küçük harfle başlayan metotların isimlerini otomatik olarak değiştirsek nasıl olur ? Bu da bir sonraki roslyn makalesinin konusu olacak :)

Bir sonraki makalede görüşmek üzere...



Roslyn Syntax Tree API'larına Giriş

Bu makaleye Github üzerinden katkıda bulunabilirsiniz.

Daha önce .NET Compiler Platform (Roslyn) ile ilgili yazdığımız tüm yazılarda ve videolarda Roslyn projesinin derleyicileri bir kara kutu olmaktan çıkardığından ve artık bizim de derleyicilerin kullandığı yapıları kullanıp elimizdeki kodu analiz edebileceğimizden çokca bahsetmiştik.

Bugün bu konuya syntax tree API'ları ile giriş yapacağız. Yazdığımız kodlar derleme işlemi sırasında ilk olarak derleyici tarafından parse edilirler ve bu işlemin sonucunda bir syntax tree oluşturulur. Bu syntax tree içerisinde yazmış olduğumuz kod içerisindeki herşey hiyerarşik bir şekilde tutulur.

Örneğin, aşağıdaki gibi son derece basit bir kodumuz olduğunu düşünelim.

class C
{
    public void M()
    { }
}

Bu kod derleyici tarafından derlendiğinde aşağıdaki gibi bir syntax tree oluşturulur.

Gördüğümüz gibi yazmış olduğumuz kod içerisinde bulunan her bir tanımlama, boşluk, keyword vb... tüm bileşenler syntax tree içerisinde eksiksiz tutuluyor. Syntax tree'ler derleme aşamasının en önemli yapılarından biri. Çünkü kod içerisindeki tüm bileşenler syntax tree içerisinde düzenleniyor ve kategorilere ayrılıyor. Derleme işlemi sırasında parserdan sonraki adımlarda da bu aşamada üretilen syntax tree kullanılıyor.

Derleyici tarafından yaratılan syntax tree içerisinde 3 farklı tipte eleman bulunuyor.

  • Syntax Node
  • Syntax Token
  • Syntax Trivia

Syntax Node'lar kod içerisindeki tanımlamaları,ifadeleri, koşul ifadeleri vb... dil içerisinde temel yapıları temsil ederler. Örneğin class tanımlaması en tepede bir syntax node ile ifade edilir. Roslyn içerisinde her yapıya özel SyntaxNode tipinden türetilmiş özel SyntaxNode sınıfları vardır. Yukarıdaki syntax tree resminde mavi olan nodelar birer syntax node'dur.

Syntax Token'lar yine dil içerisinde bulunan en ufak bileşenleri temsil eden yapılardır. Syntax tokenların tree içerisinde altında hiçbir zaman başka tokenlar veya syntax node'lar bulunmaz. Roslyn içerisinde SyntaxToken'lar için tek bir tip bulunurken bu tip içerisindeki Kind propertysi ile token tipleri birbirinden ayrıştırılabilir. Yukarıdaki syntax tree resmindeki yeşil renkli nodelar syntax tokendır.

Syntax Trivia'lar da kod içerisinde bulunan ancak derleme işlemi için çokta büyük anlam ifade etmeyen bileşenler için kullanılır. Bu bileşenler kod içerisindeki yorumlar, boşluklar gibi yapılardır. Syntax trivia'lar syntax tokenlara bağlıdırlar. Her bir syntax token'ın LeadingTrivia ve TrailingTrivia collectionları vardır. Bu collectionlar ile token'a bağlı olan trivia'lara erişilebilir.

Bu kadar teori şimdilik yeterli :) Şimdi hemen bir console uygulaması açalım ve bu API'ları nasıl kullanacağımıza bakalım.

Projemizi yarattıktan sonra yapmamız gereken ilk şey Microsoft.CodeAnalysis nuget paketini yüklemek.

Install-Package Microsoft.CodeAnalysis 

Bu işlemi de gerçekleştirdikten sonra artık hazırız. Varolan bir kodun syntax tree'sini çıkarabilmek için Microsoft.CodeAnalysis.CSharp namespace'i içerisinde CSharpSyntaxTree tipinin ParseText metodunu kullanacağız. Bu metot string olarak kendisine verilen bir kodun syntax treesini verir.

class Program
{
    static void Main()
    {
        var tree = CSharpSyntaxTree.ParseText(@"class C
        {
            public void M()
            { }
        }"
);
    }
}

ParseText metodunu çağırdıktan sonra artık elimizde bir syntax tree var. Bu syntax tree üzerinde istediğimiz elemanlara ulaşabiliriz ve ağaç üzerinde gezebiliriz. İlk olarak yaratılan veri yapısı bir ağaç olduğu için ağacın root elemanına ulaşalım.

class Program
{
    static void Main(string[] args)
    {
        var tree = CSharpSyntaxTree.ParseText(@"class C
        {
            public void M()
            { }
        }"
);

        var root = tree.GetRoot();
    }
}   

Ağacın rootuna ulaştıktan sonra artık ağaç içerisindeki her bir elamana da rahatlıkla ulaşabiliriz. Örneğin basit bir LINQ sorgusuyla tüm metot tanımlamalarına ulaşmamız mümkün.

class Program
{
    static void Main(string[] args)
    {
        var tree = CSharpSyntaxTree.ParseText(@"class C
        {
            public void M()
            { }
        }"
);

        var root = tree.GetRoot();
        var methods = root.DescendantNodes().OfType<MethodDeclarationSyntax>();
        foreach (var method in methods)
        {
            Console.WriteLine(method.ToString());
        }
    }
}

Bu kod çalıştığında parse ettiğimiz kod içerisinde tek metot olduğu için ve o metot da M metodu olduğu için M metodu doğrudan console'a yazılacak.

Olayı biraz daha karmaşıklaştıralım ve parametre kabul eden metotların listesini çıkaralım.

class Program
{
    static void Main(string[] args)
    {
        var tree = CSharpSyntaxTree.ParseText(@"class C
        {
            public void M()
            { }
            public void M2(int a)
            { }
            public void M3(int a,string b)
            { }
        }"
);

        var root = tree.GetRoot();
        var methods = root.DescendantNodes().OfType<MethodDeclarationSyntax>().Where(t => t.ParameterList.Parameters.Any());
        foreach (var method in methods)
        {
            Console.WriteLine(method.ToString());
        }
    }
}

Parse ettiğimiz koda baktığımızda yazdığımız kodun çıktısının M2 ve M3 metotları olması lazım. Hemen kodu çalıştırıp sonucunu görelim.

Şimdi eminim aklınıza takılan şöyle bir sorun var. Bu sorguları bu şekilde iyi güzel yazıyoruzda metot tanımlamalarının MethodDeclarationSyntax tipinde olduğunu veya parametrelerin bu tip içerisindeki ParameterList.Parameters collectionında tutulduğunu nasıl bileceğiz ? Bu konu tabi sadece bizim değil aynı zaman da Roslyn'i ve Roslyn-Visual Studio entagrasyonunu yazan ekibin de bir sorunuydu zamanında. Bu nedenle geliştirdikleri bir araçla bu sorunu çözdüler. Şimdi bu araç artık Visual Studio içerisinde extension olarak sunuluyor.

Syntax Visualizer dediğimiz pencere yardımıyla istediğimiz kodun syntax treesini herhangi bir kod çalıştırmadan görebiliriz ve her bir elemanın tüm propertylerine de ulaşabiliriz. Bu extensionı yüklemek için .NET Compiler Platform SDK'ini yüklememiz gerekiyor. Bu extension aynı zamanda Roslyn API'larıyla yaptığımız kod analizlerini Visual Studio extensionı olarak yayınlamamız sağlayan templateları da sağlıyor. Extensionı kurmak için buradan VS Gallery'e gidebilir veya Visual Studio içerisiden Tools => Extensions and Updates menüsü üzerinde .NET Compiler Platform SDK'ini yükleyebilirsiniz.

Extension'ı yükledikten sonra View => Other Windows => Syntax Visualizer adımlarıyla Syntax Visualizer'ı açabilirsiniz.

Parse ettiğimiz kodu da Visual Studio içerisine kopyalarsak aşağıda gördüğünüz gibi hızlı bir şekilde elemanlara ulaşabilir ve propertylerini hızlı bir şekilde kontrol edebiliriz.

Bu yazımızda syntax tree API'larını kısa bir giriş yaptık ve LINQ ile syntax tree üzerinde elemanlara nasıl erişilebiliriz konusunu inceledik. Bir sonraki yazıda syntax tree üzerinde dolaşmanın farklı bir yolunu inceleyeceğiz.

Görüşmek üzere...



.NET Compiler Platform API'larını Kullanmak İçin Visual Studio Ortamını Hazırlama

Daha önceki C# 6.0 yazılarımızda Visual Studio 2015 ile beraber sıfırdan yeniden yazılan C# ve VB compilerlarının hayatımıza gireceğinden bahsetmiştik. Hatta yeni yazılan Roslyn compilerı sayesinde C# 6.0 ve VB 12 içerisindeki bazı özelliklerin getirilmesinin de ne kadar kolaylaştığına değinmiştik.

Roslyn compilerlarının yeniden yazılma amaçlarından biri de compilerları bir kara kutu olmaktan çıkartmak.

compiler

Compilerların kara kutu olmasından kastımız input olarak aldığı source code'dan output olarak assembly çıkarması ve bu üretim esnasında yaptığı tüm işlemlerin bir kapalı kutu olarak içeride yapılması. Yani compiler sizin kodunuzu derlerken aslında bu kara kutu içerisinde pek çok işlem yapıyor ve pek çok data ve veri yapısı oluşturuyor ancak siz hiçbir şekilde bu oluşturduğu yapılara ve dataya ulaşamıyorsunuz. Ayrıca kodunuz derlenip assembly oluştuktan sonra da compiler kodunuzu derlerken oluşturduğu her türlü  veri yapısını ve datayı siliyor. Bu nedenle de şu anda Visual Studio içerisinde refactoring  ve kod analizi yapan araçları & extensionları geliştirmek de oldukça zor. Çünkü compilerla iletişime geçebileceğiniz API'lar mevcut değil.

openingcompilerRoslyn compilerları ile beraber artık compilerlar kara kutu olmaktan çıkıyorlar ve içerilerinde oluşturdukları yapıları dışarıya açabiliyorlar. Hal böyle olunca da artık kodu analiz eden ve yaptığı analize göre uygun refactoring seçeneklerini sunan extensionlar yazmak da oldukça kolay.

Şimdilik roslyn compilerları ile ilgili bu kadar giriş sanırım yeterli. (Roslyn ile ilgili daha detaylı bilgi için daha önce yazdığım bir yazıyı da okuyabilirsiniz.) Bu yazımızda amacımız Roslyn compiler API'ları ile uygulamalar geliştirmek için Visual Studio 2015 ortamını nasıl hazırlarız sorusuna cevap vermek.

Öncelikle tabi ki Visual Studio 2015 Preview'e ihtiyacımız var. Visual Studio 2015 Preview'ı ISO olarak bilgisayarınıza kuracağınız gibi Azure üzerinde Visual Studio 2015 imajlı bir VM yaratarak da ilerleyebilirsiniz.

Ortam Kurulumu

Visual Studio 2015 Preview'ı kurduktan sonra kurmamız gerek ilk bileşen Visual Studio 2015 Preview SDK. Visual Studio SDK bizim Visual Studio için extension geliştirmemiz için bize gerekli kütüphaneleri ve araçları sağlayacak olan bileşen. Güncel indirme linkini http://roslyn.codeplex.com/ adresinde bulabilirsiniz.

Sonrasında ise kuruluma .NET Compiler Platform SDK Templates 'i kurarak devam ediyoruz. Bu extension'ı kurduktan sonra artık Visual Studio 2015 Preview'ı açıp File => New Project yaptığımızda artık bize yardımcı olacak olan yeni .NET Compiler Platform proje tipleri gelecek.

Son olarak yapacağımız kurulum ise opsiyonel. Zorunlu değil ancak işimizi son derece kolaylaştıracak bir araç kendileri. Bu neden kurmanızı ben şiddetle tavsiye ediyorum :) Zaten ilerleyen yazılarda da .NET Compiler Platform Syntax Visualizer extensionına sıkça değineceğiz. Ancak şimdilik çok detaya girmeden bu noktada bırakalım.

Tüm bu kurulumları yaptıktan sonra Visual Studio 2015 Preview'ı açarsanız .NET Compiler Platform projelerinin Visual Studio 2015 içerisine eklendiğini görebilirsiniz.

 roslynprojects

Bu son görüntü de demek oluyor ki artık .NET Compiler platform API'ları ile boğuşmaya hazırız.

Bir sonraki yazıda görüşmek üzere.