summaryrefslogtreecommitdiff
path: root/cli
diff options
context:
space:
mode:
Diffstat (limited to 'cli')
-rw-r--r--cli/lsp/capabilities.rs5
-rw-r--r--cli/lsp/language_server.rs55
-rw-r--r--cli/lsp/tsc.rs16
-rw-r--r--cli/tests/integration/lsp_tests.rs60
-rw-r--r--cli/tsc/99_main_compiler.js9
-rw-r--r--cli/tsc/compiler.d.ts7
6 files changed, 150 insertions, 2 deletions
diff --git a/cli/lsp/capabilities.rs b/cli/lsp/capabilities.rs
index e05cc27b8..8f17a6aff 100644
--- a/cli/lsp/capabilities.rs
+++ b/cli/lsp/capabilities.rs
@@ -27,6 +27,7 @@ use lspower::lsp::SignatureHelpOptions;
use lspower::lsp::TextDocumentSyncCapability;
use lspower::lsp::TextDocumentSyncKind;
use lspower::lsp::TextDocumentSyncOptions;
+use lspower::lsp::TypeDefinitionProviderCapability;
use lspower::lsp::WorkDoneProgressOptions;
use lspower::lsp::WorkspaceFoldersServerCapabilities;
use lspower::lsp::WorkspaceServerCapabilities;
@@ -109,7 +110,9 @@ pub fn server_capabilities(
}),
declaration_provider: None,
definition_provider: Some(OneOf::Left(true)),
- type_definition_provider: None,
+ type_definition_provider: Some(TypeDefinitionProviderCapability::Simple(
+ true,
+ )),
implementation_provider: Some(ImplementationProviderCapability::Simple(
true,
)),
diff --git a/cli/lsp/language_server.rs b/cli/lsp/language_server.rs
index fb2b04214..a0d0ee0ad 100644
--- a/cli/lsp/language_server.rs
+++ b/cli/lsp/language_server.rs
@@ -1622,6 +1622,54 @@ impl Inner {
}
}
+ async fn goto_type_definition(
+ &mut self,
+ params: GotoTypeDefinitionParams,
+ ) -> LspResult<Option<GotoTypeDefinitionResponse>> {
+ let specifier = self
+ .url_map
+ .normalize_url(&params.text_document_position_params.text_document.uri);
+ if !self.is_diagnosable(&specifier)
+ || !self.config.specifier_enabled(&specifier)
+ {
+ return Ok(None);
+ }
+
+ let mark = self.performance.mark("goto_definition", Some(&params));
+ let asset_or_doc = self.get_cached_asset_or_document(&specifier)?;
+ let line_index = asset_or_doc.line_index();
+ let req = tsc::RequestMethod::GetTypeDefinition {
+ specifier,
+ position: line_index
+ .offset_tsc(params.text_document_position_params.position)?,
+ };
+ let maybe_definition_info: Option<Vec<tsc::DefinitionInfo>> = self
+ .ts_server
+ .request(self.snapshot()?, req)
+ .await
+ .map_err(|err| {
+ error!("Unable to get type definition from TypeScript: {}", err);
+ LspError::internal_error()
+ })?;
+
+ let response = if let Some(definition_info) = maybe_definition_info {
+ let mut location_links = Vec::new();
+ for info in definition_info {
+ if let Some(link) =
+ info.document_span.to_link(line_index.clone(), self).await
+ {
+ location_links.push(link);
+ }
+ }
+ Some(GotoTypeDefinitionResponse::Link(location_links))
+ } else {
+ None
+ };
+
+ self.performance.measure(mark);
+ Ok(response)
+ }
+
async fn completion(
&mut self,
params: CompletionParams,
@@ -2428,6 +2476,13 @@ impl lspower::LanguageServer for LanguageServer {
self.0.lock().await.goto_definition(params).await
}
+ async fn goto_type_definition(
+ &self,
+ params: GotoTypeDefinitionParams,
+ ) -> LspResult<Option<GotoTypeDefinitionResponse>> {
+ self.0.lock().await.goto_type_definition(params).await
+ }
+
async fn completion(
&self,
params: CompletionParams,
diff --git a/cli/lsp/tsc.rs b/cli/lsp/tsc.rs
index e56b7ab68..9647a79fc 100644
--- a/cli/lsp/tsc.rs
+++ b/cli/lsp/tsc.rs
@@ -2769,6 +2769,11 @@ pub enum RequestMethod {
GetSmartSelectionRange((ModuleSpecifier, u32)),
/// Get the diagnostic codes that support some form of code fix.
GetSupportedCodeFixes,
+ /// Get the type definition information for a specific position.
+ GetTypeDefinition {
+ specifier: ModuleSpecifier,
+ position: u32,
+ },
/// Resolve a call hierarchy item for a specific position.
PrepareCallHierarchy((ModuleSpecifier, u32)),
/// Resolve incoming call hierarchy items for a specific position.
@@ -2811,7 +2816,7 @@ impl RequestMethod {
"id": id,
"method": "getApplicableRefactors",
"specifier": state.denormalize_specifier(specifier),
- "range": { "pos": span.start, "end": span.start + span.length},
+ "range": { "pos": span.start, "end": span.start + span.length },
"kind": kind,
}),
RequestMethod::GetEditsForRefactor((
@@ -2950,6 +2955,15 @@ impl RequestMethod {
"id": id,
"method": "getSupportedCodeFixes",
}),
+ RequestMethod::GetTypeDefinition {
+ specifier,
+ position,
+ } => json!({
+ "id": id,
+ "method": "getTypeDefinition",
+ "specifier": state.denormalize_specifier(specifier),
+ "position": position
+ }),
RequestMethod::PrepareCallHierarchy((specifier, position)) => {
json!({
"id": id,
diff --git a/cli/tests/integration/lsp_tests.rs b/cli/tests/integration/lsp_tests.rs
index 8e7de0286..3d55ac28c 100644
--- a/cli/tests/integration/lsp_tests.rs
+++ b/cli/tests/integration/lsp_tests.rs
@@ -1267,6 +1267,66 @@ fn lsp_hover_typescript_types() {
}
#[test]
+fn lsp_goto_type_definition() {
+ let mut client = init("initialize_params.json");
+ did_open(
+ &mut client,
+ json!({
+ "textDocument": {
+ "uri": "file:///a/file.ts",
+ "languageId": "typescript",
+ "version": 1,
+ "text": "interface A {\n a: string;\n}\n\nexport class B implements A {\n a = \"a\";\n log() {\n console.log(this.a);\n }\n}\n\nconst b = new B();\nb;\n",
+ }
+ }),
+ );
+ let (maybe_res, maybe_error) = client
+ .write_request::<_, _, Value>(
+ "textDocument/typeDefinition",
+ json!({
+ "textDocument": {
+ "uri": "file:///a/file.ts"
+ },
+ "position": {
+ "line": 12,
+ "character": 1
+ }
+ }),
+ )
+ .unwrap();
+ assert!(maybe_error.is_none());
+ assert_eq!(
+ maybe_res,
+ Some(json!([
+ {
+ "targetUri": "file:///a/file.ts",
+ "targetRange": {
+ "start": {
+ "line": 4,
+ "character": 0
+ },
+ "end": {
+ "line": 9,
+ "character": 1
+ }
+ },
+ "targetSelectionRange": {
+ "start": {
+ "line": 4,
+ "character": 13
+ },
+ "end": {
+ "line": 4,
+ "character": 14
+ }
+ }
+ }
+ ]))
+ );
+ shutdown(&mut client);
+}
+
+#[test]
fn lsp_call_hierarchy() {
let mut client = init("initialize_params.json");
did_open(
diff --git a/cli/tsc/99_main_compiler.js b/cli/tsc/99_main_compiler.js
index 1b3999bf9..d309956cb 100644
--- a/cli/tsc/99_main_compiler.js
+++ b/cli/tsc/99_main_compiler.js
@@ -810,6 +810,15 @@ delete Object.prototype.__proto__;
ts.getSupportedCodeFixes(),
);
}
+ case "getTypeDefinition": {
+ return respond(
+ id,
+ languageService.getTypeDefinitionAtPosition(
+ request.specifier,
+ request.position,
+ ),
+ );
+ }
case "prepareCallHierarchy": {
return respond(
id,
diff --git a/cli/tsc/compiler.d.ts b/cli/tsc/compiler.d.ts
index 8e6b6d417..d206c0b6b 100644
--- a/cli/tsc/compiler.d.ts
+++ b/cli/tsc/compiler.d.ts
@@ -66,6 +66,7 @@ declare global {
| GetSignatureHelpItemsRequest
| GetSmartSelectionRange
| GetSupportedCodeFixes
+ | GetTypeDefinitionRequest
| PrepareCallHierarchy
| ProvideCallHierarchyIncomingCalls
| ProvideCallHierarchyOutgoingCalls;
@@ -220,6 +221,12 @@ declare global {
method: "getSupportedCodeFixes";
}
+ interface GetTypeDefinitionRequest extends BaseLanguageServerRequest {
+ method: "getTypeDefinition";
+ specifier: string;
+ position: number;
+ }
+
interface PrepareCallHierarchy extends BaseLanguageServerRequest {
method: "prepareCallHierarchy";
specifier: string;