mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
[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.
This commit is contained in:
@@ -266,6 +266,9 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
/// True if the token is an editor placeholder.
|
||||
bool isEditorPlaceholder() const;
|
||||
|
||||
/// True if the string literal token is multiline.
|
||||
bool isMultilineString() const {
|
||||
return MultilineString;
|
||||
|
||||
@@ -35,6 +35,10 @@
|
||||
|
||||
using namespace swift;
|
||||
|
||||
bool Token::isEditorPlaceholder() const {
|
||||
return is(tok::identifier) && Identifier::isEditorPlaceholder(getRawText());
|
||||
}
|
||||
|
||||
/// parseExpr
|
||||
///
|
||||
/// expr:
|
||||
@@ -2206,7 +2210,7 @@ static bool tryParseArgLabelList(Parser &P, Parser::DeclNameOptions flags,
|
||||
// An argument label.
|
||||
bool nextIsArgLabel = next.canBeArgumentLabel() || next.is(tok::colon);
|
||||
// An editor placeholder.
|
||||
bool nextIsPlaceholder = Identifier::isEditorPlaceholder(next.getText());
|
||||
bool nextIsPlaceholder = next.isEditorPlaceholder();
|
||||
|
||||
if (!(nextIsRParen || nextIsArgLabel || nextIsPlaceholder))
|
||||
return false;
|
||||
@@ -2402,7 +2406,7 @@ ParserResult<Expr> Parser::parseExprIdentifier(bool allowKeyword) {
|
||||
hasGenericArgumentList = true;
|
||||
}
|
||||
|
||||
if (name.getBaseName().isEditorPlaceholder()) {
|
||||
if (IdentTok.isEditorPlaceholder()) {
|
||||
return makeParserResult(
|
||||
status, parseExprEditorPlaceholder(IdentTok, name.getBaseIdentifier()));
|
||||
}
|
||||
@@ -3301,8 +3305,7 @@ static bool isStartOfLabelledTrailingClosure(Parser &P) {
|
||||
return true;
|
||||
// Parse editor placeholder as trailing closure so SourceKit can expand it to
|
||||
// closure literal.
|
||||
if (P.peekToken().is(tok::identifier) &&
|
||||
Identifier::isEditorPlaceholder(P.peekToken().getText()))
|
||||
if (P.peekToken().isEditorPlaceholder())
|
||||
return true;
|
||||
// Consider `label: <complete>` that the user is trying to write a closure.
|
||||
if (P.peekToken().is(tok::code_complete) && !P.peekToken().isAtStartOfLine())
|
||||
@@ -3360,8 +3363,8 @@ Parser::parseTrailingClosures(bool isExprBasic, SourceRange calleeRange,
|
||||
closure = parseExprClosure();
|
||||
} else if (Tok.is(tok::identifier)) {
|
||||
// Parse editor placeholder as a closure literal.
|
||||
assert(Identifier::isEditorPlaceholder(Tok.getText()));
|
||||
Identifier name = Context.getIdentifier(Tok.getText());
|
||||
assert(Tok.isEditorPlaceholder());
|
||||
Identifier name = Context.getIdentifier(Tok.getRawText());
|
||||
closure = makeParserResult(parseExprEditorPlaceholder(Tok, name));
|
||||
consumeToken(tok::identifier);
|
||||
} else if (Tok.is(tok::code_complete)) {
|
||||
|
||||
@@ -21,6 +21,10 @@ func testRegexLiteral() {
|
||||
func testEditorPlaceholder() -> Int {
|
||||
func foo(_ x: String) {}
|
||||
foo(<#T##x: String##String#>) // expected-error {{editor placeholder in source file}})
|
||||
|
||||
// Make sure we don't try to parse this as an editor placeholder.
|
||||
_ = `<#foo#>` // expected-error {{cannot find '<#foo#>' in scope}}
|
||||
|
||||
return <#T##Int#> // expected-error {{editor placeholder in source file}}
|
||||
}
|
||||
|
||||
@@ -79,4 +83,4 @@ using @Test
|
||||
// expected-error@-1 {{default isolation can only be set to '@MainActor' or 'nonisolated'}}
|
||||
|
||||
using test
|
||||
// expected-error@-1 {{default isolation can only be set to '@MainActor' or 'nonisolated'}}
|
||||
// expected-error@-1 {{default isolation can only be set to '@MainActor' or 'nonisolated'}}
|
||||
|
||||
@@ -27,6 +27,12 @@ f(<#T#> + 1) // expected-error{{editor placeholder in source file}}
|
||||
f(<#T##Int#>) // expected-error{{editor placeholder in source file}}
|
||||
f(<#T##String#>) // expected-error{{editor placeholder in source file}} expected-error{{cannot convert value of type 'String' to expected argument type 'Int'}}
|
||||
|
||||
<#foo#>(x:)<Int>; // expected-error {{editor placeholder in source file}}
|
||||
|
||||
// These are actually raw identifiers
|
||||
`<#foo#>` // expected-error {{cannot find '<#foo#>' in scope}}
|
||||
`<#foo#>`(x:)<Int>; // expected-error {{cannot find '<#foo#>(x:)' in scope}}
|
||||
|
||||
for x in <#T#> { // expected-error{{editor placeholder in source file}} expected-error{{for-in loop requires '()' to conform to 'Sequence'}}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user