MyDeveloperDay updated this revision to Diff 514029.
MyDeveloperDay added a comment.
for default `set;get` or `get;set` for when `AfterCSharpProperty` is true,
public Foo {
set;
get;
}
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D148467/new/
https://reviews.llvm.org/D148467
Files:
clang/docs/ClangFormatStyleOptions.rst
clang/docs/ReleaseNotes.rst
clang/include/clang/Format/Format.h
clang/lib/Format/Format.cpp
clang/lib/Format/TokenAnnotator.cpp
clang/unittests/Format/FormatTestCSharp.cpp
Index: clang/unittests/Format/FormatTestCSharp.cpp
===================================================================
--- clang/unittests/Format/FormatTestCSharp.cpp
+++ clang/unittests/Format/FormatTestCSharp.cpp
@@ -1604,5 +1604,81 @@
EXPECT_NE("", format("int where b <")); // reduced from crasher
}
+TEST_F(FormatTestCSharp, PropertyWrapping) {
+ FormatStyle Style = getMicrosoftStyle(FormatStyle::LK_CSharp);
+
+ Style.BraceWrapping.AfterCSharpProperty = false;
+ verifyFormat("class A\n"
+ "{\n"
+ " string Foo { set; get; }\n"
+ "}\n",
+ Style);
+ verifyFormat("class A\n"
+ "{\n"
+ " string Foo { get; set; }\n"
+ "}\n",
+ Style);
+ verifyFormat("class A\n"
+ "{\n"
+ " string Foo\n"
+ " {\n"
+ " set {\n"
+ " val = value;\n"
+ " }\n"
+ " get {\n"
+ " return value;\n"
+ " }\n"
+ " }\n"
+ "}\n",
+ Style);
+
+ Style.BraceWrapping.AfterCSharpProperty = true;
+
+ verifyFormat("class A\n"
+ "{\n"
+ " string Bar {\n"
+ " set;\n"
+ " get;\n"
+ " }\n"
+ "}\n",
+ Style);
+ verifyFormat("class A\n"
+ "{\n"
+ " string Bar {\n"
+ " get;\n"
+ " set;\n"
+ " }\n"
+ "}\n",
+ Style);
+ verifyFormat("class A\n"
+ "{\n"
+ " string Bar\n"
+ " {\n"
+ " set\n"
+ " {\n"
+ " val = value;\n"
+ " }\n"
+ " get\n"
+ " {\n"
+ " return value;\n"
+ " }\n"
+ " }\n"
+ "}\n",
+ Style);
+ /* TODO fix the indentation of get;
+ verifyFormat("class A\n"
+ "{\n"
+ " string Bar {\n"
+ " get;\n"
+ " set\n"
+ " {\n"
+ " val = value;\n"
+ " }\n"
+ " }\n"
+ "}\n",
+ Style);
+ */
+}
+
} // namespace format
} // end namespace clang
Index: clang/lib/Format/TokenAnnotator.cpp
===================================================================
--- clang/lib/Format/TokenAnnotator.cpp
+++ clang/lib/Format/TokenAnnotator.cpp
@@ -4984,6 +4984,13 @@
return true;
}
+ // Handle `string Foo {{set {} get {}}`.
+ if (Style.isCSharp() && Style.BraceWrapping.AfterCSharpProperty &&
+ (Line.startsWith(Keywords.kw_get) ||
+ Line.startsWith(Keywords.kw_set))) {
+ return true;
+ }
+
// Don't attempt to interpret struct return types as structs.
if (Right.isNot(TT_FunctionLBrace)) {
return (Line.startsWith(tok::kw_class) &&
@@ -4993,16 +5000,28 @@
}
}
- if (Left.is(TT_ObjCBlockLBrace) &&
- Style.AllowShortBlocksOnASingleLine == FormatStyle::SBS_Never) {
+ // Handle `string Foo {set;get }`.
+ if (Style.isCSharp() && Style.BraceWrapping.AfterCSharpProperty &&
+ (( Left.isOneOf(tok::l_brace,tok::semi) &&
+ Right.isOneOf(Keywords.kw_set,Keywords.kw_get)) ||
+ (Left.is(tok::semi) && Left.Previous &&
+ Left.Previous->is(Keywords.kw_get) && Right.is(tok::r_brace)) ||
+ (Left.is(tok::semi) && Left.Previous &&
+ Left.Previous->is(Keywords.kw_set) && Right.is(tok::r_brace))
+ )) {
return true;
}
- // Ensure wrapping after __attribute__((XX)) and @interface etc.
- if (Left.is(TT_AttributeParen) && Right.is(TT_ObjCDecl))
+if (Left.is(TT_ObjCBlockLBrace) &&
+ Style.AllowShortBlocksOnASingleLine == FormatStyle::SBS_Never) {
return true;
+}
- if (Left.is(TT_LambdaLBrace)) {
+// Ensure wrapping after __attribute__((XX)) and @interface etc.
+if (Left.is(TT_AttributeParen) && Right.is(TT_ObjCDecl))
+ return true;
+
+if (Left.is(TT_LambdaLBrace)) {
if (IsFunctionArgument(Left) &&
Style.AllowShortLambdasOnASingleLine == FormatStyle::SLS_Inline) {
return false;
@@ -5014,54 +5033,54 @@
Style.AllowShortLambdasOnASingleLine == FormatStyle::SLS_Empty)) {
return true;
}
- }
+}
- if (Style.BraceWrapping.BeforeLambdaBody && Right.is(TT_LambdaLBrace) &&
- Left.isOneOf(tok::star, tok::amp, tok::ampamp, TT_TemplateCloser)) {
+if (Style.BraceWrapping.BeforeLambdaBody && Right.is(TT_LambdaLBrace) &&
+ Left.isOneOf(tok::star, tok::amp, tok::ampamp, TT_TemplateCloser)) {
return true;
- }
+}
- // Put multiple Java annotation on a new line.
- if ((Style.Language == FormatStyle::LK_Java || Style.isJavaScript()) &&
- Left.is(TT_LeadingJavaAnnotation) &&
- Right.isNot(TT_LeadingJavaAnnotation) && Right.isNot(tok::l_paren) &&
- (Line.Last->is(tok::l_brace) || Style.BreakAfterJavaFieldAnnotations)) {
+// Put multiple Java annotation on a new line.
+if ((Style.Language == FormatStyle::LK_Java || Style.isJavaScript()) &&
+ Left.is(TT_LeadingJavaAnnotation) &&
+ Right.isNot(TT_LeadingJavaAnnotation) && Right.isNot(tok::l_paren) &&
+ (Line.Last->is(tok::l_brace) || Style.BreakAfterJavaFieldAnnotations)) {
return true;
- }
+}
- if (Right.is(TT_ProtoExtensionLSquare))
- return true;
+if (Right.is(TT_ProtoExtensionLSquare))
+ return true;
- // In text proto instances if a submessage contains at least 2 entries and at
- // least one of them is a submessage, like A { ... B { ... } ... },
- // put all of the entries of A on separate lines by forcing the selector of
- // the submessage B to be put on a newline.
- //
- // Example: these can stay on one line:
- // a { scalar_1: 1 scalar_2: 2 }
- // a { b { key: value } }
- //
- // and these entries need to be on a new line even if putting them all in one
- // line is under the column limit:
- // a {
- // scalar: 1
- // b { key: value }
- // }
- //
- // We enforce this by breaking before a submessage field that has previous
- // siblings, *and* breaking before a field that follows a submessage field.
- //
- // Be careful to exclude the case [proto.ext] { ... } since the `]` is
- // the TT_SelectorName there, but we don't want to break inside the brackets.
- //
- // Another edge case is @submessage { key: value }, which is a common
- // substitution placeholder. In this case we want to keep `@` and `submessage`
- // together.
- //
- // We ensure elsewhere that extensions are always on their own line.
- if ((Style.Language == FormatStyle::LK_Proto ||
- Style.Language == FormatStyle::LK_TextProto) &&
- Right.is(TT_SelectorName) && !Right.is(tok::r_square) && Right.Next) {
+// In text proto instances if a submessage contains at least 2 entries and at
+// least one of them is a submessage, like A { ... B { ... } ... },
+// put all of the entries of A on separate lines by forcing the selector of
+// the submessage B to be put on a newline.
+//
+// Example: these can stay on one line:
+// a { scalar_1: 1 scalar_2: 2 }
+// a { b { key: value } }
+//
+// and these entries need to be on a new line even if putting them all in one
+// line is under the column limit:
+// a {
+// scalar: 1
+// b { key: value }
+// }
+//
+// We enforce this by breaking before a submessage field that has previous
+// siblings, *and* breaking before a field that follows a submessage field.
+//
+// Be careful to exclude the case [proto.ext] { ... } since the `]` is
+// the TT_SelectorName there, but we don't want to break inside the brackets.
+//
+// Another edge case is @submessage { key: value }, which is a common
+// substitution placeholder. In this case we want to keep `@` and `submessage`
+// together.
+//
+// We ensure elsewhere that extensions are always on their own line.
+if ((Style.Language == FormatStyle::LK_Proto ||
+ Style.Language == FormatStyle::LK_TextProto) &&
+ Right.is(TT_SelectorName) && !Right.is(tok::r_square) && Right.Next) {
// Keep `@submessage` together in:
// @submessage { key: value }
if (Left.is(tok::at))
@@ -5115,15 +5134,15 @@
// put on a new line anyways.
if (Left.isOneOf(tok::r_brace, tok::greater, tok::r_square))
return true;
- }
+}
- // Deal with lambda arguments in C++ - we want consistent line breaks whether
- // they happen to be at arg0, arg1 or argN. The selection is a bit nuanced
- // as aggressive line breaks are placed when the lambda is not the last arg.
- if ((Style.Language == FormatStyle::LK_Cpp ||
- Style.Language == FormatStyle::LK_ObjC) &&
- Left.is(tok::l_paren) && Left.BlockParameterCount > 0 &&
- !Right.isOneOf(tok::l_paren, TT_LambdaLSquare)) {
+// Deal with lambda arguments in C++ - we want consistent line breaks whether
+// they happen to be at arg0, arg1 or argN. The selection is a bit nuanced
+// as aggressive line breaks are placed when the lambda is not the last arg.
+if ((Style.Language == FormatStyle::LK_Cpp ||
+ Style.Language == FormatStyle::LK_ObjC) &&
+ Left.is(tok::l_paren) && Left.BlockParameterCount > 0 &&
+ !Right.isOneOf(tok::l_paren, TT_LambdaLSquare)) {
// Multiple lambdas in the same function call force line breaks.
if (Left.BlockParameterCount > 1)
return true;
@@ -5139,9 +5158,9 @@
return false;
if (!Next->isOneOf(TT_LambdaLSquare, tok::l_brace, tok::caret))
return true;
- }
+}
- return false;
+return false;
}
bool TokenAnnotator::canBreakBefore(const AnnotatedLine &Line,
Index: clang/lib/Format/Format.cpp
===================================================================
--- clang/lib/Format/Format.cpp
+++ clang/lib/Format/Format.cpp
@@ -181,6 +181,7 @@
IO.mapOptional("AfterEnum", Wrapping.AfterEnum);
IO.mapOptional("AfterExternBlock", Wrapping.AfterExternBlock);
IO.mapOptional("AfterFunction", Wrapping.AfterFunction);
+ IO.mapOptional("AfterCSharpProperty", Wrapping.AfterCSharpProperty);
IO.mapOptional("AfterNamespace", Wrapping.AfterNamespace);
IO.mapOptional("AfterObjCDeclaration", Wrapping.AfterObjCDeclaration);
IO.mapOptional("AfterStruct", Wrapping.AfterStruct);
@@ -1188,7 +1189,8 @@
/*IndentBraces=*/false,
/*SplitEmptyFunction=*/true,
/*SplitEmptyRecord=*/true,
- /*SplitEmptyNamespace=*/true};
+ /*SplitEmptyNamespace=*/true,
+ /*AfterCSharpProperty=*/false};
switch (Expanded.BreakBeforeBraces) {
case FormatStyle::BS_Linux:
Expanded.BraceWrapping.AfterClass = true;
@@ -1354,7 +1356,8 @@
/*IndentBraces=*/false,
/*SplitEmptyFunction=*/true,
/*SplitEmptyRecord=*/true,
- /*SplitEmptyNamespace=*/true};
+ /*SplitEmptyNamespace=*/true,
+ /*AfterCSharpProperty=*/false};
LLVMStyle.BreakAfterAttributes = FormatStyle::ABS_Never;
LLVMStyle.BreakAfterJavaFieldAnnotations = false;
LLVMStyle.BreakArrays = true;
Index: clang/include/clang/Format/Format.h
===================================================================
--- clang/include/clang/Format/Format.h
+++ clang/include/clang/Format/Format.h
@@ -1205,6 +1205,19 @@
/// \endcode
///
bool SplitEmptyNamespace;
+ /// Wrap C# setter/getter properties.
+ /// \code
+ /// true:
+ /// get
+ /// {}
+ /// set
+ /// {}
+ ///
+ /// false:
+ /// get {}
+ /// set {}
+ /// \endcode
+ bool AfterCSharpProperty;
};
/// Control of individual brace wrapping cases.
Index: clang/docs/ReleaseNotes.rst
===================================================================
--- clang/docs/ReleaseNotes.rst
+++ clang/docs/ReleaseNotes.rst
@@ -461,6 +461,8 @@
- Add additional Qualifier Ordering support for special cases such
as templates, requires clauses, long qualified names.
- Fix all known issues associated with ``LambdaBodyIndentation: OuterScope``.
+- Add ``AfterCSharpProperty`` style to option ``BraceWrapping`` to allow
+ newline before the opening brace of ``set;get;``.
libclang
--------
Index: clang/docs/ClangFormatStyleOptions.rst
===================================================================
--- clang/docs/ClangFormatStyleOptions.rst
+++ clang/docs/ClangFormatStyleOptions.rst
@@ -1828,6 +1828,20 @@
{} {
}
+ * ``bool AfterCSharpProperty`` Wrap C# setter/getter properties.
+
+ .. code-block:: c++
+
+ true:
+ get
+ {}
+ set
+ {}
+
+ false:
+ get {}
+ set {}
+
.. _BreakAfterAttributes:
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits