2015-05-08 10 views
5

Roslyn ile SyntaxTree'ye bir ifade eklemekle ilgili bazı problemlerim var. Başlamak için gereken: Özel bir deyim bulduğumda, bu ifadeden sonra bir veya daha fazla ifade eklemek istiyorum.Açıklamadan sonra yeni ifade roslyn ile eklenir

"testVar" değişkenini yazan her deyimden sonra "myVar = myVar + 1" ifadesini eklemek istediğimi varsayalım.

Yani şu pasajı:

a = 10; 
testVar = 50; 
a = testVar/a; 
testVar = a; 

kod parçası haline olmalı:

a = 10; 
testVar = 50; 
myVar = myVar + 1; 
a = testVar/a; 
testVar = a; 
myVar = myVar + 1; 

Benim şu anki yaklaşımı yöntemiyle 'SyntaxNode VisitExpressionStatement (ExpressionStatement düğüm)' ile SyntaxVisitor kullanır. Bu yöntem, SyntaxTree'deki tüm ifadeleri ziyaret eder ve ziyaret edilen ifadenin döndürdüğü SyntaxNode ile değiştirilmesine izin verir. Ancak, ifadelerini değiştirmek istemiyorum, ancak bunlardan sonra temel olarak iki ifadenin döndürülmesini gerektiren yeni ifadeler ekleyin. Bunu bulduğum tek çözüm, iki ifade için bir kap olarak hizmet veren "BlockSyntax" kullanıyor (bkz. Kod parçacığı [0]). Ben kapsamları manipüle etmek istemiyorum

a = 10; 
{ 
    testVar = 50; 
    myVar = myVar + 1; 
} 
a = testVar/a; 
{ 
    testVar = a; 
    myVar = myVar + 1; 
} 

Bu yaklaşım benim için kabul edilemez: Ne yazık ki, "BlockSyntax" şu sonuca yol kendi etrafında küme parantezi tanıtır. Seçtiğim bir yerde Roslyn ile keyfi ifadeler eklemek için herhangi bir yolu var mı?

[0]

public SyntaxNode VisitExpressionStatement(ExpressionStatement node){ 
    if(node has special characteristics){ 
     var newExpression = ... 

     var newStatmentList = new Roslyn.Compilers.CSharp.SyntaxList<StatementSyntax>(); 
     newStatmentList = newStatmentList.Insert(newStatmentList.Count, node); 
     newStatmentList = newStatmentList.Insert(newStatmentList.Count, newExpression); 

     BlockSyntax newBlock = Syntax.Block(newStatmentList); 
     return newBlock; 

    } 
    else { 
     return node; 
    } 
} 

cevap

1

Stratejim BlockSyntax ile hile olmuştur. Benim similar question'a bakın.

Yaptığınız gibi BlockSyntax ekledim, ancak sonra { ve belirteçlerini eksik olarak işaretleyerek "kaldır". Henüz bu yaklaşımla herhangi bir konuya girmedim, ama bir çözümden daha çok bir çözüm gibi görünüyor.

var statements = new SyntaxList<StatementSyntax>(); 
//Tried bundling newNode and invocation together 
statements.Add(SyntaxFactory.ExpressionStatement(newNode)); 
statements.Add(SyntaxFactory.ExpressionStatement(invocation)); 
var wrapper = SyntaxFactory.Block(statements); 

//Now we can remove the { and } braces 
wrapper = wrapper.WithOpenBraceToken(SyntaxFactory.MissingToken(SyntaxKind.OpenBraceToken)) 
.WithCloseBraceToken(SyntaxFactory.MissingToken(SyntaxKind.CloseBraceToken)); 

Bunları "kaldırıyorum" diyorum. Buradaki sorun, üreteceğiniz SyntaxTree'un, C# derleyicisine hala yerleştirdiğiniz noktada bir BlockSyntax olduğu gibi görünecektir. Bu önemli olabilir veya olmayabilir. Örneğin

:

  • bir dosyaya bir dize olarak bu ağaç çıkışı ediyorsanız, iyi olacak.

  • Derhal bu ağacı derliyorsanız, derleyicinin, yeniden yazdığınız yerde var olan BlockSyntax yorumunu kullanacağını ve tüm anlamlandırma semantiğinin hala varmış gibi yürürlükte olacağını düşünüyorum. "Tuhaf" ağaçlar benim blog yazısı kontrol oluşturma konusunda daha fazla bilgi için

: Don't Trust SyntaxNode.ToFullString()