Skip to content

Commit c078899

Browse files
committed
[Parser] Correct a fixit to preserve the trailing content after replacing Protocol<A, B>. rdar://27992964
When migrating, we found our fixit to replace the old protocol composition syntax, namely "Protocol<A, B>", to the new syntax, "A & B", does not preserve the trailing content after '>'. For instance, we replace "Protocol<A, B>?" with "A & B". This patch fixes the issue by inserting whatever after '>' in the old syntax to the new replacement string. I consider this as a hack; the root-cause fix should be in the lexer to smartly separate '>' and '?' as two tokens instead of one.
1 parent d5d9d82 commit c078899

File tree

4 files changed

+23
-3
lines changed

4 files changed

+23
-3
lines changed

lib/Parse/ParseType.cpp

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -450,7 +450,7 @@ ParserResult<TypeRepr> Parser::parseTypeIdentifierOrTypeComposition() {
450450
// Skip until we hit the '>'.
451451
RAngleLoc = skipUntilGreaterInTypeList(/*protocolComposition=*/true);
452452
}
453-
453+
454454
auto composition = ProtocolCompositionTypeRepr::create(
455455
Context, Protocols, ProtocolLoc, {LAngleLoc, RAngleLoc});
456456

@@ -470,6 +470,16 @@ ParserResult<TypeRepr> Parser::parseTypeIdentifierOrTypeComposition() {
470470
replacement += extractText(*Begin);
471471
}
472472

473+
// Copy trailing content after '>' to the replacement string.
474+
// FIXME: lexer should smartly separate '>' and trailing contents like '?'.
475+
StringRef TrailingContent = L->getTokenAt(RAngleLoc).getRange().str().
476+
substr(1);
477+
if (!TrailingContent.empty()) {
478+
replacement.insert(replacement.begin(), '(');
479+
replacement += ")";
480+
replacement += TrailingContent;
481+
}
482+
473483
// Replace 'protocol<T1, T2>' with 'T1 & T2'
474484
diagnose(ProtocolLoc,
475485
Protocols.size() > 1 ? diag::deprecated_protocol_composition

test/FixCode/fixits-apply.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -270,3 +270,8 @@ func testBoolValue(a : BoolFoo) {
270270
guard a {}
271271
if a as BoolFoo {}
272272
}
273+
274+
protocol P1 {}
275+
protocol P2 {}
276+
var a : protocol<P1, P2>?
277+
var a2 : protocol<P1>= 17

test/FixCode/fixits-apply.swift.result

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -273,3 +273,8 @@ func testBoolValue(a : BoolFoo) {
273273
guard a.boolValue {}
274274
if (a as BoolFoo).boolValue {}
275275
}
276+
277+
protocol P1 {}
278+
protocol P2 {}
279+
var a : (P1 & P2)?
280+
var a2 : (P1)= 17 as! P1

test/type/protocol_composition.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ func testEquality() {
4848
let x4 : (_ : P2) -> ()
4949
x3 = x4
5050
_ = x3
51-
51+
5252
// Empty protocol-conformance types are empty.
5353
let x5 : (_ : Any) -> ()
5454
let x6 : (_ : Any2) -> ()
@@ -123,7 +123,7 @@ func testConversion() {
123123
}
124124

125125
// Test the parser's splitting of >= into > and =.
126-
var x : protocol<P5>= 17 // expected-warning {{'protocol<...>' composition syntax is deprecated and not needed here}} {{9-22=P5}}
126+
var x : protocol<P5>= 17 // expected-warning {{'protocol<...>' composition syntax is deprecated and not needed here}} {{9-22=(P5)=}}
127127

128128
typealias A = protocol<> // expected-warning {{'protocol<>' syntax is deprecated; use 'Any' instead}} {{15-25=Any}}
129129
typealias B1 = protocol<P1,P2> // expected-warning {{'protocol<...>' composition syntax is deprecated; join the protocols using '&'}} {{16-31=P1 & P2}}

0 commit comments

Comments
 (0)