Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions Sources/SwiftParser/Lookahead.swift
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,13 @@ extension Parser.Lookahead {
var lookahead = self.lookahead()
lookahead.eat(.leftBrace)

// '@_accessorBlock' is a builtin disambiguation marker.
if lookahead.peek(isAt: .identifier),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don’t you also need to consume the @ before looking at the identifier? Also, I think a test case would be good.

Also, I think this would probably belong in the while lookahead.consume(if: .atSign) != nil { loop below to make it resilient so @_accessorBlock doesn’t necessarily need to be the first attribute.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don’t you also need to consume the @ before looking at the identifier?

We know the current token is @ at line 269 above.

I think this would probably belong in the while lookahead.consume(if: .atSign) != nil { loop below to make it resilient so @_accessorBlock doesn’t necessarily need to be the first attribute.

ASTPrinter only print @_accessorBlock right after {. I don't see a reason to put it in the loop

Also, I think a test case would be good.

Sure, I will add a test case.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We know the current token is @ at line 269 above.

Ah, I got a little confused about nextToken and then using a fresh lookahead here. Opened #3172 to make this slightly easier to read.

ASTPrinter only print @_accessorBlock right after {. I don't see a reason to put it in the loop

OK, your choice. But I find it odd that order of attributes matters here when it doesn’t in any other cases.

lookahead.peek().tokenText == "_accessorBlock"
{
return true
}

// Eat attributes, if present.
while lookahead.consume(if: .atSign) != nil {
guard lookahead.consume(if: .identifier) != nil else {
Expand Down
37 changes: 37 additions & 0 deletions Tests/SwiftParserTest/DeclarationTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3768,4 +3768,41 @@ final class UsingDeclarationTests: ParserTestCase {
"""
)
}

func testAccessorBlockDisambiguationMarker() {
assertParse(
"""
var value = initialValue { @_accessorBlock
get
}
""",
substructure: VariableDeclSyntax(
bindingSpecifier: .keyword(.var),
bindings: [
PatternBindingSyntax(
pattern: IdentifierPatternSyntax(identifier: .identifier("value")),
initializer: InitializerClauseSyntax(
value: DeclReferenceExprSyntax(baseName: .identifier("initialValue"))
),
accessorBlock: AccessorBlockSyntax(
leftBrace: .leftBraceToken(),
accessors: .accessors([
AccessorDeclSyntax(
attributes: [
.attribute(
AttributeSyntax(
atSign: .atSignToken(),
attributeName: IdentifierTypeSyntax(name: .identifier("_accessorBlock"))
)
)
],
accessorSpecifier: .keyword(.get)
)
])
)
)
]
)
)
}
}