17#include "llvm/Support/Debug.h"
18#include "llvm/Support/Regex.h"
22#define DEBUG_TYPE "using-declarations-sorter"
36int compareLabelsLexicographicNumeric(StringRef A, StringRef B) {
37 SmallVector<StringRef, 2> NamesA;
38 A.split(NamesA,
"::", -1,
false);
39 SmallVector<StringRef, 2> NamesB;
40 B.split(NamesB,
"::", -1,
false);
41 size_t SizeA = NamesA.size();
42 size_t SizeB = NamesB.size();
43 for (
size_t I = 0,
E = std::min(SizeA, SizeB); I <
E; ++I) {
52 return NamesA[I].compare_insensitive(NamesB[I]);
61 int C = NamesA[I].compare_insensitive(NamesB[I]);
68int compareLabelsLexicographic(StringRef A, StringRef B) {
69 SmallVector<StringRef, 2> NamesA;
70 A.split(NamesA,
"::", -1,
false);
71 SmallVector<StringRef, 2> NamesB;
72 B.split(NamesB,
"::", -1,
false);
73 size_t SizeA = NamesA.size();
74 size_t SizeB = NamesB.size();
75 for (
size_t I = 0,
E = std::min(SizeA, SizeB); I <
E; ++I) {
77 int C = NamesA[I].compare_insensitive(NamesB[I]);
83 return SizeA == SizeB ? 0 : 1;
87 StringRef A, StringRef B,
90 return compareLabelsLexicographicNumeric(A, B);
91 return compareLabelsLexicographic(A, B);
94struct UsingDeclaration {
95 const AnnotatedLine *Line;
98 UsingDeclaration(
const AnnotatedLine *Line,
const std::string &Label)
110std::string computeUsingDeclarationLabel(
const FormatToken *UsingTok) {
111 assert(UsingTok && UsingTok->is(tok::kw_using) &&
"Expecting a using token");
113 const FormatToken *Tok = UsingTok->Next;
114 if (Tok && Tok->is(tok::kw_typename)) {
115 Label.append(
"typename ");
118 if (Tok && Tok->is(tok::coloncolon)) {
122 bool HasIdentifier =
false;
123 while (Tok && Tok->is(tok::identifier)) {
124 HasIdentifier =
true;
125 Label.append(Tok->TokenText.str());
127 if (!Tok || Tok->isNot(tok::coloncolon))
132 if (HasIdentifier && Tok && Tok->isOneOf(tok::semi, tok::comma))
137void endUsingDeclarationBlock(
138 SmallVectorImpl<UsingDeclaration> *UsingDeclarations,
139 const SourceManager &SourceMgr, tooling::Replacements *Fixes,
141 bool BlockAffected =
false;
142 for (
const UsingDeclaration &
Declaration : *UsingDeclarations) {
144 BlockAffected =
true;
148 if (!BlockAffected) {
149 UsingDeclarations->clear();
152 SmallVector<UsingDeclaration, 4> SortedUsingDeclarations(
153 UsingDeclarations->begin(), UsingDeclarations->end());
154 auto Comp = [SortUsingDeclarations](
const UsingDeclaration &Lhs,
155 const UsingDeclaration &Rhs) ->
bool {
156 return compareLabels(Lhs.Label, Rhs.Label, SortUsingDeclarations) < 0;
158 llvm::stable_sort(SortedUsingDeclarations, Comp);
159 SortedUsingDeclarations.erase(
160 llvm::unique(SortedUsingDeclarations,
161 [](
const UsingDeclaration &a,
const UsingDeclaration &
b) {
162 return a.Label ==
b.Label;
164 SortedUsingDeclarations.end());
165 for (
size_t I = 0,
E = UsingDeclarations->size(); I <
E; ++I) {
166 if (I >= SortedUsingDeclarations.size()) {
169 (*UsingDeclarations)[I].Line->First->WhitespaceRange.getBegin();
170 auto End = (*UsingDeclarations)[I].Line->Last->Tok.getEndLoc();
172 auto Err = Fixes->add(tooling::Replacement(SourceMgr,
Range,
""));
174 llvm::errs() <<
"Error while sorting using declarations: "
175 << llvm::toString(std::move(Err)) <<
"\n";
179 if ((*UsingDeclarations)[I].
Line == SortedUsingDeclarations[I].
Line)
181 auto Begin = (*UsingDeclarations)[I].Line->First->Tok.getLocation();
182 auto End = (*UsingDeclarations)[I].Line->Last->Tok.getEndLoc();
184 SortedUsingDeclarations[I].Line->First->Tok.getLocation();
185 auto SortedEnd = SortedUsingDeclarations[I].Line->Last->Tok.getEndLoc();
186 StringRef
Text(SourceMgr.getCharacterData(SortedBegin),
187 SourceMgr.getCharacterData(SortedEnd) -
188 SourceMgr.getCharacterData(SortedBegin));
190 StringRef OldText(SourceMgr.getCharacterData(
Begin),
191 SourceMgr.getCharacterData(End) -
192 SourceMgr.getCharacterData(
Begin));
193 llvm::dbgs() <<
"Replacing '" << OldText <<
"' with '" <<
Text <<
"'\n";
196 auto Err = Fixes->add(tooling::Replacement(SourceMgr,
Range,
Text));
198 llvm::errs() <<
"Error while sorting using declarations: "
199 << llvm::toString(std::move(Err)) <<
"\n";
202 UsingDeclarations->clear();
219 const auto *FirstTok =
Line->First;
220 if (
Line->InPPDirective || !
Line->startsWith(tok::kw_using) ||
221 FirstTok->Finalized) {
222 endUsingDeclarationBlock(&UsingDeclarations, SourceMgr, &Fixes,
226 if (FirstTok->NewlinesBefore > 1) {
227 endUsingDeclarationBlock(&UsingDeclarations, SourceMgr, &Fixes,
230 const auto *UsingTok =
231 FirstTok->is(tok::comment) ? FirstTok->getNextNonComment() : FirstTok;
232 std::string
Label = computeUsingDeclarationLabel(UsingTok);
234 endUsingDeclarationBlock(&UsingDeclarations, SourceMgr, &Fixes,
238 UsingDeclarations.push_back(UsingDeclaration(
Line,
Label));
240 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.