-
Notifications
You must be signed in to change notification settings - Fork 288
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
Swiftinterface symbol lookup #747
Swiftinterface symbol lookup #747
Conversation
When a symbol definition returns it is in a swiftinterface file, create textual version of swiftinterface and return that in response.
skreq[keys.usr] = symbol | ||
|
||
if let compileCommand = self.commandsByFile[uri] { | ||
skreq[keys.compilerargs] = compileCommand.compilerArgs |
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.
Wasn't sure if this was necessary
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.
Compiler args are not used for the find_usr
request, so there’s no need to specify them
// textual interface | ||
if let firstResolved = resolved.first, | ||
let moduleName = firstResolved.occurrence?.location.moduleName, | ||
firstResolved.location.uri.fileURL?.pathExtension == "swiftinterface" { |
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.
Is checking the extension of location uri enough here?
I thought I might give some extra background here. The cursor info request returns the group name (which is where the module splitting is coming from) as well as whether it's "dynamic", ie. whether it could be overridden. In the dynamic case we will also provide the "receiver" USRs which are the statically known types of the member that's being called. If the returned symbol isn't dynamic, then there's no need to do an index lookup - we can jump straight to the location provided by the result (*). In the case that location is a header we can make a choice:
If it is dynamic, we should always do an index lookup - looking up and down the hierarchy from the given receiver types. This is basically to avoid going off into a separate subtree, eg. if we had D: C, C: B, B: A, E: B and a call on (*) This result wouldn't be any more/less up to date than the index since we only index-while-building. Though if we instead had background indexing, it might be better to consider the index result all the time. We could also background build though so... 🤷The dynamic/receiver USR data is also in the index. With that said...
Depends on what we actually want to do regarding the header case above. Another case to consider is what happens when library evolution isn't enabled, though I'm not sure we really want to to support that in general. I believe (but haven't checked) that we don't return a path at all in that case, but ideally we'd still jump to the generated interface. The index wouldn't contain any results from such modules anyway. If this is just about providing the generated interface for swift modules, then this check works well enough.
Technically any library could provide this via But considering only the stdlib is likely good enough here. In that case passing the group name to the generated interface request would also be a good thing to do. Splitting works if we can't get it from the cursor info request. |
self._findUSR(request: request, uri: interfaceDocURI, snapshot: snapshot, symbol: symbol) { result in | ||
switch result { | ||
case .success(let info): | ||
request.reply(.success(InterfaceDetails(uri: interfaceDocURI, position: info.position))) | ||
case .failure: | ||
request.reply(.success(InterfaceDetails(uri: interfaceDocURI, position: 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 wonder whether we can share this code between the two if
branches
skreq[keys.usr] = symbol | ||
|
||
if let compileCommand = self.commandsByFile[uri] { | ||
skreq[keys.compilerargs] = compileCommand.compilerArgs |
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.
Compiler args are not used for the find_usr
request, so there’s no need to specify them
if let offset: Int = dict[keys.offset], | ||
let position = snapshot.positionOf(utf8Offset: offset) { | ||
return completion(.success(FindUSRInfo(position: position))) | ||
} else { | ||
return completion(.success(FindUSRInfo(position: 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.
Should be indented by 2 spaces, I think.
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.
Do you use one of the swift formats to format the code?
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.
No, SourceKit-LSP is manual 2 space indentation
Use group names when running open interface request
Sources/LanguageServerProtocol/Requests/OpenInterfaceRequest.swift
Outdated
Show resolved
Hide resolved
Sources/LanguageServerProtocol/Requests/OpenInterfaceRequest.swift
Outdated
Show resolved
Hide resolved
Sources/LanguageServerProtocol/Requests/OpenInterfaceRequest.swift
Outdated
Show resolved
Hide resolved
rename symbol to symbolUSR Cleanup OpenInterfaceRequest.init
Use SwiftPMPackage test module Added version of buildAndIndex that includes system symbols
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.
Thank you so much for this
@swift-ci Please test |
Add multiple tests for various system modules
@ahoppen Hopefully fixed the tests. Had to create a new test SwiftPM project for the swift interface tests as my edits of an existing one broke another test. Also added tests for symbols from multiple libs, with submodules and not. |
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
@swift-ci Please test |
@swift-ci Please test Windows |
@adam-fowler Could you also create a cherry-pick PR for release/5.9? I think it would be worth to include this improvement in the 5.9 release. |
ok will do |
On calling
definition
if a symbol returns it is in a file with a.swiftinterface
extension it will use OpenInterface to create the generated interface file. It will then call sourcekitdsource.request.editor.find_usr
to find the location of the symbol in the generated file.OpenInterfaceRequest
has been extended to include an optional symbol name.SourceKitServer.definition
into a separate function:respondWithInterface
, as it is called from multiple sites nowswiftInterface
file then userespondWithInterface
to build generated interface and then find symbol location in generated interface.openInterface
and also cache the line table._findUSR
function that callssource.request.editor.find_usr