Сортировать и удалять (не использовать) с помощью операторов Roslyn скрипт / код? - PullRequest
8 голосов
/ 28 марта 2012

Сортировать и удалить (не использовать) с помощью операторов Roslyn скрипт / код? Я ищу код .NET / Roslyn (компилятор как сервис), который может выполняться через проект, а также сортировать и удалять неиспользуемые операторы использования. Я считаю, что это возможно с Roslyn? Может кто-нибудь указать мне код, который может сделать это переписать?

Ответы [ 5 ]

6 голосов
/ 03 апреля 2012

Это функция в Visual Studio, но в академическом плане я думаю, что вы собирали бы, используя операторы из вашего синтаксического дерева, как это:

var usings = syntaxTree.Root.DescendentNodes().Where(node is UsingDirectiveSyntax);

... и сравните это с пространствами имен, разрешенными таблицей символов следующим образом:

private static IEnumerable<INamespaceSymbol> GetNamespaceSymbol(ISymbol symbol)
{
    if (symbol != null && symbol.ContainingNamespace != null)
        yield return symbol.ContainingNamespace;
}

var ns = semanticModel.SyntaxTree.Root.DescendentNodes().SelectMany(node =>
    GetNamespaceSymbol(semanticModel.GetSemanticInfo(node).Symbol)).Distinct();
3 голосов
/ 16 июля 2013

Roslyn CTP сентябрь 2012 г. предоставляет метод GetUnusedImportDirectives(), который очень полезен здесь.

Изменяя пример проекта OrganizeSolution , на который ссылается Мэтт, вы можете добиться как сортировки, так и удаления (неиспользованного) с помощью директив. (Устаревшую) версию этого проекта можно найти здесь: http://go.microsoft.com/fwlink/?LinkId=263977. Он устарел, потому что document.GetUpdatedDocument() больше не существует,

var document = newSolution.GetDocument(documentId);
var transformation = document.OrganizeImports();
var newDocument = transformation.GetUpdatedDocument();

можно упростить до

var document = newSolution.GetDocument(documentId);
var newDocument = document.OrganizeImports();

Добавление newDocument = RemoveUnusedImportDirectives(newDocument); и предоставление следующего метода поможет.

private static IDocument RemoveUnusedImportDirectives(IDocument document)
{
    var root = document.GetSyntaxRoot();
    var semanticModel = document.GetSemanticModel();

    // An IDocument can refer to both a CSharp as well as a VisualBasic source file.
    // Therefore we need to distinguish those cases and provide appropriate casts.  
    // Since the question was tagged c# only the CSharp way is provided.
    switch (document.LanguageServices.Language)
    {
        case LanguageNames.CSharp:
            var oldUsings = ((CompilationUnitSyntax)root).Usings;
            var unusedUsings = ((SemanticModel)semanticModel).GetUnusedImportDirectives();
            var newUsings = Syntax.List(oldUsings.Where(item => !unusedUsings.Contains(item)));
            root = ((CompilationUnitSyntax)root).WithUsings(newUsings);
            document = document.UpdateSyntaxRoot(root);
            break;

        case LanguageNames.VisualBasic:
            // TODO
            break;
    }
    return document;
}
2 голосов
/ 03 декабря 2015

Я использую следующий метод расширения для сортировки значений

internal static SyntaxList<UsingDirectiveSyntax> Sort(this SyntaxList<UsingDirectiveSyntax> usingDirectives, bool placeSystemNamespaceFirst = false) =>
    SyntaxFactory.List(
        usingDirectives
        .OrderBy(x => x.StaticKeyword.IsKind(SyntaxKind.StaticKeyword) ? 1 : x.Alias == null ? 0 : 2)
        .ThenBy(x => x.Alias?.ToString())
        .ThenByDescending(x => placeSystemNamespaceFirst && x.Name.ToString().StartsWith(nameof(System) + "."))
        .ThenBy(x => x.Name.ToString()));

и

compilationUnit = compilationUnit.WithUsings(SortUsings(compilationUnit.Usings))
1 голос
/ 04 апреля 2012

Ознакомьтесь с примером проекта OrganizeSolution, который поставляется вместе с Roslyn. Это делает что-то похожее на то, что вы хотите. Это делает сортировку. Вам также нужно будет использовать SemanticModel, как показывает Джефф, чтобы определить, нет ли ссылок на конкретное пространство имен в источнике.

0 голосов
/ 15 июля 2012

Для удаления операторов проверьте пункт 30 часто задаваемых вопросов в решении в следующем каталоге, в файле FAQ.cs: (Обратите внимание, что это для версии Roslyn CTP в июне 2012 года).

% userprofile% \ Documents \ Microsoft Roslyn CTP - июнь 2012 \ CSharp \ APISampleUnitTestsCS

Также есть часто задаваемые вопросы, относящиеся к этому проекту:

http://www.codeplex.com/Download?ProjectName=dlr&DownloadId=386858

Вот примерпереписатель из примера кода, который удаляет операторы присваивания.

// Below SyntaxRewriter removes multiple assignement statements from under the 
// SyntaxNode being visited.
public class AssignmentStatementRemover : SyntaxRewriter
{
    public override SyntaxNode VisitExpressionStatement(ExpressionStatementSyntax node)
    {
        SyntaxNode updatedNode = base.VisitExpressionStatement(node);

        if (node.Expression.Kind == SyntaxKind.AssignExpression)
        {
            if (node.Parent.Kind == SyntaxKind.Block)
            {
                // There is a parent block so it is ok to remove the statement completely.
                updatedNode = null;
            }
            else
            {
                // The parent context is some statement like an if statement without a block.
                // Return an empty statement.
                updatedNode = Syntax.EmptyStatement()
                    .WithLeadingTrivia(updatedNode.GetLeadingTrivia())
                    .WithTrailingTrivia(updatedNode.GetTrailingTrivia());
            }
        }
     return updatedNode;
    }
}
...