Skip to content
Open
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
8 changes: 5 additions & 3 deletions CodeGeneration/Sources/SyntaxSupport/DeclNodes.swift
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ public let DECL_NODES: [Node] = [
traits: [
"WithOptionalCodeBlock",
"WithAttributes",
"WithModifiers",
],
children: [
Child(
Expand All @@ -97,10 +98,10 @@ public let DECL_NODES: [Node] = [
nameForDiagnostics: "attributes"
),
Child(
name: "modifier",
kind: .node(kind: .declModifier),
name: "modifiers",
kind: .collection(kind: .declModifierList, collectionElementName: "Modifier", defaultsToEmpty: true),
nameForDiagnostics: "modifiers",
isOptional: true
documentation: "Modifiers like `mutating` or `yielding` that affect the accessor declaration."
),
Child(
name: "accessorSpecifier",
Expand Down Expand Up @@ -495,6 +496,7 @@ public let DECL_NODES: [Node] = [
.keyword(.unowned),
.keyword(.weak),
.keyword(.sending),
.keyword(.yielding),
])
),
Child(
Expand Down
5 changes: 4 additions & 1 deletion CodeGeneration/Sources/SyntaxSupport/KeywordSpec.swift
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,7 @@ public enum Keyword: CaseIterable {
case willSet
case wrt
case yield
case yielding

public var spec: KeywordSpec {
switch self {
Expand Down Expand Up @@ -537,7 +538,7 @@ public enum Keyword: CaseIterable {
case .module:
return KeywordSpec("module")
case .mutate:
return KeywordSpec("mutate", experimentalFeature: .borrowAndMutateAccessors)
return KeywordSpec("mutate")
case .mutableAddressWithNativeOwner:
return KeywordSpec("mutableAddressWithNativeOwner")
case .mutableAddressWithOwner:
Expand Down Expand Up @@ -692,6 +693,8 @@ public enum Keyword: CaseIterable {
return KeywordSpec("wrt")
case .yield:
return KeywordSpec("yield")
case .yielding:
return KeywordSpec("yielding")
}
}
}
2 changes: 1 addition & 1 deletion Sources/SwiftParser/CollectionNodes+Parsable.swift
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ extension AccessorDeclListSyntax: SyntaxParseable {
} makeMissing: { remainingTokens, arena in
return RawAccessorDeclSyntax(
attributes: RawAttributeListSyntax(elements: [], arena: arena),
modifier: nil,
modifiers: RawDeclModifierListSyntax(elements: [], arena: arena),
Comment on lines 69 to +70
Copy link
Member

Choose a reason for hiding this comment

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

We can save a few bytes in the syntax tree by using a shared empty collection. Also for RawAttributeListSyntax now that I look at it.

Suggested change
attributes: RawAttributeListSyntax(elements: [], arena: arena),
modifier: nil,
modifiers: RawDeclModifierListSyntax(elements: [], arena: arena),
attributes: self.emptyCollection(RawAttributeListSyntax.self),
modifiers: self.emptyCollection(RawDeclModifierListSyntax.sel),

accessorSpecifier: RawTokenSyntax(missing: .keyword, text: "get", arena: arena),
parameters: nil,
effectSpecifiers: nil,
Expand Down
47 changes: 27 additions & 20 deletions Sources/SwiftParser/Declarations.swift
Original file line number Diff line number Diff line change
Expand Up @@ -1658,44 +1658,51 @@ extension Parser {

struct AccessorIntroducer {
var attributes: RawAttributeListSyntax
var modifier: RawDeclModifierSyntax?
var modifiers: RawDeclModifierListSyntax
var kind: AccessorDeclSyntax.AccessorSpecifierOptions
var unexpectedBeforeToken: RawUnexpectedNodesSyntax?
var token: RawTokenSyntax
}

mutating func parseAccessorModifierList(count: Int) -> RawDeclModifierListSyntax {
var elements = [RawDeclModifierSyntax]()

for _ in 0..<count {
let (unexpectedBeforeName, name) = self.expect(anyIn: AccessorModifier.self, default: .mutating)
let modifier = RawDeclModifierSyntax(
unexpectedBeforeName,
name: name,
detail: nil,
arena: self.arena
)
elements.append(modifier)
}

return RawDeclModifierListSyntax(
elements: elements,
arena: self.arena
)
}

mutating func parseAccessorIntroducer(
forcedKind: (AccessorDeclSyntax.AccessorSpecifierOptions, TokenConsumptionHandle)? = nil
) -> AccessorIntroducer? {
// Check there is an identifier before consuming
// Look ahead to verify attributes/modifiers/kind
var look = self.lookahead()
let _ = look.consumeAttributeList()
let hasModifier = look.consume(ifAnyIn: AccessorModifier.self) != nil
let modifierCount = look.consume(anySequence: AccessorModifier.self)
guard let (kind, _) = look.at(anyIn: AccessorDeclSyntax.AccessorSpecifierOptions.self) ?? forcedKind else {
return nil
}

let attrs = self.parseAttributeList()

// Parse the contextual keywords for 'mutating' and 'nonmutating' before
// get and set.
let modifier: RawDeclModifierSyntax?
if hasModifier {
let (unexpectedBeforeName, name) = self.expect(anyIn: AccessorModifier.self, default: .mutating)
modifier = RawDeclModifierSyntax(
unexpectedBeforeName,
name: name,
detail: nil,
arena: self.arena
)
} else {
modifier = nil
}
let modifiers = self.parseAccessorModifierList(count: modifierCount)

let (unexpectedBeforeIntroducer, introducer) = self.expect(kind.spec)

return AccessorIntroducer(
attributes: attrs,
modifier: modifier,
modifiers: modifiers,
kind: kind,
unexpectedBeforeToken: unexpectedBeforeIntroducer,
token: introducer
Expand Down Expand Up @@ -1738,7 +1745,7 @@ extension Parser {
let body = self.parseOptionalCodeBlock()
return RawAccessorDeclSyntax(
attributes: introducer.attributes,
modifier: introducer.modifier,
modifiers: introducer.modifiers,
introducer.unexpectedBeforeToken,
accessorSpecifier: introducer.token,
parameters: parameters,
Expand Down
12 changes: 12 additions & 0 deletions Sources/SwiftParser/Lookahead.swift
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,18 @@ extension Parser.Lookahead {
}
}

// MARK: Skipping a sequence of tokens

extension Parser.Lookahead {
mutating func consume<SpecSet: TokenSpecSet>(anySequence: SpecSet.Type) -> Int {
var count = 0
while consume(ifAnyIn: SpecSet.self) != nil {
count += 1
}
return count
}
}

// MARK: Skipping Tokens

extension Parser.Lookahead {
Expand Down
2 changes: 1 addition & 1 deletion Sources/SwiftParser/TokenPrecedence.swift
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,7 @@ enum TokenPrecedence: Comparable {
.dependsOn, .scoped, .sending,
// Accessors
.get, .set, .didSet, .willSet, .unsafeAddress, .addressWithOwner, .addressWithNativeOwner, .unsafeMutableAddress,
.mutableAddressWithOwner, .mutableAddressWithNativeOwner, ._read, .read, ._modify, .modify, .mutate,
.mutableAddressWithOwner, .mutableAddressWithNativeOwner, ._read, .read, ._modify, .modify, .mutate, .yielding,
// Misc
.import, .using:
self = .declKeyword
Expand Down
3 changes: 3 additions & 0 deletions Sources/SwiftParser/TokenSpecSet.swift
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ enum AccessorModifier: TokenSpecSet {
case borrowing
case mutating
case nonmutating
case yielding

init?(lexeme: Lexer.Lexeme, experimentalFeatures: Parser.ExperimentalFeatures) {
switch PrepareForKeywordMatch(lexeme) {
Expand All @@ -74,6 +75,7 @@ enum AccessorModifier: TokenSpecSet {
case TokenSpec(.borrowing): self = .borrowing
case TokenSpec(.mutating): self = .mutating
case TokenSpec(.nonmutating): self = .nonmutating
case TokenSpec(.yielding): self = .yielding
default: return nil
}
}
Expand All @@ -85,6 +87,7 @@ enum AccessorModifier: TokenSpecSet {
case .borrowing: return .keyword(.borrowing)
case .mutating: return .keyword(.mutating)
case .nonmutating: return .keyword(.nonmutating)
case .yielding: return .keyword(.yielding)
}
}
}
Expand Down
12 changes: 10 additions & 2 deletions Sources/SwiftParser/generated/Parser+TokenSpecSet.swift

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

30 changes: 30 additions & 0 deletions Sources/SwiftSyntax/SwiftSyntaxCompatibility.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,36 @@
// This file provides compatibility aliases to keep dependents of SwiftSyntax building.
// All users of the declarations in this file should transition away from them ASAP.

extension AccessorDeclSyntax {
@available(*, deprecated, message: "use modifiers to see all modifiers on an accessor declaration")
public var modifier: DeclModifierSyntax? {
get {
// The legacy `modifier` API predates `yielding`
if let m = modifiers.first(where: { $0.name.text != "yielding" }) {
return m
}
return nil
}
set {
if let newValue {
modifiers = [newValue]
} else {
modifiers = []
}
}
}
@available(*, deprecated, message: "use unexpectedBetweenAttributesAndModifers")
public var unexpectedBetweenAttributesAndModifier: UnexpectedNodesSyntax? {
get { unexpectedBetweenAttributesAndModifiers }
set { unexpectedBetweenAttributesAndModifiers = newValue }
}
@available(*, deprecated, message: "use unexpectedBetweenModifiersAndAccessorSpecifier")
public var unexpectedBetweenModifierAndAccessorSpecifier: UnexpectedNodesSyntax? {
get { unexpectedBetweenModifiersAndAccessorSpecifier }
set { unexpectedBetweenModifiersAndAccessorSpecifier = newValue }
}
}

extension AccessorEffectSpecifiersSyntax {
@_disfavoredOverload
@available(*, deprecated, message: "use throwsClause instead of throwsSpecifier")
Expand Down
12 changes: 6 additions & 6 deletions Sources/SwiftSyntax/generated/ChildNameForKeyPath.swift

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 4 additions & 1 deletion Sources/SwiftSyntax/generated/Keyword.swift

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading