Penulisan ulang sintaksis

Saya perlu mengubah semua properti kelas tertentu menggunakan Roslyn.

Apa cara yang disarankan untuk menerapkan lebih dari satu transformasi ke pohon sintaksis tanpa membuat referensi ke dalamnya tidak valid?


Inilah yang saya coba dan di mana saya terjebak:

  • Pada tahap pertama, keturunan CSharpSyntaxWalker mengunjungi semua PropertyDeclarationSyntax node, dan menyimpannya dalam daftar.

  • Pada lintasan kedua, CSharpSyntaxRewriter mentransformasikan node sambil memeriksa bahwa setiap node yang dikunjungi sama dengan satu dalam daftar sebelum mengubahnya.

Masalah dengan upaya saya adalah: Ketika saya mengubah properti, saya menambahkan bidang baru ke kelas yang menyebabkan kelas bermutasi. Semua referensi dalam daftar ke properti lain menjadi tidak valid di pohon baru untuk kelas tersebut.

Tampaknya tidak efisien untuk mengunjungi kembali seluruh kelas, dan bagaimanapun saya tidak dapat mendeteksi node properti yang sudah ditangani karena perbedaan referensi.


person Liviu    schedule 29.05.2014    source sumber
comment
Bisakah Anda menjelaskan lebih detail apa yang Anda lakukan? Mungkin menunjukkan beberapa kode?   -  person Dan Puzey    schedule 29.05.2014
comment
Saya telah menambahkan lebih banyak info ke postingan asli   -  person Liviu    schedule 29.05.2014
comment
Saya pikir Anda hanya perlu memposting kode yang relevan; tidak sepenuhnya jelas bagi saya apa yang Anda lakukan.   -  person Dan Puzey    schedule 29.05.2014
comment
@DanPuzey Saya sudah mengedit pertanyaannya, tolong beri tahu saya jika yang ditanyakan OP sekarang lebih jelas menurut Anda.   -  person Benjamin Gruenbaum    schedule 01.06.2014


Jawaban (1)


Saya tidak akan merekomendasikan untuk mereferensikan node dari SyntaxTree yang ingin Anda modifikasi. Dalam kasus Anda, hanya menggunakan CSharpSyntaxRewriter dalam satu pass (tanpa menyimpan referensi dari pass pra-pemrosesan) sudah cukup, karena metode VisitPropertyDeclaration-nya hanya akan dipanggil satu kali per properti, jadi tidak perlu untuk melacak node yang telah Anda modifikasi.

CSharpSyntaxRewriter juga mengunjungi node dari bawah ke atas, jadi penggantian harus selalu dipanggil dengan node dari pohon asli. Kemungkinan besar Anda telah memodifikasi node melalui panggilan ke base.VisitPropertyDeclaration() sebelum membandingkan referensinya dengan referensi yang disimpan. Jadi Anda tetap bisa menyimpan dan membandingkan referensi jika Anda memang menginginkannya.

public class PropertyRewriter : CSharpSyntaxRewriter
{
    public override SyntaxNode VisitPropertyDeclaration(PropertyDeclarationSyntax node)
    {
        // 'node' should be still from the original syntax tree here

        node = (PropertyDeclarationSyntax)base.VisitPropertyDeclaration(node);

        // 'node' might be replaced here

        return node;
    }
}

Daripada menyimpan referensi ke node yang ingin Anda modifikasi, Anda dapat membuat anotasi pada node tersebut. Anotasi pada sebuah node akan bertahan dari modifikasi SyntraxTree yang memuatnya selama node itu sendiri tidak diganti. Anda dapat menambahkannya seperti ini:

node = node.WithAdditionalAnnotations(
        new SyntaxAnnotation("propertyToChange", "todo"));

Untuk mengambil kembali anotasi, gunakan node.GetAnnotations("propertyToChange") atau gunakan GetAnnotatedNodesOrTokens("propertyToChange") untuk mengambil semua node atau token dengan jenis anotasi tertentu ("propertyToChange").

person andyp    schedule 03.06.2014