Skip to content

Commit a3eed77

Browse files
committed
[Parse] Fix isEditorPlaceholder checks in the parser
Factor out `Token::isEditorPlaceholder` and make sure we're checking the token's raw text, ensuring we don't ignore backticks.
1 parent 85a2686 commit a3eed77

File tree

4 files changed

+23
-7
lines changed

4 files changed

+23
-7
lines changed

include/swift/Parse/Token.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,9 @@ class Token {
266266
}
267267
}
268268

269+
/// True if the token is an editor placeholder.
270+
bool isEditorPlaceholder() const;
271+
269272
/// True if the string literal token is multiline.
270273
bool isMultilineString() const {
271274
return MultilineString;

lib/Parse/ParseExpr.cpp

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,10 @@
3535

3636
using namespace swift;
3737

38+
bool Token::isEditorPlaceholder() const {
39+
return is(tok::identifier) && Identifier::isEditorPlaceholder(getRawText());
40+
}
41+
3842
/// parseExpr
3943
///
4044
/// expr:
@@ -2206,7 +2210,7 @@ static bool tryParseArgLabelList(Parser &P, Parser::DeclNameOptions flags,
22062210
// An argument label.
22072211
bool nextIsArgLabel = next.canBeArgumentLabel() || next.is(tok::colon);
22082212
// An editor placeholder.
2209-
bool nextIsPlaceholder = Identifier::isEditorPlaceholder(next.getText());
2213+
bool nextIsPlaceholder = next.isEditorPlaceholder();
22102214

22112215
if (!(nextIsRParen || nextIsArgLabel || nextIsPlaceholder))
22122216
return false;
@@ -2402,7 +2406,7 @@ ParserResult<Expr> Parser::parseExprIdentifier(bool allowKeyword) {
24022406
hasGenericArgumentList = true;
24032407
}
24042408

2405-
if (name.getBaseName().isEditorPlaceholder()) {
2409+
if (IdentTok.isEditorPlaceholder()) {
24062410
return makeParserResult(
24072411
status, parseExprEditorPlaceholder(IdentTok, name.getBaseIdentifier()));
24082412
}
@@ -3301,8 +3305,7 @@ static bool isStartOfLabelledTrailingClosure(Parser &P) {
33013305
return true;
33023306
// Parse editor placeholder as trailing closure so SourceKit can expand it to
33033307
// closure literal.
3304-
if (P.peekToken().is(tok::identifier) &&
3305-
Identifier::isEditorPlaceholder(P.peekToken().getText()))
3308+
if (P.peekToken().isEditorPlaceholder())
33063309
return true;
33073310
// Consider `label: <complete>` that the user is trying to write a closure.
33083311
if (P.peekToken().is(tok::code_complete) && !P.peekToken().isAtStartOfLine())
@@ -3360,8 +3363,8 @@ Parser::parseTrailingClosures(bool isExprBasic, SourceRange calleeRange,
33603363
closure = parseExprClosure();
33613364
} else if (Tok.is(tok::identifier)) {
33623365
// Parse editor placeholder as a closure literal.
3363-
assert(Identifier::isEditorPlaceholder(Tok.getText()));
3364-
Identifier name = Context.getIdentifier(Tok.getText());
3366+
assert(Tok.isEditorPlaceholder());
3367+
Identifier name = Context.getIdentifier(Tok.getRawText());
33653368
closure = makeParserResult(parseExprEditorPlaceholder(Tok, name));
33663369
consumeToken(tok::identifier);
33673370
} else if (Tok.is(tok::code_complete)) {

test/ASTGen/diagnostics.swift

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,10 @@ func testRegexLiteral() {
2121
func testEditorPlaceholder() -> Int {
2222
func foo(_ x: String) {}
2323
foo(<#T##x: String##String#>) // expected-error {{editor placeholder in source file}})
24+
25+
// Make sure we don't try to parse this as an editor placeholder.
26+
_ = `<#foo#>` // expected-error {{cannot find '<#foo#>' in scope}}
27+
2428
return <#T##Int#> // expected-error {{editor placeholder in source file}}
2529
}
2630

@@ -79,4 +83,4 @@ using @Test
7983
// expected-error@-1 {{default isolation can only be set to '@MainActor' or 'nonisolated'}}
8084

8185
using test
82-
// expected-error@-1 {{default isolation can only be set to '@MainActor' or 'nonisolated'}}
86+
// expected-error@-1 {{default isolation can only be set to '@MainActor' or 'nonisolated'}}

test/Sema/editor_placeholders.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,12 @@ f(<#T#> + 1) // expected-error{{editor placeholder in source file}}
2727
f(<#T##Int#>) // expected-error{{editor placeholder in source file}}
2828
f(<#T##String#>) // expected-error{{editor placeholder in source file}} expected-error{{cannot convert value of type 'String' to expected argument type 'Int'}}
2929

30+
<#foo#>(x:)<Int>; // expected-error {{editor placeholder in source file}}
31+
32+
// These are actually raw identifiers
33+
`<#foo#>` // expected-error {{cannot find '<#foo#>' in scope}}
34+
`<#foo#>`(x:)<Int>; // expected-error {{cannot find '<#foo#>(x:)' in scope}}
35+
3036
for x in <#T#> { // expected-error{{editor placeholder in source file}} expected-error{{for-in loop requires '()' to conform to 'Sequence'}}
3137

3238
}

0 commit comments

Comments
 (0)