28 IncludeSorter::IncludeStyle Style) {
35 if (Style == IncludeSorter::IS_LLVM) {
39 if (Style == IncludeSorter::IS_Google_ObjC) {
42 ".hpp",
".mm",
".m"}),
43 {
"_unittest",
"_regtest",
"_test",
"Test"});
47 size_t StartIndex = Canonical.find_last_of(
'/');
48 if (StartIndex == StringRef::npos) {
51 return Canonical.substr(0, Canonical.find_first_of(
'+', StartIndex));
55 {
"_unittest",
"_regtest",
"_test"});
66 bool IsAngled, IncludeSorter::IncludeStyle Style) {
74 return IncludeFile.ends_with(
".h") ? IncludeSorter::IK_CSystemInclude
75 : IncludeSorter::IK_CXXSystemInclude;
78 if (CanonicalFile.ends_with(CanonicalInclude) ||
79 CanonicalInclude.ends_with(CanonicalFile)) {
80 return IncludeSorter::IK_MainTUInclude;
82 if ((Style == IncludeSorter::IS_Google) ||
83 (Style == IncludeSorter::IS_Google_ObjC)) {
84 std::pair<StringRef, StringRef> Parts = CanonicalInclude.split(
"/public/");
85 StringRef FileCopy = CanonicalFile;
86 if (FileCopy.consume_front(Parts.first) &&
87 FileCopy.consume_back(Parts.second)) {
89 if (FileCopy ==
"/internal/" || FileCopy ==
"/proto/") {
90 return IncludeSorter::IK_MainTUInclude;
94 if (Style == IncludeSorter::IS_Google_ObjC) {
95 if (IncludeFile.ends_with(
".generated.h") ||
96 IncludeFile.ends_with(
".proto.h") ||
97 IncludeFile.ends_with(
".pbobjc.h")) {
98 return IncludeSorter::IK_GeneratedInclude;
101 return IncludeSorter::IK_NonSystemInclude;
105 IncludeSorter::IncludeStyle Style) {
106 if (Style == IncludeSorter::IncludeStyle::IS_Google_ObjC) {
107 const std::pair<const char *, const char *> &Mismatch =
108 std::mismatch(LHS.begin(), LHS.end(), RHS.begin(), RHS.end());
109 if ((Mismatch.first != LHS.end()) && (Mismatch.second != RHS.end())) {
110 if ((*Mismatch.first ==
'.') && (*Mismatch.second ==
'+')) {
113 if ((*Mismatch.first ==
'+') && (*Mismatch.second ==
'.')) {
118 return LHS.compare(RHS);
121IncludeSorter::IncludeSorter(
const SourceManager *SourceMgr,
122 const FileID FileID, StringRef FileName,
124 : SourceMgr(SourceMgr), Style(Style), CurrentFileID(FileID),
144 determineIncludeKind(CanonicalFile, FileName, IsAngled, Style);
150IncludeSorter::createIncludeInsertion(StringRef FileName,
bool IsAngled) {
151 std::string IncludeStmt;
152 if (Style == IncludeStyle::IS_Google_ObjC) {
153 IncludeStmt = IsAngled
154 ? llvm::Twine(
"#import <" + FileName +
">\n").str()
155 : llvm::Twine(
"#import \"" + FileName +
"\"\n").str();
157 IncludeStmt = IsAngled
158 ? llvm::Twine(
"#include <" + FileName +
">\n").str()
159 : llvm::Twine(
"#include \"" + FileName +
"\"\n").str();
161 if (SourceLocations.empty()) {
164 IncludeStmt.append(
"\n");
165 return FixItHint::CreateInsertion(
166 SourceMgr->getLocForStartOfFile(CurrentFileID), IncludeStmt);
172 if (!IncludeBucket[IncludeKind].empty()) {
173 for (
const std::string &IncludeEntry : IncludeBucket[IncludeKind]) {
175 const auto &
Location = IncludeLocations[IncludeEntry][0];
176 return FixItHint::CreateInsertion(
Location.getBegin(), IncludeStmt);
178 if (FileName == IncludeEntry) {
184 const std::string &LastInclude = IncludeBucket[IncludeKind].back();
185 SourceRange LastIncludeLocation = IncludeLocations[LastInclude].back();
186 return FixItHint::CreateInsertion(LastIncludeLocation.getEnd(),
194 IncludeKinds NonEmptyKind = IK_InvalidInclude;
195 for (
int I = IK_InvalidInclude - 1; I >= 0; --I) {
196 if (!IncludeBucket[I].empty()) {
197 NonEmptyKind =
static_cast<IncludeKinds
>(I);
198 if (NonEmptyKind < IncludeKind)
202 if (NonEmptyKind == IK_InvalidInclude) {
206 if (NonEmptyKind < IncludeKind) {
208 const std::string &LastInclude = IncludeBucket[NonEmptyKind].back();
209 SourceRange LastIncludeLocation = IncludeLocations[LastInclude].back();
210 IncludeStmt =
'\n' + IncludeStmt;
211 return FixItHint::CreateInsertion(LastIncludeLocation.getEnd(),
215 const std::string &FirstInclude = IncludeBucket[NonEmptyKind][0];
216 SourceRange FirstIncludeLocation = IncludeLocations[FirstInclude].back();
217 IncludeStmt.append(
"\n");
218 return FixItHint::CreateInsertion(FirstIncludeLocation.getBegin(),