35 #include "llvm/ADT/STLExtras.h" 36 #include "llvm/ADT/StringRef.h" 37 #include "llvm/Support/Allocator.h" 38 #include "llvm/Support/Debug.h" 39 #include "llvm/Support/Path.h" 40 #include "llvm/Support/Regex.h" 41 #include "llvm/Support/YAMLTraits.h" 46 #include <unordered_map> 48 #define DEBUG_TYPE "format-formatter" 56 template <>
struct ScalarEnumerationTraits<
FormatStyle::LanguageKind> {
58 IO.enumCase(Value,
"Cpp", FormatStyle::LK_Cpp);
59 IO.enumCase(Value,
"Java", FormatStyle::LK_Java);
60 IO.enumCase(Value,
"JavaScript", FormatStyle::LK_JavaScript);
61 IO.enumCase(Value,
"ObjC", FormatStyle::LK_ObjC);
62 IO.enumCase(Value,
"Proto", FormatStyle::LK_Proto);
63 IO.enumCase(Value,
"TableGen", FormatStyle::LK_TableGen);
64 IO.enumCase(Value,
"TextProto", FormatStyle::LK_TextProto);
68 template <>
struct ScalarEnumerationTraits<
FormatStyle::LanguageStandard> {
70 IO.enumCase(Value,
"Cpp03", FormatStyle::LS_Cpp03);
71 IO.enumCase(Value,
"C++03", FormatStyle::LS_Cpp03);
72 IO.enumCase(Value,
"Cpp11", FormatStyle::LS_Cpp11);
73 IO.enumCase(Value,
"C++11", FormatStyle::LS_Cpp11);
74 IO.enumCase(Value,
"Auto", FormatStyle::LS_Auto);
78 template <>
struct ScalarEnumerationTraits<
FormatStyle::UseTabStyle> {
80 IO.enumCase(Value,
"Never", FormatStyle::UT_Never);
81 IO.enumCase(Value,
"false", FormatStyle::UT_Never);
82 IO.enumCase(Value,
"Always", FormatStyle::UT_Always);
83 IO.enumCase(Value,
"true", FormatStyle::UT_Always);
84 IO.enumCase(Value,
"ForIndentation", FormatStyle::UT_ForIndentation);
85 IO.enumCase(Value,
"ForContinuationAndIndentation",
86 FormatStyle::UT_ForContinuationAndIndentation);
90 template <>
struct ScalarEnumerationTraits<
FormatStyle::JavaScriptQuoteStyle> {
92 IO.enumCase(Value,
"Leave", FormatStyle::JSQS_Leave);
93 IO.enumCase(Value,
"Single", FormatStyle::JSQS_Single);
94 IO.enumCase(Value,
"Double", FormatStyle::JSQS_Double);
98 template <>
struct ScalarEnumerationTraits<
FormatStyle::ShortFunctionStyle> {
100 IO.enumCase(Value,
"None", FormatStyle::SFS_None);
101 IO.enumCase(Value,
"false", FormatStyle::SFS_None);
102 IO.enumCase(Value,
"All", FormatStyle::SFS_All);
103 IO.enumCase(Value,
"true", FormatStyle::SFS_All);
104 IO.enumCase(Value,
"Inline", FormatStyle::SFS_Inline);
105 IO.enumCase(Value,
"InlineOnly", FormatStyle::SFS_InlineOnly);
106 IO.enumCase(Value,
"Empty", FormatStyle::SFS_Empty);
110 template <>
struct ScalarEnumerationTraits<
FormatStyle::BinPackStyle> {
112 IO.enumCase(Value,
"Auto", FormatStyle::BPS_Auto);
113 IO.enumCase(Value,
"Always", FormatStyle::BPS_Always);
114 IO.enumCase(Value,
"Never", FormatStyle::BPS_Never);
118 template <>
struct ScalarEnumerationTraits<
FormatStyle::BinaryOperatorStyle> {
120 IO.enumCase(Value,
"All", FormatStyle::BOS_All);
121 IO.enumCase(Value,
"true", FormatStyle::BOS_All);
122 IO.enumCase(Value,
"None", FormatStyle::BOS_None);
123 IO.enumCase(Value,
"false", FormatStyle::BOS_None);
124 IO.enumCase(Value,
"NonAssignment", FormatStyle::BOS_NonAssignment);
128 template <>
struct ScalarEnumerationTraits<
FormatStyle::BraceBreakingStyle> {
130 IO.enumCase(Value,
"Attach", FormatStyle::BS_Attach);
131 IO.enumCase(Value,
"Linux", FormatStyle::BS_Linux);
132 IO.enumCase(Value,
"Mozilla", FormatStyle::BS_Mozilla);
133 IO.enumCase(Value,
"Stroustrup", FormatStyle::BS_Stroustrup);
134 IO.enumCase(Value,
"Allman", FormatStyle::BS_Allman);
135 IO.enumCase(Value,
"GNU", FormatStyle::BS_GNU);
136 IO.enumCase(Value,
"WebKit", FormatStyle::BS_WebKit);
137 IO.enumCase(Value,
"Custom", FormatStyle::BS_Custom);
142 struct ScalarEnumerationTraits<
FormatStyle::BreakConstructorInitializersStyle> {
145 IO.enumCase(Value,
"BeforeColon", FormatStyle::BCIS_BeforeColon);
146 IO.enumCase(Value,
"BeforeComma", FormatStyle::BCIS_BeforeComma);
147 IO.enumCase(Value,
"AfterColon", FormatStyle::BCIS_AfterColon);
152 struct ScalarEnumerationTraits<
FormatStyle::BreakInheritanceListStyle> {
155 IO.enumCase(Value,
"BeforeColon", FormatStyle::BILS_BeforeColon);
156 IO.enumCase(Value,
"BeforeComma", FormatStyle::BILS_BeforeComma);
157 IO.enumCase(Value,
"AfterColon", FormatStyle::BILS_AfterColon);
162 struct ScalarEnumerationTraits<
FormatStyle::PPDirectiveIndentStyle> {
164 IO.enumCase(Value,
"None", FormatStyle::PPDIS_None);
165 IO.enumCase(Value,
"AfterHash", FormatStyle::PPDIS_AfterHash);
170 struct ScalarEnumerationTraits<
FormatStyle::ReturnTypeBreakingStyle> {
172 IO.enumCase(Value,
"None", FormatStyle::RTBS_None);
173 IO.enumCase(Value,
"All", FormatStyle::RTBS_All);
174 IO.enumCase(Value,
"TopLevel", FormatStyle::RTBS_TopLevel);
175 IO.enumCase(Value,
"TopLevelDefinitions",
176 FormatStyle::RTBS_TopLevelDefinitions);
177 IO.enumCase(Value,
"AllDefinitions", FormatStyle::RTBS_AllDefinitions);
182 struct ScalarEnumerationTraits<
FormatStyle::BreakTemplateDeclarationsStyle> {
184 IO.enumCase(Value,
"No", FormatStyle::BTDS_No);
185 IO.enumCase(Value,
"MultiLine", FormatStyle::BTDS_MultiLine);
186 IO.enumCase(Value,
"Yes", FormatStyle::BTDS_Yes);
189 IO.enumCase(Value,
"false", FormatStyle::BTDS_MultiLine);
190 IO.enumCase(Value,
"true", FormatStyle::BTDS_Yes);
195 struct ScalarEnumerationTraits<
FormatStyle::DefinitionReturnTypeBreakingStyle> {
198 IO.enumCase(Value,
"None", FormatStyle::DRTBS_None);
199 IO.enumCase(Value,
"All", FormatStyle::DRTBS_All);
200 IO.enumCase(Value,
"TopLevel", FormatStyle::DRTBS_TopLevel);
203 IO.enumCase(Value,
"false", FormatStyle::DRTBS_None);
204 IO.enumCase(Value,
"true", FormatStyle::DRTBS_All);
209 struct ScalarEnumerationTraits<
FormatStyle::NamespaceIndentationKind> {
211 FormatStyle::NamespaceIndentationKind &
Value) {
212 IO.enumCase(Value,
"None", FormatStyle::NI_None);
213 IO.enumCase(Value,
"Inner", FormatStyle::NI_Inner);
214 IO.enumCase(Value,
"All", FormatStyle::NI_All);
218 template <>
struct ScalarEnumerationTraits<
FormatStyle::BracketAlignmentStyle> {
220 IO.enumCase(Value,
"Align", FormatStyle::BAS_Align);
221 IO.enumCase(Value,
"DontAlign", FormatStyle::BAS_DontAlign);
222 IO.enumCase(Value,
"AlwaysBreak", FormatStyle::BAS_AlwaysBreak);
225 IO.enumCase(Value,
"true", FormatStyle::BAS_Align);
226 IO.enumCase(Value,
"false", FormatStyle::BAS_DontAlign);
231 struct ScalarEnumerationTraits<
FormatStyle::EscapedNewlineAlignmentStyle> {
233 FormatStyle::EscapedNewlineAlignmentStyle &
Value) {
234 IO.enumCase(Value,
"DontAlign", FormatStyle::ENAS_DontAlign);
235 IO.enumCase(Value,
"Left", FormatStyle::ENAS_Left);
236 IO.enumCase(Value,
"Right", FormatStyle::ENAS_Right);
239 IO.enumCase(Value,
"true", FormatStyle::ENAS_Left);
240 IO.enumCase(Value,
"false", FormatStyle::ENAS_Right);
244 template <>
struct ScalarEnumerationTraits<
FormatStyle::PointerAlignmentStyle> {
246 IO.enumCase(Value,
"Middle", FormatStyle::PAS_Middle);
247 IO.enumCase(Value,
"Left", FormatStyle::PAS_Left);
248 IO.enumCase(Value,
"Right", FormatStyle::PAS_Right);
251 IO.enumCase(Value,
"true", FormatStyle::PAS_Left);
252 IO.enumCase(Value,
"false", FormatStyle::PAS_Right);
257 struct ScalarEnumerationTraits<
FormatStyle::SpaceBeforeParensOptions> {
259 FormatStyle::SpaceBeforeParensOptions &
Value) {
260 IO.enumCase(Value,
"Never", FormatStyle::SBPO_Never);
261 IO.enumCase(Value,
"ControlStatements",
262 FormatStyle::SBPO_ControlStatements);
263 IO.enumCase(Value,
"Always", FormatStyle::SBPO_Always);
266 IO.enumCase(Value,
"false", FormatStyle::SBPO_Never);
267 IO.enumCase(Value,
"true", FormatStyle::SBPO_ControlStatements);
274 IO.mapOptional(
"Language", Style.
Language);
276 if (IO.outputting()) {
277 StringRef StylesArray[] = {
"LLVM",
"Google",
"Chromium",
278 "Mozilla",
"WebKit",
"GNU"};
280 for (
size_t i = 0, e = Styles.size(); i < e; ++i) {
281 StringRef StyleName(Styles[i]);
284 Style == PredefinedStyle) {
285 IO.mapOptional(
"# BasedOnStyle", StyleName);
290 StringRef BasedOnStyle;
291 IO.mapOptional(
"BasedOnStyle", BasedOnStyle);
292 if (!BasedOnStyle.empty()) {
293 FormatStyle::LanguageKind OldLanguage = Style.
Language;
294 FormatStyle::LanguageKind Language =
297 IO.setError(Twine(
"Unknown value for BasedOnStyle: ", BasedOnStyle));
305 if (!IO.outputting()) {
308 IO.mapOptional(
"IndentFunctionDeclarationAfterType",
311 IO.mapOptional(
"SpaceAfterControlStatementKeyword",
317 IO.mapOptional(
"AlignConsecutiveAssignments",
319 IO.mapOptional(
"AlignConsecutiveDeclarations",
324 IO.mapOptional(
"AllowAllParametersOfDeclarationOnNextLine",
326 IO.mapOptional(
"AllowShortBlocksOnASingleLine",
328 IO.mapOptional(
"AllowShortCaseLabelsOnASingleLine",
330 IO.mapOptional(
"AllowShortFunctionsOnASingleLine",
332 IO.mapOptional(
"AllowShortIfStatementsOnASingleLine",
334 IO.mapOptional(
"AllowShortLoopsOnASingleLine",
336 IO.mapOptional(
"AlwaysBreakAfterDefinitionReturnType",
338 IO.mapOptional(
"AlwaysBreakAfterReturnType",
348 FormatStyle::DRTBS_TopLevel)
350 FormatStyle::RTBS_TopLevelDefinitions;
353 IO.mapOptional(
"AlwaysBreakBeforeMultilineStrings",
355 IO.mapOptional(
"AlwaysBreakTemplateDeclarations",
360 IO.mapOptional(
"BreakBeforeBinaryOperators",
364 bool BreakBeforeInheritanceComma =
false;
365 IO.mapOptional(
"BreakBeforeInheritanceComma",
366 BreakBeforeInheritanceComma);
367 IO.mapOptional(
"BreakInheritanceList",
372 if (BreakBeforeInheritanceComma &&
376 IO.mapOptional(
"BreakBeforeTernaryOperators",
379 bool BreakConstructorInitializersBeforeComma =
false;
380 IO.mapOptional(
"BreakConstructorInitializersBeforeComma",
381 BreakConstructorInitializersBeforeComma);
382 IO.mapOptional(
"BreakConstructorInitializers",
387 if (BreakConstructorInitializersBeforeComma &&
391 IO.mapOptional(
"BreakAfterJavaFieldAnnotations",
397 IO.mapOptional(
"ConstructorInitializerAllOnOneLineOrOnePerLine",
399 IO.mapOptional(
"ConstructorInitializerIndentWidth",
405 IO.mapOptional(
"ExperimentalAutoDetectBinPacking",
415 IO.mapOptional(
"IndentWrappedFunctionNames",
419 IO.mapOptional(
"KeepEmptyLinesAtTheStartOfBlocks",
428 IO.mapOptional(
"ObjCSpaceBeforeProtocolList",
431 IO.mapOptional(
"PenaltyBreakBeforeFirstCallParameter",
434 IO.mapOptional(
"PenaltyBreakFirstLessLess",
437 IO.mapOptional(
"PenaltyBreakTemplateDeclaration",
440 IO.mapOptional(
"PenaltyReturnTypeOnItsOwnLine",
448 IO.mapOptional(
"SpaceAfterTemplateKeyword",
450 IO.mapOptional(
"SpaceBeforeAssignmentOperators",
452 IO.mapOptional(
"SpaceBeforeCpp11BracedList",
454 IO.mapOptional(
"SpaceBeforeCtorInitializerColon",
456 IO.mapOptional(
"SpaceBeforeInheritanceColon",
459 IO.mapOptional(
"SpaceBeforeRangeBasedForLoopColon",
462 IO.mapOptional(
"SpacesBeforeTrailingComments",
465 IO.mapOptional(
"SpacesInContainerLiterals",
467 IO.mapOptional(
"SpacesInCStyleCastParentheses",
471 IO.mapOptional(
"Standard", Style.
Standard);
472 IO.mapOptional(
"TabWidth", Style.
TabWidth);
473 IO.mapOptional(
"UseTab", Style.
UseTab);
477 template <>
struct MappingTraits<
FormatStyle::BraceWrappingFlags> {
478 static void mapping(IO &IO, FormatStyle::BraceWrappingFlags &Wrapping) {
479 IO.mapOptional(
"AfterClass", Wrapping.AfterClass);
480 IO.mapOptional(
"AfterControlStatement", Wrapping.AfterControlStatement);
481 IO.mapOptional(
"AfterEnum", Wrapping.AfterEnum);
482 IO.mapOptional(
"AfterFunction", Wrapping.AfterFunction);
483 IO.mapOptional(
"AfterNamespace", Wrapping.AfterNamespace);
484 IO.mapOptional(
"AfterObjCDeclaration", Wrapping.AfterObjCDeclaration);
485 IO.mapOptional(
"AfterStruct", Wrapping.AfterStruct);
486 IO.mapOptional(
"AfterUnion", Wrapping.AfterUnion);
487 IO.mapOptional(
"AfterExternBlock", Wrapping.AfterExternBlock);
488 IO.mapOptional(
"BeforeCatch", Wrapping.BeforeCatch);
489 IO.mapOptional(
"BeforeElse", Wrapping.BeforeElse);
490 IO.mapOptional(
"IndentBraces", Wrapping.IndentBraces);
491 IO.mapOptional(
"SplitEmptyFunction", Wrapping.SplitEmptyFunction);
492 IO.mapOptional(
"SplitEmptyRecord", Wrapping.SplitEmptyRecord);
493 IO.mapOptional(
"SplitEmptyNamespace", Wrapping.SplitEmptyNamespace);
498 static void mapping(IO &IO, FormatStyle::RawStringFormat &Format) {
499 IO.mapOptional(
"Language", Format.Language);
500 IO.mapOptional(
"Delimiters", Format.Delimiters);
501 IO.mapOptional(
"EnclosingFunctions", Format.EnclosingFunctions);
502 IO.mapOptional(
"CanonicalDelimiter", Format.CanonicalDelimiter);
503 IO.mapOptional(
"BasedOnStyle", Format.BasedOnStyle);
512 template <>
struct DocumentListTraits<
std::vector<FormatStyle>> {
513 static size_t size(IO &IO, std::vector<FormatStyle> &Seq) {
518 if (Index >= Seq.size()) {
519 assert(Index == Seq.size());
521 if (!Seq.empty() && Seq[0].Language == FormatStyle::LK_None) {
524 Template = *((
const FormatStyle *)IO.getContext());
525 Template.
Language = FormatStyle::LK_None;
527 Seq.resize(Index + 1, Template);
547 return llvm::make_error<llvm::StringError>(Message,
548 llvm::inconvertibleErrorCode());
551 const char *ParseErrorCategory::name() const noexcept {
552 return "clang-format.parse_error";
555 std::string ParseErrorCategory::message(
int EV)
const {
556 switch (static_cast<ParseError>(EV)) {
557 case ParseError::Success:
560 return "Invalid argument";
561 case ParseError::Unsuitable:
564 llvm_unreachable(
"unexpected parse error");
572 false,
false,
false,
false,
false,
573 false,
false,
true,
true,
true};
575 case FormatStyle::BS_Linux:
580 case FormatStyle::BS_Mozilla:
590 case FormatStyle::BS_Stroustrup:
595 case FormatStyle::BS_Allman:
607 case FormatStyle::BS_GNU:
608 Expanded.
BraceWrapping = {
true,
true,
true,
true,
true,
true,
true,
true,
609 true,
true,
true,
true,
true,
true,
true};
611 case FormatStyle::BS_WebKit:
622 LLVMStyle.
Language = FormatStyle::LK_Cpp;
645 LLVMStyle.
BraceWrapping = {
false,
false,
false,
false,
false,
646 false,
false,
false,
false,
false,
647 false,
false,
true,
true,
true};
666 {
"^\"(llvm|llvm-c|clang|clang-c)/", 2},
667 {
"^(<|\"(gtest|gmock|isl|json)/)", 3},
687 LLVMStyle.
Standard = FormatStyle::LS_Cpp11;
688 LLVMStyle.
UseTab = FormatStyle::UT_Never;
722 if (Language == FormatStyle::LK_TextProto) {
724 GoogleStyle.
Language = FormatStyle::LK_TextProto;
741 {
"^<ext/.*\\.h>", 2}, {
"^<.*\\.h>", 1}, {
"^<.*", 2}, {
".*", 3}};
768 FormatStyle::LK_TextProto,
780 "PARSE_PARTIAL_TEXT_PROTO",
784 "ParseTextProtoOrDie",
791 GoogleStyle.
Standard = FormatStyle::LS_Auto;
796 if (Language == FormatStyle::LK_Java) {
807 }
else if (Language == FormatStyle::LK_JavaScript) {
821 }
else if (Language == FormatStyle::LK_Proto) {
832 }
else if (Language == FormatStyle::LK_ObjC) {
842 if (Language == FormatStyle::LK_Java) {
847 }
else if (Language == FormatStyle::LK_JavaScript) {
857 if (Language == FormatStyle::LK_ObjC)
860 return ChromiumStyle;
869 FormatStyle::DRTBS_TopLevel;
921 Style.
Standard = FormatStyle::LS_Cpp03;
935 if (Name.equals_lower(
"llvm")) {
937 }
else if (Name.equals_lower(
"chromium")) {
939 }
else if (Name.equals_lower(
"mozilla")) {
941 }
else if (Name.equals_lower(
"google")) {
943 }
else if (Name.equals_lower(
"webkit")) {
945 }
else if (Name.equals_lower(
"gnu")) {
947 }
else if (Name.equals_lower(
"none")) {
960 assert(Language != FormatStyle::LK_None);
961 if (Text.trim().empty())
963 Style->StyleSet.
Clear();
964 std::vector<FormatStyle> Styles;
965 llvm::yaml::Input Input(Text);
970 Input.setContext(Style);
973 return Input.error();
975 for (
unsigned i = 0; i < Styles.size(); ++i) {
977 if (Styles[i].Language == FormatStyle::LK_None && i != 0)
980 for (
unsigned j = 0; j < i; ++j) {
981 if (Styles[i].Language == Styles[j].Language) {
982 LLVM_DEBUG(llvm::dbgs()
983 <<
"Duplicate languages in the config file on positions " 984 << j <<
" and " << i <<
"\n");
993 bool LanguageFound =
false;
994 for (
int i = Styles.size() - 1; i >= 0; --i) {
995 if (Styles[i].Language != FormatStyle::LK_None)
996 StyleSet.
Add(Styles[i]);
997 if (Styles[i].Language == Language)
998 LanguageFound =
true;
1000 if (!LanguageFound) {
1001 if (Styles.empty() || Styles[0].Language != FormatStyle::LK_None)
1005 StyleSet.
Add(std::move(DefaultStyle));
1007 *Style = *StyleSet.
Get(Language);
1013 llvm::raw_string_ostream Stream(Text);
1014 llvm::yaml::Output Output(Stream);
1018 Output << NonConstStyle;
1019 return Stream.str();
1026 auto It = Styles->find(Language);
1027 if (It == Styles->end())
1030 Style.StyleSet = *
this;
1035 assert(Style.
Language != LK_None &&
1036 "Cannot add a style for LK_None to a StyleSet");
1038 !Style.StyleSet.Styles &&
1039 "Cannot add a style associated with an existing StyleSet to a StyleSet");
1041 Styles = std::make_shared<MapType>();
1042 (*Styles)[Style.
Language] = std::move(Style);
1045 void FormatStyle::FormatStyleSet::Clear() {
1051 return StyleSet.Get(Language);
1061 std::pair<tooling::Replacements, unsigned>
1065 AffectedRangeMgr.computeAffectedLines(AnnotatedLines);
1067 requoteJSStringLiteral(AnnotatedLines, Result);
1077 requoteJSStringLiteral(
Line->Children, Result);
1078 if (!
Line->Affected)
1081 FormatTok = FormatTok->Next) {
1082 StringRef Input = FormatTok->TokenText;
1083 if (FormatTok->Finalized || !FormatTok->isStringLiteral() ||
1087 !Input.startswith(
"\"")) ||
1089 !Input.startswith(
"\'")))
1096 StringRef ReplacementText) {
1106 Replace(Start, 1, IsSingle ?
"'" :
"\"");
1107 Replace(FormatTok->Tok.getEndLoc().getLocWithOffset(-1), 1,
1108 IsSingle ?
"'" :
"\"");
1111 bool Escaped =
false;
1112 for (
size_t i = 1; i < Input.size() - 1; i++) {
1115 if (!Escaped && i + 1 < Input.size() &&
1116 ((IsSingle && Input[i + 1] ==
'"') ||
1117 (!IsSingle && Input[i + 1] ==
'\''))) {
1127 if (!Escaped && IsSingle == (Input[i] ==
'\'')) {
1149 std::pair<tooling::Replacements, unsigned>
1154 deriveLocalStyle(AnnotatedLines);
1155 AffectedRangeMgr.computeAffectedLines(AnnotatedLines);
1156 for (
unsigned i = 0, e = AnnotatedLines.size(); i != e; ++i) {
1166 BinPackInconclusiveFunctions);
1171 .format(AnnotatedLines,
false,
1177 for (
const auto &R : Whitespaces.generateReplacements())
1179 return std::make_pair(Result, 0);
1180 return std::make_pair(Result, Penalty);
1184 static bool inputUsesCRLF(StringRef
Text) {
1185 return Text.count(
'\r') * 2 > Text.count(
'\n');
1191 if (hasCpp03IncompatibleFormat(
Line->Children))
1197 if (
Tok->
is(TT_TemplateCloser) &&
1207 int AlignmentDiff = 0;
1209 AlignmentDiff += countVariableAlignments(
Line->Children);
1211 if (!
Tok->
is(TT_PointerOrReference))
1217 if (SpaceBefore && !SpaceAfter)
1219 if (!SpaceBefore && SpaceAfter)
1223 return AlignmentDiff;
1228 bool HasBinPackedFunction =
false;
1229 bool HasOnePerLineFunction =
false;
1230 for (
unsigned i = 0, e = AnnotatedLines.size(); i != e; ++i) {
1231 if (!AnnotatedLines[i]->
First->Next)
1236 HasBinPackedFunction =
true;
1238 HasOnePerLineFunction =
true;
1245 ? FormatStyle::PAS_Left
1246 : FormatStyle::PAS_Right;
1247 if (Style.
Standard == FormatStyle::LS_Auto)
1248 Style.
Standard = hasCpp03IncompatibleFormat(AnnotatedLines)
1249 ? FormatStyle::LS_Cpp11
1250 : FormatStyle::LS_Cpp03;
1251 BinPackInconclusiveFunctions =
1252 HasBinPackedFunction || !HasOnePerLineFunction;
1255 bool BinPackInconclusiveFunctions;
1268 std::pair<tooling::Replacements, unsigned>
1279 AffectedRangeMgr.computeAffectedLines(AnnotatedLines);
1281 checkEmptyNamespace(AnnotatedLines);
1283 for (
auto &
Line : AnnotatedLines) {
1284 if (
Line->Affected) {
1285 cleanupRight(
Line->First, tok::comma, tok::comma);
1286 cleanupRight(
Line->First, TT_CtorInitializerColon, tok::comma);
1287 cleanupRight(
Line->First, tok::l_paren, tok::comma);
1288 cleanupLeft(
Line->First, tok::comma, tok::r_paren);
1289 cleanupLeft(
Line->First, TT_CtorInitializerComma, tok::l_brace);
1290 cleanupLeft(
Line->First, TT_CtorInitializerColon, tok::l_brace);
1291 cleanupLeft(
Line->First, TT_CtorInitializerColon, tok::equal);
1295 return {generateFixes(), 0};
1309 std::set<unsigned> DeletedLines;
1310 for (
unsigned i = 0, e = AnnotatedLines.size(); i != e; ++i) {
1311 auto &Line = *AnnotatedLines[i];
1313 Line.
startsWith(tok::kw_inline, tok::kw_namespace)) {
1314 checkEmptyNamespace(AnnotatedLines, i, i, DeletedLines);
1318 for (
auto Line : DeletedLines) {
1332 unsigned CurrentLine,
unsigned &
NewLine,
1333 std::set<unsigned> &DeletedLines) {
1334 unsigned InitLine = CurrentLine,
End = AnnotatedLines.size();
1339 if (!AnnotatedLines[++CurrentLine]->startsWith(tok::l_brace)) {
1340 NewLine = CurrentLine;
1343 }
else if (!AnnotatedLines[CurrentLine]->endsWith(tok::l_brace)) {
1346 while (++CurrentLine < End) {
1347 if (AnnotatedLines[CurrentLine]->startsWith(tok::r_brace))
1350 if (AnnotatedLines[CurrentLine]->startsWith(tok::kw_namespace) ||
1351 AnnotatedLines[CurrentLine]->startsWith(tok::kw_inline,
1352 tok::kw_namespace)) {
1353 if (!checkEmptyNamespace(AnnotatedLines, CurrentLine, NewLine,
1360 if (containsOnlyComments(*AnnotatedLines[CurrentLine]))
1365 NewLine = CurrentLine;
1369 NewLine = CurrentLine;
1370 if (CurrentLine >= End)
1374 if (!AffectedRangeMgr.affectsCharSourceRange(CharSourceRange::getCharRange(
1375 AnnotatedLines[InitLine]->First->Tok.getLocation(),
1376 AnnotatedLines[CurrentLine]->Last->Tok.getEndLoc())))
1379 for (
unsigned i = InitLine; i <= CurrentLine; ++i) {
1380 DeletedLines.insert(i);
1390 template <
typename LeftKind,
typename RightKind>
1391 void cleanupPair(
FormatToken *Start, LeftKind LK, RightKind RK,
1395 if (!Res->is(tok::comment) &&
1396 DeletedTokens.find(Res) == DeletedTokens.end())
1400 for (
auto *Left = Start; Left;) {
1401 auto *Right = NextNotDeleted(*Left);
1404 if (Left->is(LK) && Right->is(RK)) {
1405 deleteToken(DeleteLeft ? Left : Right);
1417 template <
typename LeftKind,
typename RightKind>
1418 void cleanupLeft(
FormatToken *Start, LeftKind LK, RightKind RK) {
1419 cleanupPair(Start, LK, RK,
true);
1422 template <
typename LeftKind,
typename RightKind>
1423 void cleanupRight(
FormatToken *Start, LeftKind LK, RightKind RK) {
1424 cleanupPair(Start, LK, RK,
false);
1430 DeletedTokens.insert(Tok);
1435 std::vector<FormatToken *> Tokens;
1436 std::copy(DeletedTokens.begin(), DeletedTokens.end(),
1437 std::back_inserter(Tokens));
1443 while (Idx < Tokens.size()) {
1444 unsigned St = Idx,
End = Idx;
1445 while ((End + 1) < Tokens.size() &&
1446 Tokens[
End]->Next == Tokens[End + 1]) {
1449 auto SR = CharSourceRange::getCharRange(Tokens[St]->Tok.getLocation(),
1457 assert(
false &&
"Fixes must not conflict!");
1468 struct FormatTokenLess {
1479 std::set<FormatToken *, FormatTokenLess> DeletedTokens;
1482 class ObjCHeaderStyleGuesser :
public TokenAnalyzer {
1485 : TokenAnalyzer(Env, Style), IsObjC(
false) {}
1487 std::pair<tooling::Replacements, unsigned>
1488 analyze(TokenAnnotator &Annotator,
1489 SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
1490 FormatTokenLexer &Tokens)
override {
1491 assert(Style.
Language == FormatStyle::LK_Cpp);
1492 IsObjC = guessIsObjC(AnnotatedLines, Tokens.getKeywords());
1493 tooling::Replacements Result;
1497 bool isObjC() {
return IsObjC; }
1500 static bool guessIsObjC(
const SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
1501 const AdditionalKeywords &Keywords) {
1503 static constexpr llvm::StringLiteral FoundationIdentifiers[] = {
1518 "NSAffineTransform",
1520 "NSAttributedString",
1537 "NSInvocationOperation",
1541 "NSMutableAttributedString",
1542 "NSMutableCharacterSet",
1544 "NSMutableDictionary",
1545 "NSMutableIndexSet",
1546 "NSMutableOrderedSet",
1550 "NSNumberFormatter",
1554 "NSOperationQueuePriority",
1558 "NSQualityOfService",
1561 "NSRegularExpression",
1576 for (
auto Line : AnnotatedLines) {
1577 for (
const FormatToken *FormatTok =
Line->First; FormatTok;
1578 FormatTok = FormatTok->Next) {
1579 if ((FormatTok->Previous && FormatTok->Previous->is(tok::at) &&
1580 (FormatTok->Tok.getObjCKeywordID() != tok::objc_not_keyword ||
1581 FormatTok->isOneOf(tok::numeric_constant, tok::l_square,
1583 (FormatTok->Tok.isAnyIdentifier() &&
1584 std::binary_search(std::begin(FoundationIdentifiers),
1585 std::end(FoundationIdentifiers),
1586 FormatTok->TokenText)) ||
1587 FormatTok->is(TT_ObjCStringLiteral) ||
1588 FormatTok->isOneOf(Keywords.kw_NS_ENUM, Keywords.kw_NS_OPTIONS,
1589 TT_ObjCBlockLBrace, TT_ObjCBlockLParen,
1590 TT_ObjCDecl, TT_ObjCForIn, TT_ObjCMethodExpr,
1591 TT_ObjCMethodSpecifier, TT_ObjCProperty)) {
1594 if (guessIsObjC(
Line->Children, Keywords))
1604 struct IncludeDirective {
1616 for (
auto Range : Ranges) {
1617 if (Range.getOffset() < End &&
1618 Range.getOffset() + Range.getLength() > Start)
1631 static std::pair<unsigned, unsigned>
1635 unsigned OffsetToEOL = 0;
1636 for (
int i = 0, e = Includes.size(); i != e; ++i) {
1637 unsigned Start = Includes[Indices[i]].Offset;
1638 unsigned End = Start + Includes[Indices[i]].Text.size();
1639 if (!(Cursor >= Start && Cursor < End))
1641 CursorIndex = Indices[i];
1642 OffsetToEOL = End -
Cursor;
1645 while (--i >= 0 && Includes[CursorIndex].
Text == Includes[Indices[i]].
Text)
1649 return std::make_pair(CursorIndex, OffsetToEOL);
1663 unsigned IncludesBeginOffset = Includes.front().Offset;
1664 unsigned IncludesEndOffset =
1665 Includes.back().Offset + Includes.back().Text.size();
1666 unsigned IncludesBlockSize = IncludesEndOffset - IncludesBeginOffset;
1667 if (!
affectsRange(Ranges, IncludesBeginOffset, IncludesEndOffset))
1670 for (
unsigned i = 0, e = Includes.size(); i != e; ++i)
1671 Indices.push_back(i);
1673 Indices.begin(), Indices.end(), [&](
unsigned LHSI,
unsigned RHSI) {
1675 std::tie(Includes[RHSI].Category, Includes[RHSI].Filename);
1679 unsigned CursorIndex;
1681 unsigned CursorToEOLOffset;
1683 std::tie(CursorIndex, CursorToEOLOffset) =
1687 Indices.erase(std::unique(Indices.begin(), Indices.end(),
1688 [&](
unsigned LHSI,
unsigned RHSI) {
1689 return Includes[LHSI].Text == Includes[RHSI].Text;
1693 int CurrentCategory = Includes.front().Category;
1697 if (Indices.size() == Includes.size() &&
1698 std::is_sorted(Indices.begin(), Indices.end()) &&
1703 for (
unsigned Index : Indices) {
1704 if (!result.empty()) {
1707 tooling::IncludeStyle::IBS_Regroup &&
1708 CurrentCategory != Includes[Index].Category)
1711 result += Includes[Index].Text;
1712 if (Cursor && CursorIndex == Index)
1713 *Cursor = IncludesBeginOffset + result.size() - CursorToEOLOffset;
1714 CurrentCategory = Includes[Index].Category;
1718 FileName, Includes.front().Offset, IncludesBlockSize, result));
1729 const char IncludeRegexPattern[] =
1730 R
"(^[\t\ ]*#[\t\ ]*(import|include)[^"<]*(["<][^">]*[">]))"; 1740 unsigned SearchFrom = 0;
1741 llvm::Regex IncludeRegex(IncludeRegexPattern);
1753 bool FirstIncludeBlock =
true;
1754 bool MainIncludeFound =
false;
1755 bool FormattingOff =
false;
1758 auto Pos = Code.find(
'\n', SearchFrom);
1760 Code.substr(Prev, (Pos != StringRef::npos ? Pos : Code.size()) - Prev);
1762 StringRef Trimmed = Line.trim();
1763 if (Trimmed ==
"// clang-format off")
1764 FormattingOff =
true;
1765 else if (Trimmed ==
"// clang-format on")
1766 FormattingOff =
false;
1768 const bool EmptyLineSkipped =
1772 tooling::IncludeStyle::IBS_Regroup);
1774 if (!FormattingOff && !Line.endswith(
"\\")) {
1775 if (IncludeRegex.match(Line, &Matches)) {
1776 StringRef IncludeName = Matches[2];
1779 !MainIncludeFound && FirstIncludeBlock);
1781 MainIncludeFound =
true;
1782 IncludesInBlock.push_back({IncludeName,
Line, Prev, Category});
1783 }
else if (!IncludesInBlock.empty() && !EmptyLineSkipped) {
1786 IncludesInBlock.clear();
1787 FirstIncludeBlock =
false;
1791 if (Pos == StringRef::npos || Pos + 1 == Code.size())
1793 SearchFrom = Pos + 1;
1795 if (!IncludesInBlock.empty())
1796 sortCppIncludes(Style, IncludesInBlock, Ranges, FileName, Replaces, Cursor);
1804 return Code.size() > 188 && Code[0] == 0x47 && Code[188] == 0x47;
1807 bool isLikelyXml(StringRef Code) {
return Code.ltrim().startswith(
"<"); }
1811 StringRef FileName,
unsigned *
Cursor) {
1817 if (Style.
Language == FormatStyle::LanguageKind::LK_JavaScript &&
1820 if (Style.
Language == FormatStyle::LanguageKind::LK_JavaScript)
1826 template <
typename T>
1831 if (Replaces.
empty())
1836 return NewCode.takeError();
1838 StringRef FileName = Replaces.
begin()->getFilePath();
1841 ProcessFunc(Style, *NewCode, ChangedRanges, FileName);
1843 return Replaces.
merge(FormatReplaces);
1852 std::vector<tooling::Range> Ranges,
1856 auto SortedReplaces =
1858 if (!SortedReplaces)
1859 return SortedReplaces.takeError();
1864 std::vector<tooling::Range> Ranges,
1866 return reformat(Style, Code, Ranges, FileName);
1890 std::set<llvm::StringRef> HeadersToDelete;
1892 for (
const auto &R : Replaces) {
1893 if (isHeaderInsertion(R)) {
1896 llvm::consumeError(HeaderInsertions.
add(R));
1897 }
else if (isHeaderDeletion(R)) {
1898 HeadersToDelete.insert(R.getReplacementText());
1899 }
else if (R.getOffset() ==
UINT_MAX) {
1900 llvm::errs() <<
"Insertions other than header #include insertion are " 1902 << R.getReplacementText() <<
"\n";
1904 llvm::consumeError(Result.
add(R));
1907 if (HeaderInsertions.
empty() && HeadersToDelete.empty())
1911 StringRef FileName = Replaces.begin()->getFilePath();
1914 for (
const auto &Header : HeadersToDelete) {
1916 Includes.
remove(Header.trim(
"\"<>"), Header.startswith(
"<"));
1917 for (
const auto &R : Replaces) {
1918 auto Err = Result.
add(R);
1921 llvm::errs() <<
"Failed to add header deletion replacement for " 1928 llvm::Regex IncludeRegex = llvm::Regex(IncludeRegexPattern);
1930 for (
const auto &R : HeaderInsertions) {
1931 auto IncludeDirective = R.getReplacementText();
1932 bool Matched = IncludeRegex.match(IncludeDirective, &Matches);
1933 assert(Matched &&
"Header insertion replacement must have replacement text " 1936 auto IncludeName = Matches[2];
1938 Includes.
insert(IncludeName.trim(
"\"<>"), IncludeName.startswith(
"<"));
1940 auto Err = Result.
add(*Replace);
1942 llvm::consumeError(std::move(Err));
1961 std::vector<tooling::Range> Ranges,
1963 return cleanup(Style, Code, Ranges, FileName);
1967 fixCppIncludeInsertions(Code, Replaces, Style);
1971 namespace internal {
1972 std::pair<tooling::Replacements, unsigned>
1975 unsigned NextStartColumn,
unsigned LastStartColumn, StringRef FileName,
1985 typedef std::function<std::pair<tooling::Replacements, unsigned>(
1990 if (Style.
Language == FormatStyle::LK_Cpp) {
2002 if (Style.
Language == FormatStyle::LK_JavaScript &&
2005 return JavaScriptRequoter(Env, Expanded).process();
2009 return Formatter(Env, Expanded, Status).process();
2013 llvm::make_unique<Environment>(Code, FileName, Ranges, FirstStartColumn,
2014 NextStartColumn, LastStartColumn);
2017 unsigned Penalty = 0;
2018 for (
size_t I = 0, E = Passes.size(); I < E; ++I) {
2019 std::pair<tooling::Replacements, unsigned> PassFixes = Passes[I](*Env);
2021 CurrentCode ? StringRef(*CurrentCode) : Code, PassFixes.first);
2023 Fixes = Fixes.
merge(PassFixes.first);
2024 Penalty += PassFixes.second;
2026 CurrentCode = std::move(*NewCode);
2027 Env = llvm::make_unique<Environment>(
2028 *CurrentCode, FileName,
2030 FirstStartColumn, NextStartColumn, LastStartColumn);
2035 return {Fixes, Penalty};
2046 0, FileName, Status)
2052 StringRef FileName) {
2054 if (Style.
Language != FormatStyle::LK_Cpp)
2056 return Cleaner(
Environment(Code, FileName, Ranges), Style).process().first;
2061 StringRef FileName,
bool *IncompleteFormat) {
2063 auto Result =
reformat(Style, Code, Ranges, FileName, &Status);
2065 *IncompleteFormat =
true;
2072 StringRef FileName) {
2081 StringRef FileName) {
2089 LangOpts.CPlusPlus = 1;
2090 LangOpts.CPlusPlus11 = Style.
Standard == FormatStyle::LS_Cpp03 ? 0 : 1;
2091 LangOpts.CPlusPlus14 = Style.
Standard == FormatStyle::LS_Cpp03 ? 0 : 1;
2092 LangOpts.CPlusPlus17 = Style.
Standard == FormatStyle::LS_Cpp03 ? 0 : 1;
2093 LangOpts.CPlusPlus2a = Style.
Standard == FormatStyle::LS_Cpp03 ? 0 : 1;
2094 LangOpts.LineComment = 1;
2095 bool AlternativeOperators = Style.
isCpp();
2096 LangOpts.CXXOperatorNames = AlternativeOperators ? 1 : 0;
2100 LangOpts.MicrosoftExt = 1;
2101 LangOpts.DeclSpecKeyword = 1;
2106 "Coding style, currently supports:\n" 2107 " LLVM, Google, Chromium, Mozilla, WebKit.\n" 2108 "Use -style=file to load style configuration from\n" 2109 ".clang-format file located in one of the parent\n" 2110 "directories of the source file (or current\n" 2111 "directory for stdin).\n" 2112 "Use -style=\"{key: value, ...}\" to set specific\n" 2113 "parameters, e.g.:\n" 2114 " -style=\"{BasedOnStyle: llvm, IndentWidth: 8}\"";
2117 if (FileName.endswith(
".java"))
2118 return FormatStyle::LK_Java;
2119 if (FileName.endswith_lower(
".js") || FileName.endswith_lower(
".ts"))
2120 return FormatStyle::LK_JavaScript;
2121 if (FileName.endswith(
".m") || FileName.endswith(
".mm"))
2122 return FormatStyle::LK_ObjC;
2123 if (FileName.endswith_lower(
".proto") ||
2124 FileName.endswith_lower(
".protodevel"))
2125 return FormatStyle::LK_Proto;
2126 if (FileName.endswith_lower(
".textpb") ||
2127 FileName.endswith_lower(
".pb.txt") ||
2128 FileName.endswith_lower(
".textproto") ||
2129 FileName.endswith_lower(
".asciipb"))
2130 return FormatStyle::LK_TextProto;
2131 if (FileName.endswith_lower(
".td"))
2132 return FormatStyle::LK_TableGen;
2133 return FormatStyle::LK_Cpp;
2138 if (GuessedLanguage == FormatStyle::LK_Cpp) {
2139 auto Extension = llvm::sys::path::extension(FileName);
2142 if (Extension.empty() || Extension ==
".h") {
2143 auto NonEmptyFileName = FileName.empty() ?
"guess.h" : FileName;
2147 if (Guesser.isObjC())
2148 return FormatStyle::LK_ObjC;
2151 return GuessedLanguage;
2159 StringRef FallbackStyleName,
2171 if (StyleName.startswith(
"{")) {
2178 if (!StyleName.equals_lower(
"file")) {
2190 for (StringRef Directory = Path; !Directory.empty();
2191 Directory = llvm::sys::path::parent_path(Directory)) {
2193 auto Status = FS->
status(Directory);
2195 Status->getType() != llvm::sys::fs::file_type::directory_file) {
2201 llvm::sys::path::append(ConfigFile,
".clang-format");
2202 LLVM_DEBUG(llvm::dbgs() <<
"Trying " << ConfigFile <<
"...\n");
2204 Status = FS->
status(ConfigFile.str());
2205 bool FoundConfigFile =
2206 Status && (Status->getType() == llvm::sys::fs::file_type::regular_file);
2207 if (!FoundConfigFile) {
2209 ConfigFile = Directory;
2210 llvm::sys::path::append(ConfigFile,
"_clang-format");
2211 LLVM_DEBUG(llvm::dbgs() <<
"Trying " << ConfigFile <<
"...\n");
2212 Status = FS->
status(ConfigFile.str());
2213 FoundConfigFile = Status && (Status->getType() ==
2214 llvm::sys::fs::file_type::regular_file);
2217 if (FoundConfigFile) {
2218 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
Text =
2220 if (std::error_code EC = Text.getError())
2222 if (std::error_code ec =
2224 if (ec == ParseError::Unsuitable) {
2225 if (!UnsuitableConfigFiles.empty())
2226 UnsuitableConfigFiles.append(
", ");
2227 UnsuitableConfigFiles.append(ConfigFile);
2233 LLVM_DEBUG(llvm::dbgs()
2234 <<
"Using configuration file " << ConfigFile <<
"\n");
2238 if (!UnsuitableConfigFiles.empty())
2241 UnsuitableConfigFiles);
2242 return FallbackStyle;
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...
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.
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.
WhitespaceManager class manages whitespace around tokens and their replacements.
const AnnotatedLine * Line
SourceLocation getLocation() const
Return a source location identifier for the specified offset in the current file. ...
SourceLocation getEnd() const
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.
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.
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.
bool isObjC(ID Id)
isObjC - Is this an "ObjC" input (Obj-C and Obj-C++ sources and headers).
SourceLocation getEndLoc() const