/// <summary> /// Réordonne les membres d'un type. /// </summary> /// <param name="document">Le document.</param> /// <param name="type">Le type.</param> /// <param name="jetonAnnulation">Le jeton d'annulation.</param> /// <returns>Le nouveau document.</returns> private async Task <Document> OrdonnerMembres(Document document, TypeDeclarationSyntax type, CancellationToken jetonAnnulation) { // On récupère la racine. var racine = await document .GetSyntaxRootAsync(jetonAnnulation) .ConfigureAwait(false); var modèleSémantique = await document.GetSemanticModelAsync(jetonAnnulation); // Pour une raison étrange, TypeDeclarationSyntax n'expose pas WithMembers() alors que les trois classes qui en héritent l'expose. // Il faut donc gérer les trois cas différemment... SyntaxNode nouveauType; if (type is ClassDeclarationSyntax) { nouveauType = (type as ClassDeclarationSyntax) .WithMembers(SyntaxFactory.List(ClassOrdering.OrdonnerMembres(type.Members, modèleSémantique))); } else if (type is InterfaceDeclarationSyntax) { nouveauType = (type as InterfaceDeclarationSyntax) .WithMembers(SyntaxFactory.List(ClassOrdering.OrdonnerMembres(type.Members, modèleSémantique))); } else { nouveauType = (type as StructDeclarationSyntax) .WithMembers(SyntaxFactory.List(ClassOrdering.OrdonnerMembres(type.Members, modèleSémantique))); } // Et on met à jour la racine. var nouvelleRacine = racine.ReplaceNode(type, nouveauType); return(document.WithSyntaxRoot(nouvelleRacine)); }
/// <summary> /// Détermine si l'ordre d'assignations des champs est correct (en tête, par ordre alphabétique). /// </summary> /// <param name="context">Le contexte du symbole.</param> /// <returns>Oui ou non.</returns> private static bool OrdreÉlémentsEstFaux(SymbolAnalysisContext context) { // On récupère les informations nécessaires du contexte du symbole. var location = context.Symbol.Locations.First(); var racine = location.SourceTree.GetRoot(); var type = racine.FindNode(location.SourceSpan) as TypeDeclarationSyntax; var modèleSémantique = context.Compilation.GetSemanticModel(location.SourceTree); // On ignore la vérification sur les classes partielles. if (type == null) { return(false); } // On ignore le code généré. if (type.AttributeLists.Any(node => node.ChildNodes().Any(node2 => node2.ToString().Contains("GeneratedCode")))) { return(false); } // On récupère les éléments et on les ordonnes. var membresOrdonnés = ClassOrdering.OrdonnerMembres(type.Members, modèleSémantique); // Et on vérifie que l'ordre est le même. return(!type.Members.SequenceEqual(membresOrdonnés)); }