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) {
38 A.split(NamesA,
"::", -1,
false);
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) {
70 A.split(NamesA,
"::", -1,
false);
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");
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();
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,
223 Style.SortUsingDeclarations);
226 if (FirstTok->NewlinesBefore > 1) {
227 endUsingDeclarationBlock(&UsingDeclarations, SourceMgr, &Fixes,
228 Style.SortUsingDeclarations);
230 const auto *UsingTok =
231 FirstTok->is(tok::comment) ? FirstTok->getNextNonComment() : FirstTok;
232 std::string Label = computeUsingDeclarationLabel(UsingTok);
234 endUsingDeclarationBlock(&UsingDeclarations, SourceMgr, &Fixes,
235 Style.SortUsingDeclarations);
238 UsingDeclarations.push_back(UsingDeclaration(
Line, Label));
240 endUsingDeclarationBlock(&UsingDeclarations, SourceMgr, &Fixes,
241 Style.SortUsingDeclarations);
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.
Top level wrappers for InstallAPI frontend operations.