summaryrefslogtreecommitdiff
path: root/cli/lsp/tsc.rs
diff options
context:
space:
mode:
authorDavid Sherret <dsherret@users.noreply.github.com>2023-05-12 19:07:40 -0400
committerGitHub <noreply@github.com>2023-05-12 19:07:40 -0400
commit68c0fcb157bb47bbf58bcdcecf59d237fb84f201 (patch)
tree3c57e1c153412f18e8741e6b0af0a637389f9ea8 /cli/lsp/tsc.rs
parent7476ee34fadcefee630edbc564186155acebdf94 (diff)
refactor(lsp): make `RequestMethod` private (#19114)
Diffstat (limited to 'cli/lsp/tsc.rs')
-rw-r--r--cli/lsp/tsc.rs443
1 files changed, 412 insertions, 31 deletions
diff --git a/cli/lsp/tsc.rs b/cli/lsp/tsc.rs
index 92407bec1..bfbb5cf9a 100644
--- a/cli/lsp/tsc.rs
+++ b/cli/lsp/tsc.rs
@@ -1,5 +1,6 @@
// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
+use super::analysis::CodeActionData;
use super::code_lens;
use super::config;
use super::documents::AssetOrDocument;
@@ -53,6 +54,7 @@ use serde_repr::Serialize_repr;
use std::cmp;
use std::collections::HashMap;
use std::collections::HashSet;
+use std::ops::Range;
use std::path::Path;
use std::sync::Arc;
use std::thread;
@@ -118,7 +120,403 @@ impl TsServer {
Self(tx)
}
- pub async fn request<R>(
+ pub async fn get_diagnostics(
+ &self,
+ snapshot: Arc<StateSnapshot>,
+ specifiers: Vec<ModuleSpecifier>,
+ token: CancellationToken,
+ ) -> Result<HashMap<String, Vec<crate::tsc::Diagnostic>>, AnyError> {
+ let req = RequestMethod::GetDiagnostics(specifiers);
+ self.request_with_cancellation(snapshot, req, token).await
+ }
+
+ pub async fn find_references(
+ &self,
+ snapshot: Arc<StateSnapshot>,
+ specifier: ModuleSpecifier,
+ position: u32,
+ ) -> Result<Option<Vec<ReferencedSymbol>>, LspError> {
+ let req = RequestMethod::FindReferences {
+ specifier,
+ position,
+ };
+ self.request(snapshot, req).await.map_err(|err| {
+ log::error!("Unable to get references from TypeScript: {}", err);
+ LspError::internal_error()
+ })
+ }
+
+ pub async fn get_navigation_tree(
+ &self,
+ snapshot: Arc<StateSnapshot>,
+ specifier: ModuleSpecifier,
+ ) -> Result<NavigationTree, AnyError> {
+ self
+ .request(snapshot, RequestMethod::GetNavigationTree(specifier))
+ .await
+ }
+
+ pub async fn configure(
+ &self,
+ snapshot: Arc<StateSnapshot>,
+ tsconfig: TsConfig,
+ ) -> Result<bool, AnyError> {
+ self
+ .request(snapshot, RequestMethod::Configure(tsconfig))
+ .await
+ }
+
+ pub async fn get_supported_code_fixes(
+ &self,
+ snapshot: Arc<StateSnapshot>,
+ ) -> Result<Vec<String>, LspError> {
+ self
+ .request(snapshot, RequestMethod::GetSupportedCodeFixes)
+ .await
+ .map_err(|err| {
+ log::error!("Unable to get fixable diagnostics: {}", err);
+ LspError::internal_error()
+ })
+ }
+
+ pub async fn get_quick_info(
+ &self,
+ snapshot: Arc<StateSnapshot>,
+ specifier: ModuleSpecifier,
+ position: u32,
+ ) -> Result<Option<QuickInfo>, LspError> {
+ let req = RequestMethod::GetQuickInfo((specifier, position));
+ self.request(snapshot, req).await.map_err(|err| {
+ log::error!("Unable to get quick info: {}", err);
+ LspError::internal_error()
+ })
+ }
+
+ pub async fn get_code_fixes(
+ &self,
+ snapshot: Arc<StateSnapshot>,
+ specifier: ModuleSpecifier,
+ range: Range<u32>,
+ codes: Vec<String>,
+ ) -> Vec<CodeFixAction> {
+ let req =
+ RequestMethod::GetCodeFixes((specifier, range.start, range.end, codes));
+ match self.request(snapshot, req).await {
+ Ok(items) => items,
+ Err(err) => {
+ // sometimes tsc reports errors when retrieving code actions
+ // because they don't reflect the current state of the document
+ // so we will log them to the output, but we won't send an error
+ // message back to the client.
+ log::error!("Error getting actions from TypeScript: {}", err);
+ Vec::new()
+ }
+ }
+ }
+
+ pub async fn get_applicable_refactors(
+ &self,
+ snapshot: Arc<StateSnapshot>,
+ specifier: ModuleSpecifier,
+ range: Range<u32>,
+ only: String,
+ ) -> Result<Vec<ApplicableRefactorInfo>, LspError> {
+ let req = RequestMethod::GetApplicableRefactors((
+ specifier.clone(),
+ TextSpan {
+ start: range.start,
+ length: range.end - range.start,
+ },
+ only,
+ ));
+ self.request(snapshot, req).await.map_err(|err| {
+ log::error!("Failed to request to tsserver {}", err);
+ LspError::invalid_request()
+ })
+ }
+
+ pub async fn get_combined_code_fix(
+ &self,
+ snapshot: Arc<StateSnapshot>,
+ code_action_data: &CodeActionData,
+ ) -> Result<CombinedCodeActions, LspError> {
+ let req = RequestMethod::GetCombinedCodeFix((
+ code_action_data.specifier.clone(),
+ json!(code_action_data.fix_id.clone()),
+ ));
+ self.request(snapshot, req).await.map_err(|err| {
+ log::error!("Unable to get combined fix from TypeScript: {}", err);
+ LspError::internal_error()
+ })
+ }
+
+ pub async fn get_edits_for_refactor(
+ &self,
+ snapshot: Arc<StateSnapshot>,
+ specifier: ModuleSpecifier,
+ range: Range<u32>,
+ refactor_name: String,
+ action_name: String,
+ ) -> Result<RefactorEditInfo, LspError> {
+ let req = RequestMethod::GetEditsForRefactor((
+ specifier,
+ TextSpan {
+ start: range.start,
+ length: range.end - range.start,
+ },
+ refactor_name,
+ action_name,
+ ));
+ self.request(snapshot, req).await.map_err(|err| {
+ log::error!("Failed to request to tsserver {}", err);
+ LspError::invalid_request()
+ })
+ }
+
+ pub async fn get_document_highlights(
+ &self,
+ snapshot: Arc<StateSnapshot>,
+ specifier: ModuleSpecifier,
+ position: u32,
+ files_to_search: Vec<ModuleSpecifier>,
+ ) -> Result<Option<Vec<DocumentHighlights>>, LspError> {
+ let req = RequestMethod::GetDocumentHighlights((
+ specifier,
+ position,
+ files_to_search,
+ ));
+ self.request(snapshot, req).await.map_err(|err| {
+ log::error!("Unable to get document highlights from TypeScript: {}", err);
+ LspError::internal_error()
+ })
+ }
+
+ pub async fn get_definition(
+ &self,
+ snapshot: Arc<StateSnapshot>,
+ specifier: ModuleSpecifier,
+ position: u32,
+ ) -> Result<Option<DefinitionInfoAndBoundSpan>, LspError> {
+ let req = RequestMethod::GetDefinition((specifier, position));
+ self.request(snapshot, req).await.map_err(|err| {
+ log::error!("Unable to get definition from TypeScript: {}", err);
+ LspError::internal_error()
+ })
+ }
+
+ pub async fn get_type_definition(
+ &self,
+ snapshot: Arc<StateSnapshot>,
+ specifier: ModuleSpecifier,
+ position: u32,
+ ) -> Result<Option<Vec<DefinitionInfo>>, LspError> {
+ let req = RequestMethod::GetTypeDefinition {
+ specifier,
+ position,
+ };
+ self.request(snapshot, req).await.map_err(|err| {
+ log::error!("Unable to get type definition from TypeScript: {}", err);
+ LspError::internal_error()
+ })
+ }
+
+ pub async fn get_completions(
+ &self,
+ snapshot: Arc<StateSnapshot>,
+ specifier: ModuleSpecifier,
+ position: u32,
+ options: GetCompletionsAtPositionOptions,
+ ) -> Option<CompletionInfo> {
+ let req = RequestMethod::GetCompletions((specifier, position, options));
+ match self.request(snapshot, req).await {
+ Ok(maybe_info) => maybe_info,
+ Err(err) => {
+ log::error!("Unable to get completion info from TypeScript: {:#}", err);
+ None
+ }
+ }
+ }
+
+ pub async fn get_completion_details(
+ &self,
+ snapshot: Arc<StateSnapshot>,
+ args: GetCompletionDetailsArgs,
+ ) -> Result<Option<CompletionEntryDetails>, AnyError> {
+ let req = RequestMethod::GetCompletionDetails(args);
+ self.request(snapshot, req).await
+ }
+
+ pub async fn get_implementations(
+ &self,
+ snapshot: Arc<StateSnapshot>,
+ specifier: ModuleSpecifier,
+ position: u32,
+ ) -> Result<Option<Vec<ImplementationLocation>>, LspError> {
+ let req = RequestMethod::GetImplementation((specifier, position));
+ self.request(snapshot, req).await.map_err(|err| {
+ log::error!("Failed to request to tsserver {}", err);
+ LspError::invalid_request()
+ })
+ }
+
+ pub async fn get_outlining_spans(
+ &self,
+ snapshot: Arc<StateSnapshot>,
+ specifier: ModuleSpecifier,
+ ) -> Result<Vec<OutliningSpan>, LspError> {
+ let req = RequestMethod::GetOutliningSpans(specifier);
+ self.request(snapshot, req).await.map_err(|err| {
+ log::error!("Failed to request to tsserver {}", err);
+ LspError::invalid_request()
+ })
+ }
+
+ pub async fn provide_call_hierarchy_incoming_calls(
+ &self,
+ snapshot: Arc<StateSnapshot>,
+ specifier: ModuleSpecifier,
+ position: u32,
+ ) -> Result<Vec<CallHierarchyIncomingCall>, LspError> {
+ let req =
+ RequestMethod::ProvideCallHierarchyIncomingCalls((specifier, position));
+ self.request(snapshot, req).await.map_err(|err| {
+ log::error!("Failed to request to tsserver {}", err);
+ LspError::invalid_request()
+ })
+ }
+
+ pub async fn provide_call_hierarchy_outgoing_calls(
+ &self,
+ snapshot: Arc<StateSnapshot>,
+ specifier: ModuleSpecifier,
+ position: u32,
+ ) -> Result<Vec<CallHierarchyOutgoingCall>, LspError> {
+ let req =
+ RequestMethod::ProvideCallHierarchyOutgoingCalls((specifier, position));
+ self.request(snapshot, req).await.map_err(|err| {
+ log::error!("Failed to request to tsserver {}", err);
+ LspError::invalid_request()
+ })
+ }
+
+ pub async fn prepare_call_hierarchy(
+ &self,
+ snapshot: Arc<StateSnapshot>,
+ specifier: ModuleSpecifier,
+ position: u32,
+ ) -> Result<Option<OneOrMany<CallHierarchyItem>>, LspError> {
+ let req = RequestMethod::PrepareCallHierarchy((specifier, position));
+ self.request(snapshot, req).await.map_err(|err| {
+ log::error!("Failed to request to tsserver {}", err);
+ LspError::invalid_request()
+ })
+ }
+
+ pub async fn find_rename_locations(
+ &self,
+ snapshot: Arc<StateSnapshot>,
+ specifier: ModuleSpecifier,
+ position: u32,
+ ) -> Result<Option<Vec<RenameLocation>>, LspError> {
+ let req = RequestMethod::FindRenameLocations {
+ specifier,
+ position,
+ find_in_strings: false,
+ find_in_comments: false,
+ provide_prefix_and_suffix_text_for_rename: false,
+ };
+ self.request(snapshot, req).await.map_err(|err| {
+ log::error!("Failed to request to tsserver {}", err);
+ LspError::invalid_request()
+ })
+ }
+
+ pub async fn get_smart_selection_range(
+ &self,
+ snapshot: Arc<StateSnapshot>,
+ specifier: ModuleSpecifier,
+ position: u32,
+ ) -> Result<SelectionRange, LspError> {
+ let req = RequestMethod::GetSmartSelectionRange((specifier, position));
+
+ self.request(snapshot, req).await.map_err(|err| {
+ log::error!("Failed to request to tsserver {}", err);
+ LspError::invalid_request()
+ })
+ }
+
+ pub async fn get_encoded_semantic_classifications(
+ &self,
+ snapshot: Arc<StateSnapshot>,
+ specifier: ModuleSpecifier,
+ range: Range<u32>,
+ ) -> Result<Classifications, LspError> {
+ let req = RequestMethod::GetEncodedSemanticClassifications((
+ specifier,
+ TextSpan {
+ start: range.start,
+ length: range.end - range.start,
+ },
+ ));
+ self.request(snapshot, req).await.map_err(|err| {
+ log::error!("Failed to request to tsserver {}", err);
+ LspError::invalid_request()
+ })
+ }
+
+ pub async fn get_signature_help_items(
+ &self,
+ snapshot: Arc<StateSnapshot>,
+ specifier: ModuleSpecifier,
+ position: u32,
+ options: SignatureHelpItemsOptions,
+ ) -> Result<Option<SignatureHelpItems>, LspError> {
+ let req =
+ RequestMethod::GetSignatureHelpItems((specifier, position, options));
+ self.request(snapshot, req).await.map_err(|err| {
+ log::error!("Failed to request to tsserver: {}", err);
+ LspError::invalid_request()
+ })
+ }
+
+ pub async fn get_navigate_to_items(
+ &self,
+ snapshot: Arc<StateSnapshot>,
+ args: GetNavigateToItemsArgs,
+ ) -> Result<Vec<NavigateToItem>, LspError> {
+ let req = RequestMethod::GetNavigateToItems(args);
+ self.request(snapshot, req).await.map_err(|err| {
+ log::error!("Failed request to tsserver: {}", err);
+ LspError::invalid_request()
+ })
+ }
+
+ pub async fn provide_inlay_hints(
+ &self,
+ snapshot: Arc<StateSnapshot>,
+ specifier: ModuleSpecifier,
+ text_span: TextSpan,
+ user_preferences: UserPreferences,
+ ) -> Result<Option<Vec<InlayHint>>, LspError> {
+ let req = RequestMethod::ProvideInlayHints((
+ specifier,
+ text_span,
+ user_preferences,
+ ));
+ self.request(snapshot, req).await.map_err(|err| {
+ log::error!("Unable to get inlay hints: {}", err);
+ LspError::internal_error()
+ })
+ }
+
+ pub async fn restart(&self, snapshot: Arc<StateSnapshot>) {
+ let _: bool = self
+ .request(snapshot, RequestMethod::Restart)
+ .await
+ .unwrap();
+ }
+
+ async fn request<R>(
&self,
snapshot: Arc<StateSnapshot>,
req: RequestMethod,
@@ -131,7 +529,7 @@ impl TsServer {
.await
}
- pub async fn request_with_cancellation<R>(
+ async fn request_with_cancellation<R>(
&self,
snapshot: Arc<StateSnapshot>,
req: RequestMethod,
@@ -147,26 +545,6 @@ impl TsServer {
let value = rx.await??;
Ok(serde_json::from_value::<R>(value)?)
}
-
- // todo(dsherret): refactor the rest of the request methods to have
- // methods to call on this struct, then make `RequestMethod` and
- // friends internal
-
- pub async fn find_references(
- &self,
- snapshot: Arc<StateSnapshot>,
- specifier: &ModuleSpecifier,
- position: u32,
- ) -> Result<Option<Vec<ReferencedSymbol>>, LspError> {
- let req = RequestMethod::FindReferences {
- specifier: specifier.clone(),
- position,
- };
- self.request(snapshot, req).await.map_err(|err| {
- log::error!("Unable to get references from TypeScript: {}", err);
- LspError::internal_error()
- })
- }
}
#[derive(Debug, Clone)]
@@ -3161,9 +3539,16 @@ impl From<&CompletionItemData> for GetCompletionDetailsArgs {
}
}
+#[derive(Debug)]
+pub struct GetNavigateToItemsArgs {
+ pub search: String,
+ pub max_result_count: Option<u32>,
+ pub file: Option<String>,
+}
+
/// Methods that are supported by the Language Service in the compiler isolate.
#[derive(Debug)]
-pub enum RequestMethod {
+enum RequestMethod {
/// Configure the compilation settings for the server.
Configure(TsConfig),
/// Get rename locations at a given position.
@@ -3198,11 +3583,7 @@ pub enum RequestMethod {
/// Get implementation information for a specific position.
GetImplementation((ModuleSpecifier, u32)),
/// Get "navigate to" items, which are converted to workspace symbols
- GetNavigateToItems {
- search: String,
- max_result_count: Option<u32>,
- file: Option<String>,
- },
+ GetNavigateToItems(GetNavigateToItemsArgs),
/// Get a "navigation tree" for a specifier.
GetNavigationTree(ModuleSpecifier),
/// Get outlining spans for a specifier.
@@ -3356,11 +3737,11 @@ impl RequestMethod {
"specifier": state.denormalize_specifier(specifier),
"position": position,
}),
- RequestMethod::GetNavigateToItems {
+ RequestMethod::GetNavigateToItems(GetNavigateToItemsArgs {
search,
max_result_count,
file,
- } => json!({
+ }) => json!({
"id": id,
"method": "getNavigateToItems",
"search": search,
@@ -3470,7 +3851,7 @@ impl RequestMethod {
}
/// Send a request into a runtime and return the JSON value of the response.
-pub fn request(
+fn request(
runtime: &mut JsRuntime,
state_snapshot: Arc<StateSnapshot>,
method: RequestMethod,