Roslyn (C #) не может переименовать поле элемента списка при его использовании - PullRequest
0 голосов
/ 07 января 2019

Я думаю, что Roslyn не может переименовать поле класса, который используется в качестве элемента списка. Есть ли какое-нибудь решение, как визуальный студийный рефактор делает это хорошо?

Как видно из приведенных ниже кодов, он успешно переименовывается, если элемент явно преобразуется в локальную переменную. Но это не окончательное решение.

// ** Reference code of Simple Class's Field1 => renaming failed!
Console.WriteLine(SimpleList[0].Field1);

Следующие коды проверены в проекте ConsoleApplication.

private void Roslyn_rename_failed()
    {
        const string codes = @"
            using System;

            public class Simple
            {
                public int Field1; // <== Field to rename
            }

            public class Usage
            {
                public List<Simple> SimpleList;

                public Usage()
                {
                    // make list of Simple instance
                    SimpleList = new List<Simple>();
                    SimpleList.Add(new Simple());

                    this.Do();
                }

                public void Do()
                {
                    Simple simple = SimpleList[0];
                    // ** Reference 1 of Simple's Field1 => renaming succeeded!
                    // Console.WriteLine(simple.Field1Renamed); // <== Renamed result
                    Console.WriteLine(simple.Field1);


                    var simple2 = SimpleList[0];
                    // **  Reference 2 of Simple's Field1 => renaming failed!
                    Console.WriteLine(simple2.Field1);

                    // ** Reference 3 of Simple's Field1 => renaming failed!
                    Console.WriteLine(SimpleList[0].Field1);
                }
            }";

        // 1. solution setup
        var workspace = new AdhocWorkspace();
        var projectInfo = ProjectInfo.Create(ProjectId.CreateNewId(), VersionStamp.Create(), 
            "roslyn-rename-failed", "roslyn-rename-failed", LanguageNames.CSharp);
        var project = workspace.AddProject(projectInfo);
        var sourceText = SourceText.From(codes);
        var document = project.AddDocument("RenameFailed.cs", sourceText);

        var newProject = document.Project;
        var newSolution = document.Project.Solution;

        // 2. refactoring rename on Simple::Field1
        var newSolutions =  from doc in newProject.Documents
                            let root = doc.GetSyntaxRootAsync().Result
                            let sm = doc.GetSemanticModelAsync().Result
                            from cds in root.DescendantNodesAndSelf().OfType<ClassDeclarationSyntax>()
                            let cdsSymbol = (ITypeSymbol) sm.GetDeclaredSymbol(cds)
                            from field in cdsSymbol.GetMembers().OfType<IFieldSymbol>().Where(m => m.Name == "Field1")
                            let newName = field.Name + "Renamed"
                            select Renamer.RenameSymbolAsync(newSolution, field, newName, workspace.Options).Result;
        newSolution = newSolutions.FirstOrDefault();

        // 3. print renamed codes
        var newCodes = newSolution?.GetDocument(document.Id).GetSyntaxRootAsync().Result.ToFullString();
        Console.WriteLine(newCodes);
    }
...