2015-01-08 2 views
8

Roslyn을 사용하여 코드를 생성하는 방법을 알아 내려고합니다. 나는 CSharpSyntaxTree.ParseText과 같은 것에 대해 말하지 않고 있는데, 그것은 일부 문자열을 받아서 AST로 변환 할 것입니다. 대신,이 (의사 코드)처럼 어떻게 든 내 모델을 구축하고 싶습니다 : roslyn을 사용한 의미 코드 생성

  • 추가

    1. 컴파일 단위로 file 만들기 클래스 MyClass 추가 방법
    2. file-DoSomething
    3. 세트 본체의 MyClassDoSomething과 유사한 방식으로 System.Linq.Expressions

    최근에 우리가 발견 한 Microsoft.CodeAnalysis.CSharp.SyntaxFactory, 유망 해 보였습니다. 그러나 분명히 우리는 퀴즈를 스스로 추가해야합니다.

    SyntaxFactory.CompilationUnit()으로 트리를 만들고 앞뒤로 일부 멤버를 추가 한 후에 ToFullString()의 출력은 읽기 쉽거나 컴파일 할 수없는 텍스트 묶음 일뿐입니다 (예 : 중괄호 누락). 모델에서 텍스트를 생성 할 때 뭔가 빠졌습니까?

    편집 : 공백 행동에 영향을 미치는

    작업 공간을 사용하여 설정할 수있는 옵션 :

    public string Generate (CompilationNode rootNode) 
    { 
        var cw = new CustomWorkspace(); 
        cw.Options.WithChangedOption (CSharpFormattingOptions.IndentBraces, true); 
        var formattedCode = Formatter.Format (CreateFile(rootNode), cw); 
        return formattedCode.ToFullString(); 
    } 
    

    이 이미 더 나은 결과를 얻을 수 있습니다. 누군가가이를 좋은 해결책으로 확인하거나 오히려 해킹 할 수 있습니까?

    하나의 문제가 남아 있습니다. 현재 SF.AccessorDeclaration을 사용하여 자동 속성을 생성하려고하지만 전체 문자열로 변환 할 때 세미콜론이 누락됩니다.

  • +0

    당신의 목표는 코드를 방출하는 것입니다, 맞습니까? 컴파일하지 않습니까? – i3arnon

    +0

    예, 명시 적으로 퀴즈를 지정하지 않았습니다. 또한 ReSharper SDK를 사용하여 몇 가지 경험을 쌓았습니다. 기본적으로 동일한 응용 분야가 있습니다. 퀴즈를 모르는 공장을 가지고 있으며 생성 된 모든 코드를 깨끗하고 편집 가능하게 인쇄합니다. CodeDOM을 사용하도록 제안하는 다른 사용자의 의견을 넘어서서 Roslyn이이 문제에 적합하지 않다고 생각했으나 가장 큰 오류가있는 것처럼 보입니다 :) – Matthias

    +0

    Roslyn은 컴파일러가되어 코드를 사용하기 때문에, 그것을 생산하지 마십시오. – i3arnon

    답변

    10
    당신은 기본적으로 블록 정의를 추가해야

    후 로슬린은 당신이 (당신이 쓴 것처럼) 여기

    없이 올바르게 생성되는 간단한 클래스의 예이다 포매터를 사용할 때 당신을위한 퀴즈를 처리 자신은 퀴즈를

    var consoleWriteLine = Syntax.MemberAccessExpression(
         SyntaxKind.SimpleMemberAccessExpression, 
         Syntax.IdentifierName("Console"), 
         name: Syntax.IdentifierName("WriteLine")); 
    
        var arguments = Syntax.ArgumentList (
         Syntax.SeparatedList (
          new[] 
          { 
           Syntax.Argument (
            Syntax.LiteralExpression (
             SyntaxKind.StringLiteralExpression, 
             Syntax.Literal (@"""Goodbye everyone!""", "Goodbye everyone!"))) 
          })); 
    
        var consoleWriteLineStatement = Syntax.ExpressionStatement (Syntax.InvocationExpression (consoleWriteLine, arguments)); 
    
        var voidType = Syntax.ParseTypeName ("void"); 
        var method = Syntax.MethodDeclaration (voidType, "Method").WithBody (Syntax.Block(consoleWriteLineStatement)); 
    
        var intType = Syntax.ParseTypeName ("int"); 
        var getterBody = Syntax.ReturnStatement (Syntax.DefaultExpression (intType)); 
        var getter = Syntax.AccessorDeclaration (SyntaxKind.GetAccessorDeclaration, Syntax.Block (getterBody)); 
        var property = Syntax.PropertyDeclaration (intType, "Property").WithAccessorList (Syntax.AccessorList (Syntax.SingletonList (getter))); 
    
        var @class = Syntax.ClassDeclaration ("MyClass").WithMembers (Syntax.List (new MemberDeclarationSyntax[] { method, property })); 
    
        var cw = new CustomWorkspace(); 
        cw.Options.WithChangedOption (CSharpFormattingOptions.IndentBraces, true); 
        var formattedCode = Formatter.Format (@class, cw); 
    
        Console.WriteLine (formattedCode.ToFullString()); 
    

    주를 지정하지 : 구문 = Microsoft.CodeAnalysis.CSharp.SyntaxFactory

    이 다음 CL 생성 엉덩이 確定 :

    class MyClass 
    { 
        void Method() 
        { 
         Console.WriteLine("Goodbye everyone!"); 
        } 
    
        int Property 
        { 
         get 
         { 
          return default(int); 
         } 
        } 
    } 
    

    괜찮아요.

    관련 문제