[clang-format] Merge name and colon into a single token for C# named arguments

Summary:
Merge 'argumentName' and ':' into a single token in foo(argumentName: bar).

Add C# named argument as a token type.

Reviewers: krasimir, MyDeveloperDay

Reviewed By: krasimir

Tags: #clang-format

Differential Revision: https://reviews.llvm.org/D74894
This commit is contained in:
Jonathan Coe 2020-02-20 19:23:38 +00:00
parent e2c2eb0a55
commit a11ff39ba2
4 changed files with 53 additions and 1 deletions

View File

@ -103,6 +103,7 @@ namespace format {
TYPE(UnaryOperator) \
TYPE(CSharpStringLiteral) \
TYPE(CSharpNullCoalescing) \
TYPE(CSharpNamedArgument) \
TYPE(Unknown)
enum TokenType {

View File

@ -76,6 +76,8 @@ void FormatTokenLexer::tryMergePreviousTokens() {
return;
if (Style.isCSharp()) {
if (tryMergeCSharpNamedArgument())
return;
if (tryMergeCSharpAttributeAndTarget())
return;
if (tryMergeCSharpKeywordVariables())
@ -184,6 +186,39 @@ bool FormatTokenLexer::tryMergeJSPrivateIdentifier() {
return true;
}
// Merge 'argName' and ':' into a single token in `foo(argName: bar)`.
bool FormatTokenLexer::tryMergeCSharpNamedArgument() {
if (Tokens.size() < 2)
return false;
auto &Colon = *(Tokens.end() - 1);
if (!Colon->is(tok::colon))
return false;
auto &Name = *(Tokens.end() - 2);
if (!Name->is(tok::identifier))
return false;
const FormatToken *CommaOrLeftParen = nullptr;
for (auto I = Tokens.rbegin() + 2, E = Tokens.rend(); I != E; ++I) {
// NB: Because previous pointers are not initialized yet, this cannot use
// Token.getPreviousNonComment.
if ((*I)->isNot(tok::comment)) {
CommaOrLeftParen = *I;
break;
}
}
if (!CommaOrLeftParen || !CommaOrLeftParen->isOneOf(tok::l_paren, tok::comma))
return false;
Name->TokenText = StringRef(Name->TokenText.begin(),
Colon->TokenText.end() - Name->TokenText.begin());
Name->ColumnWidth += Colon->ColumnWidth;
Name->Type = TT_CSharpNamedArgument;
Tokens.erase(Tokens.end() - 1);
return true;
}
// Search for verbatim or interpolated string literals @"ABC" or
// $"aaaaa{abc}aaaaa" i and mark the token as TT_CSharpStringLiteral, and to
// prevent splitting of @, $ and ".

View File

@ -56,6 +56,7 @@ private:
bool tryMergeCSharpDoubleQuestion();
bool tryTransformCSharpForEach();
bool tryMergeCSharpAttributeAndTarget();
bool tryMergeCSharpNamedArgument();
bool tryMergeTokens(ArrayRef<tok::TokenKind> Kinds, TokenType NewType);

View File

@ -513,7 +513,7 @@ var x = foo(className, $@"some code:
TEST_F(FormatTestCSharp, CSharpObjectInitializers) {
FormatStyle Style = getGoogleStyle(FormatStyle::LK_CSharp);
// Start code fragemnts with a comment line so that C++ raw string literals
// Start code fragments with a comment line so that C++ raw string literals
// as seen are identical to expected formatted code.
verifyFormat(R"(//
@ -539,5 +539,20 @@ Shape[] shapes = new[] {new Circle {Radius = 2.7281, Colour = Colours.Red},
Style);
}
TEST_F(FormatTestCSharp, CSharpNamedArguments) {
FormatStyle Style = getGoogleStyle(FormatStyle::LK_CSharp);
verifyFormat(R"(//
PrintOrderDetails(orderNum: 31, productName: "Red Mug",
sellerName: "Gift Shop");)",
Style);
// Ensure that trailing comments do not cause problems.
verifyFormat(R"(//
PrintOrderDetails(orderNum: 31, productName: "Red Mug", // comment
sellerName: "Gift Shop");)",
Style);
}
} // namespace format
} // end namespace clang