2015-01-09 100 views
3

我正在開發一個應用程序,用於說明CSharp代碼。我正在用Roslyn這樣做。我面臨着splitting expressions的問題。將表達式語句拆分爲Roslyn

Sample類

class Program 
{ 
    static void Main(string[] args) 
    { 
     float floatVariable = 20; 
     Int16 intVariable = 10; 
     string str = "School"; 
     Console.Write(str + floatVariable.ToString() + intVariable.ToString()); // Facing problem with this statement 
    } 
} 

樣品我使用

string code = new StreamReader(classPath).ReadToEnd(); 
var syntaxTree = CSharpSyntaxTree.ParseText(code); 
var syntaxRoot = syntaxTree.GetRoot(); 

//This will get the method and local variables declared inside the method 
var MyMethods = syntaxRoot.DescendantNodes().OfType<MethodDeclarationSyntax>(); 
foreach (MethodDeclarationSyntax mds in MyMethods) 
{ 
    syntaxTree = CSharpSyntaxTree.ParseText(mds.ToFullString()); 
    IEnumerable<SyntaxNode> nodes = syntaxTree.GetRoot().DescendantNodes(); 
    IEnumerable<VariableDeclarationSyntax> variableDeclarations =  nodes.OfType<VariableDeclarationSyntax>(); 
    foreach (VariableDeclarationSyntax variable in variableDeclarations) 
    { 
    // I will collect the variable details like Datatype, variable names and initialized values here 
    } 


    foreach (StatementSyntax statement in mds.Body.Statements) 
    { 
     if (statement.CSharpKind() == SyntaxKind.ExpressionStatement) 
     { 
      //I want to split the expressions "Console.Write(str + floatVariable.ToString() + intVariable.ToString());" as below 

      //1. intVariable.ToString() 
      //2. floatVariable.ToString() 
      //3. str 

      //Then I have to find the whole data type from the resolved result of above 3 => string here    
     } 
    } 
} 

任何幫助的代碼將不勝感激。

編輯: 我有在分割參數表達式語句的麻煩。我試圖做到這一點,

if (statement.CSharpKind() == SyntaxKind.ExpressionStatement) 
{ 
    ExpressionStatementSyntax expression = statement as ExpressionStatementSyntax; 
    var expressions = expression.Expression.DescendantNodes(); 
} 

但是這將每個標記拆分爲一個單獨的元素。我只是想分裂Console.Write(str + floatVariable.ToString() + intVariable.ToString())成,

  1. Console.Write()
  2. 海峽
  3. intVariable.ToString()
  4. floatVariable.ToString()
+2

的[羅斯林語法樹Visualiser的](https://visualstudiogallery.msdn.microsoft.com/70e184da-9b3a- 402f-b210-d62a898e2887)可能會幫助你。 – Rawling

+1

究竟是什麼問題?從語句中獲取參數表達式?使用'+'的二進制表達式?你有什麼嘗試?它是如何失敗的? – svick

+0

@svick:我編輯了這個問題。請在**編輯**塊中找到它。 –

回答

1

很難告訴你到底想做什麼,因爲你只是在一個特定的情況下指定代碼應該做的事情,而不是一般情況。

我解釋它的方式是:

  1. 對於調用表達式,返回真實被調用,也陷入它的參數,如果有的話表達。
  2. 對於二元運算符,下降到兩個孩子。
  3. 對於所有其他表達式,直接返回表達式。

隨着本說明書並使用CSharpSyntaxVisitor,代碼看起來是這樣的:

public static IEnumerable<ExpressionSyntax> Split(ExpressionSyntax expression) 
{ 
    return new SplitVisitor().Visit(expression); 
} 

class SplitVisitor : CSharpSyntaxVisitor<IEnumerable<ExpressionSyntax>> 
{ 
    public override IEnumerable<ExpressionSyntax> VisitInvocationExpression(
     InvocationExpressionSyntax node) 
    { 
     yield return node.Expression; 

     var argumentExpressions = node.ArgumentList.Arguments 
      .SelectMany(a => Visit(a.Expression)); 
     foreach (var expression in argumentExpressions) 
      yield return expression; 
    } 

    public override IEnumerable<ExpressionSyntax> VisitBinaryExpression(
     BinaryExpressionSyntax node) 
    { 
     foreach (var expression in Visit(node.Left)) 
      yield return expression; 
     foreach (var expression in Visit(node.Right)) 
      yield return expression; 
    } 

    public override IEnumerable<ExpressionSyntax> DefaultVisit(SyntaxNode node) 
    { 
     var expression = node as ExpressionSyntax; 
     if (expression != null) 
      yield return expression; 
    } 
} 
+0

您正確理解問題,並且您的答案按預期工作。非常感謝... –

+0

但是該解決方案不適用於語句'Console.Write(str + string.Concat(「str1」,「str2」))''。 ** split **方法不管理'string.Concat(「str1」,「str2」));' 中的嵌套aruments'(「str1」,「str2」)'[請在這裏找到圖片](http://imgur.com/fW5Hkc1) –

+1

@ MeikandaNayanar.II不明白,你的圖像顯示我的Split()'確實分割了嵌套的'string.Concat(「str1」,「str2」)'到'string.Concat',''str1「'和'」str2「'中。你是說它不應該?如果是這種情況,那麼我不明白你想要'Split()'遵循的規則。 – svick