2016-03-09 4 views
1

Я пытаюсь написать инструмент командной строки, который модифицирует некоторый код с помощью Roslyn. Кажется, все идет хорошо: решение открыто, решение изменено, метод Workspace.TryApplyChanges возвращает true. Однако на диске не изменяются фактические файлы. Что происходит? Ниже приведен код верхнего уровня, который я использую.Изменение файлов с использованием Roslyn

static void Main(string[] args) 
{ 
    var solutionPath = args[0]; 
    UpdateAnnotations(solutionPath).Wait(); 
} 

static async Task<bool> UpdateAnnotations(string solutionPath) 
{ 
    using (var workspace = MSBuildWorkspace.Create()) 
    { 
     var solution = await workspace.OpenSolutionAsync(solutionPath); 
     var newSolution = await SolutionAttributeUpdater.UpdateAttributes(solution); 
     var result = workspace.TryApplyChanges(newSolution); 
     Console.WriteLine(result); 
     return result; 
    } 
} 

ответ

3

Я построил небольшую программу, используя код и получил результаты, которые я ожидал - проблема, как представляется, находится в методе SolutionAttributeUpdater.UpdateAttributes. Я получил эти результаты, используя следующую реализацию с вашей базой основной и UpdateAnnotations-методами:

public class SolutionAttributeUpdater 
{ 
    public static async Task<Solution> UpdateAttributes(Solution solution) 
    { 
     foreach (var project in solution.Projects) 
     { 
      foreach (var document in project.Documents) 
      { 
       var syntaxTree = await document.GetSyntaxTreeAsync(); 
       var root = syntaxTree.GetRoot(); 

       var descentants = root.DescendantNodes().Where(curr => curr is AttributeListSyntax).ToList(); 
       if (descentants.Any()) 
       { 
        var attributeList = SyntaxFactory.AttributeList(
         SyntaxFactory.SingletonSeparatedList(
          SyntaxFactory.Attribute(SyntaxFactory.IdentifierName("Cookies"), SyntaxFactory.AttributeArgumentList(SyntaxFactory.SeparatedList(new[] { SyntaxFactory.AttributeArgument(
            SyntaxFactory.LiteralExpression(
                   SyntaxKind.StringLiteralExpression, SyntaxFactory.Literal(@"Sample")) 
            )}))))); 
        root = root.ReplaceNodes(descentants, (node, n2) => attributeList); 
        solution = solution.WithDocumentSyntaxRoot(document.Id, root); 
       } 
      } 
     } 
     return solution; 
    } 
} 

Она была протестирована с помощью следующего класса в растворе образца:

public class SampleClass<T> 
{ 
    [DataMember("Id")] 
    public int Property { get; set; } 
    [DataMember("Id")] 
    public void DoStuff() 
    { 
     DoStuff(); 
    } 
} 

И это привело к следующему Output :

public class SampleClass<T> 
{ 
[Cookies("Sample")]  public int Property { get; set; } 
[Cookies("Sample")]  public void DoStuff() 
    { 
     DoStuff(); 
    } 
} 

Если вы посмотрите на методе UpdateAttributes я должен был заменить узлы с ReplaceNodes и уточнены решением по телефону WithDo cumentSyntaxRoot.

Я бы предположил, что либо один из этих двух вызовов отсутствует, либо что ничего не изменилось вообще - если вы вызываете рабочее пространство.TryApplyChanges (решение), вы все равно получите true как Output.

Обратите внимание, что использование нескольких вызовов root.ReplaceNode() вместо root.ReplaceNodes() также может приводить к ошибке, поскольку на измененный документ фактически используется только первое обновление - что может заставить вас поверить, что ничего не имеет вообще не изменилось, в зависимости от реализации.

+0

Вы правы, проблема была в «SolutionAttributeUpdater.UpdateAttributes». Я думал, что это работает из-за некоторых модульных тестов, но они не охватывают достаточно случаев. Прошу прощения за вашу помощь! – KeyboardDrummer