mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
[Parse] Ignore '(' on newline after attribute names
Also '#error', '#warning', and '#sourceLocation'.
Other call-like syntax (call expression, macro expansion, and custom
attribtues) requires '(' on the same line as the callee. For consistency,
built-in attributes and built-in directives should also ignore '(' on
next line.
This commit is contained in:
@@ -62,7 +62,7 @@ ERROR(pound_diagnostic_expected_string,none,
|
||||
"expected string literal in %select{#warning|#error}0 directive",(bool))
|
||||
ERROR(pound_diagnostic_expected,none,
|
||||
"expected '%0' in %select{#warning|#error}1 directive",(StringRef,bool))
|
||||
ERROR(pound_diagnostic_expected_parens,none,
|
||||
ERROR(pound_diagnostic_expected_parens,PointsToFirstBadToken,
|
||||
"%select{#warning|#error}0 directive requires parentheses",(bool))
|
||||
ERROR(pound_diagnostic_interpolation,none,
|
||||
"string interpolation is not allowed in %select{#warning|#error}0 directives",(bool))
|
||||
|
||||
@@ -2503,7 +2503,7 @@ static std::optional<Identifier> parseSingleAttrOptionImpl(
|
||||
};
|
||||
bool isDeclModifier = DeclAttribute::isDeclModifier(DK);
|
||||
|
||||
if (!P.Tok.is(tok::l_paren)) {
|
||||
if (!P.Tok.isFollowingLParen()) {
|
||||
if (allowOmitted)
|
||||
return Identifier();
|
||||
|
||||
@@ -2883,7 +2883,7 @@ ParserStatus Parser::parseNewDeclAttribute(DeclAttributes &Attributes,
|
||||
.Case("public", AccessLevel::Public)
|
||||
.Case("open", AccessLevel::Open);
|
||||
|
||||
if (!Tok.is(tok::l_paren)) {
|
||||
if (!Tok.isFollowingLParen()) {
|
||||
// Normal access control attribute.
|
||||
AttrRange = Loc;
|
||||
|
||||
@@ -3458,7 +3458,7 @@ ParserStatus Parser::parseNewDeclAttribute(DeclAttributes &Attributes,
|
||||
}
|
||||
case DeclAttrKind::PrivateImport: {
|
||||
// Parse the leading '('.
|
||||
if (Tok.isNot(tok::l_paren)) {
|
||||
if (!Tok.isFollowingLParen()) {
|
||||
diagnose(Loc, diag::attr_expected_lparen, AttrName,
|
||||
DeclAttribute::isDeclModifier(DK));
|
||||
return makeParserSuccess();
|
||||
@@ -3507,7 +3507,7 @@ ParserStatus Parser::parseNewDeclAttribute(DeclAttributes &Attributes,
|
||||
}
|
||||
case DeclAttrKind::ObjC: {
|
||||
// Unnamed @objc attribute.
|
||||
if (Tok.isNot(tok::l_paren)) {
|
||||
if (!Tok.isFollowingLParen()) {
|
||||
auto attr = ObjCAttr::createUnnamed(Context, AtLoc, Loc);
|
||||
Attributes.add(attr);
|
||||
break;
|
||||
@@ -3575,7 +3575,7 @@ ParserStatus Parser::parseNewDeclAttribute(DeclAttributes &Attributes,
|
||||
|
||||
case DeclAttrKind::DynamicReplacement: {
|
||||
// Parse the leading '('.
|
||||
if (Tok.isNot(tok::l_paren)) {
|
||||
if (!Tok.isFollowingLParen()) {
|
||||
diagnose(Loc, diag::attr_expected_lparen, AttrName,
|
||||
DeclAttribute::isDeclModifier(DK));
|
||||
return makeParserSuccess();
|
||||
@@ -3626,7 +3626,7 @@ ParserStatus Parser::parseNewDeclAttribute(DeclAttributes &Attributes,
|
||||
|
||||
case DeclAttrKind::TypeEraser: {
|
||||
// Parse leading '('
|
||||
if (Tok.isNot(tok::l_paren)) {
|
||||
if (!Tok.isFollowingLParen()) {
|
||||
diagnose(Loc, diag::attr_expected_lparen, AttrName,
|
||||
DeclAttribute::isDeclModifier(DK));
|
||||
return makeParserSuccess();
|
||||
@@ -3656,7 +3656,7 @@ ParserStatus Parser::parseNewDeclAttribute(DeclAttributes &Attributes,
|
||||
|
||||
case DeclAttrKind::Specialize:
|
||||
case DeclAttrKind::Specialized: {
|
||||
if (Tok.isNot(tok::l_paren)) {
|
||||
if (!Tok.isFollowingLParen()) {
|
||||
diagnose(Loc, diag::attr_expected_lparen, AttrName,
|
||||
DeclAttribute::isDeclModifier(DK));
|
||||
return makeParserSuccess();
|
||||
@@ -3885,7 +3885,7 @@ ParserStatus Parser::parseNewDeclAttribute(DeclAttributes &Attributes,
|
||||
break;
|
||||
}
|
||||
case DeclAttrKind::RawLayout: {
|
||||
if (Tok.isNot(tok::l_paren)) {
|
||||
if (!Tok.isFollowingLParen()) {
|
||||
diagnose(Loc, diag::attr_expected_lparen, AttrName,
|
||||
DeclAttribute::isDeclModifier(DK));
|
||||
return makeParserSuccess();
|
||||
@@ -4187,7 +4187,7 @@ ParserResult<CustomAttr> Parser::parseCustomAttribute(SourceLoc atLoc) {
|
||||
// Parse a custom attribute.
|
||||
auto type = parseType(diag::expected_type, ParseTypeReason::CustomAttribute);
|
||||
if (type.hasCodeCompletion() || type.isNull()) {
|
||||
if (Tok.is(tok::l_paren) && isCustomAttributeArgument())
|
||||
if (Tok.isFollowingLParen() && isCustomAttributeArgument())
|
||||
skipSingle();
|
||||
|
||||
return ParserResult<CustomAttr>(ParserStatus(type));
|
||||
@@ -4369,7 +4369,7 @@ ParserStatus Parser::parseDeclAttribute(DeclAttributes &Attributes,
|
||||
SourceLoc attrLoc = consumeToken();
|
||||
|
||||
// @warn_unused_result with no arguments.
|
||||
if (Tok.isNot(tok::l_paren)) {
|
||||
if (!Tok.isFollowingLParen()) {
|
||||
diagnose(AtLoc, diag::attr_warn_unused_result_removed)
|
||||
.fixItRemove(SourceRange(AtLoc, attrLoc));
|
||||
|
||||
@@ -4453,7 +4453,7 @@ ParserStatus Parser::parseDeclAttribute(DeclAttributes &Attributes,
|
||||
|
||||
// Recover by eating @foo(...) when foo is not known.
|
||||
consumeToken();
|
||||
if (Tok.is(tok::l_paren))
|
||||
if (Tok.isFollowingLParen())
|
||||
skipSingle();
|
||||
|
||||
return makeParserError();
|
||||
@@ -5925,7 +5925,7 @@ bool Parser::isStartOfSwiftDecl(bool allowPoundIfAttributes,
|
||||
// If it might be, we do some more digging.
|
||||
|
||||
// If this is 'unowned', check to see if it is valid.
|
||||
if (Tok.getText() == "unowned" && Tok2.is(tok::l_paren)) {
|
||||
if (Tok.getText() == "unowned" && Tok2.isFollowingLParen()) {
|
||||
Parser::BacktrackingScope Backtrack(*this);
|
||||
if (consumeIfParenthesizedUnowned(*this)) {
|
||||
return isStartOfSwiftDecl(/*allowPoundIfAttributes=*/false,
|
||||
@@ -5934,7 +5934,7 @@ bool Parser::isStartOfSwiftDecl(bool allowPoundIfAttributes,
|
||||
}
|
||||
|
||||
// If this is 'nonisolated', check to see if it is valid.
|
||||
if (Tok.isContextualKeyword("nonisolated") && Tok2.is(tok::l_paren)) {
|
||||
if (Tok.isContextualKeyword("nonisolated") && Tok2.isFollowingLParen()) {
|
||||
BacktrackingScope backtrack(*this);
|
||||
if (consumeIfParenthesizedNonisolated(*this)) {
|
||||
return isStartOfSwiftDecl(/*allowPoundIfAttributes=*/false,
|
||||
@@ -7277,6 +7277,12 @@ ParserStatus Parser::parseDeclPoundDiagnostic() {
|
||||
bool isError = Tok.is(tok::pound_error);
|
||||
consumeToken(isError ? tok::pound_error : tok::pound_warning);
|
||||
|
||||
if (Tok.isAtStartOfLine()) {
|
||||
diagnose(Tok, diag::pound_diagnostic_expected_parens, isError)
|
||||
.fixItInsertAfter(PreviousLoc, "(\"<#message#>\")");
|
||||
return makeParserSuccess();
|
||||
}
|
||||
|
||||
SourceLoc lParenLoc = Tok.getLoc();
|
||||
bool hadLParen = consumeIf(tok::l_paren);
|
||||
|
||||
@@ -7373,7 +7379,7 @@ ParserStatus Parser::parseLineDirective(bool isLine) {
|
||||
|
||||
unsigned StartLine = 0;
|
||||
std::optional<StringRef> Filename;
|
||||
if (!isLine) {
|
||||
if (!isLine && !Tok.isAtStartOfLine()) {
|
||||
// #sourceLocation()
|
||||
// #sourceLocation(file: "foo", line: 42)
|
||||
if (parseToken(tok::l_paren, diag::sourceLocation_expected, "("))
|
||||
|
||||
@@ -18,6 +18,10 @@ struct MyPropertyWrapper {
|
||||
struct PropertyWrapperTest {
|
||||
@MyPropertyWrapper (param: 2) // expected-warning {{extraneous whitespace between attribute name and '('; this is an error in the Swift 6 language mode}}
|
||||
var x: Int
|
||||
|
||||
@MyPropertyWrapper
|
||||
(param: 2) // expected-error {{expected 'var' keyword in property declaration}} expected-error {{property declaration does not bind any variables}} expected-error {{expected pattern}}
|
||||
var y: Int
|
||||
}
|
||||
|
||||
let closure1 = { @MainActor (a, b) in // expected-warning {{extraneous whitespace between attribute name and '('; this is an error in the Swift 6 language mode}}
|
||||
@@ -31,3 +35,10 @@ let closure2 = { @MainActor
|
||||
@
|
||||
MainActor
|
||||
func mainActorFunc() {}
|
||||
|
||||
|
||||
@inline // expected-error {{expected '(' in 'inline' attribute}}
|
||||
(never) func neverInline() {} // expected-error {{expected declaration}}
|
||||
|
||||
@objc
|
||||
(whatever) func whateverObjC() {} // expected-error {{expected declaration}}
|
||||
|
||||
@@ -84,3 +84,6 @@ class I55049 {
|
||||
// expected-error@+1 {{#line directive was renamed to #sourceLocation}}
|
||||
#line 1_000 "issue-55049.swift"
|
||||
class I55049_1 {}
|
||||
|
||||
#sourceLocation
|
||||
(file: "nextLine.swift", line: 400) // expected-warning {{expression of type '(file: String, line: Int)' is unused}}
|
||||
|
||||
@@ -82,3 +82,6 @@ protocol MyProtocol {
|
||||
""") // expected-warning @-2 {{warnings support multi-line string literals}}
|
||||
|
||||
#warning(#"warnings support \(custom string delimiters)"#) // expected-warning {{warnings support \\(custom string delimiters)}}
|
||||
|
||||
#warning // expected-error {{#warning directive requires parentheses}} {{9-9=("<#message#>")}}
|
||||
("message") // expected-warning {{string literal is unused}}
|
||||
|
||||
Reference in New Issue
Block a user