2015-05-04 11 views
5

Sto creando una correzione del codice che trasforma il modificatore di accesso dei metodi rilevati public. L'implementazione è semplice: rimuovi tutti i modificatori di accesso esistenti e aggiungi public nella parte anteriore. Successivamente sostituisco il nodo e restituisco la soluzione.La formattazione di una firma del metodo perde il rientro

Ciò tuttavia risulta in un elenco di modificatori simile al seguente: publicvirtual void Method(). Sopra i modificatori incollati l'uno contro l'altro, quella riga di codice è indentata in modo errato. Assomiglia a questo:

 [TestClass] 
     public class MyClass 
     { 
      [TestMethod] 
publicvirtual void Method() 
      { 

      } 
     } 

Quindi come soluzione, invece, formatto il codice. Utilizzando

var formattedMethod = Formatter.Format(newMethod, 
             newMethod.Modifiers.Span, 
             document.Project.Solution.Workspace, 
             document.Project.Solution.Workspace.Options); 

posso formattare i modificatori, ma sono ancora erroneamente frastagliato:

 [TestClass] 
     public class MyClass 
     { 
      [TestMethod] 
public virtual void Method() 
      { 

      } 
     } 

Presumo che ciò è dovuto al fatto di curiosità, ma anteponendo il metodo formattato con i principali curiosità del metodo originale non fare la differenza . Voglio evitare di formattare l'intero documento perché, beh, questa non è un'azione per formattare l'intero documento.

L'intera applicazione dedicata del presente Codice Fix:

private Task<Solution> MakePublicAsync(Document document, SyntaxNode root, MethodDeclarationSyntax method) 
{ 
    var removableModifiers = new[] 
    { 
     SyntaxFactory.Token(SyntaxKind.InternalKeyword), 
     SyntaxFactory.Token(SyntaxKind.ProtectedKeyword), 
     SyntaxFactory.Token(SyntaxKind.PrivateKeyword) 
    }; 

    var modifierList = new SyntaxTokenList() 
          .Add(SyntaxFactory.Token(SyntaxKind.PublicKeyword)) 
          .AddRange(method.Modifiers.Where(x => !removableModifiers.Select(y => y.RawKind).Contains(x.RawKind))); 

    var newMethod = method.WithModifiers(modifierList); 
    var formattedMethod = Formatter.Format(newMethod, newMethod.Modifiers.Span, document.Project.Solution.Workspace, document.Project.Solution.Workspace.Options); 

    var newRoot = root.ReplaceNode(method, formattedMethod.WithLeadingTrivia(method.GetLeadingTrivia())); 
    var newDocument = document.WithSyntaxRoot(newRoot); 

    return Task.FromResult(newDocument.Project.Solution); 
} 

risposta

2

Invece di chiamare Formatter.Format manualmente, appena messo il Formatter.Annotation sui vostri nodi fissi, e il motore CodeFix chiamerà automaticamente per voi.

Il problema è che è necessario chiamare Format sulla radice dell'albero, ma specificare l'arco di albero che si desidera formattato, altrimenti il ​​formattatore verrà eseguito su solo l'albero si passa, senza contesto da suo genitore.

+0

Stavo per postare la mia soluzione: se antepongo la trivia al 'SyntaxNode' che ricevo da' SyntaxFactory.Token (SyntaxKind.PublicKeyword) ', tutti i miei test funzionano. Diresti che la soluzione di annotazione del formatter è preferita a questo? –

+0

Sì, in generale mi sento di raccomandare solo l'annotazione, quindi corrisponderà alle impostazioni degli utenti e verrà formattato tutto insieme al resto delle modifiche. –

+0

Dove esattamente dovrei applicare questa annotazione? Quando lo faccio a livello di metodo, il metodo stesso viene formattato, ma l'intero metodo è gravemente rientrato. Voglio evitare di formattare l'intero documento in quanto sarebbe piuttosto fastidioso ogni volta che si utilizza una correzione del codice. –

0

Il problema era che non avevo i miei test rientrati nella rappresentazione stringa stessa, in questo modo:

 var original = @" 
    using System; 
    using System.Text; 

    namespace ConsoleApplication1 
    { 
     class MyClass 
     { 
      void Method(Nullable<int> myVar = 5) 
      { 

      } 
     } 
    }"; 

Come potete vedere c'è ancora una scheda tra il margine sinistro e il codice vero e proprio. Apparentemente il formattatore di Roslyn non è in grado di gestire questo scenario (che, ammettiamolo, non è una situazione comune).

In una situazione diversa da questa, però, probabilmente siete interessati al formattatore, motivo per cui accetterò la risposta di Kevin.