diff options
author | Krasimir Georgiev <krasimir@google.com> | 2017-11-09 15:41:23 +0000 |
---|---|---|
committer | Krasimir Georgiev <krasimir@google.com> | 2017-11-09 15:41:23 +0000 |
commit | 818da9bb299cad1a75e5e31dbd96dabb22f54cb8 (patch) | |
tree | 1a7c9a1c5b4372a8532403a04a50f554432d27ab /clang/lib/Format/UsingDeclarationsSorter.cpp | |
parent | 1696bb65233cdbef0a1138175cd540fc1b86e540 (diff) | |
download | bcm5719-llvm-818da9bb299cad1a75e5e31dbd96dabb22f54cb8.tar.gz bcm5719-llvm-818da9bb299cad1a75e5e31dbd96dabb22f54cb8.zip |
[clang-format] Sort using declarations by splitting on '::'
Summary: This patch improves using declarations sorting.
Reviewers: bkramer
Reviewed By: bkramer
Subscribers: cfe-commits, klimek
Differential Revision: https://reviews.llvm.org/D39786
llvm-svn: 317794
Diffstat (limited to 'clang/lib/Format/UsingDeclarationsSorter.cpp')
-rw-r--r-- | clang/lib/Format/UsingDeclarationsSorter.cpp | 60 |
1 files changed, 40 insertions, 20 deletions
diff --git a/clang/lib/Format/UsingDeclarationsSorter.cpp b/clang/lib/Format/UsingDeclarationsSorter.cpp index e9c535da925..72151137eed 100644 --- a/clang/lib/Format/UsingDeclarationsSorter.cpp +++ b/clang/lib/Format/UsingDeclarationsSorter.cpp @@ -26,6 +26,45 @@ namespace format { namespace { +// The order of using declaration is defined as follows: +// Split the strings by "::" and discard any initial empty strings. The last +// element of each list is a non-namespace name; all others are namespace +// names. Sort the lists of names lexicographically, where the sort order of +// individual names is that all non-namespace names come before all namespace +// names, and within those groups, names are in case-insensitive lexicographic +// order. +int compareLabels(StringRef A, StringRef B) { + SmallVector<StringRef, 2> NamesA; + A.split(NamesA, "::", /*MaxSplit=*/-1, /*KeepEmpty=*/false); + SmallVector<StringRef, 2> NamesB; + B.split(NamesB, "::", /*MaxSplit=*/-1, /*KeepEmpty=*/false); + size_t SizeA = NamesA.size(); + size_t SizeB = NamesB.size(); + for (size_t I = 0, E = std::min(SizeA, SizeB); I < E; ++I) { + if (I + 1 == SizeA) { + // I is the last index of NamesA and NamesA[I] is a non-namespace name. + + // Non-namespace names come before all namespace names. + if (SizeB > SizeA) + return -1; + + // Two names within a group compare case-insensitively. + return NamesA[I].compare_lower(NamesB[I]); + } + + // I is the last index of NamesB and NamesB[I] is a non-namespace name. + // Non-namespace names come before all namespace names. + if (I + 1 == SizeB) + return 1; + + // Two namespaces names within a group compare case-insensitively. + int C = NamesA[I].compare_lower(NamesB[I]); + if (C != 0) + return C; + } + return 0; +} + struct UsingDeclaration { const AnnotatedLine *Line; std::string Label; @@ -33,27 +72,8 @@ struct UsingDeclaration { UsingDeclaration(const AnnotatedLine *Line, const std::string &Label) : Line(Line), Label(Label) {} - // Compares lexicographically with the exception that '_' is just before 'A'. bool operator<(const UsingDeclaration &Other) const { - size_t Size = Label.size(); - size_t OtherSize = Other.Label.size(); - for (size_t I = 0, E = std::min(Size, OtherSize); I < E; ++I) { - char Rank = rank(Label[I]); - char OtherRank = rank(Other.Label[I]); - if (Rank != OtherRank) - return Rank < OtherRank; - } - return Size < OtherSize; - } - - // Returns the position of c in a lexicographic ordering with the exception - // that '_' is just before 'A'. - static char rank(char c) { - if (c == '_') - return 'A'; - if ('A' <= c && c < '_') - return c + 1; - return c; + return compareLabels(Label, Other.Label) < 0; } }; |