@@ -410,30 +410,20 @@ ParserResult<TypeRepr> Parser::parseTypeIdentifierOrTypeComposition() {
410
410
SourceLoc ProtocolLoc = consumeToken (tok::kw_protocol);
411
411
SourceLoc LAngleLoc = consumeStartingLess ();
412
412
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
-
427
413
// Parse the type-composition-list.
428
414
ParserStatus Status;
429
415
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
+ }
437
427
438
428
// Check for the terminating '>'.
439
429
SourceLoc RAngleLoc = PreviousLoc;
@@ -456,33 +446,40 @@ ParserResult<TypeRepr> Parser::parseTypeIdentifierOrTypeComposition() {
456
446
if (Status.isSuccess ()) {
457
447
// Only if we have complete protocol<...> construct, diagnose deprecated.
458
448
459
- auto extractText = [&](IdentTypeRepr *Ty) -> StringRef {
460
- auto SourceRange = Ty->getSourceRange ();
461
- return SourceMgr.extractText (
462
- Lexer::getCharSourceRangeFromSourceRange (SourceMgr, SourceRange));
463
- };
464
449
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 ();
469
459
replacement += extractText (*Begin);
460
+ while (++Begin != Protocols.end ()) {
461
+ replacement += " & " ;
462
+ replacement += extractText (*Begin);
463
+ }
470
464
}
471
465
472
466
// Copy trailing content after '>' to the replacement string.
473
467
// FIXME: lexer should smartly separate '>' and trailing contents like '?'.
474
468
StringRef TrailingContent = L->getTokenAt (RAngleLoc).getRange ().str ().
475
469
substr (1 );
476
470
if (!TrailingContent.empty ()) {
477
- replacement.insert (replacement.begin (), ' (' );
478
- replacement += " )" ;
471
+ if (Protocols.size () > 1 ) {
472
+ replacement.insert (replacement.begin (), ' (' );
473
+ replacement += " )" ;
474
+ }
479
475
replacement += TrailingContent;
480
476
}
481
477
482
478
// Replace 'protocol<T1, T2>' with 'T1 & T2'
483
479
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)
486
483
.highlight (composition->getSourceRange ())
487
484
.fixItReplace (composition->getSourceRange (), replacement);
488
485
}
0 commit comments