Swiftinterface symbol lookup by adam-fowler · Pull Request #747 · swiftlang/sourcekit-lsp (original) (raw)

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:

  1. Jump to the header
  2. Do an index lookup for the definition and jump to that (if we have the definition)
  3. Jump to the generated interface for that module
  4. Provide the user a choice for one of these

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 C.foo() we wouldn't want to provide E.foo() as a result, but we would want to give D.foo() since it's possible that's the actual call.

(*) 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...

Is checking the extension of location uri enough here?

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.

Is there a better way to do this? Are there other modules that might be split up like this?

Technically any library could provide this via -group-info-path, though it really only matters for when there's no source. The index records group names as if they were submodules for the stdlib, but for all other modules that's not the case. So the only accurate place to get this from is the cursor info request.

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.