[clang] 2bd6974 - [clang-format] Wrap lines for C# property accessors
Jonathan Coe via cfe-commits
cfe-commits at lists.llvm.org
Tue Feb 25 06:24:09 PST 2020
Author: Jonathan Coe
Date: 2020-02-25T14:23:47Z
New Revision: 2bd6974aaa664f01e8822514295425fee380b131
URL: https://github.com/llvm/llvm-project/commit/2bd6974aaa664f01e8822514295425fee380b131
DIFF: https://github.com/llvm/llvm-project/commit/2bd6974aaa664f01e8822514295425fee380b131.diff
LOG: [clang-format] Wrap lines for C# property accessors
Summary: Ensure that auto-implemented properties `{ get; private set }` are wrapped on to one line for C# code.
Reviewers: MyDeveloperDay, krasimir
Reviewed By: MyDeveloperDay, krasimir
Subscribers: cfe-commits
Tags: #clang-format, #clang
Differential Revision: https://reviews.llvm.org/D75006
Added:
Modified:
clang/lib/Format/UnwrappedLineFormatter.cpp
clang/unittests/Format/FormatTestCSharp.cpp
Removed:
################################################################################
diff --git a/clang/lib/Format/UnwrappedLineFormatter.cpp b/clang/lib/Format/UnwrappedLineFormatter.cpp
index 0e1b5e95e9dd..da9ee41da71b 100644
--- a/clang/lib/Format/UnwrappedLineFormatter.cpp
+++ b/clang/lib/Format/UnwrappedLineFormatter.cpp
@@ -292,6 +292,13 @@ class LineJoiner {
}
}
+ // Try to merge a CSharp property declaration like `{ get; private set }`.
+ if (Style.isCSharp()) {
+ unsigned CSPA = tryMergeCSharpPropertyAccessor(I, E, Limit);
+ if (CSPA > 0)
+ return CSPA;
+ }
+
// Try to merge a function block with left brace unwrapped
if (TheLine->Last->is(TT_FunctionLBrace) &&
TheLine->First != TheLine->Last) {
@@ -421,6 +428,64 @@ class LineJoiner {
return 0;
}
+ // true for lines of the form [access-modifier] {get,set} [;]
+ bool isMergeablePropertyAccessor(const AnnotatedLine *Line) {
+ auto *Tok = Line->First;
+ if (!Tok)
+ return false;
+
+ if (Tok->isOneOf(tok::kw_public, tok::kw_protected, tok::kw_private,
+ Keywords.kw_internal))
+ Tok = Tok->Next;
+
+ if (!Tok || (Tok->TokenText != "get" && Tok->TokenText != "set"))
+ return false;
+
+ if (!Tok->Next || Tok->Next->is(tok::semi))
+ return true;
+
+ return false;
+ }
+
+ unsigned tryMergeCSharpPropertyAccessor(
+ SmallVectorImpl<AnnotatedLine *>::const_iterator I,
+ SmallVectorImpl<AnnotatedLine *>::const_iterator E, unsigned /*Limit*/) {
+
+ auto CurrentLine = I;
+ // Does line start with `{`
+ if (!(*CurrentLine)->Last || (*CurrentLine)->Last->isNot(TT_FunctionLBrace))
+ return 0;
+ ++CurrentLine;
+
+ unsigned MergedLines = 0;
+ bool HasGetOrSet = false;
+ while (CurrentLine != E) {
+ bool LineIsGetOrSet = isMergeablePropertyAccessor(*CurrentLine);
+ HasGetOrSet = HasGetOrSet || LineIsGetOrSet;
+ if (LineIsGetOrSet) {
+ ++CurrentLine;
+ ++MergedLines;
+ continue;
+ }
+ auto *Tok = (*CurrentLine)->First;
+ if (Tok && Tok->is(tok::r_brace)) {
+ ++CurrentLine;
+ ++MergedLines;
+ // See if the next line is a default value so that we can merge `{ get;
+ // set } = 0`
+ if (CurrentLine != E && (*CurrentLine)->First &&
+ (*CurrentLine)->First->is(tok::equal)) {
+ ++MergedLines;
+ }
+ break;
+ }
+ // Not a '}' or a get/set line so do not merege lines.
+ return 0;
+ }
+
+ return HasGetOrSet ? MergedLines : 0;
+ }
+
unsigned
tryMergeSimplePPDirective(SmallVectorImpl<AnnotatedLine *>::const_iterator I,
SmallVectorImpl<AnnotatedLine *>::const_iterator E,
diff --git a/clang/unittests/Format/FormatTestCSharp.cpp b/clang/unittests/Format/FormatTestCSharp.cpp
index 1800768d6771..68a8e9fefe2d 100644
--- a/clang/unittests/Format/FormatTestCSharp.cpp
+++ b/clang/unittests/Format/FormatTestCSharp.cpp
@@ -240,18 +240,12 @@ TEST_F(FormatTestCSharp, Attributes) {
verifyFormat("[TestMethod]\n"
"public string Host\n"
- "{\n"
- " set;\n"
- " get;\n"
- "}");
+ "{ set; get; }");
verifyFormat("[TestMethod(\"start\", HelpText = \"Starts the server "
"listening on provided host\")]\n"
"public string Host\n"
- "{\n"
- " set;\n"
- " get;\n"
- "}");
+ "{ set; get; }");
verifyFormat(
"[DllImport(\"Hello\", EntryPoint = \"hello_world\")]\n"
@@ -554,5 +548,32 @@ PrintOrderDetails(orderNum: 31, productName: "Red Mug", // comment
Style);
}
+TEST_F(FormatTestCSharp, CSharpPropertyAccessors) {
+ FormatStyle Style = getGoogleStyle(FormatStyle::LK_CSharp);
+
+ verifyFormat("int Value { get }", Style);
+ verifyFormat("int Value { get; }", Style);
+ verifyFormat("int Value { internal get; }", Style);
+ verifyFormat("int Value { get; } = 0", Style);
+ verifyFormat("int Value { set }", Style);
+ verifyFormat("int Value { set; }", Style);
+ verifyFormat("int Value { internal set; }", Style);
+ verifyFormat("int Value { set; } = 0", Style);
+ verifyFormat("int Value { get; set }", Style);
+ verifyFormat("int Value { set; get }", Style);
+ verifyFormat("int Value { get; private set; }", Style);
+ verifyFormat("int Value { get; set; }", Style);
+ verifyFormat("int Value { get; set; } = 0", Style);
+ verifyFormat("int Value { internal get; internal set; }", Style);
+
+ // Do not wrap expression body definitions.
+ verifyFormat(R"(//
+public string Name {
+ get => _name;
+ set => _name = value;
+})",
+ Style);
+}
+
} // namespace format
} // end namespace clang
More information about the cfe-commits
mailing list