diff --git a/clang/lib/Format/FormatToken.h b/clang/lib/Format/FormatToken.h index b00b8ab7b927ce..fa76da15a53d3a 100644 --- a/clang/lib/Format/FormatToken.h +++ b/clang/lib/Format/FormatToken.h @@ -954,6 +954,7 @@ struct AdditionalKeywords { kw_event = &IdentTable.get("event"); kw_fixed = &IdentTable.get("fixed"); kw_foreach = &IdentTable.get("foreach"); + kw_init = &IdentTable.get("init"); kw_implicit = &IdentTable.get("implicit"); kw_internal = &IdentTable.get("internal"); kw_lock = &IdentTable.get("lock"); @@ -986,11 +987,11 @@ struct AdditionalKeywords { CSharpExtraKeywords = std::unordered_set( {kw_base, kw_byte, kw_checked, kw_decimal, kw_delegate, kw_event, - kw_fixed, kw_foreach, kw_implicit, kw_in, kw_interface, kw_internal, - kw_is, kw_lock, kw_null, kw_object, kw_out, kw_override, kw_params, - kw_readonly, kw_ref, kw_string, kw_stackalloc, kw_sbyte, kw_sealed, - kw_uint, kw_ulong, kw_unchecked, kw_unsafe, kw_ushort, kw_when, - kw_where, + kw_fixed, kw_foreach, kw_implicit, kw_in, kw_init, kw_interface, + kw_internal, kw_is, kw_lock, kw_null, kw_object, kw_out, kw_override, + kw_params, kw_readonly, kw_ref, kw_string, kw_stackalloc, kw_sbyte, + kw_sealed, kw_uint, kw_ulong, kw_unchecked, kw_unsafe, kw_ushort, + kw_when, kw_where, // Keywords from the JavaScript section. kw_as, kw_async, kw_await, kw_declare, kw_finally, kw_from, kw_function, kw_get, kw_import, kw_is, kw_let, kw_module, kw_readonly, @@ -1078,6 +1079,7 @@ struct AdditionalKeywords { IdentifierInfo *kw_fixed; IdentifierInfo *kw_foreach; IdentifierInfo *kw_implicit; + IdentifierInfo *kw_init; IdentifierInfo *kw_internal; IdentifierInfo *kw_lock; diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp index 3015cd2be8879a..236e9a73b33a82 100644 --- a/clang/lib/Format/TokenAnnotator.cpp +++ b/clang/lib/Format/TokenAnnotator.cpp @@ -1652,7 +1652,7 @@ class AnnotatingParser { Current.Previous->isOneOf( tok::kw_namespace, tok::r_paren, tok::r_square, tok::r_brace, tok::kw_false, tok::kw_true, Keywords.kw_type, Keywords.kw_get, - Keywords.kw_set) || + Keywords.kw_init, Keywords.kw_set) || Current.Previous->Tok.isLiteral()) { Current.setType(TT_NonNullAssertion); return; diff --git a/clang/lib/Format/UnwrappedLineParser.cpp b/clang/lib/Format/UnwrappedLineParser.cpp index a62aa5e6498394..994b197347bc1f 100644 --- a/clang/lib/Format/UnwrappedLineParser.cpp +++ b/clang/lib/Format/UnwrappedLineParser.cpp @@ -1837,16 +1837,16 @@ bool UnwrappedLineParser::tryToParsePropertyAccessor() { FormatToken *Tok = Tokens->getNextToken(); // A trivial property accessor is of the form: - // { [ACCESS_SPECIFIER] [get]; [ACCESS_SPECIFIER] [set] } + // { [ACCESS_SPECIFIER] [get]; [ACCESS_SPECIFIER] [set|init] } // Track these as they do not require line breaks to be introduced. - bool HasGetOrSet = false; + bool HasSpecialAccessor = false; bool IsTrivialPropertyAccessor = true; while (!eof()) { if (Tok->isOneOf(tok::semi, tok::kw_public, tok::kw_private, tok::kw_protected, Keywords.kw_internal, Keywords.kw_get, - Keywords.kw_set)) { - if (Tok->isOneOf(Keywords.kw_get, Keywords.kw_set)) - HasGetOrSet = true; + Keywords.kw_init, Keywords.kw_set)) { + if (Tok->isOneOf(Keywords.kw_get, Keywords.kw_init, Keywords.kw_set)) + HasSpecialAccessor = true; Tok = Tokens->getNextToken(); continue; } @@ -1855,7 +1855,7 @@ bool UnwrappedLineParser::tryToParsePropertyAccessor() { break; } - if (!HasGetOrSet) { + if (!HasSpecialAccessor) { Tokens->setPosition(StoredPosition); return false; } @@ -1897,7 +1897,8 @@ bool UnwrappedLineParser::tryToParsePropertyAccessor() { nextToken(); break; default: - if (FormatTok->isOneOf(Keywords.kw_get, Keywords.kw_set) && + if (FormatTok->isOneOf(Keywords.kw_get, Keywords.kw_init, + Keywords.kw_set) && !IsTrivialPropertyAccessor) { // Non-trivial get/set needs to be on its own line. addUnwrappedLine(); diff --git a/clang/unittests/Format/FormatTestCSharp.cpp b/clang/unittests/Format/FormatTestCSharp.cpp index 26c62c145064db..2a7642012a5f9a 100644 --- a/clang/unittests/Format/FormatTestCSharp.cpp +++ b/clang/unittests/Format/FormatTestCSharp.cpp @@ -960,9 +960,11 @@ TEST_F(FormatTestCSharp, CSharpPropertyAccessors) { verifyFormat("int Value { get; } = 0", Style); verifyFormat("int Value { set }", Style); verifyFormat("int Value { set; }", Style); + verifyFormat("int Value { init; }", Style); verifyFormat("int Value { internal set; }", Style); verifyFormat("int Value { set; } = 0", Style); verifyFormat("int Value { get; set }", Style); + verifyFormat("int Value { get; init; }", Style); verifyFormat("int Value { set; get }", Style); verifyFormat("int Value { get; private set; }", Style); verifyFormat("int Value { get; set; }", Style); @@ -974,6 +976,18 @@ TEST_F(FormatTestCSharp, CSharpPropertyAccessors) { public string Name { get => _name; set => _name = value; +})", + Style); + verifyFormat(R"(// +public string Name { + init => _name = value; + get => _name; +})", + Style); + verifyFormat(R"(// +public string Name { + set => _name = value; + get => _name; })", Style);