-
Notifications
You must be signed in to change notification settings - Fork 440
Replace expression in ClosureCaptureSyntax
with initializer clause
#2763
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Replace expression in ClosureCaptureSyntax
with initializer clause
#2763
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead of removing any public API, could you add the existing API signatures as deprecated methods to SwiftSyntaxCompatibility.swift with the most reasonable implementation possible?
Also, could you add the changes to the 601 release notes?
let name: RawTokenSyntax | ||
let initializer: RawInitializerClauseSyntax? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You should be able to hoist the parsing of name
out of the if
statement and then use self.at(.equal)
instead of self.peek(isAt: .equal)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the suggestion. I moved name parsing to before the if
statement.
As an interesting artifact, self
token will not be remapped to identifier
when parsing capture of [self = 123]
form. Out of curiosity, was there a particular reason for this remapping? As far as I checked, e.g. in let self = 123
self
is classified as a keyword.
…to release notes.
extension ClosureCaptureSyntax { | ||
@available(*, deprecated, renamed: "unexpectedBetweenNameAndEqual") | ||
public var unexpectedBetweenNameAndAssignToken: UnexpectedNodesSyntax? { | ||
get { | ||
return unexpectedBetweenNameAndEqual | ||
} | ||
set { | ||
unexpectedBetweenNameAndEqual = newValue | ||
} | ||
} | ||
|
||
@available(*, deprecated, renamed: "equal") | ||
public var assignToken: TokenSyntax? { | ||
get { | ||
return equal | ||
} | ||
set { | ||
equal = newValue | ||
} | ||
} | ||
|
||
@available(*, deprecated, renamed: "unexpectedBetweenEqualAndExpression") | ||
public var unexpectedBetweenAssignTokenAndExpression: UnexpectedNodesSyntax? { | ||
get { | ||
return unexpectedBetweenEqualAndExpression | ||
} | ||
set { | ||
unexpectedBetweenEqualAndExpression = newValue | ||
} | ||
} | ||
|
||
@available(*, deprecated, renamed: "ClosureCaptureSyntax(leadingTrivia:_:specifier:_:name:_:equal:_:expression:_:trailingComma:_:trailingTrivia:)") | ||
@_disfavoredOverload | ||
public init( | ||
leadingTrivia: Trivia? = nil, | ||
_ unexpectedBeforeSpecifier: UnexpectedNodesSyntax? = nil, | ||
specifier: ClosureCaptureSpecifierSyntax? = nil, | ||
_ unexpectedBetweenSpecifierAndName: UnexpectedNodesSyntax? = nil, | ||
name: TokenSyntax? = nil, | ||
_ unexpectedBetweenNameAndAssignToken: UnexpectedNodesSyntax? = nil, | ||
assignToken: TokenSyntax? = nil, | ||
_ unexpectedBetweenAssignTokenAndExpression: UnexpectedNodesSyntax? = nil, | ||
expression: some ExprSyntaxProtocol, | ||
_ unexpectedBetweenExpressionAndTrailingComma: UnexpectedNodesSyntax? = nil, | ||
trailingComma: TokenSyntax? = nil, | ||
_ unexpectedAfterTrailingComma: UnexpectedNodesSyntax? = nil, | ||
trailingTrivia: Trivia? = nil | ||
|
||
) { | ||
self.init( | ||
leadingTrivia: leadingTrivia, | ||
unexpectedBeforeSpecifier, | ||
specifier: specifier, | ||
unexpectedBetweenSpecifierAndName, | ||
name: name, | ||
unexpectedBetweenNameAndAssignToken, | ||
equal: assignToken, | ||
unexpectedBetweenAssignTokenAndExpression, | ||
expression: expression, | ||
unexpectedBetweenExpressionAndTrailingComma, | ||
trailingComma: trailingComma, | ||
unexpectedAfterTrailingComma, | ||
trailingTrivia: trailingTrivia | ||
) | ||
} | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
People might still be relying on these compatibility overloads, so we shouldn’t remove them.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added those to SwiftSyntaxCompatibility.swift
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should continue to offer deprecated compatibility versions of all the old signatures in this file. SwiftSyntaxCompatibility.swift should have a few examples.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added those to SwiftSyntaxCompatibility.swift
.
public var name: TokenSyntax? { | ||
public var name: TokenSyntax { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changing name
to be non-optional is an API-breaking change because eg. closuereCapture.name?.text
will stop compiling. There is no way of making it API-compatible. Could you highlight it in the release notes?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for pointing this out. I added a note under "API-Incompatible Changes" in the release notes.
Release Notes/601.md
Outdated
- `ClosureCaptureSyntax` now has a new node structure. | ||
- Description: `ClosureCaptureSyntax` now has an `initializer` property instead of `equal` and `expression`. Additionally, the `name` property is no longer optional. | ||
- Pull request: https://github.com/swiftlang/swift-syntax/pull/2763 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would move this to the Deprecations
section because that’s the way that users are most likely to hit it: They were using it before and now they have a deprecation warning.
New APIs is intended for features that didn’t exist before.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the suggestion. I moved it to the note under "Deprecations".
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for adding the compatibility layers. Looks good to me 👍🏽
@swift-ci Please test |
The CI failed because we removed the |
There’s a merge conflict in the release notes now, could you resolve that @MAJKFL? |
Should be good to go now. Could you please test it @ahoppen? |
@swift-ci Please test |
Head branch was pushed to by a user without write access
Had to fix failing |
@swift-ci please test |
@swift-ci please test Windows |
1 similar comment
@swift-ci please test Windows |
Ah, drat:
|
Hmm... this is an interesting one. Inside override func visit(_ node: ClosureCaptureSyntax) -> SyntaxVisitorContinueKind {
before(node.firstToken(viewMode: .sourceAccurate), tokens: .open)
after(node.specifier?.lastToken(viewMode: .sourceAccurate), tokens: .break)
// before(node.equal, tokens: .break)
// after(node.equal, tokens: .break)
if let trailingComma = node.trailingComma {
before(trailingComma, tokens: .close)
after(trailingComma, tokens: .break(.same))
} else {
after(node.lastToken(viewMode: .sourceAccurate), tokens: .close)
}
return .visitChildren
} Does it mean we need to fix it there? Or do you think there is a way to fix it in this PR and I'm missing something? |
Yes, I think it's okay to fix it there. Edit: Argh, I'm not really sure now. Could it be that the now-deprecated |
The |
I agree that we should just update swift-format to stop using the compatibility layer nodes. In cases like this where the fundamental structure of a node changes, it's important that we visit the tree in the way that reflects the actual structure. |
@swift-ci Please test |
This PR adjusts
ClosureCaptureSyntax
node.name
is no longer optional, making it more convenient to refer it by name (as discussed under [SwiftLexicalLookup][GSoC] Add initial name lookup functionality #2719).equal
andexpression
were replaced by the optionalinitializer
property of theInitializerClauseSyntax
type, making it more uniform with variable declarations likelet a = b
and function parameters likea: Int = 123
.name
is not optional and equal sign is no longer part of the node itself.