mirror of
https://github.com/denoland/deno.git
synced 2024-12-22 15:24:46 -05:00
feat(lsp): add type definition provider (#12789)
This commit is contained in:
parent
bf5657cd59
commit
210300d049
6 changed files with 150 additions and 2 deletions
|
@ -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,
|
||||
)),
|
||||
|
|
|
@ -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(¶ms.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(¶ms));
|
||||
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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -1266,6 +1266,66 @@ fn lsp_hover_typescript_types() {
|
|||
shutdown(&mut client);
|
||||
}
|
||||
|
||||
#[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");
|
||||
|
|
|
@ -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,
|
||||
|
|
7
cli/tsc/compiler.d.ts
vendored
7
cli/tsc/compiler.d.ts
vendored
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue