@@ -4,7 +4,6 @@ use crate::{
44 Call, Error, OffsetEncoding, Result,
55};
66
7−use anyhow::anyhow;
87use helix_core::{find_root, ChangeSet, Rope};
98use lsp_types as lsp;
109use serde::Deserialize;
@@ -546,16 +545,17 @@ impl Client {
546545 new_text: &Rope,
547546 changes: &ChangeSet,
548547 ) -> Option<impl Future<Output = Result<()>>> {
549− // figure out what kind of sync the server supports
550−
551548 let capabilities = self.capabilities.get().unwrap();
552549
550+ // Return early if the server does not support document sync.
553551 let sync_capabilities = match capabilities.text_document_sync {
554− Some(lsp::TextDocumentSyncCapability::Kind(kind))
555− | Some(lsp::TextDocumentSyncCapability::Options(lsp::TextDocumentSyncOptions {
556− change: Some(kind),
557− ..
558− })) => kind,
552+ Some(
553+ lsp::TextDocumentSyncCapability::Kind(kind)
554+ | lsp::TextDocumentSyncCapability::Options(lsp::TextDocumentSyncOptions {
555+ change: Some(kind),
556+ ..
557+ }),
558+ ) => kind,
559559 // None | SyncOptions { changes: None }
560560 _ => return None,
561561 };
@@ -631,8 +631,12 @@ impl Client {
631631 text_document: lsp::TextDocumentIdentifier,
632632 position: lsp::Position,
633633 work_done_token: Option<lsp::ProgressToken>,
634− ) -> impl Future<Output = Result<Value>> {
635− // ) -> Result<Vec<lsp::CompletionItem>> {
634+ ) -> Option<impl Future<Output = Result<Value>>> {
635+ let capabilities = self.capabilities.get().unwrap();
636+
637+ // Return early if the server does not support completion.
638+ capabilities.completion_provider.as_ref()?;
639+
636640 let params = lsp::CompletionParams {
637641 text_document_position: lsp::TextDocumentPositionParams {
638642 text_document,
@@ -647,14 +651,25 @@ impl Client {
647651 // lsp::CompletionContext { trigger_kind: , trigger_character: Some(), }
648652 };
649653
650− self.call::<lsp::request::Completion>(params)
654+ Some(self.call::<lsp::request::Completion>(params))
651655 }
652656
653657 pub fn resolve_completion_item(
654658 &self,
655659 completion_item: lsp::CompletionItem,
656− ) -> impl Future<Output = Result<Value>> {
657− self.call::<lsp::request::ResolveCompletionItem>(completion_item)
660+ ) -> Option<impl Future<Output = Result<Value>>> {
661+ let capabilities = self.capabilities.get().unwrap();
662+
663+ // Return early if the server does not support resolving completion items.
664+ match capabilities.completion_provider {
665+ Some(lsp::CompletionOptions {
666+ resolve_provider: Some(true),
667+ ..
668+ }) => (),
669+ _ => return None,
670+ }
671+
672+ Some(self.call::<lsp::request::ResolveCompletionItem>(completion_item))
658673 }
659674
660675 pub fn text_document_signature_help(
@@ -665,7 +680,7 @@ impl Client {
665680 ) -> Option<impl Future<Output = Result<Value>>> {
666681 let capabilities = self.capabilities.get().unwrap();
667682
668− // Return early if signature help is not supported
683+ // Return early if the server does not support signature help.
669684 capabilities.signature_help_provider.as_ref()?;
670685
671686 let params = lsp::SignatureHelpParams {
@@ -686,7 +701,18 @@ impl Client {
686701 text_document: lsp::TextDocumentIdentifier,
687702 position: lsp::Position,
688703 work_done_token: Option<lsp::ProgressToken>,
689− ) -> impl Future<Output = Result<Value>> {
704+ ) -> Option<impl Future<Output = Result<Value>>> {
705+ let capabilities = self.capabilities.get().unwrap();
706+
707+ // Return early if the server does not support hover.
708+ match capabilities.hover_provider {
709+ Some(
710+ lsp::HoverProviderCapability::Simple(true)
711+ | lsp::HoverProviderCapability::Options(_),
712+ ) => (),
713+ _ => return None,
714+ }
715+
690716 let params = lsp::HoverParams {
691717 text_document_position_params: lsp::TextDocumentPositionParams {
692718 text_document,
@@ -696,7 +722,7 @@ impl Client {
696722 // lsp::SignatureHelpContext
697723 };
698724
699− self.call::<lsp::request::HoverRequest>(params)
725+ Some(self.call::<lsp::request::HoverRequest>(params))
700726 }
701727
702728 // formatting
@@ -709,13 +735,11 @@ impl Client {
709735 ) -> Option<impl Future<Output = Result<Vec<lsp::TextEdit>>>> {
710736 let capabilities = self.capabilities.get().unwrap();
711737
712− // check if we're able to format
738+ // Return early if the server does not support formatting.
713739 match capabilities.document_formatting_provider {
714− Some(lsp::OneOf::Left(true)) | Some(lsp::OneOf::Right(_)) => (),
715− // None | Some(false)
740+ Some(lsp::OneOf::Left(true) | lsp::OneOf::Right(_)) => (),
716741 _ => return None,
717742 };
718− // TODO: return err::unavailable so we can fall back to tree sitter formatting
719743
720744 // merge FormattingOptions with 'config.format'
721745 let config_format = self
@@ -750,22 +774,20 @@ impl Client {
750774 })
751775 }
752776
753− pub async fn text_document_range_formatting(
777+ pub fn text_document_range_formatting(
754778 &self,
755779 text_document: lsp::TextDocumentIdentifier,
756780 range: lsp::Range,
757781 options: lsp::FormattingOptions,
758782 work_done_token: Option<lsp::ProgressToken>,
759− ) -> anyhow::Result<Vec<lsp::TextEdit>> {
783+ ) -> Option<impl Future<Output = Result<Vec<lsp::TextEdit>>>> {
760784 let capabilities = self.capabilities.get().unwrap();
761785
762− // check if we're able to format
786+ // Return early if the server does not support range formatting.
763787 match capabilities.document_range_formatting_provider {
764− Some(lsp::OneOf::Left(true)) | Some(lsp::OneOf::Right(_)) => (),
765− // None | Some(false)
766− _ => return Ok(Vec::new()),
788+ Some(lsp::OneOf::Left(true) | lsp::OneOf::Right(_)) => (),
789+ _ => return None,
767790 };
768− // TODO: return err::unavailable so we can fall back to tree sitter formatting
769791
770792 let params = lsp::DocumentRangeFormattingParams {
771793 text_document,
@@ -774,11 +796,13 @@ impl Client {
774796 work_done_progress_params: lsp::WorkDoneProgressParams { work_done_token },
775797 };
776798
777− let response = self
778− .request::<lsp::request::RangeFormatting>(params)
779− .await?;
799+ let request = self.call::<lsp::request::RangeFormatting>(params);
780800
781− Ok(response.unwrap_or_default())
801+ Some(async move {
802+ let json = request.await?;
803+ let response: Option<Vec<lsp::TextEdit>> = serde_json::from_value(json)?;
804+ Ok(response.unwrap_or_default())
805+ })
782806 }
783807
784808 pub fn text_document_document_highlight(
@@ -786,7 +810,15 @@ impl Client {
786810 text_document: lsp::TextDocumentIdentifier,
787811 position: lsp::Position,
788812 work_done_token: Option<lsp::ProgressToken>,
789− ) -> impl Future<Output = Result<Value>> {
813+ ) -> Option<impl Future<Output = Result<Value>>> {
814+ let capabilities = self.capabilities.get().unwrap();
815+
816+ // Return early if the server does not support document highlight.
817+ match capabilities.document_highlight_provider {
818+ Some(lsp::OneOf::Left(true) | lsp::OneOf::Right(_)) => (),
819+ _ => return None,
820+ }
821+
790822 let params = lsp::DocumentHighlightParams {
791823 text_document_position_params: lsp::TextDocumentPositionParams {
792824 text_document,
@@ -798,7 +830,7 @@ impl Client {
798830 },
799831 };
800832
801− self.call::<lsp::request::DocumentHighlightRequest>(params)
833+ Some(self.call::<lsp::request::DocumentHighlightRequest>(params))
802834 }
803835
804836 fn goto_request<
@@ -831,8 +863,20 @@ impl Client {
831863 text_document: lsp::TextDocumentIdentifier,
832864 position: lsp::Position,
833865 work_done_token: Option<lsp::ProgressToken>,
834− ) -> impl Future<Output = Result<Value>> {
835− self.goto_request::<lsp::request::GotoDefinition>(text_document, position, work_done_token)
866+ ) -> Option<impl Future<Output = Result<Value>>> {
867+ let capabilities = self.capabilities.get().unwrap();
868+
869+ // Return early if the server does not support goto-definition.
870+ match capabilities.definition_provider {
871+ Some(lsp::OneOf::Left(true) | lsp::OneOf::Right(_)) => (),
872+ _ => return None,
873+ }
874+
875+ Some(self.goto_request::<lsp::request::GotoDefinition>(
876+ text_document,
877+ position,
878+ work_done_token,
879+ ))
836880 }
837881
838882 pub fn goto_type_definition(
@@ -840,12 +884,23 @@ impl Client {
840884 text_document: lsp::TextDocumentIdentifier,
841885 position: lsp::Position,
842886 work_done_token: Option<lsp::ProgressToken>,
843− ) -> impl Future<Output = Result<Value>> {
844− self.goto_request::<lsp::request::GotoTypeDefinition>(
887+ ) -> Option<impl Future<Output = Result<Value>>> {
888+ let capabilities = self.capabilities.get().unwrap();
889+
890+ // Return early if the server does not support goto-type-definition.
891+ match capabilities.type_definition_provider {
892+ Some(
893+ lsp::TypeDefinitionProviderCapability::Simple(true)
894+ | lsp::TypeDefinitionProviderCapability::Options(_),
895+ ) => (),
896+ _ => return None,
897+ }
898+
899+ Some(self.goto_request::<lsp::request::GotoTypeDefinition>(
845900 text_document,
846901 position,
847902 work_done_token,
848− )
903+ ))
849904 }
850905
851906 pub fn goto_implementation(
@@ -853,12 +908,23 @@ impl Client {
853908 text_document: lsp::TextDocumentIdentifier,
854909 position: lsp::Position,
855910 work_done_token: Option<lsp::ProgressToken>,
856− ) -> impl Future<Output = Result<Value>> {
857− self.goto_request::<lsp::request::GotoImplementation>(
911+ ) -> Option<impl Future<Output = Result<Value>>> {
912+ let capabilities = self.capabilities.get().unwrap();
913+
914+ // Return early if the server does not support goto-definition.
915+ match capabilities.implementation_provider {
916+ Some(
917+ lsp::ImplementationProviderCapability::Simple(true)
918+ | lsp::ImplementationProviderCapability::Options(_),
919+ ) => (),
920+ _ => return None,
921+ }
922+
923+ Some(self.goto_request::<lsp::request::GotoImplementation>(
858924 text_document,
859925 position,
860926 work_done_token,
861− )
927+ ))
862928 }
863929
864930 pub fn goto_reference(
@@ -866,7 +932,15 @@ impl Client {
866932 text_document: lsp::TextDocumentIdentifier,
867933 position: lsp::Position,
868934 work_done_token: Option<lsp::ProgressToken>,
869− ) -> impl Future<Output = Result<Value>> {
935+ ) -> Option<impl Future<Output = Result<Value>>> {
936+ let capabilities = self.capabilities.get().unwrap();
937+
938+ // Return early if the server does not support goto-reference.
939+ match capabilities.references_provider {
940+ Some(lsp::OneOf::Left(true) | lsp::OneOf::Right(_)) => (),
941+ _ => return None,
942+ }
943+
870944 let params = lsp::ReferenceParams {
871945 text_document_position: lsp::TextDocumentPositionParams {
872946 text_document,
@@ -881,31 +955,47 @@ impl Client {
881955 },
882956 };
883957
884− self.call::<lsp::request::References>(params)
958+ Some(self.call::<lsp::request::References>(params))
885959 }
886960
887961 pub fn document_symbols(
888962 &self,
889963 text_document: lsp::TextDocumentIdentifier,
890− ) -> impl Future<Output = Result<Value>> {
964+ ) -> Option<impl Future<Output = Result<Value>>> {
965+ let capabilities = self.capabilities.get().unwrap();
966+
967+ // Return early if the server does not support document symbols.
968+ match capabilities.document_symbol_provider {
969+ Some(lsp::OneOf::Left(true) | lsp::OneOf::Right(_)) => (),
970+ _ => return None,
971+ }
972+
891973 let params = lsp::DocumentSymbolParams {
892974 text_document,
893975 work_done_progress_params: lsp::WorkDoneProgressParams::default(),
894976 partial_result_params: lsp::PartialResultParams::default(),
895977 };
896978
897− self.call::<lsp::request::DocumentSymbolRequest>(params)
979+ Some(self.call::<lsp::request::DocumentSymbolRequest>(params))
898980 }
899981
900982 // empty string to get all symbols
901− pub fn workspace_symbols(&self, query: String) -> impl Future<Output = Result<Value>> {
983+ pub fn workspace_symbols(&self, query: String) -> Option<impl Future<Output = Result<Value>>> {
984+ let capabilities = self.capabilities.get().unwrap();
985+
986+ // Return early if the server does not support workspace symbols.
987+ match capabilities.workspace_symbol_provider {
988+ Some(lsp::OneOf::Left(true) | lsp::OneOf::Right(_)) => (),
989+ _ => return None,
990+ }
991+
902992 let params = lsp::WorkspaceSymbolParams {
903993 query,
904994 work_done_progress_params: lsp::WorkDoneProgressParams::default(),
905995 partial_result_params: lsp::PartialResultParams::default(),
906996 };
907997
908− self.call::<lsp::request::WorkspaceSymbol>(params)
998+ Some(self.call::<lsp::request::WorkspaceSymbol>(params))
909999 }
9101000
9111001 pub fn code_actions(
@@ -913,7 +1003,18 @@ impl Client {
9131003 text_document: lsp::TextDocumentIdentifier,
9141004 range: lsp::Range,
9151005 context: lsp::CodeActionContext,
916− ) -> impl Future<Output = Result<Value>> {
1006+ ) -> Option<impl Future<Output = Result<Value>>> {
1007+ let capabilities = self.capabilities.get().unwrap();
1008+
1009+ // Return early if the server does not support code actions.
1010+ match capabilities.code_action_provider {
1011+ Some(
1012+ lsp::CodeActionProviderCapability::Simple(true)
1013+ | lsp::CodeActionProviderCapability::Options(_),
1014+ ) => (),
1015+ _ => return None,
1016+ }
1017+
9171018 let params = lsp::CodeActionParams {
9181019 text_document,
9191020 range,
@@ -922,26 +1023,22 @@ impl Client {
9221023 partial_result_params: lsp::PartialResultParams::default(),
9231024 };
9241025
925− self.call::<lsp::request::CodeActionRequest>(params)
1026+ Some(self.call::<lsp::request::CodeActionRequest>(params))
9261027 }
9271028
928− pub async fn rename_symbol(
1029+ pub fn rename_symbol(
9291030 &self,
9301031 text_document: lsp::TextDocumentIdentifier,
9311032 position: lsp::Position,
9321033 new_name: String,
933− ) -> anyhow::Result<lsp::WorkspaceEdit> {
1034+ ) -> Option<impl Future<Output = Result<lsp::WorkspaceEdit>>> {
9341035 let capabilities = self.capabilities.get().unwrap();
9351036
936− // check if we're able to rename
1037+ // Return early if the language server does not support renaming.
9371038 match capabilities.rename_provider {
9381039 Some(lsp::OneOf::Left(true)) | Some(lsp::OneOf::Right(_)) => (),
9391040 // None | Some(false)
940− _ => {
941− log::warn!("rename_symbol failed: The server does not support rename");
942− let err = "The server does not support rename";
943− return Err(anyhow!(err));
944− }
1041+ _ => return None,
9451042 };
9461043
9471044 let params = lsp::RenameParams {
@@ -955,11 +1052,21 @@ impl Client {
9551052 },
9561053 };
9571054
958− let response = self.request::<lsp::request::Rename>(params).await?;
959− Ok(response.unwrap_or_default())
1055+ let request = self.call::<lsp::request::Rename>(params);
1056+
1057+ Some(async move {
1058+ let json = request.await?;
1059+ let response: Option<lsp::WorkspaceEdit> = serde_json::from_value(json)?;
1060+ Ok(response.unwrap_or_default())
1061+ })
9601062 }
9611063
962− pub fn command(&self, command: lsp::Command) -> impl Future<Output = Result<Value>> {
1064+ pub fn command(&self, command: lsp::Command) -> Option<impl Future<Output = Result<Value>>> {
1065+ let capabilities = self.capabilities.get().unwrap();
1066+
1067+ // Return early if the language server does not support executing commands.
1068+ capabilities.execute_command_provider.as_ref()?;
1069+
9631070 let params = lsp::ExecuteCommandParams {
9641071 command: command.command,
9651072 arguments: command.arguments.unwrap_or_default(),
@@ -968,6 +1075,6 @@ impl Client {
9681075 },
9691076 };
9701077
971− self.call::<lsp::request::ExecuteCommand>(params)
1078+ Some(self.call::<lsp::request::ExecuteCommand>(params))
9721079 }
9731080}