public static void SortUsingDirectives( this List <UsingDirectiveSyntax> usingDirectives, SyntaxList <UsingDirectiveSyntax> existingDirectives, bool placeSystemNamespaceFirst) { var systemFirstInstance = UsingsAndExternAliasesDirectiveComparer.SystemFirstInstance; var normalInstance = UsingsAndExternAliasesDirectiveComparer.NormalInstance; var specialCaseSystem = placeSystemNamespaceFirst; var comparers = specialCaseSystem ? (systemFirstInstance, normalInstance) : (normalInstance, systemFirstInstance); // First, see if the usings were sorted according to the user's preference. If so, // keep the same sorting after we add the using. However, if the usings weren't sorted // according to their preference, then see if they're sorted in the other way. If so // preserve that sorting as well. That way if the user is working with a file that // was written on a machine with a different default, the usings will stay in a // reasonable order. if (existingDirectives.IsSorted(comparers.Item1)) { usingDirectives.Sort(comparers.Item1); } else if (existingDirectives.IsSorted(comparers.Item2)) { usingDirectives.Sort(comparers.Item2); } }
private void CheckUsings(SyntaxNode node, SyntaxList <UsingDirectiveSyntax> usings) { if (!usings.IsSorted(_comparer)) { _diagnostics.Add(Diagnostic.Create( DiagnosticDescriptor, Location.Create(node.SyntaxTree, usings.Span))); } }
private static int?TryGetDesiredIndexIfGroupedWorker <TDeclarationSyntax>( SyntaxList <TDeclarationSyntax> declarationList, TDeclarationSyntax declaration, IList <bool> availableIndices, IComparer <TDeclarationSyntax> comparerWithoutNameCheck, IComparer <TDeclarationSyntax> comparerWithNameCheck) where TDeclarationSyntax : SyntaxNode { if (!declarationList.IsSorted(comparerWithoutNameCheck)) { // Existing declarations weren't grouped. Don't try to find a location // to this declaration into. return(null); } // The list was grouped (by type, staticness, accessibility). Try to find a location // to put the new declaration into. var result = Array.BinarySearch(declarationList.ToArray(), declaration, comparerWithoutNameCheck); var desiredGroupIndex = result < 0 ? ~result : result; Debug.Assert(desiredGroupIndex >= 0); Debug.Assert(desiredGroupIndex <= declarationList.Count); // Now, walk forward until we hit the last member of this group. while (desiredGroupIndex < declarationList.Count) { // Stop walking forward if we hit an unavailable index. if (availableIndices != null && !availableIndices[desiredGroupIndex]) { break; } if (0 != comparerWithoutNameCheck.Compare(declaration, declarationList[desiredGroupIndex])) { // Found the index of an item not of our group. break; } desiredGroupIndex++; } // Now, walk backward until we find the last member with the same name // as us. We want to keep overloads together, so we'll place ourselves // after that member. var currentIndex = desiredGroupIndex; while (currentIndex > 0) { var previousIndex = currentIndex - 1; // Stop walking backward if we hit an unavailable index. if (availableIndices != null && !availableIndices[previousIndex]) { break; } if (0 != comparerWithoutNameCheck.Compare(declaration, declarationList[previousIndex])) { // Hit the previous group of items. break; } // Still in the same group. If we find something with the same name // then place ourselves after it. if (0 == comparerWithNameCheck.Compare(declaration, declarationList[previousIndex])) { // Found something with the same name. Generate after this item. return(currentIndex); } currentIndex--; } // Couldn't find anything with our name. Just place us at the end of this group. return(desiredGroupIndex); }
protected static int GetInsertionIndex <TDeclaration>( SyntaxList <TDeclaration> declarationList, TDeclaration declaration, CodeGenerationOptions options, IList <bool> availableIndices, Func <SyntaxList <TDeclaration>, TDeclaration> after = null, Func <SyntaxList <TDeclaration>, TDeclaration> before = null) where TDeclaration : SyntaxNode { Contract.ThrowIfTrue(availableIndices != null && availableIndices.Count != declarationList.Count + 1); if (options != null) { // Try to strictly obey the after option by inserting immediately after the member containing the location if (options.AfterThisLocation != null) { var afterMember = declarationList.LastOrDefault(m => m.SpanStart <= options.AfterThisLocation.SourceSpan.Start); if (afterMember != null) { var index = declarationList.IndexOf(afterMember); index = GetPreferredIndex(index + 1, availableIndices, forward: true); if (index != -1) { return(index); } } } // Try to strictly obey the before option by inserting immediately before the member containing the location if (options.BeforeThisLocation != null) { var beforeMember = declarationList.FirstOrDefault(m => m.Span.End >= options.BeforeThisLocation.SourceSpan.End); if (beforeMember != null) { var index = declarationList.IndexOf(beforeMember); index = GetPreferredIndex(index, availableIndices, forward: false); if (index != -1) { return(index); } } } if (options.AutoInsertionLocation) { if (declarationList.IsEmpty()) { return(0); } else if (declarationList.IsSorted(CSharpDeclarationComparer.Instance)) { var result = Array.BinarySearch(declarationList.ToArray(), declaration, CSharpDeclarationComparer.Instance); var index = GetPreferredIndex(result < 0 ? ~result : result, availableIndices, forward: true); if (index != -1) { return(index); } } if (after != null) { var member = after(declarationList); if (member != null) { var index = declarationList.IndexOf(member); if (index >= 0) { index = GetPreferredIndex(index + 1, availableIndices, forward: true); if (index != -1) { return(index); } } } } if (before != null) { var member = before(declarationList); if (member != null) { var index = declarationList.IndexOf(member); if (index >= 0) { index = GetPreferredIndex(index, availableIndices, forward: false); if (index != -1) { return(index); } } } } } } // Otherwise, add the declaration to the end. { var index = GetPreferredIndex(declarationList.Count, availableIndices, forward: false); if (index != -1) { return(index); } } return(declarationList.Count); }