mirror of
https://github.com/zed-industries/zed.git
synced 2024-11-08 07:35:01 +03:00
Editor: support go to implementation (#7890)
Release Notes: - Added "Go to implementation" support in editor.
This commit is contained in:
parent
94bc216bbd
commit
b716035d02
@ -165,6 +165,8 @@ gpui::actions!(
|
|||||||
GoToPrevHunk,
|
GoToPrevHunk,
|
||||||
GoToTypeDefinition,
|
GoToTypeDefinition,
|
||||||
GoToTypeDefinitionSplit,
|
GoToTypeDefinitionSplit,
|
||||||
|
GoToImplementation,
|
||||||
|
GoToImplementationSplit,
|
||||||
OpenUrl,
|
OpenUrl,
|
||||||
HalfPageDown,
|
HalfPageDown,
|
||||||
HalfPageUp,
|
HalfPageUp,
|
||||||
|
@ -1346,6 +1346,7 @@ pub(crate) struct NavigationData {
|
|||||||
enum GotoDefinitionKind {
|
enum GotoDefinitionKind {
|
||||||
Symbol,
|
Symbol,
|
||||||
Type,
|
Type,
|
||||||
|
Implementation,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
@ -7352,6 +7353,18 @@ impl Editor {
|
|||||||
self.go_to_definition_of_kind(GotoDefinitionKind::Symbol, false, cx);
|
self.go_to_definition_of_kind(GotoDefinitionKind::Symbol, false, cx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn go_to_implementation(&mut self, _: &GoToImplementation, cx: &mut ViewContext<Self>) {
|
||||||
|
self.go_to_definition_of_kind(GotoDefinitionKind::Implementation, false, cx);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn go_to_implementation_split(
|
||||||
|
&mut self,
|
||||||
|
_: &GoToImplementationSplit,
|
||||||
|
cx: &mut ViewContext<Self>,
|
||||||
|
) {
|
||||||
|
self.go_to_definition_of_kind(GotoDefinitionKind::Implementation, true, cx);
|
||||||
|
}
|
||||||
|
|
||||||
pub fn go_to_type_definition(&mut self, _: &GoToTypeDefinition, cx: &mut ViewContext<Self>) {
|
pub fn go_to_type_definition(&mut self, _: &GoToTypeDefinition, cx: &mut ViewContext<Self>) {
|
||||||
self.go_to_definition_of_kind(GotoDefinitionKind::Type, false, cx);
|
self.go_to_definition_of_kind(GotoDefinitionKind::Type, false, cx);
|
||||||
}
|
}
|
||||||
@ -7389,6 +7402,7 @@ impl Editor {
|
|||||||
let definitions = project.update(cx, |project, cx| match kind {
|
let definitions = project.update(cx, |project, cx| match kind {
|
||||||
GotoDefinitionKind::Symbol => project.definition(&buffer, head, cx),
|
GotoDefinitionKind::Symbol => project.definition(&buffer, head, cx),
|
||||||
GotoDefinitionKind::Type => project.type_definition(&buffer, head, cx),
|
GotoDefinitionKind::Type => project.type_definition(&buffer, head, cx),
|
||||||
|
GotoDefinitionKind::Implementation => project.implementation(&buffer, head, cx),
|
||||||
});
|
});
|
||||||
|
|
||||||
cx.spawn(|editor, mut cx| async move {
|
cx.spawn(|editor, mut cx| async move {
|
||||||
|
@ -260,6 +260,8 @@ impl EditorElement {
|
|||||||
register_action(view, cx, Editor::go_to_prev_hunk);
|
register_action(view, cx, Editor::go_to_prev_hunk);
|
||||||
register_action(view, cx, Editor::go_to_definition);
|
register_action(view, cx, Editor::go_to_definition);
|
||||||
register_action(view, cx, Editor::go_to_definition_split);
|
register_action(view, cx, Editor::go_to_definition_split);
|
||||||
|
register_action(view, cx, Editor::go_to_implementation);
|
||||||
|
register_action(view, cx, Editor::go_to_implementation_split);
|
||||||
register_action(view, cx, Editor::go_to_type_definition);
|
register_action(view, cx, Editor::go_to_type_definition);
|
||||||
register_action(view, cx, Editor::go_to_type_definition_split);
|
register_action(view, cx, Editor::go_to_type_definition_split);
|
||||||
register_action(view, cx, Editor::open_url);
|
register_action(view, cx, Editor::open_url);
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
DisplayPoint, Editor, EditorMode, FindAllReferences, GoToDefinition, GoToTypeDefinition,
|
DisplayPoint, Editor, EditorMode, FindAllReferences, GoToDefinition, GoToImplementation,
|
||||||
Rename, RevealInFinder, SelectMode, ToggleCodeActions,
|
GoToTypeDefinition, Rename, RevealInFinder, SelectMode, ToggleCodeActions,
|
||||||
};
|
};
|
||||||
use gpui::{DismissEvent, Pixels, Point, Subscription, View, ViewContext};
|
use gpui::{DismissEvent, Pixels, Point, Subscription, View, ViewContext};
|
||||||
|
|
||||||
@ -48,6 +48,7 @@ pub fn deploy_context_menu(
|
|||||||
menu.action("Rename Symbol", Box::new(Rename))
|
menu.action("Rename Symbol", Box::new(Rename))
|
||||||
.action("Go to Definition", Box::new(GoToDefinition))
|
.action("Go to Definition", Box::new(GoToDefinition))
|
||||||
.action("Go to Type Definition", Box::new(GoToTypeDefinition))
|
.action("Go to Type Definition", Box::new(GoToTypeDefinition))
|
||||||
|
.action("Go to Implementation", Box::new(GoToImplementation))
|
||||||
.action("Find All References", Box::new(FindAllReferences))
|
.action("Find All References", Box::new(FindAllReferences))
|
||||||
.action(
|
.action(
|
||||||
"Code Actions",
|
"Code Actions",
|
||||||
|
@ -1136,6 +1136,7 @@ impl LanguageServer {
|
|||||||
document_formatting_provider: Some(OneOf::Left(true)),
|
document_formatting_provider: Some(OneOf::Left(true)),
|
||||||
document_range_formatting_provider: Some(OneOf::Left(true)),
|
document_range_formatting_provider: Some(OneOf::Left(true)),
|
||||||
definition_provider: Some(OneOf::Left(true)),
|
definition_provider: Some(OneOf::Left(true)),
|
||||||
|
implementation_provider: Some(ImplementationProviderCapability::Simple(true)),
|
||||||
type_definition_provider: Some(TypeDefinitionProviderCapability::Simple(true)),
|
type_definition_provider: Some(TypeDefinitionProviderCapability::Simple(true)),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}
|
}
|
||||||
|
@ -105,6 +105,10 @@ pub(crate) struct GetTypeDefinition {
|
|||||||
pub position: PointUtf16,
|
pub position: PointUtf16,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) struct GetImplementation {
|
||||||
|
pub position: PointUtf16,
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) struct GetReferences {
|
pub(crate) struct GetReferences {
|
||||||
pub position: PointUtf16,
|
pub position: PointUtf16,
|
||||||
}
|
}
|
||||||
@ -492,6 +496,99 @@ impl LspCommand for GetDefinition {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[async_trait(?Send)]
|
||||||
|
impl LspCommand for GetImplementation {
|
||||||
|
type Response = Vec<LocationLink>;
|
||||||
|
type LspRequest = lsp::request::GotoImplementation;
|
||||||
|
type ProtoRequest = proto::GetImplementation;
|
||||||
|
|
||||||
|
fn to_lsp(
|
||||||
|
&self,
|
||||||
|
path: &Path,
|
||||||
|
_: &Buffer,
|
||||||
|
_: &Arc<LanguageServer>,
|
||||||
|
_: &AppContext,
|
||||||
|
) -> lsp::GotoImplementationParams {
|
||||||
|
lsp::GotoImplementationParams {
|
||||||
|
text_document_position_params: lsp::TextDocumentPositionParams {
|
||||||
|
text_document: lsp::TextDocumentIdentifier {
|
||||||
|
uri: lsp::Url::from_file_path(path).unwrap(),
|
||||||
|
},
|
||||||
|
position: point_to_lsp(self.position),
|
||||||
|
},
|
||||||
|
work_done_progress_params: Default::default(),
|
||||||
|
partial_result_params: Default::default(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn response_from_lsp(
|
||||||
|
self,
|
||||||
|
message: Option<lsp::GotoImplementationResponse>,
|
||||||
|
project: Model<Project>,
|
||||||
|
buffer: Model<Buffer>,
|
||||||
|
server_id: LanguageServerId,
|
||||||
|
cx: AsyncAppContext,
|
||||||
|
) -> Result<Vec<LocationLink>> {
|
||||||
|
location_links_from_lsp(message, project, buffer, server_id, cx).await
|
||||||
|
}
|
||||||
|
|
||||||
|
fn to_proto(&self, project_id: u64, buffer: &Buffer) -> proto::GetImplementation {
|
||||||
|
proto::GetImplementation {
|
||||||
|
project_id,
|
||||||
|
buffer_id: buffer.remote_id().into(),
|
||||||
|
position: Some(language::proto::serialize_anchor(
|
||||||
|
&buffer.anchor_before(self.position),
|
||||||
|
)),
|
||||||
|
version: serialize_version(&buffer.version()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn from_proto(
|
||||||
|
message: proto::GetImplementation,
|
||||||
|
_: Model<Project>,
|
||||||
|
buffer: Model<Buffer>,
|
||||||
|
mut cx: AsyncAppContext,
|
||||||
|
) -> Result<Self> {
|
||||||
|
let position = message
|
||||||
|
.position
|
||||||
|
.and_then(deserialize_anchor)
|
||||||
|
.ok_or_else(|| anyhow!("invalid position"))?;
|
||||||
|
buffer
|
||||||
|
.update(&mut cx, |buffer, _| {
|
||||||
|
buffer.wait_for_version(deserialize_version(&message.version))
|
||||||
|
})?
|
||||||
|
.await?;
|
||||||
|
Ok(Self {
|
||||||
|
position: buffer.update(&mut cx, |buffer, _| position.to_point_utf16(buffer))?,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn response_to_proto(
|
||||||
|
response: Vec<LocationLink>,
|
||||||
|
project: &mut Project,
|
||||||
|
peer_id: PeerId,
|
||||||
|
_: &clock::Global,
|
||||||
|
cx: &mut AppContext,
|
||||||
|
) -> proto::GetImplementationResponse {
|
||||||
|
let links = location_links_to_proto(response, project, peer_id, cx);
|
||||||
|
proto::GetImplementationResponse { links }
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn response_from_proto(
|
||||||
|
self,
|
||||||
|
message: proto::GetImplementationResponse,
|
||||||
|
project: Model<Project>,
|
||||||
|
_: Model<Buffer>,
|
||||||
|
cx: AsyncAppContext,
|
||||||
|
) -> Result<Vec<LocationLink>> {
|
||||||
|
location_links_from_proto(message.links, project, cx).await
|
||||||
|
}
|
||||||
|
|
||||||
|
fn buffer_id_from_proto(message: &proto::GetImplementation) -> Result<BufferId> {
|
||||||
|
BufferId::new(message.buffer_id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[async_trait(?Send)]
|
#[async_trait(?Send)]
|
||||||
impl LspCommand for GetTypeDefinition {
|
impl LspCommand for GetTypeDefinition {
|
||||||
type Response = Vec<LocationLink>;
|
type Response = Vec<LocationLink>;
|
||||||
|
@ -4646,6 +4646,7 @@ impl Project {
|
|||||||
cx,
|
cx,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn type_definition<T: ToPointUtf16>(
|
pub fn type_definition<T: ToPointUtf16>(
|
||||||
&self,
|
&self,
|
||||||
buffer: &Model<Buffer>,
|
buffer: &Model<Buffer>,
|
||||||
@ -4653,10 +4654,33 @@ impl Project {
|
|||||||
cx: &mut ModelContext<Self>,
|
cx: &mut ModelContext<Self>,
|
||||||
) -> Task<Result<Vec<LocationLink>>> {
|
) -> Task<Result<Vec<LocationLink>>> {
|
||||||
let position = position.to_point_utf16(buffer.read(cx));
|
let position = position.to_point_utf16(buffer.read(cx));
|
||||||
|
|
||||||
self.type_definition_impl(buffer, position, cx)
|
self.type_definition_impl(buffer, position, cx)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn implementation_impl(
|
||||||
|
&self,
|
||||||
|
buffer: &Model<Buffer>,
|
||||||
|
position: PointUtf16,
|
||||||
|
cx: &mut ModelContext<Self>,
|
||||||
|
) -> Task<Result<Vec<LocationLink>>> {
|
||||||
|
self.request_lsp(
|
||||||
|
buffer.clone(),
|
||||||
|
LanguageServerToQuery::Primary,
|
||||||
|
GetImplementation { position },
|
||||||
|
cx,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn implementation<T: ToPointUtf16>(
|
||||||
|
&self,
|
||||||
|
buffer: &Model<Buffer>,
|
||||||
|
position: T,
|
||||||
|
cx: &mut ModelContext<Self>,
|
||||||
|
) -> Task<Result<Vec<LocationLink>>> {
|
||||||
|
let position = position.to_point_utf16(buffer.read(cx));
|
||||||
|
self.implementation_impl(buffer, position, cx)
|
||||||
|
}
|
||||||
|
|
||||||
fn references_impl(
|
fn references_impl(
|
||||||
&self,
|
&self,
|
||||||
buffer: &Model<Buffer>,
|
buffer: &Model<Buffer>,
|
||||||
|
@ -12,6 +12,14 @@ message Envelope {
|
|||||||
uint32 id = 1;
|
uint32 id = 1;
|
||||||
optional uint32 responding_to = 2;
|
optional uint32 responding_to = 2;
|
||||||
optional PeerId original_sender_id = 3;
|
optional PeerId original_sender_id = 3;
|
||||||
|
|
||||||
|
/*
|
||||||
|
When you are adding a new message type, instead of adding it in semantic order
|
||||||
|
and bumping the message ID's of everything that follows, add it at the end of the
|
||||||
|
file and bump the max number. See this
|
||||||
|
https://github.com/zed-industries/zed/pull/7890#discussion_r1496621823
|
||||||
|
|
||||||
|
*/
|
||||||
oneof payload {
|
oneof payload {
|
||||||
Hello hello = 4;
|
Hello hello = 4;
|
||||||
Ack ack = 5;
|
Ack ack = 5;
|
||||||
@ -48,6 +56,7 @@ message Envelope {
|
|||||||
GetDefinitionResponse get_definition_response = 33;
|
GetDefinitionResponse get_definition_response = 33;
|
||||||
GetTypeDefinition get_type_definition = 34;
|
GetTypeDefinition get_type_definition = 34;
|
||||||
GetTypeDefinitionResponse get_type_definition_response = 35;
|
GetTypeDefinitionResponse get_type_definition_response = 35;
|
||||||
|
|
||||||
GetReferences get_references = 36;
|
GetReferences get_references = 36;
|
||||||
GetReferencesResponse get_references_response = 37;
|
GetReferencesResponse get_references_response = 37;
|
||||||
GetDocumentHighlights get_document_highlights = 38;
|
GetDocumentHighlights get_document_highlights = 38;
|
||||||
@ -183,7 +192,10 @@ message Envelope {
|
|||||||
LspExtExpandMacroResponse lsp_ext_expand_macro_response = 155;
|
LspExtExpandMacroResponse lsp_ext_expand_macro_response = 155;
|
||||||
SetRoomParticipantRole set_room_participant_role = 156;
|
SetRoomParticipantRole set_room_participant_role = 156;
|
||||||
|
|
||||||
UpdateUserChannels update_user_channels = 157;
|
UpdateUserChannels update_user_channels = 157;
|
||||||
|
|
||||||
|
GetImplementation get_implementation = 162;
|
||||||
|
GetImplementationResponse get_implementation_response = 163;
|
||||||
}
|
}
|
||||||
|
|
||||||
reserved 158 to 161;
|
reserved 158 to 161;
|
||||||
@ -503,6 +515,16 @@ message GetTypeDefinition {
|
|||||||
message GetTypeDefinitionResponse {
|
message GetTypeDefinitionResponse {
|
||||||
repeated LocationLink links = 1;
|
repeated LocationLink links = 1;
|
||||||
}
|
}
|
||||||
|
message GetImplementation {
|
||||||
|
uint64 project_id = 1;
|
||||||
|
uint64 buffer_id = 2;
|
||||||
|
Anchor position = 3;
|
||||||
|
repeated VectorClockEntry version = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
message GetImplementationResponse {
|
||||||
|
repeated LocationLink links = 1;
|
||||||
|
}
|
||||||
|
|
||||||
message GetReferences {
|
message GetReferences {
|
||||||
uint64 project_id = 1;
|
uint64 project_id = 1;
|
||||||
|
@ -192,6 +192,8 @@ messages!(
|
|||||||
(GetReferencesResponse, Background),
|
(GetReferencesResponse, Background),
|
||||||
(GetTypeDefinition, Background),
|
(GetTypeDefinition, Background),
|
||||||
(GetTypeDefinitionResponse, Background),
|
(GetTypeDefinitionResponse, Background),
|
||||||
|
(GetImplementation, Background),
|
||||||
|
(GetImplementationResponse, Background),
|
||||||
(GetUsers, Foreground),
|
(GetUsers, Foreground),
|
||||||
(Hello, Foreground),
|
(Hello, Foreground),
|
||||||
(IncomingCall, Foreground),
|
(IncomingCall, Foreground),
|
||||||
@ -312,6 +314,7 @@ request_messages!(
|
|||||||
(GetCodeActions, GetCodeActionsResponse),
|
(GetCodeActions, GetCodeActionsResponse),
|
||||||
(GetCompletions, GetCompletionsResponse),
|
(GetCompletions, GetCompletionsResponse),
|
||||||
(GetDefinition, GetDefinitionResponse),
|
(GetDefinition, GetDefinitionResponse),
|
||||||
|
(GetImplementation, GetImplementationResponse),
|
||||||
(GetDocumentHighlights, GetDocumentHighlightsResponse),
|
(GetDocumentHighlights, GetDocumentHighlightsResponse),
|
||||||
(GetHover, GetHoverResponse),
|
(GetHover, GetHoverResponse),
|
||||||
(GetNotifications, GetNotificationsResponse),
|
(GetNotifications, GetNotificationsResponse),
|
||||||
@ -388,6 +391,7 @@ entity_messages!(
|
|||||||
GetCodeActions,
|
GetCodeActions,
|
||||||
GetCompletions,
|
GetCompletions,
|
||||||
GetDefinition,
|
GetDefinition,
|
||||||
|
GetImplementation,
|
||||||
GetDocumentHighlights,
|
GetDocumentHighlights,
|
||||||
GetHover,
|
GetHover,
|
||||||
GetProjectSymbols,
|
GetProjectSymbols,
|
||||||
|
Loading…
Reference in New Issue
Block a user