很难确切地解释我所说的上下文go-to-implementation是什么意思,所以在Rust中采用以下示例代码:
struct A {}
struct B {}
impl From<A> for B {
fn from(a: A) -> Self {
B{}
}
}
fn fun() -> B {
let a = A{};
a.into()
}
能够将光标放在fun
最后一行对into()
的调用上,并期望能够轻松转到From<A> for B
中from()
的定义(期望看到a
(类型A
)如何成为B
型的东西)对我来说似乎很有用。 真正发生的是去实现请求将我带到标准库中的通用实现:
// From implies Into
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_unstable(feature = "const_convert", issue = "88674")]
impl<T, U> const Into<U> for T
where
U: ~const From<T>,
{
/// Calls `U::from(self)`.
///
/// That is, this conversion is whatever the implementation of
/// <code>[From]<T> for U</code> chooses to do.
fn into(self) -> U { // <- I'm taken here
U::from(self)
}
}
这是正确的。但是,上下文丢失了,现在无法从下面的行返回到源代码中的实际目标,因为有许多From
实现。LSP 的实现可以确切地知道,在最近的跳跃上下文中,T
=A
和U
=B
,因此:
- 编辑器可以暂时将此上下文显示为内联提示(直到上下文重置),
- 在下一个转到实现请求中,上下文可用于知道给定上下文(
T
和U
)只有一个From
实现,并专门跳转到行:fn from(a: A) -> Self {
。
此功能的实现是否需要更改协议定义本身? 协议中是否有任何用于处理通用代码的功能可以指出我正确的方法?
转到实现功能在 https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_implementation 中描述
看起来请求被传递ImplementationParams
其中包含要检索其实现的位置。
LocationLink
数组可用于传递多个先前的 go-to-implementation请求(或者,实际上是任何 go-to-* 请求)的上下文,这将允许语言服务器根据包含某种类型实例化的上下文限制返回的LocationLink
数。
因此,是的,协议需要扩展以支持此功能。
还有另一种可能。go-to-* 上下文堆栈可以在服务器中维护,每个 go-to-* 请求都会将新的上下文推送到堆栈上。对此堆栈的分析将允许服务器在上下文中限制建议的 go-to-* 位置列表,但它也允许它根据首选上下文堆栈以不同的方式生成代码提示/诊断,包括用于上下文类型具体化的新型提示/悬停。 到目前为止,它不需要修改协议。但实际上,至少需要弹出和清除堆栈的方法。
可以通过定义新的服务器和客户端功能来实现向后兼容性。