forked from OSchip/llvm-project
[clang-format] Handle C variables with name that matches c++ access specifier
Reviewed By: MyDeveloperDay, curdeius, HazardyKnusperkeks Differential Revision: https://reviews.llvm.org/D117416
This commit is contained in:
parent
446425f898
commit
d1aed486ef
|
@ -123,6 +123,34 @@ namespace format {
|
|||
TYPE(CSharpGenericTypeConstraintComma) \
|
||||
TYPE(Unknown)
|
||||
|
||||
/// Sorted operators that can follow a C variable.
|
||||
static const std::vector<clang::tok::TokenKind> COperatorsFollowingVar = [] {
|
||||
std::vector<clang::tok::TokenKind> ReturnVal = {
|
||||
tok::l_square, tok::r_square,
|
||||
tok::l_paren, tok::r_paren,
|
||||
tok::r_brace, tok::period,
|
||||
tok::ellipsis, tok::ampamp,
|
||||
tok::ampequal, tok::star,
|
||||
tok::starequal, tok::plus,
|
||||
tok::plusplus, tok::plusequal,
|
||||
tok::minus, tok::arrow,
|
||||
tok::minusminus, tok::minusequal,
|
||||
tok::exclaim, tok::exclaimequal,
|
||||
tok::slash, tok::slashequal,
|
||||
tok::percent, tok::percentequal,
|
||||
tok::less, tok::lessless,
|
||||
tok::lessequal, tok::lesslessequal,
|
||||
tok::greater, tok::greatergreater,
|
||||
tok::greaterequal, tok::greatergreaterequal,
|
||||
tok::caret, tok::caretequal,
|
||||
tok::pipe, tok::pipepipe,
|
||||
tok::pipeequal, tok::question,
|
||||
tok::semi, tok::equal,
|
||||
tok::equalequal, tok::comma};
|
||||
assert(std::is_sorted(ReturnVal.begin(), ReturnVal.end()));
|
||||
return ReturnVal;
|
||||
}();
|
||||
|
||||
/// Determines the semantic type of a syntactic token, e.g. whether "<" is a
|
||||
/// template opener or binary operator.
|
||||
enum TokenType : uint8_t {
|
||||
|
|
|
@ -100,10 +100,27 @@ private:
|
|||
if (Style.Language == FormatStyle::LK_Java || Style.isJavaScript() ||
|
||||
Style.isCSharp())
|
||||
return 0;
|
||||
if (RootToken.isAccessSpecifier(false) ||
|
||||
RootToken.isObjCAccessSpecifier() ||
|
||||
(RootToken.isOneOf(Keywords.kw_signals, Keywords.kw_qsignals) &&
|
||||
RootToken.Next && RootToken.Next->is(tok::colon))) {
|
||||
|
||||
auto IsAccessModifier = [this, &RootToken]() {
|
||||
if (RootToken.isAccessSpecifier(Style.isCpp()))
|
||||
return true;
|
||||
else if (RootToken.isObjCAccessSpecifier())
|
||||
return true;
|
||||
// Handle Qt signals.
|
||||
else if ((RootToken.isOneOf(Keywords.kw_signals, Keywords.kw_qsignals) &&
|
||||
RootToken.Next && RootToken.Next->is(tok::colon)))
|
||||
return true;
|
||||
else if (RootToken.Next &&
|
||||
RootToken.Next->isOneOf(Keywords.kw_slots, Keywords.kw_qslots) &&
|
||||
RootToken.Next->Next && RootToken.Next->Next->is(tok::colon))
|
||||
return true;
|
||||
// Handle malformed access specifier e.g. 'private' without trailing ':'.
|
||||
else if (!RootToken.Next && RootToken.isAccessSpecifier(false))
|
||||
return true;
|
||||
return false;
|
||||
};
|
||||
|
||||
if (IsAccessModifier()) {
|
||||
// The AccessModifierOffset may be overridden by IndentAccessModifiers,
|
||||
// in which case we take a negative value of the IndentWidth to simulate
|
||||
// the upper indent level.
|
||||
|
|
|
@ -2708,14 +2708,25 @@ void UnwrappedLineParser::parseSwitch() {
|
|||
}
|
||||
|
||||
void UnwrappedLineParser::parseAccessSpecifier() {
|
||||
FormatToken *AccessSpecifierCandidate = FormatTok;
|
||||
nextToken();
|
||||
// Understand Qt's slots.
|
||||
if (FormatTok->isOneOf(Keywords.kw_slots, Keywords.kw_qslots))
|
||||
nextToken();
|
||||
// Otherwise, we don't know what it is, and we'd better keep the next token.
|
||||
if (FormatTok->Tok.is(tok::colon))
|
||||
if (FormatTok->Tok.is(tok::colon)) {
|
||||
nextToken();
|
||||
addUnwrappedLine();
|
||||
addUnwrappedLine();
|
||||
} else if (!FormatTok->Tok.is(tok::coloncolon) &&
|
||||
!std::binary_search(COperatorsFollowingVar.begin(),
|
||||
COperatorsFollowingVar.end(),
|
||||
FormatTok->Tok.getKind())) {
|
||||
// Not a variable name nor namespace name.
|
||||
addUnwrappedLine();
|
||||
} else if (AccessSpecifierCandidate) {
|
||||
// Consider the access specifier to be a C identifier.
|
||||
AccessSpecifierCandidate->Tok.setKind(tok::identifier);
|
||||
}
|
||||
}
|
||||
|
||||
void UnwrappedLineParser::parseConcept() {
|
||||
|
|
|
@ -3123,6 +3123,46 @@ TEST_F(FormatTest, UnderstandsAccessSpecifiers) {
|
|||
"label:\n"
|
||||
" signals.baz();\n"
|
||||
"}");
|
||||
verifyFormat("private[1];");
|
||||
verifyFormat("testArray[public] = 1;");
|
||||
verifyFormat("public();");
|
||||
verifyFormat("myFunc(public);");
|
||||
verifyFormat("std::vector<int> testVec = {private};");
|
||||
verifyFormat("private.p = 1;");
|
||||
verifyFormat("void function(private...){};");
|
||||
verifyFormat("if (private && public)\n");
|
||||
verifyFormat("private &= true;");
|
||||
verifyFormat("int x = private * public;");
|
||||
verifyFormat("public *= private;");
|
||||
verifyFormat("int x = public + private;");
|
||||
verifyFormat("private++;");
|
||||
verifyFormat("++private;");
|
||||
verifyFormat("public += private;");
|
||||
verifyFormat("public = public - private;");
|
||||
verifyFormat("public->foo();");
|
||||
verifyFormat("private--;");
|
||||
verifyFormat("--private;");
|
||||
verifyFormat("public -= 1;");
|
||||
verifyFormat("if (!private && !public)\n");
|
||||
verifyFormat("public != private;");
|
||||
verifyFormat("int x = public / private;");
|
||||
verifyFormat("public /= 2;");
|
||||
verifyFormat("public = public % 2;");
|
||||
verifyFormat("public %= 2;");
|
||||
verifyFormat("if (public < private)\n");
|
||||
verifyFormat("public << private;");
|
||||
verifyFormat("public <<= private;");
|
||||
verifyFormat("if (public > private)\n");
|
||||
verifyFormat("public >> private;");
|
||||
verifyFormat("public >>= private;");
|
||||
verifyFormat("public ^ private;");
|
||||
verifyFormat("public ^= private;");
|
||||
verifyFormat("public | private;");
|
||||
verifyFormat("public |= private;");
|
||||
verifyFormat("auto x = private ? 1 : 2;");
|
||||
verifyFormat("if (public == private)\n");
|
||||
verifyFormat("void foo(public, private)");
|
||||
verifyFormat("public::foo();");
|
||||
}
|
||||
|
||||
TEST_F(FormatTest, SeparatesLogicalBlocks) {
|
||||
|
|
Loading…
Reference in New Issue