mirror of
https://github.com/denoland/deno.git
synced 2025-09-26 20:29:11 +00:00
parent
b233985fea
commit
77cfadf532
7 changed files with 240 additions and 1 deletions
|
@ -15,6 +15,7 @@ use lspower::lsp::HoverProviderCapability;
|
||||||
use lspower::lsp::ImplementationProviderCapability;
|
use lspower::lsp::ImplementationProviderCapability;
|
||||||
use lspower::lsp::OneOf;
|
use lspower::lsp::OneOf;
|
||||||
use lspower::lsp::SaveOptions;
|
use lspower::lsp::SaveOptions;
|
||||||
|
use lspower::lsp::SelectionRangeProviderCapability;
|
||||||
use lspower::lsp::ServerCapabilities;
|
use lspower::lsp::ServerCapabilities;
|
||||||
use lspower::lsp::SignatureHelpOptions;
|
use lspower::lsp::SignatureHelpOptions;
|
||||||
use lspower::lsp::TextDocumentSyncCapability;
|
use lspower::lsp::TextDocumentSyncCapability;
|
||||||
|
@ -104,7 +105,9 @@ pub fn server_capabilities(
|
||||||
document_formatting_provider: Some(OneOf::Left(true)),
|
document_formatting_provider: Some(OneOf::Left(true)),
|
||||||
document_range_formatting_provider: None,
|
document_range_formatting_provider: None,
|
||||||
document_on_type_formatting_provider: None,
|
document_on_type_formatting_provider: None,
|
||||||
selection_range_provider: None,
|
selection_range_provider: Some(SelectionRangeProviderCapability::Simple(
|
||||||
|
true,
|
||||||
|
)),
|
||||||
folding_range_provider: None,
|
folding_range_provider: None,
|
||||||
rename_provider: Some(OneOf::Left(true)),
|
rename_provider: Some(OneOf::Left(true)),
|
||||||
document_link_provider: None,
|
document_link_provider: None,
|
||||||
|
|
|
@ -1590,6 +1590,48 @@ impl Inner {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn selection_range(
|
||||||
|
&self,
|
||||||
|
params: SelectionRangeParams,
|
||||||
|
) -> LspResult<Option<Vec<SelectionRange>>> {
|
||||||
|
if !self.enabled() {
|
||||||
|
return Ok(None);
|
||||||
|
}
|
||||||
|
let mark = self.performance.mark("selection_range");
|
||||||
|
let specifier = self.url_map.normalize_url(¶ms.text_document.uri);
|
||||||
|
|
||||||
|
let line_index =
|
||||||
|
if let Some(line_index) = self.get_line_index_sync(&specifier) {
|
||||||
|
line_index
|
||||||
|
} else {
|
||||||
|
return Err(LspError::invalid_params(format!(
|
||||||
|
"An unexpected specifier ({}) was provided.",
|
||||||
|
specifier
|
||||||
|
)));
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut selection_ranges = Vec::<SelectionRange>::new();
|
||||||
|
for position in params.positions {
|
||||||
|
let req = tsc::RequestMethod::GetSmartSelectionRange((
|
||||||
|
specifier.clone(),
|
||||||
|
line_index.offset_tsc(position)?,
|
||||||
|
));
|
||||||
|
|
||||||
|
let selection_range: tsc::SelectionRange = self
|
||||||
|
.ts_server
|
||||||
|
.request(self.snapshot(), req)
|
||||||
|
.await
|
||||||
|
.map_err(|err| {
|
||||||
|
error!("Failed to request to tsserver {}", err);
|
||||||
|
LspError::invalid_request()
|
||||||
|
})?;
|
||||||
|
|
||||||
|
selection_ranges.push(selection_range.to_selection_range(&line_index));
|
||||||
|
}
|
||||||
|
self.performance.measure(mark);
|
||||||
|
Ok(Some(selection_ranges))
|
||||||
|
}
|
||||||
|
|
||||||
async fn signature_help(
|
async fn signature_help(
|
||||||
&self,
|
&self,
|
||||||
params: SignatureHelpParams,
|
params: SignatureHelpParams,
|
||||||
|
@ -1794,6 +1836,13 @@ impl lspower::LanguageServer for LanguageServer {
|
||||||
self.0.lock().await.request_else(method, params).await
|
self.0.lock().await.request_else(method, params).await
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn selection_range(
|
||||||
|
&self,
|
||||||
|
params: SelectionRangeParams,
|
||||||
|
) -> LspResult<Option<Vec<SelectionRange>>> {
|
||||||
|
self.0.lock().await.selection_range(params).await
|
||||||
|
}
|
||||||
|
|
||||||
async fn signature_help(
|
async fn signature_help(
|
||||||
&self,
|
&self,
|
||||||
params: SignatureHelpParams,
|
params: SignatureHelpParams,
|
||||||
|
@ -2411,6 +2460,114 @@ mod tests {
|
||||||
harness.run().await;
|
harness.run().await;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn test_selection_range() {
|
||||||
|
let mut harness = LspTestHarness::new(vec![
|
||||||
|
("initialize_request.json", LspResponse::RequestAny),
|
||||||
|
("initialized_notification.json", LspResponse::None),
|
||||||
|
(
|
||||||
|
"selection_range_did_open_notification.json",
|
||||||
|
LspResponse::None,
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"selection_range_request.json",
|
||||||
|
LspResponse::Request(
|
||||||
|
2,
|
||||||
|
json!([{
|
||||||
|
"range": {
|
||||||
|
"start": {
|
||||||
|
"line": 2,
|
||||||
|
"character": 8
|
||||||
|
},
|
||||||
|
"end": {
|
||||||
|
"line": 2,
|
||||||
|
"character": 9
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"parent": {
|
||||||
|
"range": {
|
||||||
|
"start": {
|
||||||
|
"line": 2,
|
||||||
|
"character": 8
|
||||||
|
},
|
||||||
|
"end": {
|
||||||
|
"line": 2,
|
||||||
|
"character": 15
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"parent": {
|
||||||
|
"range": {
|
||||||
|
"start": {
|
||||||
|
"line": 2,
|
||||||
|
"character": 4
|
||||||
|
},
|
||||||
|
"end": {
|
||||||
|
"line": 4,
|
||||||
|
"character": 5
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"parent": {
|
||||||
|
"range": {
|
||||||
|
"start": {
|
||||||
|
"line": 1,
|
||||||
|
"character": 13
|
||||||
|
},
|
||||||
|
"end": {
|
||||||
|
"line": 6,
|
||||||
|
"character": 2
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"parent": {
|
||||||
|
"range": {
|
||||||
|
"start": {
|
||||||
|
"line": 1,
|
||||||
|
"character": 2
|
||||||
|
},
|
||||||
|
"end": {
|
||||||
|
"line": 6,
|
||||||
|
"character": 3
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"parent": {
|
||||||
|
"range": {
|
||||||
|
"start": {
|
||||||
|
"line": 0,
|
||||||
|
"character": 11
|
||||||
|
},
|
||||||
|
"end": {
|
||||||
|
"line": 7,
|
||||||
|
"character": 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"parent": {
|
||||||
|
"range": {
|
||||||
|
"start": {
|
||||||
|
"line": 0,
|
||||||
|
"character": 0
|
||||||
|
},
|
||||||
|
"end": {
|
||||||
|
"line": 7,
|
||||||
|
"character": 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}]),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"shutdown_request.json",
|
||||||
|
LspResponse::Request(3, json!(null)),
|
||||||
|
),
|
||||||
|
("exit_notification.json", LspResponse::None),
|
||||||
|
]);
|
||||||
|
harness.run().await;
|
||||||
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_code_lens_request() {
|
async fn test_code_lens_request() {
|
||||||
let mut harness = LspTestHarness::new(vec![
|
let mut harness = LspTestHarness::new(vec![
|
||||||
|
|
|
@ -1311,6 +1311,31 @@ impl SignatureHelpParameter {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Deserialize)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
pub struct SelectionRange {
|
||||||
|
text_span: TextSpan,
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
parent: Option<Box<SelectionRange>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SelectionRange {
|
||||||
|
pub fn to_selection_range(
|
||||||
|
&self,
|
||||||
|
line_index: &LineIndex,
|
||||||
|
) -> lsp::SelectionRange {
|
||||||
|
lsp::SelectionRange {
|
||||||
|
range: self.text_span.to_range(line_index),
|
||||||
|
parent: match &self.parent {
|
||||||
|
Some(parent_selection) => {
|
||||||
|
Some(Box::new(parent_selection.to_selection_range(line_index)))
|
||||||
|
}
|
||||||
|
None => None,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Deserialize)]
|
#[derive(Debug, Clone, Deserialize)]
|
||||||
struct Response {
|
struct Response {
|
||||||
id: usize,
|
id: usize,
|
||||||
|
@ -1856,6 +1881,8 @@ pub enum RequestMethod {
|
||||||
GetReferences((ModuleSpecifier, u32)),
|
GetReferences((ModuleSpecifier, u32)),
|
||||||
/// Get signature help items for a specific position.
|
/// Get signature help items for a specific position.
|
||||||
GetSignatureHelpItems((ModuleSpecifier, u32, SignatureHelpItemsOptions)),
|
GetSignatureHelpItems((ModuleSpecifier, u32, SignatureHelpItemsOptions)),
|
||||||
|
/// Get a selection range for a specific position.
|
||||||
|
GetSmartSelectionRange((ModuleSpecifier, u32)),
|
||||||
/// Get the diagnostic codes that support some form of code fix.
|
/// Get the diagnostic codes that support some form of code fix.
|
||||||
GetSupportedCodeFixes,
|
GetSupportedCodeFixes,
|
||||||
}
|
}
|
||||||
|
@ -1977,6 +2004,14 @@ impl RequestMethod {
|
||||||
"options": options,
|
"options": options,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
RequestMethod::GetSmartSelectionRange((specifier, position)) => {
|
||||||
|
json!({
|
||||||
|
"id": id,
|
||||||
|
"method": "getSmartSelectionRange",
|
||||||
|
"specifier": specifier,
|
||||||
|
"position": position
|
||||||
|
})
|
||||||
|
}
|
||||||
RequestMethod::GetSupportedCodeFixes => json!({
|
RequestMethod::GetSupportedCodeFixes => json!({
|
||||||
"id": id,
|
"id": id,
|
||||||
"method": "getSupportedCodeFixes",
|
"method": "getSupportedCodeFixes",
|
||||||
|
|
12
cli/tests/lsp/selection_range_did_open_notification.json
Normal file
12
cli/tests/lsp/selection_range_did_open_notification.json
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
{
|
||||||
|
"jsonrpc": "2.0",
|
||||||
|
"method": "textDocument/didOpen",
|
||||||
|
"params": {
|
||||||
|
"textDocument": {
|
||||||
|
"uri": "file:///a/file.ts",
|
||||||
|
"languageId": "typescript",
|
||||||
|
"version": 1,
|
||||||
|
"text": "class Foo {\n bar(a, b) {\n if (a === b) {\n return true;\n }\n return false;\n }\n}"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
16
cli/tests/lsp/selection_range_request.json
Normal file
16
cli/tests/lsp/selection_range_request.json
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
{
|
||||||
|
"jsonrpc": "2.0",
|
||||||
|
"id": 2,
|
||||||
|
"method": "textDocument/selectionRange",
|
||||||
|
"params": {
|
||||||
|
"textDocument": {
|
||||||
|
"uri": "file:///a/file.ts"
|
||||||
|
},
|
||||||
|
"positions": [
|
||||||
|
{
|
||||||
|
"line": 2,
|
||||||
|
"character": 8
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
|
@ -703,6 +703,15 @@ delete Object.prototype.__proto__;
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
case "getSmartSelectionRange": {
|
||||||
|
return respond(
|
||||||
|
id,
|
||||||
|
languageService.getSmartSelectionRange(
|
||||||
|
request.specifier,
|
||||||
|
request.position,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
case "getSupportedCodeFixes": {
|
case "getSupportedCodeFixes": {
|
||||||
return respond(
|
return respond(
|
||||||
id,
|
id,
|
||||||
|
|
7
cli/tsc/compiler.d.ts
vendored
7
cli/tsc/compiler.d.ts
vendored
|
@ -61,6 +61,7 @@ declare global {
|
||||||
| GetQuickInfoRequest
|
| GetQuickInfoRequest
|
||||||
| GetReferencesRequest
|
| GetReferencesRequest
|
||||||
| GetSignatureHelpItemsRequest
|
| GetSignatureHelpItemsRequest
|
||||||
|
| GetSmartSelectionRange
|
||||||
| GetSupportedCodeFixes;
|
| GetSupportedCodeFixes;
|
||||||
|
|
||||||
interface BaseLanguageServerRequest {
|
interface BaseLanguageServerRequest {
|
||||||
|
@ -169,6 +170,12 @@ declare global {
|
||||||
options: ts.SignatureHelpItemsOptions;
|
options: ts.SignatureHelpItemsOptions;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface GetSmartSelectionRange extends BaseLanguageServerRequest {
|
||||||
|
method: "getSmartSelectionRange";
|
||||||
|
specifier: string;
|
||||||
|
position: number;
|
||||||
|
}
|
||||||
|
|
||||||
interface GetSupportedCodeFixes extends BaseLanguageServerRequest {
|
interface GetSupportedCodeFixes extends BaseLanguageServerRequest {
|
||||||
method: "getSupportedCodeFixes";
|
method: "getSupportedCodeFixes";
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue