2012-03-28 5 views
7

Ordinamento e rimozione (non utilizzato) utilizzando le istruzioni Script/codice di Roslyn? Sto cercando un codice .NET/Roslyn (compilatore come servizio) che può essere eseguito attraverso un progetto e ordinare e rimuovere istruzioni usando inutilizzate. Credo che questo sia possibile con Roslyn? Qualcuno può indicarmi codice che potrebbe fare questa riscrittura?Ordina e rimuovi (inutilizzato) usando le istruzioni Script/codice di Roslyn?

risposta

5

questa è una caratteristica in Visual Studio, ma accademicamente penso che sarebbe raccogliere utilizzando le istruzioni dal SyntaxTree in questo modo:

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

... e si confronti con gli spazi dei nomi risolti dalla tabella dei simboli In questo modo:

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(); 
+1

È possibile utilizzare ".OfType ()" invece di" .Dove (nodo è UsingDirectiveSyntax) " –

1

Consultare il progetto di esempio OrganizeSolution fornito con Roslyn. Fa qualcosa di simile a quello che vuoi. Fa la parte di selezione. Dovrai anche usare SemanticModel come Jeff shows per determinare se non ci sono riferimenti ad un particolare spazio dei nomi nella sorgente.

0

Per la rimozione delle istruzioni, consultare la sezione delle domande frequenti 30 nella soluzione nella seguente directory, nel file FAQ.cs: (Nota questa è per la versione CTP di Roslyn del giugno 2012).

% userprofile% \ Documenti \ Microsoft Roslyn CTP - Giugno 2012 \ CSharp \ APISampleUnitTestsCS

C'è anche una FAQ che si riferisce a questo progetto:

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

Ecco la rewriter campione il codice di esempio, che rimuove le istruzioni di assegnazione.

// 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; 
    } 
} 
1

Roslyn CTP settembre 2012 fornisce un metodo GetUnusedImportDirectives(), che è di grande utilità qui.

Modificando il progetto di esempio OrganizeSolution cui si fa riferimento, è possibile ottenere sia l'ordinamento che la rimozione (inutilizzata) delle direttive. Una versione (obsoleta) di questo progetto può essere trovata qui: http://go.microsoft.com/fwlink/?LinkId=263977. E non è aggiornato perché document.GetUpdatedDocument() non esiste più,

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

può essere semplificata

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

Aggiunta newDocument = RemoveUnusedImportDirectives(newDocument); e fornendo le seguenti modalità farà il trucco.

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; 
} 
1

Io uso questo il seguente metodo di estensione per ordinare usings

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())); 

e

compilationUnit = compilationUnit.WithUsings(SortUsings(compilationUnit.Usings)) 
Problemi correlati