mirror of
https://github.com/denoland/deno.git
synced 2024-11-24 15:19:26 -05:00
parent
97dc2918fd
commit
424c086a2b
7 changed files with 240 additions and 1 deletions
|
@ -15,6 +15,7 @@ use lspower::lsp::HoverProviderCapability;
|
|||
use lspower::lsp::ImplementationProviderCapability;
|
||||
use lspower::lsp::OneOf;
|
||||
use lspower::lsp::SaveOptions;
|
||||
use lspower::lsp::SelectionRangeProviderCapability;
|
||||
use lspower::lsp::ServerCapabilities;
|
||||
use lspower::lsp::SignatureHelpOptions;
|
||||
use lspower::lsp::TextDocumentSyncCapability;
|
||||
|
@ -104,7 +105,9 @@ pub fn server_capabilities(
|
|||
document_formatting_provider: Some(OneOf::Left(true)),
|
||||
document_range_formatting_provider: None,
|
||||
document_on_type_formatting_provider: None,
|
||||
selection_range_provider: None,
|
||||
selection_range_provider: Some(SelectionRangeProviderCapability::Simple(
|
||||
true,
|
||||
)),
|
||||
folding_range_provider: None,
|
||||
rename_provider: Some(OneOf::Left(true)),
|
||||
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(
|
||||
&self,
|
||||
params: SignatureHelpParams,
|
||||
|
@ -1794,6 +1836,13 @@ impl lspower::LanguageServer for LanguageServer {
|
|||
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(
|
||||
&self,
|
||||
params: SignatureHelpParams,
|
||||
|
@ -2411,6 +2460,114 @@ mod tests {
|
|||
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]
|
||||
async fn test_code_lens_request() {
|
||||
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)]
|
||||
struct Response {
|
||||
id: usize,
|
||||
|
@ -1856,6 +1881,8 @@ pub enum RequestMethod {
|
|||
GetReferences((ModuleSpecifier, u32)),
|
||||
/// Get signature help items for a specific position.
|
||||
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.
|
||||
GetSupportedCodeFixes,
|
||||
}
|
||||
|
@ -1977,6 +2004,14 @@ impl RequestMethod {
|
|||
"options": options,
|
||||
})
|
||||
}
|
||||
RequestMethod::GetSmartSelectionRange((specifier, position)) => {
|
||||
json!({
|
||||
"id": id,
|
||||
"method": "getSmartSelectionRange",
|
||||
"specifier": specifier,
|
||||
"position": position
|
||||
})
|
||||
}
|
||||
RequestMethod::GetSupportedCodeFixes => json!({
|
||||
"id": id,
|
||||
"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": {
|
||||
return respond(
|
||||
id,
|
||||
|
|
7
cli/tsc/compiler.d.ts
vendored
7
cli/tsc/compiler.d.ts
vendored
|
@ -61,6 +61,7 @@ declare global {
|
|||
| GetQuickInfoRequest
|
||||
| GetReferencesRequest
|
||||
| GetSignatureHelpItemsRequest
|
||||
| GetSmartSelectionRange
|
||||
| GetSupportedCodeFixes;
|
||||
|
||||
interface BaseLanguageServerRequest {
|
||||
|
@ -169,6 +170,12 @@ declare global {
|
|||
options: ts.SignatureHelpItemsOptions;
|
||||
}
|
||||
|
||||
interface GetSmartSelectionRange extends BaseLanguageServerRequest {
|
||||
method: "getSmartSelectionRange";
|
||||
specifier: string;
|
||||
position: number;
|
||||
}
|
||||
|
||||
interface GetSupportedCodeFixes extends BaseLanguageServerRequest {
|
||||
method: "getSupportedCodeFixes";
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue