Index: clang/lib/Format/TokenAnnotator.cpp =================================================================== --- clang/lib/Format/TokenAnnotator.cpp +++ clang/lib/Format/TokenAnnotator.cpp @@ -3520,6 +3520,13 @@ return false; if (Right.is(TT_CSharpGenericTypeConstraint)) return true; + + // Break after C# [...] and before public/protected/private/internal. + if (Left.is(TT_AttributeSquare) && Left.is(tok::r_square) && + (Right.isAccessSpecifier(/*ColonRequired=*/false) || + Right.is(Keywords.kw_internal))) + return true; + } else if (Style.Language == FormatStyle::LK_JavaScript) { // FIXME: This might apply to other languages and token kinds. if (Right.is(tok::string_literal) && Left.is(tok::plus) && Left.Previous && Index: clang/unittests/Format/FormatTestCSharp.cpp =================================================================== --- clang/unittests/Format/FormatTestCSharp.cpp +++ clang/unittests/Format/FormatTestCSharp.cpp @@ -247,6 +247,16 @@ verifyFormat("[TestMethod]\n" "public string Host { set; get; }"); + // Adjacent attributes caused line wrapping issues + verifyFormat("[JsonProperty(\"foo\")]\n" + "public string Foo { set; get; }\n" + "[JsonProperty(\"bar\")]\n" + "public string Bar { set; get; }\n" + "[JsonProperty(\"bar\")]\n" + "protected string Bar { set; get; }\n" + "[JsonProperty(\"bar\")]\n" + "internal string Bar { set; get; }"); + verifyFormat("[TestMethod(\"start\", HelpText = \"Starts the server " "listening on provided host\")]\n" "public string Host { set; get; }");