forked from OSchip/llvm-project
[clang-format] Recognize C# named argument colons as a token type
Summary: No longer merge 'name' and ':' into a single token. Ensure that line breaks cannot be placed before or after a named-argument colon. Ensure that no space is inserted before a named-argument colon. Reviewers: krasimir Reviewed By: krasimir Subscribers: cfe-commits, MyDeveloperDay Tags: #clang-format, #clang Differential Revision: https://reviews.llvm.org/D75244
This commit is contained in:
parent
7ea9a6e022
commit
7dfe0cc7f5
|
@ -103,7 +103,7 @@ namespace format {
|
|||
TYPE(UnaryOperator) \
|
||||
TYPE(CSharpStringLiteral) \
|
||||
TYPE(CSharpNullCoalescing) \
|
||||
TYPE(CSharpNamedArgument) \
|
||||
TYPE(CSharpNamedArgumentColon) \
|
||||
TYPE(Unknown)
|
||||
|
||||
enum TokenType {
|
||||
|
|
|
@ -76,8 +76,6 @@ void FormatTokenLexer::tryMergePreviousTokens() {
|
|||
return;
|
||||
|
||||
if (Style.isCSharp()) {
|
||||
if (tryMergeCSharpNamedArgument())
|
||||
return;
|
||||
if (tryMergeCSharpAttributeAndTarget())
|
||||
return;
|
||||
if (tryMergeCSharpKeywordVariables())
|
||||
|
@ -186,39 +184,6 @@ 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 ".
|
||||
|
@ -609,7 +574,7 @@ void FormatTokenLexer::handleCSharpVerbatimAndInterpolatedStrings() {
|
|||
size_t LastBreak = LiteralText.rfind('\n');
|
||||
if (LastBreak != StringRef::npos) {
|
||||
CSharpStringLiteral->IsMultiline = true;
|
||||
unsigned StartColumn = 0; // The template tail spans the entire line.
|
||||
unsigned StartColumn = 0;
|
||||
CSharpStringLiteral->LastLineColumnWidth = encoding::columnWidthWithTabs(
|
||||
LiteralText.substr(LastBreak + 1, LiteralText.size()), StartColumn,
|
||||
Style.TabWidth, Encoding);
|
||||
|
|
|
@ -56,7 +56,6 @@ private:
|
|||
bool tryMergeCSharpDoubleQuestion();
|
||||
bool tryTransformCSharpForEach();
|
||||
bool tryMergeCSharpAttributeAndTarget();
|
||||
bool tryMergeCSharpNamedArgument();
|
||||
|
||||
bool tryMergeTokens(ArrayRef<tok::TokenKind> Kinds, TokenType NewType);
|
||||
|
||||
|
|
|
@ -776,6 +776,11 @@ private:
|
|||
Tok->Type = TT_JsTypeColon;
|
||||
break;
|
||||
}
|
||||
} else if (Style.isCSharp()) {
|
||||
if (Contexts.back().ContextKind == tok::l_paren) {
|
||||
Tok->Type = TT_CSharpNamedArgumentColon;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (Contexts.back().ColonIsDictLiteral ||
|
||||
Style.Language == FormatStyle::LK_Proto ||
|
||||
|
@ -3052,6 +3057,8 @@ bool TokenAnnotator::spaceRequiredBefore(const AnnotatedLine &Line,
|
|||
return Style.SpacesInContainerLiterals;
|
||||
if (Right.is(TT_AttributeColon))
|
||||
return false;
|
||||
if (Right.is(TT_CSharpNamedArgumentColon))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
if (Left.is(TT_UnaryOperator)) {
|
||||
|
@ -3200,7 +3207,11 @@ bool TokenAnnotator::mustBreakBefore(const AnnotatedLine &Line,
|
|||
if (Right.NewlinesBefore > 1 && Style.MaxEmptyLinesToKeep > 0)
|
||||
return true;
|
||||
|
||||
if (Style.Language == FormatStyle::LK_JavaScript) {
|
||||
if (Style.isCSharp()) {
|
||||
if (Right.is(TT_CSharpNamedArgumentColon) ||
|
||||
Left.is(TT_CSharpNamedArgumentColon))
|
||||
return false;
|
||||
} else if (Style.Language == FormatStyle::LK_JavaScript) {
|
||||
// FIXME: This might apply to other languages and token kinds.
|
||||
if (Right.is(tok::string_literal) && Left.is(tok::plus) && Left.Previous &&
|
||||
Left.Previous->is(tok::string_literal))
|
||||
|
@ -3485,9 +3496,12 @@ bool TokenAnnotator::mustBreakBefore(const AnnotatedLine &Line,
|
|||
bool TokenAnnotator::canBreakBefore(const AnnotatedLine &Line,
|
||||
const FormatToken &Right) {
|
||||
const FormatToken &Left = *Right.Previous;
|
||||
|
||||
// Language-specific stuff.
|
||||
if (Style.Language == FormatStyle::LK_Java) {
|
||||
if (Style.isCSharp()) {
|
||||
if (Left.is(TT_CSharpNamedArgumentColon) ||
|
||||
Right.is(TT_CSharpNamedArgumentColon))
|
||||
return false;
|
||||
} else if (Style.Language == FormatStyle::LK_Java) {
|
||||
if (Left.isOneOf(Keywords.kw_throws, Keywords.kw_extends,
|
||||
Keywords.kw_implements))
|
||||
return false;
|
||||
|
|
|
@ -546,6 +546,8 @@ PrintOrderDetails(orderNum: 31, productName: "Red Mug",
|
|||
PrintOrderDetails(orderNum: 31, productName: "Red Mug", // comment
|
||||
sellerName: "Gift Shop");)",
|
||||
Style);
|
||||
|
||||
verifyFormat(R"(foreach (var tickCount in task.Begin(seed: 0)) {)", Style);
|
||||
}
|
||||
|
||||
TEST_F(FormatTestCSharp, CSharpPropertyAccessors) {
|
||||
|
|
Loading…
Reference in New Issue