TGViewer
.NET Разработчик .NET Разработчик @netdeveloperdiary · 6.75K subscribers
Post #2640 2.47K
День 2187. #ЗаметкиНаПолях
Используем Roslyn для Анализа и Изменения Кода Решения
Roslyn можно использовать как библиотеку для анализа и генерации кода. Например, вы можете создать консольное приложение, которое загружает решение, находит шаблоны и переписывает код.

Создадим консольное приложение и добавим необходимые NuGet-пакеты:
dotnet new console
dotnet add package Microsoft.Build.Locator
dotnet add package Microsoft.CodeAnalysis.CSharp
dotnet add package Microsoft.CodeAnalysis.CSharp.Workspaces
dotnet add package Microsoft.CodeAnalysis.Workspaces.Common
dotnet add package Microsoft.CodeAnalysis.Workspaces.MSBuild


Вот пример, как создать рабочее пространство Roslyn из решения:
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.MSBuild;

// Находим сборки MSBuild в вашей системе
Microsoft.Build.Locator.MSBuildLocator.RegisterDefaults();

// Возможно надо восстановить NuGet-пакеты решения перед тем, как открыть его в Roslyn.
// Зависимости могут потребоваться для корректного анализа.

// Создаём рабочее пространство Roslyn и загружаем решение
var ws = MSBuildWorkspace.Create();
var solution =
await ws.OpenSolutionAsync(@"my_solution.sln");


Теперь можно работать с решением. Вот несколько примеров.

Анализируем синтаксические деревья:
foreach (var proj in solution.Projects)
{
foreach (var doc in proj.Documents)
{
var syntree = await doc.GetSyntaxTreeAsync();
var semanticModel = await doc.GetSemanticModelAsync();
// Анализируем дерево
// Можно использовать CSharpSyntaxWalker для обхода
}
}


Получаем все ссылки на символ:
var comp = 
await solution.Projects.First().GetCompilationAsync();
var symbol =
comp.GetSpecialType(SpecialType.System_String);
var refs =
await SymbolFinder.FindReferencesAsync(symbol, solution);


Переименовываем символ
var symbol = comp
.GetSymbolsWithName(s => s == "MyMethod")
.Single();
var newSolution = await Renamer
.RenameSymbolAsync(
solution,
symbol,
new SymbolRenameOptions()
{
RenameOverloads = true
},
"MyMethod2");
ws.TryApplyChanges(newSolution);


Обновляем документ с помощью DocumentEditor
foreach (var proj in solution.Projects)
{
foreach (var doc in proj.Documents)
{
var editor =
await DocumentEditor.CreateAsync(doc);

// Изменяем
foreach(var emptyStatement in
editor
.OriginalRoot
.DescendantNodes()
.OfType<EmptyStatementSyntax>())
{
editor.RemoveNode(emptyStatement);
}

// Применяем изменения
var newDoc = editor.GetChangedDocument();
if (!ws.TryApplyChanges(newDoc.Project.Solution))
{
Console.WriteLine("Failed!");
}
}
}


Обновляем документ с помощью CSharpSyntaxRewriter:
foreach (var proj in solution.Projects)
{
foreach (var doc in proj.Documents)
{
// Изменяем
var root = await doc.GetSyntaxRootAsync();
if(root is null)
continue;

var newRoot =
new CustomRewriter().Visit(root);
var newDoc =
doc.WithSyntaxRoot(newRoot);

// Применяем изменения
if (!ws.TryApplyChanges(newDoc.Project.Solution))
{
Console.WriteLine("Failed!");
}
}
}

internal sealed class CustomRewriter :
CSharpSyntaxRewriter
{
public override SyntaxNode?
VisitIfStatement(IfStatementSyntax node)
=> node.WithLeadingTrivia(
SyntaxFactory
.ParseLeadingTrivia("/* comment */"));
}


Выберите любое «подопытное» решение, введите его путь вместо my_solution.sln, вставьте любой из примеров и можете пройти его в отладчике пошагово, чтобы посмотреть, как работает анализатор.

Источник: https://www.meziantou.net/using-roslyn-to-analyze-and-rewrite-code-in-a-solution.htm
  • 👍 20
More from @netdeveloperdiary
  1. Oct 5, 2026День 2805. #ЧтоНовенького #NET11 Аргументы в Выражениях Коллекций в C#15 В C#15 реализован…
  2. Oct 4, 2026День 2804. #ВопросыНаСобеседовании Марк Прайс предложил свой набор из 60 вопросов (как тех…
  3. Oct 3, 2026Post #3360
  4. Oct 3, 2026День 2803. #Оффтоп Чем Заняться, Пока Работают Агенты? У VS Code Есть Ответ Сейчас большую…
  5. Oct 2, 2026День 2802. #Карьера #Юмор Секреты Программирования, Известные Только Легендам Ещё один пос…
  6. Oct 1, 2026Post #3357
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →