mirror of
https://github.com/denoland/deno.git
synced 2024-12-22 15:24:46 -05:00
parent
82431062fa
commit
5db16d1229
7 changed files with 506 additions and 56 deletions
|
@ -31,6 +31,7 @@ static FILE_PROTO_RE: Lazy<Regex> =
|
||||||
const CURRENT_PATH: &str = ".";
|
const CURRENT_PATH: &str = ".";
|
||||||
const PARENT_PATH: &str = "..";
|
const PARENT_PATH: &str = "..";
|
||||||
const LOCAL_PATHS: &[&str] = &[CURRENT_PATH, PARENT_PATH];
|
const LOCAL_PATHS: &[&str] = &[CURRENT_PATH, PARENT_PATH];
|
||||||
|
const IMPORT_COMMIT_CHARS: &[&str] = &["\"", "'", "/"];
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
|
@ -182,6 +183,9 @@ pub async fn get_import_completions(
|
||||||
detail: Some("(local)".to_string()),
|
detail: Some("(local)".to_string()),
|
||||||
sort_text: Some("1".to_string()),
|
sort_text: Some("1".to_string()),
|
||||||
insert_text: Some(s.to_string()),
|
insert_text: Some(s.to_string()),
|
||||||
|
commit_characters: Some(
|
||||||
|
IMPORT_COMMIT_CHARS.iter().map(|&c| c.into()).collect(),
|
||||||
|
),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
@ -231,6 +235,9 @@ fn get_base_import_map_completions(
|
||||||
detail: Some("(import map)".to_string()),
|
detail: Some("(import map)".to_string()),
|
||||||
sort_text: Some(label.clone()),
|
sort_text: Some(label.clone()),
|
||||||
insert_text: Some(label),
|
insert_text: Some(label),
|
||||||
|
commit_characters: Some(
|
||||||
|
IMPORT_COMMIT_CHARS.iter().map(|&c| c.into()).collect(),
|
||||||
|
),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -284,6 +291,9 @@ fn get_import_map_completions(
|
||||||
sort_text: Some("1".to_string()),
|
sort_text: Some("1".to_string()),
|
||||||
filter_text: Some(new_text),
|
filter_text: Some(new_text),
|
||||||
text_edit,
|
text_edit,
|
||||||
|
commit_characters: Some(
|
||||||
|
IMPORT_COMMIT_CHARS.iter().map(|&c| c.into()).collect(),
|
||||||
|
),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
|
@ -311,6 +321,9 @@ fn get_import_map_completions(
|
||||||
detail: Some("(import map)".to_string()),
|
detail: Some("(import map)".to_string()),
|
||||||
sort_text: Some("1".to_string()),
|
sort_text: Some("1".to_string()),
|
||||||
text_edit,
|
text_edit,
|
||||||
|
commit_characters: Some(
|
||||||
|
IMPORT_COMMIT_CHARS.iter().map(|&c| c.into()).collect(),
|
||||||
|
),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -382,6 +395,9 @@ fn get_local_completions(
|
||||||
filter_text,
|
filter_text,
|
||||||
sort_text: Some("1".to_string()),
|
sort_text: Some("1".to_string()),
|
||||||
text_edit,
|
text_edit,
|
||||||
|
commit_characters: Some(
|
||||||
|
IMPORT_COMMIT_CHARS.iter().map(|&c| c.into()).collect(),
|
||||||
|
),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}),
|
}),
|
||||||
Ok(file_type) if file_type.is_file() => {
|
Ok(file_type) if file_type.is_file() => {
|
||||||
|
@ -393,6 +409,9 @@ fn get_local_completions(
|
||||||
filter_text,
|
filter_text,
|
||||||
sort_text: Some("1".to_string()),
|
sort_text: Some("1".to_string()),
|
||||||
text_edit,
|
text_edit,
|
||||||
|
commit_characters: Some(
|
||||||
|
IMPORT_COMMIT_CHARS.iter().map(|&c| c.into()).collect(),
|
||||||
|
),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
|
@ -463,6 +482,9 @@ fn get_workspace_completions(
|
||||||
detail,
|
detail,
|
||||||
sort_text: Some("1".to_string()),
|
sort_text: Some("1".to_string()),
|
||||||
text_edit,
|
text_edit,
|
||||||
|
commit_characters: Some(
|
||||||
|
IMPORT_COMMIT_CHARS.iter().map(|&c| c.into()).collect(),
|
||||||
|
),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
|
@ -484,7 +506,7 @@ fn get_workspace_completions(
|
||||||
/// assert_eq!(relative_specifier(&specifier, &base), "../b.ts");
|
/// assert_eq!(relative_specifier(&specifier, &base), "../b.ts");
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
fn relative_specifier(
|
pub fn relative_specifier(
|
||||||
specifier: &ModuleSpecifier,
|
specifier: &ModuleSpecifier,
|
||||||
base: &ModuleSpecifier,
|
base: &ModuleSpecifier,
|
||||||
) -> String {
|
) -> String {
|
||||||
|
@ -812,6 +834,9 @@ mod tests {
|
||||||
},
|
},
|
||||||
new_text: "https://deno.land/x/a/b/c.ts".to_string(),
|
new_text: "https://deno.land/x/a/b/c.ts".to_string(),
|
||||||
})),
|
})),
|
||||||
|
commit_characters: Some(
|
||||||
|
IMPORT_COMMIT_CHARS.iter().map(|&c| c.into()).collect()
|
||||||
|
),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}]
|
}]
|
||||||
);
|
);
|
||||||
|
|
|
@ -1764,10 +1764,14 @@ impl Inner {
|
||||||
Some(response)
|
Some(response)
|
||||||
} else {
|
} else {
|
||||||
let line_index = asset_or_doc.line_index();
|
let line_index = asset_or_doc.line_index();
|
||||||
let trigger_character = if let Some(context) = ¶ms.context {
|
let (trigger_character, trigger_kind) =
|
||||||
context.trigger_character.clone()
|
if let Some(context) = ¶ms.context {
|
||||||
|
(
|
||||||
|
context.trigger_character.clone(),
|
||||||
|
Some(context.trigger_kind.into()),
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
None
|
(None, None)
|
||||||
};
|
};
|
||||||
let position =
|
let position =
|
||||||
line_index.offset_tsc(params.text_document_position.position)?;
|
line_index.offset_tsc(params.text_document_position.position)?;
|
||||||
|
@ -1776,14 +1780,30 @@ impl Inner {
|
||||||
position,
|
position,
|
||||||
tsc::GetCompletionsAtPositionOptions {
|
tsc::GetCompletionsAtPositionOptions {
|
||||||
user_preferences: tsc::UserPreferences {
|
user_preferences: tsc::UserPreferences {
|
||||||
allow_text_changes_in_new_files: Some(specifier.scheme() == "file"),
|
|
||||||
include_automatic_optional_chain_completions: Some(true),
|
|
||||||
provide_refactor_not_applicable_reason: Some(true),
|
|
||||||
include_completions_with_insert_text: Some(true),
|
|
||||||
allow_incomplete_completions: Some(true),
|
allow_incomplete_completions: Some(true),
|
||||||
|
allow_text_changes_in_new_files: Some(specifier.scheme() == "file"),
|
||||||
|
import_module_specifier_ending: Some(
|
||||||
|
tsc::ImportModuleSpecifierEnding::Index,
|
||||||
|
),
|
||||||
|
include_automatic_optional_chain_completions: Some(true),
|
||||||
|
include_completions_for_import_statements: Some(
|
||||||
|
self.config.get_workspace_settings().suggest.auto_imports,
|
||||||
|
),
|
||||||
|
include_completions_for_module_exports: Some(true),
|
||||||
|
include_completions_with_object_literal_method_snippets: Some(true),
|
||||||
|
include_completions_with_class_member_snippets: Some(true),
|
||||||
|
include_completions_with_insert_text: Some(true),
|
||||||
|
include_completions_with_snippet_text: Some(true),
|
||||||
|
jsx_attribute_completion_style: Some(
|
||||||
|
tsc::JsxAttributeCompletionStyle::Auto,
|
||||||
|
),
|
||||||
|
provide_prefix_and_suffix_text_for_rename: Some(true),
|
||||||
|
provide_refactor_not_applicable_reason: Some(true),
|
||||||
|
use_label_details_in_completion_entries: Some(true),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
trigger_character,
|
trigger_character,
|
||||||
|
trigger_kind,
|
||||||
},
|
},
|
||||||
));
|
));
|
||||||
let snapshot = self.snapshot();
|
let snapshot = self.snapshot();
|
||||||
|
@ -1822,7 +1842,8 @@ impl Inner {
|
||||||
"Could not decode data field of completion item.",
|
"Could not decode data field of completion item.",
|
||||||
)
|
)
|
||||||
})?;
|
})?;
|
||||||
if let Some(data) = data.tsc {
|
if let Some(data) = &data.tsc {
|
||||||
|
let specifier = data.specifier.clone();
|
||||||
let req = tsc::RequestMethod::GetCompletionDetails(data.into());
|
let req = tsc::RequestMethod::GetCompletionDetails(data.into());
|
||||||
let maybe_completion_info: Option<tsc::CompletionEntryDetails> =
|
let maybe_completion_info: Option<tsc::CompletionEntryDetails> =
|
||||||
self.ts_server.request(self.snapshot(), req).await.map_err(
|
self.ts_server.request(self.snapshot(), req).await.map_err(
|
||||||
|
@ -1832,7 +1853,15 @@ impl Inner {
|
||||||
},
|
},
|
||||||
)?;
|
)?;
|
||||||
if let Some(completion_info) = maybe_completion_info {
|
if let Some(completion_info) = maybe_completion_info {
|
||||||
completion_info.as_completion_item(¶ms, self)
|
completion_info
|
||||||
|
.as_completion_item(¶ms, data, &specifier, self)
|
||||||
|
.map_err(|err| {
|
||||||
|
error!(
|
||||||
|
"Failed to serialize virtual_text_document response: {}",
|
||||||
|
err
|
||||||
|
);
|
||||||
|
LspError::internal_error()
|
||||||
|
})?
|
||||||
} else {
|
} else {
|
||||||
error!(
|
error!(
|
||||||
"Received an undefined response from tsc for completion details."
|
"Received an undefined response from tsc for completion details."
|
||||||
|
|
322
cli/lsp/tsc.rs
322
cli/lsp/tsc.rs
|
@ -1,6 +1,7 @@
|
||||||
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
|
||||||
|
|
||||||
use super::code_lens;
|
use super::code_lens;
|
||||||
|
use super::completions::relative_specifier;
|
||||||
use super::config;
|
use super::config;
|
||||||
use super::documents::AssetOrDocument;
|
use super::documents::AssetOrDocument;
|
||||||
use super::language_server;
|
use super::language_server;
|
||||||
|
@ -511,7 +512,7 @@ pub enum ScriptElementKind {
|
||||||
Link,
|
Link,
|
||||||
#[serde(rename = "link name")]
|
#[serde(rename = "link name")]
|
||||||
LinkName,
|
LinkName,
|
||||||
#[serde(rename = "link test")]
|
#[serde(rename = "link text")]
|
||||||
LinkText,
|
LinkText,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -636,7 +637,7 @@ pub struct SymbolDisplayPart {
|
||||||
target: Option<DocumentSpan>,
|
target: Option<DocumentSpan>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize)]
|
#[derive(Debug, Deserialize, Serialize)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct JsDocTagInfo {
|
pub struct JsDocTagInfo {
|
||||||
name: String,
|
name: String,
|
||||||
|
@ -1285,7 +1286,14 @@ pub struct TextChange {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TextChange {
|
impl TextChange {
|
||||||
pub fn as_text_edit(
|
pub fn as_text_edit(&self, line_index: Arc<LineIndex>) -> lsp::TextEdit {
|
||||||
|
lsp::TextEdit {
|
||||||
|
range: self.span.to_range(line_index),
|
||||||
|
new_text: self.new_text.clone(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn as_text_or_annotated_text_edit(
|
||||||
&self,
|
&self,
|
||||||
line_index: Arc<LineIndex>,
|
line_index: Arc<LineIndex>,
|
||||||
) -> lsp::OneOf<lsp::TextEdit, lsp::AnnotatedTextEdit> {
|
) -> lsp::OneOf<lsp::TextEdit, lsp::AnnotatedTextEdit> {
|
||||||
|
@ -1315,7 +1323,7 @@ impl FileTextChanges {
|
||||||
let edits = self
|
let edits = self
|
||||||
.text_changes
|
.text_changes
|
||||||
.iter()
|
.iter()
|
||||||
.map(|tc| tc.as_text_edit(asset_or_doc.line_index()))
|
.map(|tc| tc.as_text_or_annotated_text_edit(asset_or_doc.line_index()))
|
||||||
.collect();
|
.collect();
|
||||||
Ok(lsp::TextDocumentEdit {
|
Ok(lsp::TextDocumentEdit {
|
||||||
text_document: lsp::OptionalVersionedTextDocumentIdentifier {
|
text_document: lsp::OptionalVersionedTextDocumentIdentifier {
|
||||||
|
@ -1359,7 +1367,7 @@ impl FileTextChanges {
|
||||||
let edits = self
|
let edits = self
|
||||||
.text_changes
|
.text_changes
|
||||||
.iter()
|
.iter()
|
||||||
.map(|tc| tc.as_text_edit(line_index.clone()))
|
.map(|tc| tc.as_text_or_annotated_text_edit(line_index.clone()))
|
||||||
.collect();
|
.collect();
|
||||||
ops.push(lsp::DocumentChangeOperation::Edit(lsp::TextDocumentEdit {
|
ops.push(lsp::DocumentChangeOperation::Edit(lsp::TextDocumentEdit {
|
||||||
text_document: lsp::OptionalVersionedTextDocumentIdentifier {
|
text_document: lsp::OptionalVersionedTextDocumentIdentifier {
|
||||||
|
@ -1579,13 +1587,13 @@ impl RefactorEditInfo {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize)]
|
#[derive(Debug, Deserialize, Serialize)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct CodeAction {
|
pub struct CodeAction {
|
||||||
// description: String,
|
description: String,
|
||||||
// changes: Vec<FileTextChanges>,
|
changes: Vec<FileTextChanges>,
|
||||||
// #[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
// commands: Option<Vec<Value>>,
|
commands: Option<Vec<Value>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, Eq)]
|
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, Eq)]
|
||||||
|
@ -1816,25 +1824,97 @@ impl CallHierarchyOutgoingCall {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize)]
|
/// Used to convert completion code actions into a command and additional text
|
||||||
|
/// edits to pass in the completion item.
|
||||||
|
fn parse_code_actions(
|
||||||
|
maybe_code_actions: Option<&Vec<CodeAction>>,
|
||||||
|
data: &CompletionItemData,
|
||||||
|
specifier: &ModuleSpecifier,
|
||||||
|
language_server: &language_server::Inner,
|
||||||
|
) -> Result<(Option<lsp::Command>, Option<Vec<lsp::TextEdit>>), AnyError> {
|
||||||
|
if let Some(code_actions) = maybe_code_actions {
|
||||||
|
let mut additional_text_edits: Vec<lsp::TextEdit> = Vec::new();
|
||||||
|
let mut has_remaining_commands_or_edits = false;
|
||||||
|
for ts_action in code_actions {
|
||||||
|
if ts_action.commands.is_some() {
|
||||||
|
has_remaining_commands_or_edits = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
let asset_or_doc =
|
||||||
|
language_server.get_asset_or_document(&data.specifier)?;
|
||||||
|
for change in &ts_action.changes {
|
||||||
|
let change_specifier = normalize_specifier(&change.file_name)?;
|
||||||
|
if data.specifier == change_specifier {
|
||||||
|
additional_text_edits.extend(change.text_changes.iter().map(|tc| {
|
||||||
|
update_import_statement(
|
||||||
|
tc.as_text_edit(asset_or_doc.line_index()),
|
||||||
|
data,
|
||||||
|
)
|
||||||
|
}));
|
||||||
|
} else {
|
||||||
|
has_remaining_commands_or_edits = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut command: Option<lsp::Command> = None;
|
||||||
|
if has_remaining_commands_or_edits {
|
||||||
|
let actions: Vec<Value> = code_actions
|
||||||
|
.iter()
|
||||||
|
.map(|ca| {
|
||||||
|
let changes: Vec<FileTextChanges> = ca
|
||||||
|
.changes
|
||||||
|
.clone()
|
||||||
|
.into_iter()
|
||||||
|
.filter(|ch| {
|
||||||
|
normalize_specifier(&ch.file_name).unwrap() == data.specifier
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
json!({
|
||||||
|
"commands": ca.commands,
|
||||||
|
"description": ca.description,
|
||||||
|
"changes": changes,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
command = Some(lsp::Command {
|
||||||
|
title: "".to_string(),
|
||||||
|
command: "_typescript.applyCompletionCodeAction".to_string(),
|
||||||
|
arguments: Some(vec![json!(specifier.to_string()), json!(actions)]),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if additional_text_edits.is_empty() {
|
||||||
|
Ok((command, None))
|
||||||
|
} else {
|
||||||
|
Ok((command, Some(additional_text_edits)))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Ok((None, None))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize, Serialize)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct CompletionEntryDetails {
|
pub struct CompletionEntryDetails {
|
||||||
display_parts: Vec<SymbolDisplayPart>,
|
display_parts: Vec<SymbolDisplayPart>,
|
||||||
documentation: Option<Vec<SymbolDisplayPart>>,
|
documentation: Option<Vec<SymbolDisplayPart>>,
|
||||||
tags: Option<Vec<JsDocTagInfo>>,
|
tags: Option<Vec<JsDocTagInfo>>,
|
||||||
// name: String,
|
name: String,
|
||||||
// kind: ScriptElementKind,
|
kind: ScriptElementKind,
|
||||||
// kind_modifiers: String,
|
kind_modifiers: String,
|
||||||
// code_actions: Option<Vec<CodeAction>>,
|
code_actions: Option<Vec<CodeAction>>,
|
||||||
// source_display: Option<Vec<SymbolDisplayPart>>,
|
source_display: Option<Vec<SymbolDisplayPart>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CompletionEntryDetails {
|
impl CompletionEntryDetails {
|
||||||
pub fn as_completion_item(
|
pub fn as_completion_item(
|
||||||
&self,
|
&self,
|
||||||
original_item: &lsp::CompletionItem,
|
original_item: &lsp::CompletionItem,
|
||||||
|
data: &CompletionItemData,
|
||||||
|
specifier: &ModuleSpecifier,
|
||||||
language_server: &language_server::Inner,
|
language_server: &language_server::Inner,
|
||||||
) -> lsp::CompletionItem {
|
) -> Result<lsp::CompletionItem, AnyError> {
|
||||||
let detail = if original_item.detail.is_some() {
|
let detail = if original_item.detail.is_some() {
|
||||||
original_item.detail.clone()
|
original_item.detail.clone()
|
||||||
} else if !self.display_parts.is_empty() {
|
} else if !self.display_parts.is_empty() {
|
||||||
|
@ -1862,15 +1942,22 @@ impl CompletionEntryDetails {
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
// TODO(@kitsonk) add `self.code_actions`
|
let (command, additional_text_edits) = parse_code_actions(
|
||||||
|
self.code_actions.as_ref(),
|
||||||
|
data,
|
||||||
|
specifier,
|
||||||
|
language_server,
|
||||||
|
)?;
|
||||||
// TODO(@kitsonk) add `use_code_snippet`
|
// TODO(@kitsonk) add `use_code_snippet`
|
||||||
|
|
||||||
lsp::CompletionItem {
|
Ok(lsp::CompletionItem {
|
||||||
data: None,
|
data: None,
|
||||||
detail,
|
detail,
|
||||||
documentation,
|
documentation,
|
||||||
|
command,
|
||||||
|
additional_text_edits,
|
||||||
..original_item.clone()
|
..original_item.clone()
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1951,6 +2038,36 @@ pub struct CompletionItemData {
|
||||||
pub use_code_snippet: bool,
|
pub use_code_snippet: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize, Serialize)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
struct CompletionEntryDataImport {
|
||||||
|
module_specifier: String,
|
||||||
|
file_name: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Modify an import statement text replacement to have the correct import
|
||||||
|
/// specifier to work with Deno module resolution.
|
||||||
|
fn update_import_statement(
|
||||||
|
mut text_edit: lsp::TextEdit,
|
||||||
|
item_data: &CompletionItemData,
|
||||||
|
) -> lsp::TextEdit {
|
||||||
|
if let Some(data) = &item_data.data {
|
||||||
|
if let Ok(import_data) =
|
||||||
|
serde_json::from_value::<CompletionEntryDataImport>(data.clone())
|
||||||
|
{
|
||||||
|
if let Ok(import_specifier) = normalize_specifier(&import_data.file_name)
|
||||||
|
{
|
||||||
|
let new_module_specifier =
|
||||||
|
relative_specifier(&import_specifier, &item_data.specifier);
|
||||||
|
text_edit.new_text = text_edit
|
||||||
|
.new_text
|
||||||
|
.replace(&import_data.module_specifier, &new_module_specifier);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
text_edit
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Default, Deserialize, Serialize)]
|
#[derive(Debug, Default, Deserialize, Serialize)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct CompletionEntry {
|
pub struct CompletionEntry {
|
||||||
|
@ -2087,8 +2204,7 @@ impl CompletionEntry {
|
||||||
let use_code_snippet = settings.complete_function_calls
|
let use_code_snippet = settings.complete_function_calls
|
||||||
&& (kind == Some(lsp::CompletionItemKind::FUNCTION)
|
&& (kind == Some(lsp::CompletionItemKind::FUNCTION)
|
||||||
|| kind == Some(lsp::CompletionItemKind::METHOD));
|
|| kind == Some(lsp::CompletionItemKind::METHOD));
|
||||||
// TODO(@kitsonk) missing from types: https://github.com/gluon-lang/lsp-types/issues/204
|
let commit_characters = self.get_commit_characters(info, settings);
|
||||||
let _commit_characters = self.get_commit_characters(info, settings);
|
|
||||||
let mut insert_text = self.insert_text.clone();
|
let mut insert_text = self.insert_text.clone();
|
||||||
let range = self.replacement_span.clone();
|
let range = self.replacement_span.clone();
|
||||||
let mut filter_text = self.get_filter_text();
|
let mut filter_text = self.get_filter_text();
|
||||||
|
@ -2158,9 +2274,8 @@ impl CompletionEntry {
|
||||||
insert_text,
|
insert_text,
|
||||||
detail,
|
detail,
|
||||||
tags,
|
tags,
|
||||||
data: Some(json!({
|
commit_characters,
|
||||||
"tsc": tsc,
|
data: Some(json!({ "tsc": tsc })),
|
||||||
})),
|
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2662,6 +2777,27 @@ fn start(
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize_repr, Serialize_repr)]
|
||||||
|
#[repr(u32)]
|
||||||
|
pub enum CompletionTriggerKind {
|
||||||
|
Invoked = 1,
|
||||||
|
TriggerCharacter = 2,
|
||||||
|
TriggerForIncompleteCompletions = 3,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<lsp::CompletionTriggerKind> for CompletionTriggerKind {
|
||||||
|
fn from(kind: lsp::CompletionTriggerKind) -> Self {
|
||||||
|
match kind {
|
||||||
|
lsp::CompletionTriggerKind::INVOKED => Self::Invoked,
|
||||||
|
lsp::CompletionTriggerKind::TRIGGER_CHARACTER => Self::TriggerCharacter,
|
||||||
|
lsp::CompletionTriggerKind::TRIGGER_FOR_INCOMPLETE_COMPLETIONS => {
|
||||||
|
Self::TriggerForIncompleteCompletions
|
||||||
|
}
|
||||||
|
_ => Self::Invoked,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Serialize)]
|
#[derive(Debug, Serialize)]
|
||||||
#[serde(rename_all = "kebab-case")]
|
#[serde(rename_all = "kebab-case")]
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
|
@ -2690,6 +2826,15 @@ pub enum ImportModuleSpecifierEnding {
|
||||||
Js,
|
Js,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize)]
|
||||||
|
#[serde(rename_all = "kebab-case")]
|
||||||
|
#[allow(dead_code)]
|
||||||
|
pub enum IncludeInlayParameterNameHints {
|
||||||
|
None,
|
||||||
|
Literals,
|
||||||
|
All,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Serialize)]
|
#[derive(Debug, Serialize)]
|
||||||
#[serde(rename_all = "kebab-case")]
|
#[serde(rename_all = "kebab-case")]
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
|
@ -2699,6 +2844,15 @@ pub enum IncludePackageJsonAutoImports {
|
||||||
Off,
|
Off,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize)]
|
||||||
|
#[serde(rename_all = "kebab-case")]
|
||||||
|
#[allow(dead_code)]
|
||||||
|
pub enum JsxAttributeCompletionStyle {
|
||||||
|
Auto,
|
||||||
|
Braces,
|
||||||
|
None,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Default, Serialize)]
|
#[derive(Debug, Default, Serialize)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct GetCompletionsAtPositionOptions {
|
pub struct GetCompletionsAtPositionOptions {
|
||||||
|
@ -2706,6 +2860,8 @@ pub struct GetCompletionsAtPositionOptions {
|
||||||
pub user_preferences: UserPreferences,
|
pub user_preferences: UserPreferences,
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
pub trigger_character: Option<String>,
|
pub trigger_character: Option<String>,
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub trigger_kind: Option<CompletionTriggerKind>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Default, Serialize)]
|
#[derive(Debug, Default, Serialize)]
|
||||||
|
@ -2726,6 +2882,12 @@ pub struct UserPreferences {
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
pub include_completions_with_insert_text: Option<bool>,
|
pub include_completions_with_insert_text: Option<bool>,
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub include_completions_with_class_member_snippets: Option<bool>,
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub include_completions_with_object_literal_method_snippets: Option<bool>,
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub use_label_details_in_completion_entries: Option<bool>,
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
pub allow_incomplete_completions: Option<bool>,
|
pub allow_incomplete_completions: Option<bool>,
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
pub import_module_specifier_preference:
|
pub import_module_specifier_preference:
|
||||||
|
@ -2740,6 +2902,24 @@ pub struct UserPreferences {
|
||||||
pub include_package_json_auto_imports: Option<IncludePackageJsonAutoImports>,
|
pub include_package_json_auto_imports: Option<IncludePackageJsonAutoImports>,
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
pub provide_refactor_not_applicable_reason: Option<bool>,
|
pub provide_refactor_not_applicable_reason: Option<bool>,
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub jsx_attribute_completion_style: Option<JsxAttributeCompletionStyle>,
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub include_inlay_parameter_name_hints:
|
||||||
|
Option<IncludeInlayParameterNameHints>,
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub include_inlay_parameter_name_hints_when_argument_matches_name:
|
||||||
|
Option<bool>,
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub include_inlay_function_parameter_type_hints: Option<bool>,
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub include_inlay_variable_type_hints: Option<bool>,
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub include_inlay_property_declaration_type_hints: Option<bool>,
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub include_inlay_function_like_return_type_hints: Option<bool>,
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub include_inlay_enum_member_value_hints: Option<bool>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Serialize)]
|
#[derive(Debug, Serialize)]
|
||||||
|
@ -2789,17 +2969,20 @@ pub struct GetCompletionDetailsArgs {
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
pub source: Option<String>,
|
pub source: Option<String>,
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub preferences: Option<UserPreferences>,
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
pub data: Option<Value>,
|
pub data: Option<Value>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<CompletionItemData> for GetCompletionDetailsArgs {
|
impl From<&CompletionItemData> for GetCompletionDetailsArgs {
|
||||||
fn from(item_data: CompletionItemData) -> Self {
|
fn from(item_data: &CompletionItemData) -> Self {
|
||||||
Self {
|
Self {
|
||||||
specifier: item_data.specifier,
|
specifier: item_data.specifier.clone(),
|
||||||
position: item_data.position,
|
position: item_data.position,
|
||||||
name: item_data.name,
|
name: item_data.name.clone(),
|
||||||
source: item_data.source,
|
source: item_data.source.clone(),
|
||||||
data: item_data.data,
|
preferences: None,
|
||||||
|
data: item_data.data.clone(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3809,6 +3992,7 @@ mod tests {
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
trigger_character: Some(".".to_string()),
|
trigger_character: Some(".".to_string()),
|
||||||
|
trigger_kind: None,
|
||||||
},
|
},
|
||||||
)),
|
)),
|
||||||
Default::default(),
|
Default::default(),
|
||||||
|
@ -3825,6 +4009,7 @@ mod tests {
|
||||||
position,
|
position,
|
||||||
name: "log".to_string(),
|
name: "log".to_string(),
|
||||||
source: None,
|
source: None,
|
||||||
|
preferences: None,
|
||||||
data: None,
|
data: None,
|
||||||
}),
|
}),
|
||||||
Default::default(),
|
Default::default(),
|
||||||
|
@ -3919,4 +4104,79 @@ mod tests {
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_update_import_statement() {
|
||||||
|
let fixtures = vec![
|
||||||
|
(
|
||||||
|
"file:///a/a.ts",
|
||||||
|
"./b",
|
||||||
|
"file:///a/b.ts",
|
||||||
|
"import { b } from \"./b\";\n\n",
|
||||||
|
"import { b } from \"./b.ts\";\n\n",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"file:///a/a.ts",
|
||||||
|
"../b/b",
|
||||||
|
"file:///b/b.ts",
|
||||||
|
"import { b } from \"../b/b\";\n\n",
|
||||||
|
"import { b } from \"../b/b.ts\";\n\n",
|
||||||
|
),
|
||||||
|
("file:///a/a.ts", "./b", "file:///a/b.ts", ", b", ", b"),
|
||||||
|
];
|
||||||
|
|
||||||
|
for (
|
||||||
|
specifier_text,
|
||||||
|
module_specifier,
|
||||||
|
file_name,
|
||||||
|
orig_text,
|
||||||
|
expected_text,
|
||||||
|
) in fixtures
|
||||||
|
{
|
||||||
|
let specifier = ModuleSpecifier::parse(specifier_text).unwrap();
|
||||||
|
let item_data = CompletionItemData {
|
||||||
|
specifier: specifier.clone(),
|
||||||
|
position: 0,
|
||||||
|
name: "b".to_string(),
|
||||||
|
source: None,
|
||||||
|
data: Some(json!({
|
||||||
|
"moduleSpecifier": module_specifier,
|
||||||
|
"fileName": file_name,
|
||||||
|
})),
|
||||||
|
use_code_snippet: false,
|
||||||
|
};
|
||||||
|
let actual = update_import_statement(
|
||||||
|
lsp::TextEdit {
|
||||||
|
range: lsp::Range {
|
||||||
|
start: lsp::Position {
|
||||||
|
line: 0,
|
||||||
|
character: 0,
|
||||||
|
},
|
||||||
|
end: lsp::Position {
|
||||||
|
line: 0,
|
||||||
|
character: 0,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
new_text: orig_text.to_string(),
|
||||||
|
},
|
||||||
|
&item_data,
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
actual,
|
||||||
|
lsp::TextEdit {
|
||||||
|
range: lsp::Range {
|
||||||
|
start: lsp::Position {
|
||||||
|
line: 0,
|
||||||
|
character: 0,
|
||||||
|
},
|
||||||
|
end: lsp::Position {
|
||||||
|
line: 0,
|
||||||
|
character: 0,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
new_text: expected_text.to_string(),
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -774,35 +774,40 @@ fn lsp_import_map_import_completions() {
|
||||||
"kind": 19,
|
"kind": 19,
|
||||||
"detail": "(local)",
|
"detail": "(local)",
|
||||||
"sortText": "1",
|
"sortText": "1",
|
||||||
"insertText": "."
|
"insertText": ".",
|
||||||
|
"commitCharacters": ["\"", "'", "/"],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"label": "..",
|
"label": "..",
|
||||||
"kind": 19,
|
"kind": 19,
|
||||||
"detail": "(local)",
|
"detail": "(local)",
|
||||||
"sortText": "1",
|
"sortText": "1",
|
||||||
"insertText": ".."
|
"insertText": "..",
|
||||||
|
"commitCharacters": ["\"", "'", "/"],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"label": "std",
|
"label": "std",
|
||||||
"kind": 19,
|
"kind": 19,
|
||||||
"detail": "(import map)",
|
"detail": "(import map)",
|
||||||
"sortText": "std",
|
"sortText": "std",
|
||||||
"insertText": "std"
|
"insertText": "std",
|
||||||
|
"commitCharacters": ["\"", "'", "/"],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"label": "fs",
|
"label": "fs",
|
||||||
"kind": 17,
|
"kind": 17,
|
||||||
"detail": "(import map)",
|
"detail": "(import map)",
|
||||||
"sortText": "fs",
|
"sortText": "fs",
|
||||||
"insertText": "fs"
|
"insertText": "fs",
|
||||||
|
"commitCharacters": ["\"", "'", "/"],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"label": "/~",
|
"label": "/~",
|
||||||
"kind": 19,
|
"kind": 19,
|
||||||
"detail": "(import map)",
|
"detail": "(import map)",
|
||||||
"sortText": "/~",
|
"sortText": "/~",
|
||||||
"insertText": "/~"
|
"insertText": "/~",
|
||||||
|
"commitCharacters": ["\"", "'", "/"],
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}))
|
}))
|
||||||
|
@ -883,7 +888,8 @@ fn lsp_import_map_import_completions() {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"newText": "/~/b.ts"
|
"newText": "/~/b.ts"
|
||||||
}
|
},
|
||||||
|
"commitCharacters": ["\"", "'", "/"],
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}))
|
}))
|
||||||
|
@ -3490,6 +3496,7 @@ fn lsp_completions_optional() {
|
||||||
"sortText": "11",
|
"sortText": "11",
|
||||||
"filterText": "b",
|
"filterText": "b",
|
||||||
"insertText": "b",
|
"insertText": "b",
|
||||||
|
"commitCharacters": [".", ",", ";", "("],
|
||||||
"data": {
|
"data": {
|
||||||
"tsc": {
|
"tsc": {
|
||||||
"specifier": "file:///a/file.ts",
|
"specifier": "file:///a/file.ts",
|
||||||
|
@ -3527,6 +3534,124 @@ fn lsp_completions_optional() {
|
||||||
shutdown(&mut client);
|
shutdown(&mut client);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn lsp_completions_auto_import() {
|
||||||
|
let mut client = init("initialize_params.json");
|
||||||
|
did_open(
|
||||||
|
&mut client,
|
||||||
|
json!({
|
||||||
|
"textDocument": {
|
||||||
|
"uri": "file:///a/b.ts",
|
||||||
|
"languageId": "typescript",
|
||||||
|
"version": 1,
|
||||||
|
"text": "export const foo = \"foo\";\n",
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
did_open(
|
||||||
|
&mut client,
|
||||||
|
json!({
|
||||||
|
"textDocument": {
|
||||||
|
"uri": "file:///a/file.ts",
|
||||||
|
"languageId": "typescript",
|
||||||
|
"version": 1,
|
||||||
|
"text": "export {};\n\n",
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
let (maybe_res, maybe_err) = client
|
||||||
|
.write_request(
|
||||||
|
"textDocument/completion",
|
||||||
|
json!({
|
||||||
|
"textDocument": {
|
||||||
|
"uri": "file:///a/file.ts"
|
||||||
|
},
|
||||||
|
"position": {
|
||||||
|
"line": 2,
|
||||||
|
"character": 0,
|
||||||
|
},
|
||||||
|
"context": {
|
||||||
|
"triggerKind": 1,
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
assert!(maybe_err.is_none());
|
||||||
|
if let Some(lsp::CompletionResponse::List(list)) = maybe_res {
|
||||||
|
assert!(!list.is_incomplete);
|
||||||
|
if !list.items.iter().any(|item| item.label == "foo") {
|
||||||
|
panic!("completions items missing 'foo' symbol");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
panic!("unexpected completion response");
|
||||||
|
}
|
||||||
|
let (maybe_res, maybe_err) = client
|
||||||
|
.write_request(
|
||||||
|
"completionItem/resolve",
|
||||||
|
json!({
|
||||||
|
"label": "foo",
|
||||||
|
"kind": 6,
|
||||||
|
"sortText": "16",
|
||||||
|
"commitCharacters": [
|
||||||
|
".",
|
||||||
|
",",
|
||||||
|
";",
|
||||||
|
"("
|
||||||
|
],
|
||||||
|
"data": {
|
||||||
|
"tsc": {
|
||||||
|
"specifier": "file:///a/file.ts",
|
||||||
|
"position": 12,
|
||||||
|
"name": "foo",
|
||||||
|
"source": "./b",
|
||||||
|
"data": {
|
||||||
|
"exportName": "foo",
|
||||||
|
"moduleSpecifier": "./b",
|
||||||
|
"fileName": "file:///a/b.ts"
|
||||||
|
},
|
||||||
|
"useCodeSnippet": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
assert!(maybe_err.is_none());
|
||||||
|
assert_eq!(
|
||||||
|
maybe_res,
|
||||||
|
Some(json!({
|
||||||
|
"label": "foo",
|
||||||
|
"kind": 6,
|
||||||
|
"detail": "const foo: \"foo\"",
|
||||||
|
"documentation": {
|
||||||
|
"kind": "markdown",
|
||||||
|
"value": ""
|
||||||
|
},
|
||||||
|
"sortText": "16",
|
||||||
|
"additionalTextEdits": [
|
||||||
|
{
|
||||||
|
"range": {
|
||||||
|
"start": {
|
||||||
|
"line": 0,
|
||||||
|
"character": 0
|
||||||
|
},
|
||||||
|
"end": {
|
||||||
|
"line": 0,
|
||||||
|
"character": 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"newText": "import { foo } from \"./b.ts\";\n\n"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"commitCharacters": [
|
||||||
|
".",
|
||||||
|
",",
|
||||||
|
";",
|
||||||
|
"("
|
||||||
|
]
|
||||||
|
}))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn lsp_completions_registry() {
|
fn lsp_completions_registry() {
|
||||||
let _g = http_server();
|
let _g = http_server();
|
||||||
|
|
|
@ -6,14 +6,24 @@
|
||||||
"kind": 19,
|
"kind": 19,
|
||||||
"detail": "(local)",
|
"detail": "(local)",
|
||||||
"sortText": "1",
|
"sortText": "1",
|
||||||
"insertText": "."
|
"insertText": ".",
|
||||||
|
"commitCharacters": [
|
||||||
|
"\"",
|
||||||
|
"'",
|
||||||
|
"/"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"label": "..",
|
"label": "..",
|
||||||
"kind": 19,
|
"kind": 19,
|
||||||
"detail": "(local)",
|
"detail": "(local)",
|
||||||
"sortText": "1",
|
"sortText": "1",
|
||||||
"insertText": ".."
|
"insertText": "..",
|
||||||
|
"commitCharacters": [
|
||||||
|
"\"",
|
||||||
|
"'",
|
||||||
|
"/"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"label": "http://localhost:4545",
|
"label": "http://localhost:4545",
|
||||||
|
|
|
@ -718,10 +718,9 @@ delete Object.prototype.__proto__;
|
||||||
request.args.specifier,
|
request.args.specifier,
|
||||||
request.args.position,
|
request.args.position,
|
||||||
request.args.name,
|
request.args.name,
|
||||||
undefined,
|
{},
|
||||||
request.args.source,
|
request.args.source,
|
||||||
undefined,
|
request.args.preferences,
|
||||||
// @ts-expect-error this exists in 4.3 but not part of the d.ts
|
|
||||||
request.args.data,
|
request.args.data,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
6
cli/tsc/compiler.d.ts
vendored
6
cli/tsc/compiler.d.ts
vendored
|
@ -50,6 +50,7 @@ declare global {
|
||||||
}
|
}
|
||||||
|
|
||||||
type LanguageServerRequest =
|
type LanguageServerRequest =
|
||||||
|
| Restart
|
||||||
| ConfigureRequest
|
| ConfigureRequest
|
||||||
| FindRenameLocationsRequest
|
| FindRenameLocationsRequest
|
||||||
| GetAssets
|
| GetAssets
|
||||||
|
@ -138,7 +139,8 @@ declare global {
|
||||||
position: number;
|
position: number;
|
||||||
name: string;
|
name: string;
|
||||||
source?: string;
|
source?: string;
|
||||||
data?: unknown;
|
preferences?: ts.UserPreferences;
|
||||||
|
data?: ts.CompletionEntryData;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -252,7 +254,7 @@ declare global {
|
||||||
position: number;
|
position: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Restart {
|
interface Restart extends BaseLanguageServerRequest {
|
||||||
method: "restart";
|
method: "restart";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue