-
Notifications
You must be signed in to change notification settings - Fork 440
[SwiftLexicalLookup] Add ASTScope related fixes and lookInMembers result kind. #2852
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
[SwiftLexicalLookup] Add ASTScope related fixes and lookInMembers result kind. #2852
Conversation
…ve wild card filtering.
…alizer decl scopes to function scope. Introduce `self` keyword on the edge of computed properties.
With the recent changes in this PR, public var description: String {
return components.map { String($0) }.joined(separator: ".")
} As for now,
It might be necessary to revisit some of those cases in the future, but I agreed with @DougGregor to ignore them for now. Here’s a sample output of properly matched results for one of the references from
|
@swift-ci please test |
@MAJKFL looks like you need to run the format script |
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.
Left a few comments of things I noticed while reading through the change.
Super exciting to see this progressing and seeing you continue working on it after the GSoC project is over, @MAJKFL ❤️
case .protocolDecl(let protocolDecl): | ||
return protocolDecl.name.positionAfterSkippingLeadingTrivia |
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.
Why do we only need this for protocols and not other type declarations?
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.
In this PR, protocol declarations are the only places we are introducing Self
keyword, so handling other declarations wouldn’t matter in this case. I changed associated syntax node type of ImplicitDecl.Self
to ProtocolDeclSyntax
, to be more explicit and remove this nested switch
.
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.
So, you’re not handling Self
in classes yet?
class Foo {
func bar() -> Self { fatalError() }
}
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.
Interestingly, it seems to me like ASTScope
doesn’t introduce implicit Self
in nominal type declarations. I suppose this could be implicitly modeled by the lookInMembers
result? Here’s the entire output of the validation function for the snippet you’ve provided
-----> Lookup started at: 2:17 ("Self")
| ASTScope | SwiftLexicalLookup
> ✅ | Look memb: 1:7 | Look memb: 1:7
-----> Lookup started at: 2:17 ("Self")
| ASTScope | SwiftLexicalLookup
> ✅ | Look memb: 1:7 | Look memb: 1:7
-----> Lookup started at: 2:24 ("fatalError")
| ASTScope | SwiftLexicalLookup
> ✅ | self 2:8 | self 2:8
> ✅ |End here: Look memb: 1:7| Look memb: 1:7
-----> Lookup started at: 2:24 ("fatalError")
| ASTScope | SwiftLexicalLookup
> ✅ | self 2:8 | self 2:8
> ✅ | Look memb: 1:7 | Look memb: 1:7
Nevertheless, there certainly are more places Self
is introduced apart from protocol declarations. This seems to be also the case for extension declarations. I fixed it now as well and this is how the output looks like for the following snippet (you can also notice here the duplicate omission I’ve mentioned in my previous comment)
protocol Foo {}
extension Foo {
func bar() -> Self { fatalError() }
}
-----> Lookup started at: 2:11 ("Foo")
| ASTScope | SwiftLexicalLookup
-----> Lookup started at: 2:11 ("Foo")
| ASTScope | SwiftLexicalLookup
-----> Lookup started at: 3:17 ("Self")
| ASTScope | SwiftLexicalLookup
> ✅ | End here: Self 2:1 | Self 2:1
> ⏩ | ----- | Look memb: 2:11
-----> Lookup started at: 3:24 ("fatalError")
| ASTScope | SwiftLexicalLookup
> ✅ | self 3:8 | self 3:8
> ✅ | Self 2:1 | Self 2:1
> ✅ |End here: Look memb: 2:11| Look memb: 2:11
-----> Lookup started at: 3:24 ("fatalError")
| ASTScope | SwiftLexicalLookup
> ✅ | self 3:8 | self 3:8
> ✅ | Self 2:1 | Self 2:1
> ✅ | Look memb: 2:11 | Look memb: 2:11
> ℹ️ | Omitted ASTScope name: Self 2:1
> ℹ️ | Omitted ASTScope name: Self 2:1
let implicitSelf: [LookupName] = [.implicit(.self(self))] | ||
.filter { name in | ||
checkIdentifier(identifier, refersTo: name, at: lookUpPosition) | ||
} |
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.
Should we only add self
if this is a member? Ie. we shouldn’t add self
in a top level variable with an accessor, right?
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.
This case was handled here implicitly. The result with self
was handed over to a special function that passed it to AccessorBlockSyntax
parent which later handed it off to it’s SubscriptDeclSyntax
parent.
I’ve noticed now this solution wasn’t perfect though. It was quite inflexible and didn’t work for variable declaration accessors. To fix this, I introduced now a new specialized scope kind: CanInterleaveResultsLaterScopeSyntax
with lookupWithInterleavedResults
function to further generalize this behavior. Now accessor can hand the result with self
keyword to it’s CanInterleaveResultsLaterScopeSyntax
parent. The self
keyword is introduced properly by accessors inside subscript
and variables and it does differentiate whether it’s a member or not.
…sLaterScopeSyntax.
@_spi(Experimental) public var introducedNames: [LookupName] { | ||
implicitInstanceAndTypeNames | ||
} | ||
protocol CanInterleaveResultsLaterScopeSyntax: ScopeSyntax { |
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.
Could you add a comment explaining what it means to interleave results later?
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 documentation comments to the definition of lookupWithInterleavedResults
function and it's concrete implementations.
…tion of a variable with accessors in global scope. Add suggested changes and documentation.
@swift-ci please test |
@swift-ci please test Windows |
let lookInMembers: [LookupResult] = | ||
inheritanceClause?.range.contains(lookUpPosition) ?? false ? [] : [.lookInMembers(self)] |
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 blacklisting the inheritance clause, wouldn’t it be better to whitelist the memberBlock
? I got to this because I was thinking that self
shouldn’t be available in the generic parameters of the type.
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.
That's a good point. As for now, I couldn't find a specific case this wouldn't work and it definitely improves readability of this part of code as well. I changed it to check if lookup was started inside memberBlock
.
macOS failure is a formatting issue:
|
@swift-ci please build toolchain |
Oh, so the comments were the problem, so that's why running formatting script didn't help. Thanks for pointing this out! Hopefully should be fixed now. |
…ookup position from inheritance clause.
@swift-ci please test |
1 similar comment
@swift-ci please test |
@swift-ci test macOS |
@swift-ci please test |
Seems like everything passed now, do you think @ahoppen it's good to merge? |
This PR brings closer the current
SwiftLexicalLookup
unqualified lookup implementation toASTScope
. Changes include:lookInMembers
result kind. It prompts client where to perform member lookup.ASTScope::lookupLocalDecls
stopAfterInnermostBraceStmt
parameter.self
keyword behavior. Compiler introduces it on a function boundary, that's why this PR moves it into function declaration scope.accessibleAfter
for generic parameters.This PR also includes a simple debug description functionality for all lookup components to make it easier to work with the library.