17#define DEBUG_TYPE "using-declarations-sorter"
31int compareLabelsLexicographicNumeric(StringRef A, StringRef B) {
32 SmallVector<StringRef, 2> NamesA;
33 A.split(NamesA,
"::", -1,
false);
34 SmallVector<StringRef, 2> NamesB;
35 B.split(NamesB,
"::", -1,
false);
36 size_t SizeA = NamesA.size();
37 size_t SizeB = NamesB.size();
38 for (
size_t I = 0, E = std::min(SizeA, SizeB); I < E; ++I) {
47 return NamesA[I].compare_insensitive(NamesB[I]);
56 int C = NamesA[I].compare_insensitive(NamesB[I]);
63int compareLabelsLexicographic(StringRef A, StringRef B) {
64 SmallVector<StringRef, 2> NamesA;
65 A.split(NamesA,
"::", -1,
false);
66 SmallVector<StringRef, 2> NamesB;
67 B.split(NamesB,
"::", -1,
false);
68 size_t SizeA = NamesA.size();
69 size_t SizeB = NamesB.size();
70 for (
size_t I = 0, E = std::min(SizeA, SizeB); I < E; ++I) {
72 int C = NamesA[I].compare_insensitive(NamesB[I]);
78 return SizeA == SizeB ? 0 : 1;
82 StringRef A, StringRef B,
85 return compareLabelsLexicographicNumeric(A, B);
86 return compareLabelsLexicographic(A, B);
89struct UsingDeclaration {
90 const AnnotatedLine *Line;
93 UsingDeclaration(
const AnnotatedLine *Line,
const std::string &Label)
105std::string computeUsingDeclarationLabel(
const FormatToken *UsingTok) {
106 assert(UsingTok && UsingTok->is(tok::kw_using) &&
"Expecting a using token");
108 const FormatToken *Tok = UsingTok->Next;
109 if (Tok && Tok->is(tok::kw_typename)) {
110 Label.append(
"typename ");
113 if (Tok && Tok->is(tok::coloncolon)) {
117 bool HasIdentifier =
false;
118 while (Tok && Tok->is(tok::identifier)) {
119 HasIdentifier =
true;
120 Label.append(Tok->TokenText.str());
122 if (!Tok || Tok->isNot(tok::coloncolon))
127 if (HasIdentifier && Tok && Tok->isOneOf(tok::semi, tok::comma))
132void endUsingDeclarationBlock(
133 SmallVectorImpl<UsingDeclaration> *UsingDeclarations,
134 const SourceManager &SourceMgr, tooling::Replacements *Fixes,
136 bool BlockAffected =
false;
137 for (
const UsingDeclaration &
Declaration : *UsingDeclarations) {
139 BlockAffected =
true;
143 if (!BlockAffected) {
144 UsingDeclarations->clear();
147 SmallVector<UsingDeclaration, 4> SortedUsingDeclarations(
148 UsingDeclarations->begin(), UsingDeclarations->end());
149 auto Comp = [SortUsingDeclarations](
const UsingDeclaration &Lhs,
150 const UsingDeclaration &Rhs) ->
bool {
151 return compareLabels(Lhs.Label, Rhs.Label, SortUsingDeclarations) < 0;
153 llvm::stable_sort(SortedUsingDeclarations, Comp);
154 SortedUsingDeclarations.erase(
155 std::unique(SortedUsingDeclarations.begin(),
156 SortedUsingDeclarations.end(),
157 [](
const UsingDeclaration &a,
const UsingDeclaration &
b) {
158 return a.Label == b.Label;
160 SortedUsingDeclarations.end());
161 for (
size_t I = 0, E = UsingDeclarations->size(); I < E; ++I) {
162 if (I >= SortedUsingDeclarations.size()) {
165 (*UsingDeclarations)[I].Line->First->WhitespaceRange.getBegin();
166 auto End = (*UsingDeclarations)[I].Line->Last->Tok.getEndLoc();
168 auto Err = Fixes->add(tooling::Replacement(SourceMgr, Range,
""));
170 llvm::errs() <<
"Error while sorting using declarations: "
171 << llvm::toString(std::move(Err)) <<
"\n";
175 if ((*UsingDeclarations)[I].
Line == SortedUsingDeclarations[I].
Line)
177 auto Begin = (*UsingDeclarations)[I].Line->First->Tok.getLocation();
178 auto End = (*UsingDeclarations)[I].Line->Last->Tok.getEndLoc();
180 SortedUsingDeclarations[I].Line->First->Tok.getLocation();
181 auto SortedEnd = SortedUsingDeclarations[I].Line->Last->Tok.getEndLoc();
182 StringRef
Text(SourceMgr.getCharacterData(SortedBegin),
183 SourceMgr.getCharacterData(SortedEnd) -
184 SourceMgr.getCharacterData(SortedBegin));
186 StringRef OldText(SourceMgr.getCharacterData(
Begin),
187 SourceMgr.getCharacterData(End) -
188 SourceMgr.getCharacterData(
Begin));
189 llvm::dbgs() <<
"Replacing '" << OldText <<
"' with '" <<
Text <<
"'\n";
192 auto Err = Fixes->add(tooling::Replacement(SourceMgr, Range,
Text));
194 llvm::errs() <<
"Error while sorting using declarations: "
195 << llvm::toString(std::move(Err)) <<
"\n";
198 UsingDeclarations->clear();
215 const auto *FirstTok =
Line->First;
216 if (
Line->InPPDirective || !
Line->startsWith(tok::kw_using) ||
217 FirstTok->Finalized) {
218 endUsingDeclarationBlock(&UsingDeclarations, SourceMgr, &Fixes,
222 if (FirstTok->NewlinesBefore > 1) {
223 endUsingDeclarationBlock(&UsingDeclarations, SourceMgr, &Fixes,
226 const auto *UsingTok =
227 FirstTok->is(tok::comment) ? FirstTok->getNextNonComment() : FirstTok;
228 std::string
Label = computeUsingDeclarationLabel(UsingTok);
230 endUsingDeclarationBlock(&UsingDeclarations, SourceMgr, &Fixes,
234 UsingDeclarations.push_back(UsingDeclaration(
Line,
Label));
236 endUsingDeclarationBlock(&UsingDeclarations, SourceMgr, &Fixes,
This file declares UsingDeclarationsSorter, a TokenAnalyzer that sorts consecutive using declarations...
static CharSourceRange getCharRange(SourceRange R)
This class handles loading and caching of source files into memory.
bool Comp(InterpState &S, CodePtr OpPC)
1) Pops the value from the stack.
The JSON file list parser is used to communicate input to InstallAPI.