-
Notifications
You must be signed in to change notification settings - Fork 446
SwiftSyntax support for module selectors #3091
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
base: main
Are you sure you want to change the base?
Conversation
🥳 |
This capability is currently unused, but it’ll matter soon.
1f47aa2
to
eaa6956
Compare
And make sure it doesn’t break Objective-C selector lexing.
Treating introducers as keywords is now always conditional on whether `shouldParsePatternBinding(introducer:)` returns `true`. That method has also been modified to correctly handle an edge case with wildcard patterns.
Initializers for nodes with experimental node children need to be marked `@_spi`. This PR: • Adds that attribute. • Generates an alternative which *doesn’t* use SPI as part of the compatibility layer. • As a side effect, adds a `Child.Refactoring.introduced` case that can be used to generate compatibility `unexpected` properties. No functional change in this commit, but it will affect the code generation in the next one.
da6eff6
to
f94b58a
Compare
@swift-ci please test |
@swift-ci please test |
1 similar comment
@swift-ci please test |
@swift-ci please test |
@swift-ci please test macOS |
@swift-ci please test Linux |
This build failure seems to be real:
|
I can't actually reproduce that failure locally, but I'm pushing a speculative fix. |
@swift-ci please test |
@swift-ci please test macOS |
@swift-ci please test Linux |
@swift-ci please test Windows |
We are good now with macOS and Linux. Let's try Windows again. @swift-ci please test Windows. |
hmm, the Windows CI hit a compiler crasher:
|
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.
Apologies I didn't review this sooner. I still haven't look into the implementation closely, but here's the first round 🙇
// Technically the current token *should* be an identifier, but we also want to diagnose other tokens that might be | ||
// used by accident (particularly keywords and `_`). However, we don't want to consume tokens which would make the | ||
// surrounding structure mis-parse. | ||
return self.at(anyIn: StructuralTokens.self) == nil |
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 don't think it's a good idea to (almost) always consider <token>
::
as a module qualifier. E..g.
class
::
This looks to me an incomplete class
declaration and just an orphan ::
. Even if it's on the same line with no-space, I don't think we need to parse it as a module selector.
Changes the syntax tree to represent module selectors: • A `ModuleSelectorSyntax` node represents a module selector abstractly. • The following nodes now have an optional `moduleSelector` child: • `DeclReferenceExprSyntax` • `IdentifierTypeSyntax` • `MacroExpansionExprSyntax` • `MemberTypeSyntax` • BasicFormat knows the preferred format for module selectors. Other components, particularly the parser, were also updated to continue building, though without any changes in behavior. Parser implementation will come in a future commit.
Changes it to share code with `parseTypeIdentifier()` and clean up the member type parsing a little. Also tweaks call sites of `parseTypeIdentifier()`.
Okay, this is a dramatically simpler implementation that doesn't try to do anything special to handle module selectors at invalid locations. I can't say I'm happy with some of the recovery behavior I'm seeing—in particular, parameter lists and tuple patterns seem to just throw up their hands in a pretty ugly way instead of recovering to a |
This commit ports over tests from the compiler’s (future) `test/NameLookup/module_selector.swift` file and makes sure the correct uses parse as expected. It also tests that ill-formed module selectors (ones with a missing or non-identifier module name) are diagnosed correctly. This commit doesn’t handle module selectors in scoped `import` statements; the related test has been XFAILed.
|
||
extension Parser { | ||
/// Parses one or more module selectors, if present. | ||
mutating func parseModuleSelector() -> RawModuleSelectorSyntax? { |
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 know there're several parsing functions that doesn't follow this convention, but:
mutating func parseModuleSelector() -> RawModuleSelectorSyntax? { | |
mutating func parseModuleSelectorIfPresent() -> RawModuleSelectorSyntax? { |
or check self.isAtModuleSelector()
before calling this and make this non-optional.
@@ -68,6 +213,9 @@ extension Parser { | |||
} | |||
|
|||
mutating func parseDeclReferenceExpr(_ flags: DeclNameOptions = []) -> RawDeclReferenceExprSyntax { | |||
// Consume a module selector if present. | |||
let moduleSelector = self.parseModuleSelector() |
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 think presence of the module selector should affect flags
(DeclNameOptions.keywords
).
It would be weird if ModName::default
is rejected, but foo.ModName::default
is allowed.
related: https://forums.swift.org/t/pitch-module-selectors/80835/82
} | ||
|
||
// Technically the current token *should* be an identifier, but we also want to diagnose other tokens that might be | ||
// used by accident (particularly keywords and `_`). However, we don't want to consume tokens which would make the |
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.
Would you show me some examples where consuming keywords as a invalid module identifiers improves the diagnostics?
IMO, keyword as a module name rule should follow existing keyword rules should be like:
- Bare keywords as module names are allowed after
.
(following SE-0071). Otherwise it's not a module selector even if there's::
after that - Some special keywords such as
Self
,self
andAny
should be parsed as reserved names (even without.
). And the type checker should reject/diagnose them accordingly.
This PR adds module selectors to SwiftSyntax and SwiftParser (draft of matching compiler feature in swiftlang/swift#34556). This feature was pitched ages ago; a proper proposal is
on my todo listnow available.Note: This PR is still a work in progress—in particular, I need to go back and improve the tests, both by expanding their coverage and by adding assertions about the resulting syntax trees—but I'd appreciate feedback on the design while I'm working on that.Reviewers: If you review this commit-by-commit, I've separated out the big dumb mechanical changes from the ones that actually change parsing logic.