private static void BuildReplaceMapForConditionalDirectives(UsingsSorter usingsHelper, Dictionary <UsingDirectiveSyntax, UsingDirectiveSyntax> replaceMap, IndentationSettings indentationSettings, TreeTextSpan rootSpan) { foreach (var childSpan in rootSpan.Children) { var originalUsings = usingsHelper.GetContainedUsings(childSpan); if (originalUsings.Count > 0) { // sort the original using declarations on Span.Start, in order to have the correct replace mapping. originalUsings.Sort(CompareSpanStart); var indentationSteps = IndentationHelper.GetIndentationSteps(indentationSettings, originalUsings[0].Parent); if (originalUsings[0].Parent is NamespaceDeclarationSyntax) { indentationSteps++; } var indentation = IndentationHelper.GenerateIndentationString(indentationSettings, indentationSteps); var modifiedUsings = usingsHelper.GenerateGroupedUsings(childSpan, indentation, false, qualifyNames: false); for (var i = 0; i < originalUsings.Count; i++) { replaceMap.Add(originalUsings[i], modifiedUsings[i]); } } BuildReplaceMapForConditionalDirectives(usingsHelper, replaceMap, indentationSettings, childSpan); } }
private static void BuildReplaceMapForNamespaces(UsingsSorter usingsHelper, Dictionary <UsingDirectiveSyntax, UsingDirectiveSyntax> replaceMap, IndentationSettings indentationSettings, bool qualifyNames) { var usingsPerNamespace = usingsHelper .GetContainedUsings(TreeTextSpan.Empty) .GroupBy(ud => ud.Parent) .Select(gr => gr.ToList()); foreach (var usingList in usingsPerNamespace) { if (usingList.Count > 0) { // sort the original using declarations on Span.Start, in order to have the correct replace mapping. usingList.Sort(CompareSpanStart); var indentationSteps = IndentationHelper.GetIndentationSteps(indentationSettings, usingList[0].Parent); if (usingList[0].Parent is NamespaceDeclarationSyntax) { indentationSteps++; } var indentation = IndentationHelper.GenerateIndentationString(indentationSettings, indentationSteps); var modifiedUsings = usingsHelper.GenerateGroupedUsings(usingList, indentation, false, qualifyNames); for (var i = 0; i < usingList.Count; i++) { replaceMap.Add(usingList[i], modifiedUsings[i]); } } } }
private static async Task <Document> GetTransformedDocumentAsync(Document document, SyntaxNode syntaxRoot, bool forcePreservePlacement, CancellationToken cancellationToken) { var fileHeader = GetFileHeader(syntaxRoot); var compilationUnit = (CompilationUnitSyntax)syntaxRoot; var settings = SettingsHelper.GetStyleCopSettings(document.Project.AnalyzerOptions, cancellationToken); var semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); var usingDirectivesPlacement = forcePreservePlacement ? UsingDirectivesPlacement.Preserve : DeterminePlacement(compilationUnit, settings); var usingsHelper = new UsingsSorter(settings, semanticModel, compilationUnit, fileHeader); var usingsIndentation = DetermineIndentation(compilationUnit, settings.Indentation, usingDirectivesPlacement); // - The strategy is to strip all using directive that are not inside a conditional directive and replace them later with a sorted list at the correct spot // - The using directives that are inside a conditional directive are replaced (in sorted order) on the spot. // - Conditional directives are not moved, as correctly parsing them is too tricky // - No using directives will be stripped when there are multiple namespaces. In that case everything is replaced on the spot. List <UsingDirectiveSyntax> stripList; var replaceMap = new Dictionary <UsingDirectiveSyntax, UsingDirectiveSyntax>(); // When there are multiple namespaces, do not move using statements outside of them, only sort. if (usingDirectivesPlacement == UsingDirectivesPlacement.Preserve) { BuildReplaceMapForNamespaces(usingsHelper, replaceMap, settings.Indentation, false); stripList = new List <UsingDirectiveSyntax>(); } else { stripList = BuildStripList(usingsHelper); } BuildReplaceMapForConditionalDirectives(usingsHelper, replaceMap, settings.Indentation, usingsHelper.ConditionalRoot); var usingSyntaxRewriter = new UsingSyntaxRewriter(stripList, replaceMap, fileHeader); var newSyntaxRoot = usingSyntaxRewriter.Visit(syntaxRoot); if (usingDirectivesPlacement == UsingDirectivesPlacement.InsideNamespace) { newSyntaxRoot = AddUsingsToNamespace(newSyntaxRoot, usingsHelper, usingsIndentation, replaceMap.Any()); } else if (usingDirectivesPlacement == UsingDirectivesPlacement.OutsideNamespace) { newSyntaxRoot = AddUsingsToCompilationRoot(newSyntaxRoot, usingsHelper, usingsIndentation, replaceMap.Any()); } // Final cleanup newSyntaxRoot = StripMultipleBlankLines(newSyntaxRoot); newSyntaxRoot = ReAddFileHeader(newSyntaxRoot, fileHeader); var newDocument = document.WithSyntaxRoot(newSyntaxRoot.WithoutFormatting()); return(newDocument); }
private static SyntaxNode AddUsingsToNamespace(SyntaxNode newSyntaxRoot, UsingsSorter usingsHelper, string usingsIndentation, bool hasConditionalDirectives) { var rootNamespace = ((CompilationUnitSyntax)newSyntaxRoot).Members.OfType <NamespaceDeclarationSyntax>().First(); var withTrailingBlankLine = hasConditionalDirectives || rootNamespace.Members.Any() || rootNamespace.Externs.Any(); var groupedUsings = usingsHelper.GenerateGroupedUsings(TreeTextSpan.Empty, usingsIndentation, withTrailingBlankLine, qualifyNames: false); groupedUsings = groupedUsings.AddRange(rootNamespace.Usings); var newRootNamespace = rootNamespace.WithUsings(groupedUsings); newSyntaxRoot = newSyntaxRoot.ReplaceNode(rootNamespace, newRootNamespace); return(newSyntaxRoot); }
private static SyntaxNode AddUsingsToCompilationRoot(SyntaxNode newSyntaxRoot, UsingsSorter usingsHelper, string usingsIndentation, bool hasConditionalDirectives) { var newCompilationUnit = (CompilationUnitSyntax)newSyntaxRoot; var withTrailingBlankLine = hasConditionalDirectives || newCompilationUnit.AttributeLists.Any() || newCompilationUnit.Members.Any() || newCompilationUnit.Externs.Any(); var groupedUsings = usingsHelper.GenerateGroupedUsings(TreeTextSpan.Empty, usingsIndentation, withTrailingBlankLine, qualifyNames: true); groupedUsings = groupedUsings.AddRange(newCompilationUnit.Usings); newSyntaxRoot = newCompilationUnit.WithUsings(groupedUsings); return(newSyntaxRoot); }
private static List <UsingDirectiveSyntax> BuildStripList(UsingsSorter usingsHelper) { return(usingsHelper.GetContainedUsings(TreeTextSpan.Empty).ToList()); }