[clang] e8c5fea - [clang-format] Special handling of spaces for C# code
Jonathan Coe via cfe-commits
cfe-commits at lists.llvm.org
Wed Feb 26 07:34:42 PST 2020
Author: Jonathan Coe
Date: 2020-02-26T15:27:03Z
New Revision: e8c5fea243ce30640ec9707fabdb635a49b3153c
URL: https://github.com/llvm/llvm-project/commit/e8c5fea243ce30640ec9707fabdb635a49b3153c
DIFF: https://github.com/llvm/llvm-project/commit/e8c5fea243ce30640ec9707fabdb635a49b3153c.diff
LOG: [clang-format] Special handling of spaces for C# code
Summary:
Ensure that there are spaces around braces '{', '}'.
Ensure that there is a space before and after '=>'.
Ensure that 'async' and 'when' are considered as keywords when inserting spaces.
Reviewers: krasimir, MyDeveloperDay
Reviewed By: krasimir
Tags: #clang-format
Differential Revision: https://reviews.llvm.org/D75129
Added:
Modified:
clang/lib/Format/FormatToken.h
clang/lib/Format/TokenAnnotator.cpp
clang/unittests/Format/FormatTestCSharp.cpp
Removed:
################################################################################
diff --git a/clang/lib/Format/FormatToken.h b/clang/lib/Format/FormatToken.h
index dc68cbc79734..6bbfdcf37f93 100644
--- a/clang/lib/Format/FormatToken.h
+++ b/clang/lib/Format/FormatToken.h
@@ -771,6 +771,7 @@ struct AdditionalKeywords {
kw_unchecked = &IdentTable.get("unchecked");
kw_unsafe = &IdentTable.get("unsafe");
kw_ushort = &IdentTable.get("ushort");
+ kw_when = &IdentTable.get("when");
// Keep this at the end of the constructor to make sure everything here
// is
@@ -787,7 +788,7 @@ struct AdditionalKeywords {
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_uint, kw_ulong, kw_unchecked, kw_unsafe, kw_ushort, kw_when,
// 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,
@@ -891,6 +892,7 @@ struct AdditionalKeywords {
IdentifierInfo *kw_unchecked;
IdentifierInfo *kw_unsafe;
IdentifierInfo *kw_ushort;
+ IdentifierInfo *kw_when;
/// Returns \c true if \p Tok is a true JavaScript identifier, returns
/// \c false if it is a keyword or a pseudo keyword.
diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp
index d71c4f470378..04b20599638d 100644
--- a/clang/lib/Format/TokenAnnotator.cpp
+++ b/clang/lib/Format/TokenAnnotator.cpp
@@ -2870,21 +2870,34 @@ bool TokenAnnotator::spaceRequiredBefore(const AnnotatedLine &Line,
if (Left.is(tok::numeric_constant) && Right.is(tok::percent))
return Right.WhitespaceRange.getEnd() != Right.WhitespaceRange.getBegin();
} else if (Style.isCSharp()) {
+ // Require spaces around '{' and before '}' unless they appear in
+ // interpolated strings. Interpolated strings are merged into a single token
+ // so cannot have spaces inserted by this function.
+
+ // Space before { (including space within '{ {').
+ if (Right.is(tok::l_brace))
+ return true;
+
+ // Spaces inside braces.
+ if (Left.is(tok::l_brace) && Right.isNot(tok::r_brace))
+ return true;
+
+ if (Left.isNot(tok::l_brace) && Right.is(tok::r_brace))
+ return true;
+
+ // Spaces around '=>'.
+ if (Left.is(TT_JsFatArrow) || Right.is(TT_JsFatArrow))
+ return true;
+
// space between type and variable e.g. Dictionary<string,string> foo;
if (Left.is(TT_TemplateCloser) && Right.is(TT_StartOfName))
return true;
+
// space between keywords and paren e.g. "using ("
if (Right.is(tok::l_paren))
- if (Left.is(tok::kw_using))
+ if (Left.isOneOf(tok::kw_using, Keywords.kw_async, Keywords.kw_when))
return Style.SpaceBeforeParens == FormatStyle::SBPO_ControlStatements ||
spaceRequiredBeforeParens(Right);
- // space between ']' and '{'
- if (Left.is(tok::r_square) && Right.is(tok::l_brace))
- return true;
- // space before '{' in "new MyType {"
- if (Right.is(tok::l_brace) && Left.Previous &&
- Left.Previous->is(tok::kw_new))
- return true;
} else if (Style.Language == FormatStyle::LK_JavaScript) {
if (Left.is(TT_JsFatArrow))
return true;
diff --git a/clang/unittests/Format/FormatTestCSharp.cpp b/clang/unittests/Format/FormatTestCSharp.cpp
index 68a8e9fefe2d..3bdaf3d5a9f3 100644
--- a/clang/unittests/Format/FormatTestCSharp.cpp
+++ b/clang/unittests/Format/FormatTestCSharp.cpp
@@ -525,11 +525,11 @@ Shape[] shapes = new[] {
// Omitted final `,`s will change the formatting.
verifyFormat(R"(//
-Shape[] shapes = new[] {new Circle {Radius = 2.7281, Colour = Colours.Red},
- new Square {
- Side = 101.1,
- Colour = Colours.Yellow,
- }};)",
+Shape[] shapes = new[] { new Circle { Radius = 2.7281, Colour = Colours.Red },
+ new Square {
+ Side = 101.1,
+ Colour = Colours.Yellow,
+ } };)",
Style);
}
@@ -575,5 +575,27 @@ public string Name {
Style);
}
+TEST_F(FormatTestCSharp, CSharpSpaces) {
+ FormatStyle Style = getGoogleStyle(FormatStyle::LK_CSharp);
+ Style.SpaceBeforeSquareBrackets = false;
+ Style.SpacesInSquareBrackets = false;
+ Style.SpaceBeforeCpp11BracedList = true;
+ Style.Cpp11BracedListStyle = false;
+ Style.SpacesInContainerLiterals = false;
+
+ verifyFormat(R"(new Car { "Door", 0.1 })", Style);
+ verifyFormat(R"(new Car { 0.1, "Door" })", Style);
+ verifyFormat(R"(new string[] { "A" })", Style);
+ verifyFormat(R"(new string[] {})", Style);
+ verifyFormat(R"(new Car { someVariableName })", Style);
+ verifyFormat(R"(new Car { someVariableName })", Style);
+ verifyFormat(R"(new Dictionary<string, string> { ["Key"] = "Value" };)",
+ Style);
+ verifyFormat(R"(Apply(x => x.Name, x => () => x.ID);)", Style);
+ verifyFormat(R"(bool[] xs = { true, true };)", Style);
+ verifyFormat(R"(taskContext.Factory.Run(async () => doThing(args);)", Style);
+ verifyFormat(R"(catch (TestException) when (innerFinallyExecuted))", Style);
+}
+
} // namespace format
} // end namespace clang
More information about the cfe-commits
mailing list