34 #include "llvm/ADT/STLExtras.h" 35 #include "llvm/Support/Allocator.h" 36 #include "llvm/Support/Debug.h" 37 #include "llvm/Support/Path.h" 38 #include "llvm/Support/Regex.h" 39 #include "llvm/Support/YAMLTraits.h" 44 #define DEBUG_TYPE "format-formatter" 53 template <>
struct ScalarEnumerationTraits<
FormatStyle::LanguageKind> {
55 IO.enumCase(Value,
"Cpp", FormatStyle::LK_Cpp);
56 IO.enumCase(Value,
"Java", FormatStyle::LK_Java);
57 IO.enumCase(Value,
"JavaScript", FormatStyle::LK_JavaScript);
58 IO.enumCase(Value,
"ObjC", FormatStyle::LK_ObjC);
59 IO.enumCase(Value,
"Proto", FormatStyle::LK_Proto);
60 IO.enumCase(Value,
"TableGen", FormatStyle::LK_TableGen);
61 IO.enumCase(Value,
"TextProto", FormatStyle::LK_TextProto);
65 template <>
struct ScalarEnumerationTraits<
FormatStyle::LanguageStandard> {
67 IO.enumCase(Value,
"Cpp03", FormatStyle::LS_Cpp03);
68 IO.enumCase(Value,
"C++03", FormatStyle::LS_Cpp03);
69 IO.enumCase(Value,
"Cpp11", FormatStyle::LS_Cpp11);
70 IO.enumCase(Value,
"C++11", FormatStyle::LS_Cpp11);
71 IO.enumCase(Value,
"Auto", FormatStyle::LS_Auto);
75 template <>
struct ScalarEnumerationTraits<
FormatStyle::UseTabStyle> {
77 IO.enumCase(Value,
"Never", FormatStyle::UT_Never);
78 IO.enumCase(Value,
"false", FormatStyle::UT_Never);
79 IO.enumCase(Value,
"Always", FormatStyle::UT_Always);
80 IO.enumCase(Value,
"true", FormatStyle::UT_Always);
81 IO.enumCase(Value,
"ForIndentation", FormatStyle::UT_ForIndentation);
82 IO.enumCase(Value,
"ForContinuationAndIndentation",
83 FormatStyle::UT_ForContinuationAndIndentation);
87 template <>
struct ScalarEnumerationTraits<
FormatStyle::JavaScriptQuoteStyle> {
89 IO.enumCase(Value,
"Leave", FormatStyle::JSQS_Leave);
90 IO.enumCase(Value,
"Single", FormatStyle::JSQS_Single);
91 IO.enumCase(Value,
"Double", FormatStyle::JSQS_Double);
95 template <>
struct ScalarEnumerationTraits<
FormatStyle::ShortFunctionStyle> {
97 IO.enumCase(Value,
"None", FormatStyle::SFS_None);
98 IO.enumCase(Value,
"false", FormatStyle::SFS_None);
99 IO.enumCase(Value,
"All", FormatStyle::SFS_All);
100 IO.enumCase(Value,
"true", FormatStyle::SFS_All);
101 IO.enumCase(Value,
"Inline", FormatStyle::SFS_Inline);
102 IO.enumCase(Value,
"InlineOnly", FormatStyle::SFS_InlineOnly);
103 IO.enumCase(Value,
"Empty", FormatStyle::SFS_Empty);
107 template <>
struct ScalarEnumerationTraits<
FormatStyle::BinaryOperatorStyle> {
109 IO.enumCase(Value,
"All", FormatStyle::BOS_All);
110 IO.enumCase(Value,
"true", FormatStyle::BOS_All);
111 IO.enumCase(Value,
"None", FormatStyle::BOS_None);
112 IO.enumCase(Value,
"false", FormatStyle::BOS_None);
113 IO.enumCase(Value,
"NonAssignment", FormatStyle::BOS_NonAssignment);
117 template <>
struct ScalarEnumerationTraits<
FormatStyle::BraceBreakingStyle> {
119 IO.enumCase(Value,
"Attach", FormatStyle::BS_Attach);
120 IO.enumCase(Value,
"Linux", FormatStyle::BS_Linux);
121 IO.enumCase(Value,
"Mozilla", FormatStyle::BS_Mozilla);
122 IO.enumCase(Value,
"Stroustrup", FormatStyle::BS_Stroustrup);
123 IO.enumCase(Value,
"Allman", FormatStyle::BS_Allman);
124 IO.enumCase(Value,
"GNU", FormatStyle::BS_GNU);
125 IO.enumCase(Value,
"WebKit", FormatStyle::BS_WebKit);
126 IO.enumCase(Value,
"Custom", FormatStyle::BS_Custom);
131 struct ScalarEnumerationTraits<
FormatStyle::BreakConstructorInitializersStyle> {
134 IO.enumCase(Value,
"BeforeColon", FormatStyle::BCIS_BeforeColon);
135 IO.enumCase(Value,
"BeforeComma", FormatStyle::BCIS_BeforeComma);
136 IO.enumCase(Value,
"AfterColon", FormatStyle::BCIS_AfterColon);
141 struct ScalarEnumerationTraits<
FormatStyle::PPDirectiveIndentStyle> {
143 IO.enumCase(Value,
"None", FormatStyle::PPDIS_None);
144 IO.enumCase(Value,
"AfterHash", FormatStyle::PPDIS_AfterHash);
149 struct ScalarEnumerationTraits<
FormatStyle::ReturnTypeBreakingStyle> {
151 IO.enumCase(Value,
"None", FormatStyle::RTBS_None);
152 IO.enumCase(Value,
"All", FormatStyle::RTBS_All);
153 IO.enumCase(Value,
"TopLevel", FormatStyle::RTBS_TopLevel);
154 IO.enumCase(Value,
"TopLevelDefinitions",
155 FormatStyle::RTBS_TopLevelDefinitions);
156 IO.enumCase(Value,
"AllDefinitions", FormatStyle::RTBS_AllDefinitions);
161 struct ScalarEnumerationTraits<
FormatStyle::DefinitionReturnTypeBreakingStyle> {
164 IO.enumCase(Value,
"None", FormatStyle::DRTBS_None);
165 IO.enumCase(Value,
"All", FormatStyle::DRTBS_All);
166 IO.enumCase(Value,
"TopLevel", FormatStyle::DRTBS_TopLevel);
169 IO.enumCase(Value,
"false", FormatStyle::DRTBS_None);
170 IO.enumCase(Value,
"true", FormatStyle::DRTBS_All);
175 struct ScalarEnumerationTraits<
FormatStyle::NamespaceIndentationKind> {
177 FormatStyle::NamespaceIndentationKind &
Value) {
178 IO.enumCase(Value,
"None", FormatStyle::NI_None);
179 IO.enumCase(Value,
"Inner", FormatStyle::NI_Inner);
180 IO.enumCase(Value,
"All", FormatStyle::NI_All);
184 template <>
struct ScalarEnumerationTraits<
FormatStyle::BracketAlignmentStyle> {
186 IO.enumCase(Value,
"Align", FormatStyle::BAS_Align);
187 IO.enumCase(Value,
"DontAlign", FormatStyle::BAS_DontAlign);
188 IO.enumCase(Value,
"AlwaysBreak", FormatStyle::BAS_AlwaysBreak);
191 IO.enumCase(Value,
"true", FormatStyle::BAS_Align);
192 IO.enumCase(Value,
"false", FormatStyle::BAS_DontAlign);
197 struct ScalarEnumerationTraits<
FormatStyle::EscapedNewlineAlignmentStyle> {
199 FormatStyle::EscapedNewlineAlignmentStyle &
Value) {
200 IO.enumCase(Value,
"DontAlign", FormatStyle::ENAS_DontAlign);
201 IO.enumCase(Value,
"Left", FormatStyle::ENAS_Left);
202 IO.enumCase(Value,
"Right", FormatStyle::ENAS_Right);
205 IO.enumCase(Value,
"true", FormatStyle::ENAS_Left);
206 IO.enumCase(Value,
"false", FormatStyle::ENAS_Right);
210 template <>
struct ScalarEnumerationTraits<
FormatStyle::PointerAlignmentStyle> {
212 IO.enumCase(Value,
"Middle", FormatStyle::PAS_Middle);
213 IO.enumCase(Value,
"Left", FormatStyle::PAS_Left);
214 IO.enumCase(Value,
"Right", FormatStyle::PAS_Right);
217 IO.enumCase(Value,
"true", FormatStyle::PAS_Left);
218 IO.enumCase(Value,
"false", FormatStyle::PAS_Right);
223 struct ScalarEnumerationTraits<
FormatStyle::SpaceBeforeParensOptions> {
225 FormatStyle::SpaceBeforeParensOptions &
Value) {
226 IO.enumCase(Value,
"Never", FormatStyle::SBPO_Never);
227 IO.enumCase(Value,
"ControlStatements",
228 FormatStyle::SBPO_ControlStatements);
229 IO.enumCase(Value,
"Always", FormatStyle::SBPO_Always);
232 IO.enumCase(Value,
"false", FormatStyle::SBPO_Never);
233 IO.enumCase(Value,
"true", FormatStyle::SBPO_ControlStatements);
240 IO.mapOptional(
"Language", Style.
Language);
242 if (IO.outputting()) {
243 StringRef StylesArray[] = {
"LLVM",
"Google",
"Chromium",
244 "Mozilla",
"WebKit",
"GNU"};
246 for (
size_t i = 0, e = Styles.size(); i < e; ++i) {
247 StringRef StyleName(Styles[i]);
250 Style == PredefinedStyle) {
251 IO.mapOptional(
"# BasedOnStyle", StyleName);
256 StringRef BasedOnStyle;
257 IO.mapOptional(
"BasedOnStyle", BasedOnStyle);
258 if (!BasedOnStyle.empty()) {
259 FormatStyle::LanguageKind OldLanguage = Style.
Language;
260 FormatStyle::LanguageKind Language =
263 IO.setError(Twine(
"Unknown value for BasedOnStyle: ", BasedOnStyle));
271 if (!IO.outputting()) {
274 IO.mapOptional(
"IndentFunctionDeclarationAfterType",
277 IO.mapOptional(
"SpaceAfterControlStatementKeyword",
283 IO.mapOptional(
"AlignConsecutiveAssignments",
285 IO.mapOptional(
"AlignConsecutiveDeclarations",
290 IO.mapOptional(
"AllowAllParametersOfDeclarationOnNextLine",
292 IO.mapOptional(
"AllowShortBlocksOnASingleLine",
294 IO.mapOptional(
"AllowShortCaseLabelsOnASingleLine",
296 IO.mapOptional(
"AllowShortFunctionsOnASingleLine",
298 IO.mapOptional(
"AllowShortIfStatementsOnASingleLine",
300 IO.mapOptional(
"AllowShortLoopsOnASingleLine",
302 IO.mapOptional(
"AlwaysBreakAfterDefinitionReturnType",
304 IO.mapOptional(
"AlwaysBreakAfterReturnType",
314 FormatStyle::DRTBS_TopLevel)
316 FormatStyle::RTBS_TopLevelDefinitions;
319 IO.mapOptional(
"AlwaysBreakBeforeMultilineStrings",
321 IO.mapOptional(
"AlwaysBreakTemplateDeclarations",
326 IO.mapOptional(
"BreakBeforeBinaryOperators",
329 IO.mapOptional(
"BreakBeforeInheritanceComma",
331 IO.mapOptional(
"BreakBeforeTernaryOperators",
334 bool BreakConstructorInitializersBeforeComma =
false;
335 IO.mapOptional(
"BreakConstructorInitializersBeforeComma",
336 BreakConstructorInitializersBeforeComma);
337 IO.mapOptional(
"BreakConstructorInitializers",
342 if (BreakConstructorInitializersBeforeComma &&
346 IO.mapOptional(
"BreakAfterJavaFieldAnnotations",
352 IO.mapOptional(
"ConstructorInitializerAllOnOneLineOrOnePerLine",
354 IO.mapOptional(
"ConstructorInitializerIndentWidth",
360 IO.mapOptional(
"ExperimentalAutoDetectBinPacking",
370 IO.mapOptional(
"IndentWrappedFunctionNames",
374 IO.mapOptional(
"KeepEmptyLinesAtTheStartOfBlocks",
382 IO.mapOptional(
"ObjCSpaceBeforeProtocolList",
385 IO.mapOptional(
"PenaltyBreakBeforeFirstCallParameter",
388 IO.mapOptional(
"PenaltyBreakFirstLessLess",
392 IO.mapOptional(
"PenaltyReturnTypeOnItsOwnLine",
400 IO.mapOptional(
"SpaceAfterTemplateKeyword",
402 IO.mapOptional(
"SpaceBeforeAssignmentOperators",
406 IO.mapOptional(
"SpacesBeforeTrailingComments",
409 IO.mapOptional(
"SpacesInContainerLiterals",
411 IO.mapOptional(
"SpacesInCStyleCastParentheses",
415 IO.mapOptional(
"Standard", Style.
Standard);
416 IO.mapOptional(
"TabWidth", Style.
TabWidth);
417 IO.mapOptional(
"UseTab", Style.
UseTab);
421 template <>
struct MappingTraits<
FormatStyle::BraceWrappingFlags> {
422 static void mapping(IO &IO, FormatStyle::BraceWrappingFlags &Wrapping) {
423 IO.mapOptional(
"AfterClass", Wrapping.AfterClass);
424 IO.mapOptional(
"AfterControlStatement", Wrapping.AfterControlStatement);
425 IO.mapOptional(
"AfterEnum", Wrapping.AfterEnum);
426 IO.mapOptional(
"AfterFunction", Wrapping.AfterFunction);
427 IO.mapOptional(
"AfterNamespace", Wrapping.AfterNamespace);
428 IO.mapOptional(
"AfterObjCDeclaration", Wrapping.AfterObjCDeclaration);
429 IO.mapOptional(
"AfterStruct", Wrapping.AfterStruct);
430 IO.mapOptional(
"AfterUnion", Wrapping.AfterUnion);
431 IO.mapOptional(
"AfterExternBlock", Wrapping.AfterExternBlock);
432 IO.mapOptional(
"BeforeCatch", Wrapping.BeforeCatch);
433 IO.mapOptional(
"BeforeElse", Wrapping.BeforeElse);
434 IO.mapOptional(
"IndentBraces", Wrapping.IndentBraces);
435 IO.mapOptional(
"SplitEmptyFunction", Wrapping.SplitEmptyFunction);
436 IO.mapOptional(
"SplitEmptyRecord", Wrapping.SplitEmptyRecord);
437 IO.mapOptional(
"SplitEmptyNamespace", Wrapping.SplitEmptyNamespace);
443 IO.mapOptional(
"Regex", Category.Regex);
444 IO.mapOptional(
"Priority", Category.Priority);
448 template <>
struct ScalarEnumerationTraits<
FormatStyle::IncludeBlocksStyle> {
450 IO.enumCase(Value,
"Preserve", FormatStyle::IBS_Preserve);
451 IO.enumCase(Value,
"Merge", FormatStyle::IBS_Merge);
452 IO.enumCase(Value,
"Regroup", FormatStyle::IBS_Regroup);
457 static void mapping(IO &IO, FormatStyle::RawStringFormat &Format) {
458 IO.mapOptional(
"Delimiter", Format.Delimiter);
459 IO.mapOptional(
"Language", Format.Language);
460 IO.mapOptional(
"BasedOnStyle", Format.BasedOnStyle);
469 template <>
struct DocumentListTraits<
std::vector<FormatStyle>> {
470 static size_t size(IO &IO, std::vector<FormatStyle> &Seq) {
475 if (Index >= Seq.size()) {
476 assert(Index == Seq.size());
478 if (!Seq.empty() && Seq[0].Language == FormatStyle::LK_None) {
481 Template = *((
const FormatStyle *)IO.getContext());
482 Template.
Language = FormatStyle::LK_None;
484 Seq.resize(Index + 1, Template);
504 return llvm::make_error<llvm::StringError>(Message,
505 llvm::inconvertibleErrorCode());
508 const char *ParseErrorCategory::name() const noexcept {
509 return "clang-format.parse_error";
512 std::string ParseErrorCategory::message(
int EV)
const {
513 switch (static_cast<ParseError>(EV)) {
514 case ParseError::Success:
517 return "Invalid argument";
518 case ParseError::Unsuitable:
521 llvm_unreachable(
"unexpected parse error");
529 false,
false,
false,
false,
false,
530 false,
false,
true,
true,
true};
532 case FormatStyle::BS_Linux:
537 case FormatStyle::BS_Mozilla:
547 case FormatStyle::BS_Stroustrup:
552 case FormatStyle::BS_Allman:
564 case FormatStyle::BS_GNU:
565 Expanded.
BraceWrapping = {
true,
true,
true,
true,
true,
true,
true,
true,
566 true,
true,
true,
true,
true,
true,
true};
568 case FormatStyle::BS_WebKit:
579 LLVMStyle.
Language = FormatStyle::LK_Cpp;
602 LLVMStyle.
BraceWrapping = {
false,
false,
false,
false,
false,
603 false,
false,
false,
false,
false,
604 false,
false,
true,
true,
true};
623 {
"^(<|\"(gtest|gmock|isl|json)/)", 3},
642 LLVMStyle.
Standard = FormatStyle::LS_Cpp11;
643 LLVMStyle.
UseTab = FormatStyle::UT_Never;
673 if (Language == FormatStyle::LK_TextProto) {
675 GoogleStyle.
Language = FormatStyle::LK_TextProto;
691 {
"^<ext/.*\\.h>", 2}, {
"^<.*\\.h>", 1}, {
"^<.*", 2}, {
".*", 3}};
699 GoogleStyle.
Standard = FormatStyle::LS_Auto;
704 if (Language == FormatStyle::LK_Java) {
715 }
else if (Language == FormatStyle::LK_JavaScript) {
724 "(taze:|^/[ \t]*<|(@[A-Za-z_0-9-]+[ \\t]*{)|@see)";
730 }
else if (Language == FormatStyle::LK_Proto) {
733 }
else if (Language == FormatStyle::LK_ObjC) {
742 if (Language == FormatStyle::LK_Java) {
747 }
else if (Language == FormatStyle::LK_JavaScript) {
757 if (Language == FormatStyle::LK_ObjC)
760 return ChromiumStyle;
769 FormatStyle::DRTBS_TopLevel;
820 Style.
Standard = FormatStyle::LS_Cpp03;
834 if (Name.equals_lower(
"llvm")) {
836 }
else if (Name.equals_lower(
"chromium")) {
838 }
else if (Name.equals_lower(
"mozilla")) {
840 }
else if (Name.equals_lower(
"google")) {
842 }
else if (Name.equals_lower(
"webkit")) {
844 }
else if (Name.equals_lower(
"gnu")) {
846 }
else if (Name.equals_lower(
"none")) {
859 assert(Language != FormatStyle::LK_None);
860 if (Text.trim().empty())
863 std::vector<FormatStyle> Styles;
864 llvm::yaml::Input Input(Text);
869 Input.setContext(Style);
872 return Input.error();
874 for (
unsigned i = 0; i < Styles.size(); ++i) {
876 if (Styles[i].Language == FormatStyle::LK_None && i != 0)
879 for (
unsigned j = 0; j < i; ++j) {
880 if (Styles[i].Language == Styles[j].Language) {
882 <<
"Duplicate languages in the config file on positions " << j
883 <<
" and " << i <<
"\n");
891 for (
int i = Styles.size() - 1; i >= 0; --i) {
892 if (Styles[i].Language == Language ||
893 Styles[i].Language == FormatStyle::LK_None) {
904 llvm::raw_string_ostream Stream(Text);
905 llvm::yaml::Output Output(Stream);
909 Output << NonConstStyle;
920 std::pair<tooling::Replacements, unsigned>
924 AffectedRangeMgr.computeAffectedLines(AnnotatedLines.begin(),
925 AnnotatedLines.end());
927 requoteJSStringLiteral(AnnotatedLines, Result);
937 requoteJSStringLiteral(
Line->Children, Result);
941 FormatTok = FormatTok->Next) {
942 StringRef Input = FormatTok->TokenText;
943 if (FormatTok->Finalized || !FormatTok->isStringLiteral() ||
947 !Input.startswith(
"\"")) ||
949 !Input.startswith(
"\'")))
956 StringRef ReplacementText) {
966 Replace(Start, 1, IsSingle ?
"'" :
"\"");
967 Replace(FormatTok->Tok.getEndLoc().getLocWithOffset(-1), 1,
968 IsSingle ?
"'" :
"\"");
971 bool Escaped =
false;
972 for (
size_t i = 1; i < Input.size() - 1; i++) {
975 if (!Escaped && i + 1 < Input.size() &&
976 ((IsSingle && Input[i + 1] ==
'"') ||
977 (!IsSingle && Input[i + 1] ==
'\''))) {
987 if (!Escaped && IsSingle == (Input[i] ==
'\'')) {
1009 std::pair<tooling::Replacements, unsigned>
1014 deriveLocalStyle(AnnotatedLines);
1015 AffectedRangeMgr.computeAffectedLines(AnnotatedLines.begin(),
1016 AnnotatedLines.end());
1017 for (
unsigned i = 0, e = AnnotatedLines.size(); i != e; ++i) {
1027 BinPackInconclusiveFunctions);
1032 .format(AnnotatedLines,
false,
1038 for (
const auto &R : Whitespaces.generateReplacements())
1040 return std::make_pair(Result, 0);
1041 return std::make_pair(Result, Penalty);
1045 static bool inputUsesCRLF(StringRef
Text) {
1046 return Text.count(
'\r') * 2 > Text.count(
'\n');
1052 if (hasCpp03IncompatibleFormat(
Line->Children))
1058 if (
Tok->
is(TT_TemplateCloser) &&
1068 int AlignmentDiff = 0;
1070 AlignmentDiff += countVariableAlignments(
Line->Children);
1072 if (!
Tok->
is(TT_PointerOrReference))
1078 if (SpaceBefore && !SpaceAfter)
1080 if (!SpaceBefore && SpaceAfter)
1084 return AlignmentDiff;
1089 bool HasBinPackedFunction =
false;
1090 bool HasOnePerLineFunction =
false;
1091 for (
unsigned i = 0, e = AnnotatedLines.size(); i != e; ++i) {
1092 if (!AnnotatedLines[i]->First->Next)
1097 HasBinPackedFunction =
true;
1099 HasOnePerLineFunction =
true;
1106 ? FormatStyle::PAS_Left
1107 : FormatStyle::PAS_Right;
1108 if (Style.
Standard == FormatStyle::LS_Auto)
1109 Style.
Standard = hasCpp03IncompatibleFormat(AnnotatedLines)
1110 ? FormatStyle::LS_Cpp11
1111 : FormatStyle::LS_Cpp03;
1112 BinPackInconclusiveFunctions =
1113 HasBinPackedFunction || !HasOnePerLineFunction;
1116 bool BinPackInconclusiveFunctions;
1129 std::pair<tooling::Replacements, unsigned>
1140 AffectedRangeMgr.computeAffectedLines(AnnotatedLines.begin(),
1141 AnnotatedLines.end());
1143 checkEmptyNamespace(AnnotatedLines);
1145 for (
auto &
Line : AnnotatedLines) {
1146 if (
Line->Affected) {
1147 cleanupRight(
Line->First, tok::comma, tok::comma);
1148 cleanupRight(
Line->First, TT_CtorInitializerColon, tok::comma);
1149 cleanupRight(
Line->First, tok::l_paren, tok::comma);
1150 cleanupLeft(
Line->First, tok::comma, tok::r_paren);
1151 cleanupLeft(
Line->First, TT_CtorInitializerComma, tok::l_brace);
1152 cleanupLeft(
Line->First, TT_CtorInitializerColon, tok::l_brace);
1153 cleanupLeft(
Line->First, TT_CtorInitializerColon, tok::equal);
1157 return {generateFixes(), 0};
1171 std::set<unsigned> DeletedLines;
1172 for (
unsigned i = 0, e = AnnotatedLines.size(); i != e; ++i) {
1173 auto &Line = *AnnotatedLines[i];
1175 Line.
startsWith(tok::kw_inline, tok::kw_namespace)) {
1176 checkEmptyNamespace(AnnotatedLines, i, i, DeletedLines);
1180 for (
auto Line : DeletedLines) {
1194 unsigned CurrentLine,
unsigned &
NewLine,
1195 std::set<unsigned> &DeletedLines) {
1196 unsigned InitLine = CurrentLine,
End = AnnotatedLines.size();
1201 if (!AnnotatedLines[++CurrentLine]->startsWith(tok::l_brace)) {
1202 NewLine = CurrentLine;
1205 }
else if (!AnnotatedLines[CurrentLine]->endsWith(tok::l_brace)) {
1208 while (++CurrentLine < End) {
1209 if (AnnotatedLines[CurrentLine]->startsWith(tok::r_brace))
1212 if (AnnotatedLines[CurrentLine]->startsWith(tok::kw_namespace) ||
1213 AnnotatedLines[CurrentLine]->startsWith(tok::kw_inline,
1214 tok::kw_namespace)) {
1215 if (!checkEmptyNamespace(AnnotatedLines, CurrentLine, NewLine,
1222 if (containsOnlyComments(*AnnotatedLines[CurrentLine]))
1227 NewLine = CurrentLine;
1231 NewLine = CurrentLine;
1232 if (CurrentLine >= End)
1236 if (!AffectedRangeMgr.affectsCharSourceRange(CharSourceRange::getCharRange(
1237 AnnotatedLines[InitLine]->First->Tok.getLocation(),
1238 AnnotatedLines[CurrentLine]->Last->Tok.getEndLoc())))
1241 for (
unsigned i = InitLine; i <= CurrentLine; ++i) {
1242 DeletedLines.insert(i);
1252 template <
typename LeftKind,
typename RightKind>
1253 void cleanupPair(
FormatToken *Start, LeftKind LK, RightKind RK,
1257 if (!Res->is(tok::comment) &&
1258 DeletedTokens.find(Res) == DeletedTokens.end())
1262 for (
auto *Left = Start; Left;) {
1263 auto *Right = NextNotDeleted(*Left);
1266 if (Left->is(LK) && Right->is(RK)) {
1267 deleteToken(DeleteLeft ? Left : Right);
1279 template <
typename LeftKind,
typename RightKind>
1280 void cleanupLeft(
FormatToken *Start, LeftKind LK, RightKind RK) {
1281 cleanupPair(Start, LK, RK,
true);
1284 template <
typename LeftKind,
typename RightKind>
1285 void cleanupRight(
FormatToken *Start, LeftKind LK, RightKind RK) {
1286 cleanupPair(Start, LK, RK,
false);
1292 DeletedTokens.insert(Tok);
1297 std::vector<FormatToken *> Tokens;
1298 std::copy(DeletedTokens.begin(), DeletedTokens.end(),
1299 std::back_inserter(Tokens));
1305 while (Idx < Tokens.size()) {
1306 unsigned St = Idx,
End = Idx;
1307 while ((End + 1) < Tokens.size() &&
1308 Tokens[
End]->Next == Tokens[End + 1]) {
1311 auto SR = CharSourceRange::getCharRange(Tokens[St]->Tok.getLocation(),
1319 assert(
false &&
"Fixes must not conflict!");
1330 struct FormatTokenLess {
1341 std::set<FormatToken *, FormatTokenLess> DeletedTokens;
1344 struct IncludeDirective {
1356 for (
auto Range : Ranges) {
1357 if (Range.getOffset() < End &&
1358 Range.getOffset() + Range.getLength() > Start)
1371 static std::pair<unsigned, unsigned>
1375 unsigned OffsetToEOL = 0;
1376 for (
int i = 0, e = Includes.size(); i != e; ++i) {
1377 unsigned Start = Includes[Indices[i]].Offset;
1378 unsigned End = Start + Includes[Indices[i]].Text.size();
1379 if (!(Cursor >= Start && Cursor < End))
1381 CursorIndex = Indices[i];
1382 OffsetToEOL = End -
Cursor;
1385 while (--i >= 0 && Includes[CursorIndex].
Text == Includes[Indices[i]].
Text)
1389 return std::make_pair(CursorIndex, OffsetToEOL);
1403 unsigned IncludesBeginOffset = Includes.front().Offset;
1404 unsigned IncludesEndOffset =
1405 Includes.back().Offset + Includes.back().Text.size();
1406 unsigned IncludesBlockSize = IncludesEndOffset - IncludesBeginOffset;
1407 if (!
affectsRange(Ranges, IncludesBeginOffset, IncludesEndOffset))
1410 for (
unsigned i = 0, e = Includes.size(); i != e; ++i)
1411 Indices.push_back(i);
1413 Indices.begin(), Indices.end(), [&](
unsigned LHSI,
unsigned RHSI) {
1415 std::tie(Includes[RHSI].Category, Includes[RHSI].Filename);
1419 unsigned CursorIndex;
1421 unsigned CursorToEOLOffset;
1423 std::tie(CursorIndex, CursorToEOLOffset) =
1427 Indices.erase(std::unique(Indices.begin(), Indices.end(),
1428 [&](
unsigned LHSI,
unsigned RHSI) {
1429 return Includes[LHSI].Text == Includes[RHSI].Text;
1433 int CurrentCategory = Includes.front().Category;
1437 if (Indices.size() == Includes.size() &&
1438 std::is_sorted(Indices.begin(), Indices.end()) &&
1443 for (
unsigned Index : Indices) {
1444 if (!result.empty()) {
1447 CurrentCategory != Includes[Index].Category)
1450 result += Includes[Index].Text;
1451 if (Cursor && CursorIndex == Index)
1452 *Cursor = IncludesBeginOffset + result.size() - CursorToEOLOffset;
1453 CurrentCategory = Includes[Index].Category;
1457 FileName, Includes.front().Offset, IncludesBlockSize, result));
1470 class IncludeCategoryManager {
1473 : Style(Style), FileName(FileName) {
1474 FileStem = llvm::sys::path::stem(FileName);
1476 CategoryRegexs.emplace_back(
Category.Regex, llvm::Regex::IgnoreCase);
1477 IsMainFile = FileName.endswith(
".c") || FileName.endswith(
".cc") ||
1478 FileName.endswith(
".cpp") || FileName.endswith(
".c++") ||
1479 FileName.endswith(
".cxx") || FileName.endswith(
".m") ||
1480 FileName.endswith(
".mm");
1486 int getIncludePriority(StringRef IncludeName,
bool CheckMainHeader) {
1488 for (
unsigned i = 0, e = CategoryRegexs.size(); i != e; ++i)
1489 if (CategoryRegexs[i].
match(IncludeName)) {
1493 if (CheckMainHeader && IsMainFile && Ret > 0 && isMainHeader(IncludeName))
1499 bool isMainHeader(StringRef IncludeName)
const {
1500 if (!IncludeName.startswith(
"\""))
1502 StringRef HeaderStem =
1503 llvm::sys::path::stem(IncludeName.drop_front(1).drop_back(1));
1504 if (FileStem.startswith(HeaderStem) ||
1505 FileStem.startswith_lower(HeaderStem)) {
1506 llvm::Regex MainIncludeRegex(
1508 llvm::Regex::IgnoreCase);
1509 if (MainIncludeRegex.match(FileStem))
1522 const char IncludeRegexPattern[] =
1523 R
"(^[\t\ ]*#[\t\ ]*(import|include)[^"<]*(["<][^">]*[">]))"; 1533 unsigned SearchFrom = 0;
1534 llvm::Regex IncludeRegex(IncludeRegexPattern);
1545 IncludeCategoryManager Categories(Style, FileName);
1546 bool FirstIncludeBlock =
true;
1547 bool MainIncludeFound =
false;
1548 bool FormattingOff =
false;
1551 auto Pos = Code.find(
'\n', SearchFrom);
1553 Code.substr(Prev, (Pos != StringRef::npos ? Pos : Code.size()) - Prev);
1555 StringRef Trimmed = Line.trim();
1556 if (Trimmed ==
"// clang-format off")
1557 FormattingOff =
true;
1558 else if (Trimmed ==
"// clang-format on")
1559 FormattingOff =
false;
1561 const bool EmptyLineSkipped =
1562 Trimmed.empty() && (Style.
IncludeBlocks == FormatStyle::IBS_Merge ||
1565 if (!FormattingOff && !Line.endswith(
"\\")) {
1566 if (IncludeRegex.match(Line, &Matches)) {
1567 StringRef IncludeName = Matches[2];
1568 int Category = Categories.getIncludePriority(
1570 !MainIncludeFound && FirstIncludeBlock);
1572 MainIncludeFound =
true;
1573 IncludesInBlock.push_back({IncludeName,
Line, Prev, Category});
1574 }
else if (!IncludesInBlock.empty() && !EmptyLineSkipped) {
1577 IncludesInBlock.clear();
1578 FirstIncludeBlock =
false;
1582 if (Pos == StringRef::npos || Pos + 1 == Code.size())
1584 SearchFrom = Pos + 1;
1586 if (!IncludesInBlock.empty())
1587 sortCppIncludes(Style, IncludesInBlock, Ranges, FileName, Replaces, Cursor);
1595 return Code.size() > 188 && Code[0] == 0x47 && Code[188] == 0x47;
1598 bool isLikelyXml(StringRef Code) {
return Code.ltrim().startswith(
"<"); }
1602 StringRef FileName,
unsigned *
Cursor) {
1608 if (Style.
Language == FormatStyle::LanguageKind::LK_JavaScript &&
1611 if (Style.
Language == FormatStyle::LanguageKind::LK_JavaScript)
1617 template <
typename T>
1622 if (Replaces.
empty())
1627 return NewCode.takeError();
1629 StringRef FileName = Replaces.
begin()->getFilePath();
1632 ProcessFunc(Style, *NewCode, ChangedRanges, FileName);
1634 return Replaces.
merge(FormatReplaces);
1642 auto SortIncludes = [](
const FormatStyle &Style, StringRef Code,
1643 std::vector<tooling::Range> Ranges,
1647 auto SortedReplaces =
1649 if (!SortedReplaces)
1650 return SortedReplaces.takeError();
1654 auto Reformat = [](
const FormatStyle &Style, StringRef Code,
1655 std::vector<tooling::Range> Ranges,
1657 return reformat(Style, Code, Ranges, FileName);
1677 unsigned getOffsetAfterTokenSequence(
1680 GetOffsetAfterSequence) {
1681 std::unique_ptr<Environment> Env =
1682 Environment::CreateVirtualEnvironment(Code, FileName, {});
1684 Lexer Lex(Env->getFileID(), SourceMgr.getBuffer(Env->getFileID()), SourceMgr,
1688 Lex.LexFromRawLexer(Tok);
1689 return GetOffsetAfterSequence(SourceMgr, Lex, Tok);
1695 bool checkAndConsumeDirectiveWithName(
Lexer &Lex, StringRef Name,
Token &
Tok) {
1697 Tok.
is(tok::raw_identifier) &&
1699 Tok.
is(tok::raw_identifier);
1706 while (Tok.
is(tok::comment))
1715 unsigned getOffsetAfterHeaderGuardsAndComments(StringRef FileName,
1718 return getOffsetAfterTokenSequence(
1719 FileName, Code, Style,
1721 skipComments(Lex, Tok);
1723 if (checkAndConsumeDirectiveWithName(Lex,
"ifndef", Tok)) {
1724 skipComments(Lex, Tok);
1725 if (checkAndConsumeDirectiveWithName(Lex,
"define", Tok))
1728 return InitialOffset;
1736 bool checkAndConsumeInclusiveDirective(
Lexer &Lex,
Token &Tok) {
1737 auto Matched = [&]() {
1745 if (Tok.
is(tok::string_literal))
1747 if (Tok.
is(tok::less)) {
1750 if (Tok.
is(tok::greater))
1770 unsigned getMaxHeaderInsertionOffset(StringRef FileName, StringRef Code,
1772 return getOffsetAfterTokenSequence(
1773 FileName, Code, Style,
1775 skipComments(Lex, Tok);
1777 while (checkAndConsumeInclusiveDirective(Lex, Tok))
1783 bool isDeletedHeader(llvm::StringRef HeaderName,
1784 const std::set<llvm::StringRef> &HeadersToDelete) {
1785 return HeadersToDelete.count(HeaderName) ||
1786 HeadersToDelete.count(HeaderName.trim(
"\"<>"));
1797 std::set<llvm::StringRef> HeadersToDelete;
1799 for (
const auto &R : Replaces) {
1800 if (isHeaderInsertion(R)) {
1803 llvm::consumeError(HeaderInsertions.
add(R));
1804 }
else if (isHeaderDeletion(R)) {
1805 HeadersToDelete.insert(R.getReplacementText());
1806 }
else if (R.getOffset() ==
UINT_MAX) {
1807 llvm::errs() <<
"Insertions other than header #include insertion are " 1809 << R.getReplacementText() <<
"\n";
1811 llvm::consumeError(Result.
add(R));
1814 if (HeaderInsertions.
empty() && HeadersToDelete.empty())
1817 llvm::Regex IncludeRegex(IncludeRegexPattern);
1818 llvm::Regex DefineRegex(R
"(^[\t\ ]*#[\t\ ]*define[\t\ ]*[^\\]*$)"); 1821 StringRef FileName = Replaces.begin()->getFilePath(); 1822 IncludeCategoryManager Categories(Style, FileName); 1825 std::map<int, int> CategoryEndOffsets;
1828 std::set<int> Priorities = {0,
INT_MAX};
1830 Priorities.insert(
Category.Priority);
1831 int FirstIncludeOffset = -1;
1833 unsigned MinInsertOffset =
1834 getOffsetAfterHeaderGuardsAndComments(FileName, Code, Style);
1835 StringRef TrimmedCode = Code.drop_front(MinInsertOffset);
1837 unsigned MaxInsertOffset =
1839 getMaxHeaderInsertionOffset(FileName, TrimmedCode, Style);
1841 TrimmedCode.split(Lines,
'\n');
1842 unsigned Offset = MinInsertOffset;
1843 unsigned NextLineOffset;
1844 std::set<StringRef> ExistingIncludes;
1845 for (
auto Line : Lines) {
1846 NextLineOffset =
std::min(Code.size(), Offset +
Line.size() + 1);
1847 if (IncludeRegex.match(
Line, &Matches)) {
1849 StringRef IncludeName = Matches[2];
1850 ExistingIncludes.insert(IncludeName);
1852 if (Offset <= MaxInsertOffset) {
1853 int Category = Categories.getIncludePriority(
1854 IncludeName, FirstIncludeOffset < 0);
1855 CategoryEndOffsets[
Category] = NextLineOffset;
1856 if (FirstIncludeOffset < 0)
1857 FirstIncludeOffset =
Offset;
1859 if (isDeletedHeader(IncludeName, HeadersToDelete)) {
1867 llvm::errs() <<
"Failed to add header deletion replacement for " 1873 Offset = NextLineOffset;
1880 auto Highest = Priorities.begin();
1881 if (CategoryEndOffsets.find(*Highest) == CategoryEndOffsets.end()) {
1882 if (FirstIncludeOffset >= 0)
1883 CategoryEndOffsets[*Highest] = FirstIncludeOffset;
1885 CategoryEndOffsets[*Highest] = MinInsertOffset;
1891 for (
auto I = ++Priorities.begin(), E = Priorities.end(); I != E; ++I)
1892 if (CategoryEndOffsets.find(*I) == CategoryEndOffsets.end())
1893 CategoryEndOffsets[*I] = CategoryEndOffsets[*std::prev(I)];
1895 bool NeedNewLineAtEnd = !Code.empty() && Code.back() !=
'\n';
1896 for (
const auto &R : HeaderInsertions) {
1897 auto IncludeDirective = R.getReplacementText();
1898 bool Matched = IncludeRegex.match(IncludeDirective, &Matches);
1899 assert(Matched &&
"Header insertion replacement must have replacement text " 1902 auto IncludeName = Matches[2];
1903 if (ExistingIncludes.find(IncludeName) != ExistingIncludes.end()) {
1904 DEBUG(llvm::dbgs() <<
"Skip adding existing include : " << IncludeName
1909 Categories.getIncludePriority(IncludeName,
true);
1910 Offset = CategoryEndOffsets[
Category];
1911 std::string NewInclude = !IncludeDirective.endswith(
"\n")
1912 ? (IncludeDirective +
"\n").str()
1913 : IncludeDirective.str();
1916 if (NeedNewLineAtEnd && Offset == Code.size()) {
1917 NewInclude =
"\n" + NewInclude;
1918 NeedNewLineAtEnd =
false;
1921 auto Err = Result.
add(NewReplace);
1923 llvm::consumeError(std::move(Err));
1939 auto Cleanup = [](
const FormatStyle &Style, StringRef Code,
1940 std::vector<tooling::Range> Ranges,
1942 return cleanup(Style, Code, Ranges, FileName);
1946 fixCppIncludeInsertions(Code, Replaces, Style);
1950 namespace internal {
1951 std::pair<tooling::Replacements, unsigned>
1954 unsigned NextStartColumn,
unsigned LastStartColumn, StringRef FileName,
1964 typedef std::function<std::pair<tooling::Replacements, unsigned>(
1969 if (Style.
Language == FormatStyle::LK_Cpp) {
1981 if (Style.
Language == FormatStyle::LK_JavaScript &&
1984 return JavaScriptRequoter(Env, Expanded).process();
1988 return Formatter(Env, Expanded, Status).process();
1991 std::unique_ptr<Environment> Env = Environment::CreateVirtualEnvironment(
1992 Code, FileName, Ranges, FirstStartColumn, NextStartColumn,
1996 unsigned Penalty = 0;
1997 for (
size_t I = 0, E = Passes.size(); I < E; ++I) {
1998 std::pair<tooling::Replacements, unsigned> PassFixes = Passes[I](*Env);
2000 CurrentCode ? StringRef(*CurrentCode) : Code, PassFixes.first);
2002 Fixes = Fixes.
merge(PassFixes.first);
2003 Penalty += PassFixes.second;
2005 CurrentCode = std::move(*NewCode);
2006 Env = Environment::CreateVirtualEnvironment(
2007 *CurrentCode, FileName,
2009 FirstStartColumn, NextStartColumn, LastStartColumn);
2014 return {Fixes, Penalty};
2025 0, FileName, Status)
2031 StringRef FileName) {
2033 if (Style.
Language != FormatStyle::LK_Cpp)
2035 std::unique_ptr<Environment> Env =
2036 Environment::CreateVirtualEnvironment(Code, FileName, Ranges);
2037 Cleaner Clean(*Env, Style);
2038 return Clean.process().first;
2043 StringRef FileName,
bool *IncompleteFormat) {
2045 auto Result =
reformat(Style, Code, Ranges, FileName, &Status);
2047 *IncompleteFormat =
true;
2054 StringRef FileName) {
2055 std::unique_ptr<Environment> Env =
2056 Environment::CreateVirtualEnvironment(Code, FileName, Ranges);
2064 StringRef FileName) {
2065 std::unique_ptr<Environment> Env =
2066 Environment::CreateVirtualEnvironment(Code, FileName, Ranges);
2068 return Sorter.
process().first;
2073 LangOpts.CPlusPlus = 1;
2074 LangOpts.CPlusPlus11 = Style.
Standard == FormatStyle::LS_Cpp03 ? 0 : 1;
2075 LangOpts.CPlusPlus14 = Style.
Standard == FormatStyle::LS_Cpp03 ? 0 : 1;
2076 LangOpts.CPlusPlus17 = Style.
Standard == FormatStyle::LS_Cpp03 ? 0 : 1;
2077 LangOpts.CPlusPlus2a = Style.
Standard == FormatStyle::LS_Cpp03 ? 0 : 1;
2078 LangOpts.LineComment = 1;
2079 bool AlternativeOperators = Style.
isCpp();
2080 LangOpts.CXXOperatorNames = AlternativeOperators ? 1 : 0;
2084 LangOpts.MicrosoftExt = 1;
2085 LangOpts.DeclSpecKeyword = 1;
2090 "Coding style, currently supports:\n" 2091 " LLVM, Google, Chromium, Mozilla, WebKit.\n" 2092 "Use -style=file to load style configuration from\n" 2093 ".clang-format file located in one of the parent\n" 2094 "directories of the source file (or current\n" 2095 "directory for stdin).\n" 2096 "Use -style=\"{key: value, ...}\" to set specific\n" 2097 "parameters, e.g.:\n" 2098 " -style=\"{BasedOnStyle: llvm, IndentWidth: 8}\"";
2101 if (FileName.endswith(
".java"))
2102 return FormatStyle::LK_Java;
2103 if (FileName.endswith_lower(
".js") || FileName.endswith_lower(
".ts"))
2104 return FormatStyle::LK_JavaScript;
2105 if (FileName.endswith(
".m") || FileName.endswith(
".mm"))
2106 return FormatStyle::LK_ObjC;
2107 if (FileName.endswith_lower(
".proto") ||
2108 FileName.endswith_lower(
".protodevel"))
2109 return FormatStyle::LK_Proto;
2110 if (FileName.endswith_lower(
".textpb") ||
2111 FileName.endswith_lower(
".pb.txt") ||
2112 FileName.endswith_lower(
".textproto") ||
2113 FileName.endswith_lower(
".asciipb"))
2114 return FormatStyle::LK_TextProto;
2115 if (FileName.endswith_lower(
".td"))
2116 return FormatStyle::LK_TableGen;
2117 return FormatStyle::LK_Cpp;
2121 StringRef FallbackStyleName,
2132 if (Style.
Language == FormatStyle::LK_Cpp && FileName.endswith(
".h") &&
2133 (Code.contains(
"\n- (") || Code.contains(
"\n+ (") ||
2134 Code.contains(
"\n@end\n") || Code.contains(
"\n@end ") ||
2135 Code.endswith(
"@end")))
2136 Style.
Language = FormatStyle::LK_ObjC;
2142 if (StyleName.startswith(
"{")) {
2149 if (!StyleName.equals_lower(
"file")) {
2161 for (StringRef Directory = Path; !Directory.empty();
2162 Directory = llvm::sys::path::parent_path(Directory)) {
2164 auto Status = FS->
status(Directory);
2166 Status->getType() != llvm::sys::fs::file_type::directory_file) {
2172 llvm::sys::path::append(ConfigFile,
".clang-format");
2173 DEBUG(llvm::dbgs() <<
"Trying " << ConfigFile <<
"...\n");
2175 Status = FS->
status(ConfigFile.str());
2176 bool FoundConfigFile =
2177 Status && (Status->getType() == llvm::sys::fs::file_type::regular_file);
2178 if (!FoundConfigFile) {
2180 ConfigFile = Directory;
2181 llvm::sys::path::append(ConfigFile,
"_clang-format");
2182 DEBUG(llvm::dbgs() <<
"Trying " << ConfigFile <<
"...\n");
2183 Status = FS->
status(ConfigFile.str());
2184 FoundConfigFile = Status && (Status->getType() ==
2185 llvm::sys::fs::file_type::regular_file);
2188 if (FoundConfigFile) {
2189 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
Text =
2191 if (std::error_code EC = Text.getError())
2193 if (std::error_code ec =
2195 if (ec == ParseError::Unsuitable) {
2196 if (!UnsuitableConfigFiles.empty())
2197 UnsuitableConfigFiles.append(
", ");
2198 UnsuitableConfigFiles.append(ConfigFile);
2204 DEBUG(llvm::dbgs() <<
"Using configuration file " << ConfigFile <<
"\n");
2208 if (!UnsuitableConfigFiles.empty())
2211 UnsuitableConfigFiles);
2212 return FallbackStyle;
Lexer - This provides a simple interface that turns a text buffer into a stream of tokens...
SourceLocation getLocWithOffset(int Offset) const
Return a source location with the specified offset from this SourceLocation.
DominatorTree GraphTraits specialization so the DominatorTree can be iterable by generic graph iterat...
bool LexFromRawLexer(Token &Result)
LexFromRawLexer - Lex a token from a designated raw lexer (one with no associated preprocessor object...
bool is(tok::TokenKind K) const
is/isNot - Predicates to check if this token is a specific kind, as in "if (Tok.is(tok::l_brace)) {...
Defines the SourceManager interface.
IntrusiveRefCntPtr< FileSystem > getRealFileSystem()
Gets an vfs::FileSystem for the 'real' file system, as seen by the operating system.
AffectedRangeManager class manages affected ranges in the code.
bool isBeforeInTranslationUnit(SourceLocation LHS, SourceLocation RHS) const
Determines the order of 2 source locations in the translation unit.
StringRef getBufferData(FileID FID, bool *Invalid=nullptr) const
Return a StringRef to the source buffer data for the specified FileID.
The virtual file system interface.
This file implements a token annotator, i.e.
Token - This structure provides full information about a lexed token.
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
virtual llvm::ErrorOr< Status > status(const Twine &Path)=0
Get the status of the entry at Path, if one exists.
Defines the Diagnostic-related interfaces.
SmallVector< BoundNodes, 1 > match(MatcherT Matcher, const NodeT &Node, ASTContext &Context)
Returns the results of matching Matcher on Node.
WhitespaceManager class manages whitespace around tokens and their replacements.
const AnnotatedLine * Line
const FunctionProtoType * T
SourceLocation getLocation() const
Return a source location identifier for the specified offset in the current file. ...
char __ovld __cnfn min(char x, char y)
Returns y if y < x, otherwise it returns x.
SourceLocation getEnd() const
unsigned getFileOffset(SourceLocation SpellingLoc) const
Returns the offset from the start of the file that the specified SourceLocation represents.
Encodes a location in the source.
This file contains the declaration of the UnwrappedLineParser, which turns a stream of tokens into Un...
std::error_code makeAbsolute(SmallVectorImpl< char > &Path) const
Make Path an absolute path.
bool isNot(tok::TokenKind K) const
Dataflow Directional Tag Classes.
This file implements a sorter for JavaScript ES6 imports.
Defines the virtual file system interface vfs::FileSystem.
std::string toString(const til::SExpr *E)
llvm::ErrorOr< std::unique_ptr< llvm::MemoryBuffer > > getBufferForFile(const Twine &Name, int64_t FileSize=-1, bool RequiresNullTerminator=true, bool IsVolatile=false)
This is a convenience method that opens a file, gets its content and then closes the file...
This file declares an abstract TokenAnalyzer, and associated helper classes.
StringRef getRawIdentifier() const
getRawIdentifier - For a raw identifier token (i.e., an identifier lexed in raw mode), returns a reference to the text substring in the buffer if known.
This file implements an indenter that manages the indentation of continuations.
This file declares UsingDeclarationsSorter, a TokenAnalyzer that sorts consecutive using declarations...
SourceLocation getBegin() const
This class handles loading and caching of source files into memory.
SourceLocation getEndLoc() const