@@ -410,30 +410,20 @@ ParserResult<TypeRepr> Parser::parseTypeIdentifierOrTypeComposition() {
410410 SourceLoc ProtocolLoc = consumeToken (tok::kw_protocol);
411411 SourceLoc LAngleLoc = consumeStartingLess ();
412412
413- // Check for empty protocol composition.
414- if (startsWithGreater (Tok)) {
415- SourceLoc RAngleLoc = consumeStartingGreater ();
416- auto AnyRange = SourceRange (ProtocolLoc, RAngleLoc);
417-
418- // Warn that 'protocol<>' is deprecated and offer to
419- // replace with the 'Any' keyword
420- diagnose (LAngleLoc, diag::deprecated_any_composition)
421- .fixItReplace (AnyRange, " Any" );
422-
423- return makeParserResult (
424- ProtocolCompositionTypeRepr::createEmptyComposition (Context, ProtocolLoc));
425- }
426-
427413 // Parse the type-composition-list.
428414 ParserStatus Status;
429415 SmallVector<IdentTypeRepr *, 4 > Protocols;
430- do {
431- // Parse the type-identifier.
432- ParserResult<TypeRepr> Protocol = parseTypeIdentifier ();
433- Status |= Protocol;
434- if (auto *ident = dyn_cast_or_null<IdentTypeRepr>(Protocol.getPtrOrNull ()))
435- Protocols.push_back (ident);
436- } while (consumeIf (tok::comma));
416+ bool IsEmpty = startsWithGreater (Tok);
417+ if (!IsEmpty) {
418+ do {
419+ // Parse the type-identifier.
420+ ParserResult<TypeRepr> Protocol = parseTypeIdentifier ();
421+ Status |= Protocol;
422+ if (auto *ident = dyn_cast_or_null<IdentTypeRepr>(
423+ Protocol.getPtrOrNull ()))
424+ Protocols.push_back (ident);
425+ } while (consumeIf (tok::comma));
426+ }
437427
438428 // Check for the terminating '>'.
439429 SourceLoc RAngleLoc = PreviousLoc;
@@ -456,33 +446,40 @@ ParserResult<TypeRepr> Parser::parseTypeIdentifierOrTypeComposition() {
456446 if (Status.isSuccess ()) {
457447 // Only if we have complete protocol<...> construct, diagnose deprecated.
458448
459- auto extractText = [&](IdentTypeRepr *Ty) -> StringRef {
460- auto SourceRange = Ty->getSourceRange ();
461- return SourceMgr.extractText (
462- Lexer::getCharSourceRangeFromSourceRange (SourceMgr, SourceRange));
463- };
464449 SmallString<32 > replacement;
465- auto Begin = Protocols.begin ();
466- replacement += extractText (*Begin);
467- while (++Begin != Protocols.end ()) {
468- replacement += " & " ;
450+ if (Protocols.empty ()) {
451+ replacement = " Any" ;
452+ } else {
453+ auto extractText = [&](IdentTypeRepr *Ty) -> StringRef {
454+ auto SourceRange = Ty->getSourceRange ();
455+ return SourceMgr.extractText (
456+ Lexer::getCharSourceRangeFromSourceRange (SourceMgr, SourceRange));
457+ };
458+ auto Begin = Protocols.begin ();
469459 replacement += extractText (*Begin);
460+ while (++Begin != Protocols.end ()) {
461+ replacement += " & " ;
462+ replacement += extractText (*Begin);
463+ }
470464 }
471465
472466 // Copy trailing content after '>' to the replacement string.
473467 // FIXME: lexer should smartly separate '>' and trailing contents like '?'.
474468 StringRef TrailingContent = L->getTokenAt (RAngleLoc).getRange ().str ().
475469 substr (1 );
476470 if (!TrailingContent.empty ()) {
477- replacement.insert (replacement.begin (), ' (' );
478- replacement += " )" ;
471+ if (Protocols.size () > 1 ) {
472+ replacement.insert (replacement.begin (), ' (' );
473+ replacement += " )" ;
474+ }
479475 replacement += TrailingContent;
480476 }
481477
482478 // Replace 'protocol<T1, T2>' with 'T1 & T2'
483479 diagnose (ProtocolLoc,
484- Protocols.size () > 1 ? diag::deprecated_protocol_composition
485- : diag::deprecated_protocol_composition_single)
480+ IsEmpty ? diag::deprecated_any_composition :
481+ Protocols.size () > 1 ? diag::deprecated_protocol_composition :
482+ diag::deprecated_protocol_composition_single)
486483 .highlight (composition->getSourceRange ())
487484 .fixItReplace (composition->getSourceRange (), replacement);
488485 }
0 commit comments