|
@@ -25,6 +25,21 @@ namespace format {
|
|
|
|
|
|
namespace {
|
|
|
|
|
|
+/// \brief Returns \c true if the token can be used as an identifier in
|
|
|
+/// an Objective-C \c @selector, \c false otherwise.
|
|
|
+///
|
|
|
+/// Because getFormattingLangOpts() always lexes source code as
|
|
|
+/// Objective-C++, C++ keywords like \c new and \c delete are
|
|
|
+/// lexed as tok::kw_*, not tok::identifier, even for Objective-C.
|
|
|
+///
|
|
|
+/// For Objective-C and Objective-C++, both identifiers and keywords
|
|
|
+/// are valid inside @selector(...) (or a macro which
|
|
|
+/// invokes @selector(...)). So, we allow treat any identifier or
|
|
|
+/// keyword as a potential Objective-C selector component.
|
|
|
+static bool canBeObjCSelectorComponent(const FormatToken &Tok) {
|
|
|
+ return Tok.Tok.getIdentifierInfo() != nullptr;
|
|
|
+}
|
|
|
+
|
|
|
/// \brief A parser that gathers additional information about tokens.
|
|
|
///
|
|
|
/// The \c TokenAnnotator tries to match parenthesis and square brakets and
|
|
@@ -703,9 +718,10 @@ private:
|
|
|
Tok->Type = TT_CtorInitializerColon;
|
|
|
else
|
|
|
Tok->Type = TT_InheritanceColon;
|
|
|
- } else if (Tok->Previous->is(tok::identifier) && Tok->Next &&
|
|
|
+ } else if (canBeObjCSelectorComponent(*Tok->Previous) && Tok->Next &&
|
|
|
(Tok->Next->isOneOf(tok::r_paren, tok::comma) ||
|
|
|
- Tok->Next->startsSequence(tok::identifier, tok::colon))) {
|
|
|
+ (canBeObjCSelectorComponent(*Tok->Next) && Tok->Next->Next &&
|
|
|
+ Tok->Next->Next->is(tok::colon)))) {
|
|
|
// This handles a special macro in ObjC code where selectors including
|
|
|
// the colon are passed as macro arguments.
|
|
|
Tok->Type = TT_ObjCMethodExpr;
|
|
@@ -1346,7 +1362,7 @@ private:
|
|
|
TT_LeadingJavaAnnotation)) {
|
|
|
Current.Type = Current.Previous->Type;
|
|
|
}
|
|
|
- } else if (Current.isOneOf(tok::identifier, tok::kw_new) &&
|
|
|
+ } else if (canBeObjCSelectorComponent(Current) &&
|
|
|
// FIXME(bug 36976): ObjC return types shouldn't use TT_CastRParen.
|
|
|
Current.Previous && Current.Previous->is(TT_CastRParen) &&
|
|
|
Current.Previous->MatchingParen &&
|
|
@@ -2650,7 +2666,7 @@ bool TokenAnnotator::spaceRequiredBefore(const AnnotatedLine &Line,
|
|
|
if (Line.Type == LT_ObjCMethodDecl) {
|
|
|
if (Left.is(TT_ObjCMethodSpecifier))
|
|
|
return true;
|
|
|
- if (Left.is(tok::r_paren) && Right.isOneOf(tok::identifier, tok::kw_new))
|
|
|
+ if (Left.is(tok::r_paren) && canBeObjCSelectorComponent(Right))
|
|
|
// Don't space between ')' and <id> or ')' and 'new'. 'new' is not a
|
|
|
// keyword in Objective-C, and '+ (instancetype)new;' is a standard class
|
|
|
// method declaration.
|
|
@@ -3128,6 +3144,7 @@ void TokenAnnotator::printDebugInfo(const AnnotatedLine &Line) {
|
|
|
for (unsigned i = 0, e = Tok->FakeLParens.size(); i != e; ++i)
|
|
|
llvm::errs() << Tok->FakeLParens[i] << "/";
|
|
|
llvm::errs() << " FakeRParens=" << Tok->FakeRParens;
|
|
|
+ llvm::errs() << " II=" << Tok->Tok.getIdentifierInfo();
|
|
|
llvm::errs() << " Text='" << Tok->TokenText << "'\n";
|
|
|
if (!Tok->Next)
|
|
|
assert(Tok == Line.Last);
|