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 std::unique(SortedUsingDeclarations.begin(),
161 SortedUsingDeclarations.end(),
162 [](
const UsingDeclaration &a,
const UsingDeclaration &
b) {
163 return a.Label == b.Label;
165 SortedUsingDeclarations.end());
166 for (
size_t I = 0,
E = UsingDeclarations->size(); I <
E; ++I) {
167 if (I >= SortedUsingDeclarations.size()) {
170 (*UsingDeclarations)[I].Line->First->WhitespaceRange.getBegin();
171 auto End = (*UsingDeclarations)[I].Line->Last->Tok.getEndLoc();
173 auto Err = Fixes->add(tooling::Replacement(SourceMgr,
Range,
""));
175 llvm::errs() <<
"Error while sorting using declarations: "
176 << llvm::toString(std::move(Err)) <<
"\n";
180 if ((*UsingDeclarations)[I].
Line == SortedUsingDeclarations[I].
Line)
182 auto Begin = (*UsingDeclarations)[I].Line->First->Tok.getLocation();
183 auto End = (*UsingDeclarations)[I].Line->Last->Tok.getEndLoc();
185 SortedUsingDeclarations[I].Line->First->Tok.getLocation();
186 auto SortedEnd = SortedUsingDeclarations[I].Line->Last->Tok.getEndLoc();
187 StringRef
Text(SourceMgr.getCharacterData(SortedBegin),
188 SourceMgr.getCharacterData(SortedEnd) -
189 SourceMgr.getCharacterData(SortedBegin));
191 StringRef OldText(SourceMgr.getCharacterData(
Begin),
192 SourceMgr.getCharacterData(End) -
193 SourceMgr.getCharacterData(
Begin));
194 llvm::dbgs() <<
"Replacing '" << OldText <<
"' with '" <<
Text <<
"'\n";
197 auto Err = Fixes->add(tooling::Replacement(SourceMgr,
Range,
Text));
199 llvm::errs() <<
"Error while sorting using declarations: "
200 << llvm::toString(std::move(Err)) <<
"\n";
203 UsingDeclarations->clear();
220 const auto *FirstTok =
Line->First;
221 if (
Line->InPPDirective || !
Line->startsWith(tok::kw_using) ||
222 FirstTok->Finalized) {
223 endUsingDeclarationBlock(&UsingDeclarations, SourceMgr, &Fixes,
227 if (FirstTok->NewlinesBefore > 1) {
228 endUsingDeclarationBlock(&UsingDeclarations, SourceMgr, &Fixes,
231 const auto *UsingTok =
232 FirstTok->is(tok::comment) ? FirstTok->getNextNonComment() : FirstTok;
233 std::string
Label = computeUsingDeclarationLabel(UsingTok);
235 endUsingDeclarationBlock(&UsingDeclarations, SourceMgr, &Fixes,
239 UsingDeclarations.push_back(UsingDeclaration(
Line,
Label));
241 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.