mirror of
https://github.com/denoland/deno.git
synced 2025-02-08 07:16:56 -05:00
parent
6d2656fd56
commit
7d78f58187
11 changed files with 628 additions and 2 deletions
|
@ -141,6 +141,6 @@ pub fn server_capabilities(
|
||||||
"denoConfigTasks": true,
|
"denoConfigTasks": true,
|
||||||
"testingApi":true,
|
"testingApi":true,
|
||||||
})),
|
})),
|
||||||
inlay_hint_provider: None,
|
inlay_hint_provider: Some(OneOf::Left(true)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -106,6 +106,101 @@ impl Default for CompletionSettings {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Default, Clone, Deserialize, Serialize, PartialEq, Eq)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
pub struct InlayHintsSettings {
|
||||||
|
#[serde(default)]
|
||||||
|
pub parameter_names: InlayHintsParamNamesOptions,
|
||||||
|
#[serde(default)]
|
||||||
|
pub parameter_types: InlayHintsParamTypesOptions,
|
||||||
|
#[serde(default)]
|
||||||
|
pub variable_types: InlayHintsVarTypesOptions,
|
||||||
|
#[serde(default)]
|
||||||
|
pub property_declaration_types: InlayHintsPropDeclTypesOptions,
|
||||||
|
#[serde(default)]
|
||||||
|
pub function_like_return_types: InlayHintsFuncLikeReturnTypesOptions,
|
||||||
|
#[serde(default)]
|
||||||
|
pub enum_member_values: InlayHintsEnumMemberValuesOptions,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, Eq)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
pub struct InlayHintsParamNamesOptions {
|
||||||
|
#[serde(default)]
|
||||||
|
pub enabled: InlayHintsParamNamesEnabled,
|
||||||
|
#[serde(default = "is_true")]
|
||||||
|
pub suppress_when_argument_matches_name: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for InlayHintsParamNamesOptions {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
enabled: InlayHintsParamNamesEnabled::None,
|
||||||
|
suppress_when_argument_matches_name: true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, Eq)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
pub enum InlayHintsParamNamesEnabled {
|
||||||
|
None,
|
||||||
|
Literals,
|
||||||
|
All,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for InlayHintsParamNamesEnabled {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self::None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Default, Clone, Deserialize, Serialize, PartialEq, Eq)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
pub struct InlayHintsParamTypesOptions {
|
||||||
|
#[serde(default)]
|
||||||
|
pub enabled: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, Eq)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
pub struct InlayHintsVarTypesOptions {
|
||||||
|
#[serde(default)]
|
||||||
|
pub enabled: bool,
|
||||||
|
#[serde(default = "is_true")]
|
||||||
|
pub suppress_when_argument_matches_name: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for InlayHintsVarTypesOptions {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
enabled: false,
|
||||||
|
suppress_when_argument_matches_name: true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Default, Clone, Deserialize, Serialize, PartialEq, Eq)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
pub struct InlayHintsPropDeclTypesOptions {
|
||||||
|
#[serde(default)]
|
||||||
|
pub enabled: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Default, Clone, Deserialize, Serialize, PartialEq, Eq)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
pub struct InlayHintsFuncLikeReturnTypesOptions {
|
||||||
|
#[serde(default)]
|
||||||
|
pub enabled: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Default, Clone, Deserialize, Serialize, PartialEq, Eq)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
pub struct InlayHintsEnumMemberValuesOptions {
|
||||||
|
#[serde(default)]
|
||||||
|
pub enabled: bool,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, Eq)]
|
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, Eq)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct ImportCompletionSettings {
|
pub struct ImportCompletionSettings {
|
||||||
|
@ -202,6 +297,9 @@ pub struct WorkspaceSettings {
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub code_lens: CodeLensSettings,
|
pub code_lens: CodeLensSettings,
|
||||||
|
|
||||||
|
#[serde(default)]
|
||||||
|
pub inlay_hints: InlayHintsSettings,
|
||||||
|
|
||||||
/// A flag that indicates if internal debug logging should be made available.
|
/// A flag that indicates if internal debug logging should be made available.
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub internal_debug: bool,
|
pub internal_debug: bool,
|
||||||
|
@ -238,6 +336,19 @@ impl WorkspaceSettings {
|
||||||
pub fn enabled_code_lens(&self) -> bool {
|
pub fn enabled_code_lens(&self) -> bool {
|
||||||
self.code_lens.implementations || self.code_lens.references
|
self.code_lens.implementations || self.code_lens.references
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Determine if any inlay hints are enabled. This allows short circuiting
|
||||||
|
/// when there are no inlay hints enabled.
|
||||||
|
pub fn enabled_inlay_hints(&self) -> bool {
|
||||||
|
!matches!(
|
||||||
|
self.inlay_hints.parameter_names.enabled,
|
||||||
|
InlayHintsParamNamesEnabled::None
|
||||||
|
) || self.inlay_hints.parameter_types.enabled
|
||||||
|
|| self.inlay_hints.variable_types.enabled
|
||||||
|
|| self.inlay_hints.property_declaration_types.enabled
|
||||||
|
|| self.inlay_hints.function_like_return_types.enabled
|
||||||
|
|| self.inlay_hints.enum_member_values.enabled
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Default)]
|
#[derive(Debug, Clone, Default)]
|
||||||
|
@ -566,6 +677,26 @@ mod tests {
|
||||||
references_all_functions: false,
|
references_all_functions: false,
|
||||||
test: true,
|
test: true,
|
||||||
},
|
},
|
||||||
|
inlay_hints: InlayHintsSettings {
|
||||||
|
parameter_names: InlayHintsParamNamesOptions {
|
||||||
|
enabled: InlayHintsParamNamesEnabled::None,
|
||||||
|
suppress_when_argument_matches_name: true
|
||||||
|
},
|
||||||
|
parameter_types: InlayHintsParamTypesOptions { enabled: false },
|
||||||
|
variable_types: InlayHintsVarTypesOptions {
|
||||||
|
enabled: false,
|
||||||
|
suppress_when_argument_matches_name: true
|
||||||
|
},
|
||||||
|
property_declaration_types: InlayHintsPropDeclTypesOptions {
|
||||||
|
enabled: false
|
||||||
|
},
|
||||||
|
function_like_return_types: InlayHintsFuncLikeReturnTypesOptions {
|
||||||
|
enabled: false
|
||||||
|
},
|
||||||
|
enum_member_values: InlayHintsEnumMemberValuesOptions {
|
||||||
|
enabled: false
|
||||||
|
},
|
||||||
|
},
|
||||||
internal_debug: false,
|
internal_debug: false,
|
||||||
lint: true,
|
lint: true,
|
||||||
suggest: CompletionSettings {
|
suggest: CompletionSettings {
|
||||||
|
|
|
@ -196,6 +196,13 @@ impl LanguageServer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn inlay_hint(
|
||||||
|
&self,
|
||||||
|
params: InlayHintParams,
|
||||||
|
) -> LspResult<Option<Vec<InlayHint>>> {
|
||||||
|
self.0.lock().await.inlay_hint(params).await
|
||||||
|
}
|
||||||
|
|
||||||
pub async fn virtual_text_document(
|
pub async fn virtual_text_document(
|
||||||
&self,
|
&self,
|
||||||
params: Option<Value>,
|
params: Option<Value>,
|
||||||
|
@ -2896,6 +2903,50 @@ impl Inner {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn inlay_hint(
|
||||||
|
&self,
|
||||||
|
params: InlayHintParams,
|
||||||
|
) -> LspResult<Option<Vec<InlayHint>>> {
|
||||||
|
let specifier = self.url_map.normalize_url(¶ms.text_document.uri);
|
||||||
|
let workspace_settings = self.config.get_workspace_settings();
|
||||||
|
if !self.is_diagnosable(&specifier)
|
||||||
|
|| !self.config.specifier_enabled(&specifier)
|
||||||
|
|| !workspace_settings.enabled_inlay_hints()
|
||||||
|
{
|
||||||
|
return Ok(None);
|
||||||
|
}
|
||||||
|
|
||||||
|
let mark = self.performance.mark("inlay_hint", Some(¶ms));
|
||||||
|
let asset_or_doc = self.get_asset_or_document(&specifier)?;
|
||||||
|
let line_index = asset_or_doc.line_index();
|
||||||
|
let range = tsc::TextSpan::from_range(¶ms.range, line_index.clone())
|
||||||
|
.map_err(|err| {
|
||||||
|
error!("Failed to convert range to text_span: {}", err);
|
||||||
|
LspError::internal_error()
|
||||||
|
})?;
|
||||||
|
let req = tsc::RequestMethod::ProvideInlayHints((
|
||||||
|
specifier.clone(),
|
||||||
|
range,
|
||||||
|
(&workspace_settings).into(),
|
||||||
|
));
|
||||||
|
let maybe_inlay_hints: Option<Vec<tsc::InlayHint>> = self
|
||||||
|
.ts_server
|
||||||
|
.request(self.snapshot(), req)
|
||||||
|
.await
|
||||||
|
.map_err(|err| {
|
||||||
|
error!("Unable to get inlay hints: {}", err);
|
||||||
|
LspError::internal_error()
|
||||||
|
})?;
|
||||||
|
let maybe_inlay_hints = maybe_inlay_hints.map(|hints| {
|
||||||
|
hints
|
||||||
|
.iter()
|
||||||
|
.map(|hint| hint.to_lsp(line_index.clone()))
|
||||||
|
.collect()
|
||||||
|
});
|
||||||
|
self.performance.measure(mark);
|
||||||
|
Ok(maybe_inlay_hints)
|
||||||
|
}
|
||||||
|
|
||||||
async fn reload_import_registries(&mut self) -> LspResult<Option<Value>> {
|
async fn reload_import_registries(&mut self) -> LspResult<Option<Value>> {
|
||||||
fs_util::remove_dir_all_if_exists(&self.module_registries_location)
|
fs_util::remove_dir_all_if_exists(&self.module_registries_location)
|
||||||
.await
|
.await
|
||||||
|
|
|
@ -11,6 +11,9 @@ pub const RELOAD_IMPORT_REGISTRIES_REQUEST: &str =
|
||||||
"deno/reloadImportRegistries";
|
"deno/reloadImportRegistries";
|
||||||
pub const VIRTUAL_TEXT_DOCUMENT: &str = "deno/virtualTextDocument";
|
pub const VIRTUAL_TEXT_DOCUMENT: &str = "deno/virtualTextDocument";
|
||||||
|
|
||||||
|
// While lsp_types supports inlay hints currently, tower_lsp does not.
|
||||||
|
pub const INLAY_HINT: &str = "textDocument/inlayHint";
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Serialize)]
|
#[derive(Debug, Deserialize, Serialize)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct CacheParams {
|
pub struct CacheParams {
|
||||||
|
|
|
@ -58,6 +58,7 @@ pub async fn start() -> Result<(), AnyError> {
|
||||||
lsp_custom::VIRTUAL_TEXT_DOCUMENT,
|
lsp_custom::VIRTUAL_TEXT_DOCUMENT,
|
||||||
LanguageServer::virtual_text_document,
|
LanguageServer::virtual_text_document,
|
||||||
)
|
)
|
||||||
|
.custom_method(lsp_custom::INLAY_HINT, LanguageServer::inlay_hint)
|
||||||
.finish();
|
.finish();
|
||||||
|
|
||||||
Server::new(stdin, stdout, socket).serve(service).await;
|
Server::new(stdin, stdout, socket).serve(service).await;
|
||||||
|
|
|
@ -288,6 +288,7 @@ pub fn get_repl_workspace_settings() -> WorkspaceSettings {
|
||||||
cache: None,
|
cache: None,
|
||||||
import_map: None,
|
import_map: None,
|
||||||
code_lens: Default::default(),
|
code_lens: Default::default(),
|
||||||
|
inlay_hints: Default::default(),
|
||||||
internal_debug: false,
|
internal_debug: false,
|
||||||
lint: false,
|
lint: false,
|
||||||
tls_certificate: None,
|
tls_certificate: None,
|
||||||
|
|
113
cli/lsp/tsc.rs
113
cli/lsp/tsc.rs
|
@ -618,6 +618,15 @@ pub struct TextSpan {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TextSpan {
|
impl TextSpan {
|
||||||
|
pub fn from_range(
|
||||||
|
range: &lsp::Range,
|
||||||
|
line_index: Arc<LineIndex>,
|
||||||
|
) -> Result<Self, AnyError> {
|
||||||
|
let start = line_index.offset_tsc(range.start)?;
|
||||||
|
let length = line_index.offset_tsc(range.end)? - start;
|
||||||
|
Ok(Self { start, length })
|
||||||
|
}
|
||||||
|
|
||||||
pub fn to_range(&self, line_index: Arc<LineIndex>) -> lsp::Range {
|
pub fn to_range(&self, line_index: Arc<LineIndex>) -> lsp::Range {
|
||||||
lsp::Range {
|
lsp::Range {
|
||||||
start: line_index.position_tsc(self.start.into()),
|
start: line_index.position_tsc(self.start.into()),
|
||||||
|
@ -932,6 +941,48 @@ impl NavigateToItem {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Deserialize)]
|
||||||
|
pub enum InlayHintKind {
|
||||||
|
Type,
|
||||||
|
Parameter,
|
||||||
|
Enum,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl InlayHintKind {
|
||||||
|
pub fn to_lsp(&self) -> Option<lsp::InlayHintKind> {
|
||||||
|
match self {
|
||||||
|
Self::Enum => None,
|
||||||
|
Self::Parameter => Some(lsp::InlayHintKind::PARAMETER),
|
||||||
|
Self::Type => Some(lsp::InlayHintKind::TYPE),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Deserialize)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
pub struct InlayHint {
|
||||||
|
pub text: String,
|
||||||
|
pub position: u32,
|
||||||
|
pub kind: InlayHintKind,
|
||||||
|
pub whitespace_before: Option<bool>,
|
||||||
|
pub whitespace_after: Option<bool>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl InlayHint {
|
||||||
|
pub fn to_lsp(&self, line_index: Arc<LineIndex>) -> lsp::InlayHint {
|
||||||
|
lsp::InlayHint {
|
||||||
|
position: line_index.position_tsc(self.position.into()),
|
||||||
|
label: lsp::InlayHintLabel::String(self.text.clone()),
|
||||||
|
kind: self.kind.to_lsp(),
|
||||||
|
padding_left: self.whitespace_before,
|
||||||
|
padding_right: self.whitespace_after,
|
||||||
|
text_edits: None,
|
||||||
|
tooltip: None,
|
||||||
|
data: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Deserialize)]
|
#[derive(Debug, Clone, Deserialize)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct NavigationTree {
|
pub struct NavigationTree {
|
||||||
|
@ -2830,6 +2881,18 @@ pub enum IncludeInlayParameterNameHints {
|
||||||
All,
|
All,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<&config::InlayHintsParamNamesEnabled>
|
||||||
|
for IncludeInlayParameterNameHints
|
||||||
|
{
|
||||||
|
fn from(setting: &config::InlayHintsParamNamesEnabled) -> Self {
|
||||||
|
match setting {
|
||||||
|
config::InlayHintsParamNamesEnabled::All => Self::All,
|
||||||
|
config::InlayHintsParamNamesEnabled::Literals => Self::Literals,
|
||||||
|
config::InlayHintsParamNamesEnabled::None => Self::None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Serialize)]
|
#[derive(Debug, Serialize)]
|
||||||
#[serde(rename_all = "kebab-case")]
|
#[serde(rename_all = "kebab-case")]
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
|
@ -2910,6 +2973,8 @@ pub struct UserPreferences {
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
pub include_inlay_variable_type_hints: Option<bool>,
|
pub include_inlay_variable_type_hints: Option<bool>,
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub include_inlay_variable_type_hints_when_type_matches_name: Option<bool>,
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
pub include_inlay_property_declaration_type_hints: Option<bool>,
|
pub include_inlay_property_declaration_type_hints: Option<bool>,
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
pub include_inlay_function_like_return_type_hints: Option<bool>,
|
pub include_inlay_function_like_return_type_hints: Option<bool>,
|
||||||
|
@ -2921,6 +2986,43 @@ pub struct UserPreferences {
|
||||||
pub auto_import_file_exclude_patterns: Option<Vec<String>>,
|
pub auto_import_file_exclude_patterns: Option<Vec<String>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<&config::WorkspaceSettings> for UserPreferences {
|
||||||
|
fn from(workspace_settings: &config::WorkspaceSettings) -> Self {
|
||||||
|
let inlay_hints = &workspace_settings.inlay_hints;
|
||||||
|
Self {
|
||||||
|
include_inlay_parameter_name_hints: Some(
|
||||||
|
(&inlay_hints.parameter_names.enabled).into(),
|
||||||
|
),
|
||||||
|
include_inlay_parameter_name_hints_when_argument_matches_name: Some(
|
||||||
|
inlay_hints
|
||||||
|
.parameter_names
|
||||||
|
.suppress_when_argument_matches_name,
|
||||||
|
),
|
||||||
|
include_inlay_function_parameter_type_hints: Some(
|
||||||
|
inlay_hints.parameter_types.enabled,
|
||||||
|
),
|
||||||
|
include_inlay_variable_type_hints: Some(
|
||||||
|
inlay_hints.variable_types.enabled,
|
||||||
|
),
|
||||||
|
include_inlay_variable_type_hints_when_type_matches_name: Some(
|
||||||
|
inlay_hints
|
||||||
|
.variable_types
|
||||||
|
.suppress_when_argument_matches_name,
|
||||||
|
),
|
||||||
|
include_inlay_property_declaration_type_hints: Some(
|
||||||
|
inlay_hints.property_declaration_types.enabled,
|
||||||
|
),
|
||||||
|
include_inlay_function_like_return_type_hints: Some(
|
||||||
|
inlay_hints.function_like_return_types.enabled,
|
||||||
|
),
|
||||||
|
include_inlay_enum_member_value_hints: Some(
|
||||||
|
inlay_hints.enum_member_values.enabled,
|
||||||
|
),
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Serialize)]
|
#[derive(Debug, Serialize)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct SignatureHelpItemsOptions {
|
pub struct SignatureHelpItemsOptions {
|
||||||
|
@ -3053,6 +3155,8 @@ pub enum RequestMethod {
|
||||||
ProvideCallHierarchyIncomingCalls((ModuleSpecifier, u32)),
|
ProvideCallHierarchyIncomingCalls((ModuleSpecifier, u32)),
|
||||||
/// Resolve outgoing call hierarchy items for a specific position.
|
/// Resolve outgoing call hierarchy items for a specific position.
|
||||||
ProvideCallHierarchyOutgoingCalls((ModuleSpecifier, u32)),
|
ProvideCallHierarchyOutgoingCalls((ModuleSpecifier, u32)),
|
||||||
|
/// Resolve inlay hints for a specific text span
|
||||||
|
ProvideInlayHints((ModuleSpecifier, TextSpan, UserPreferences)),
|
||||||
|
|
||||||
// Special request, used only internally by the LSP
|
// Special request, used only internally by the LSP
|
||||||
Restart,
|
Restart,
|
||||||
|
@ -3269,6 +3373,15 @@ impl RequestMethod {
|
||||||
"position": position
|
"position": position
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
RequestMethod::ProvideInlayHints((specifier, span, preferences)) => {
|
||||||
|
json!({
|
||||||
|
"id": id,
|
||||||
|
"method": "provideInlayHints",
|
||||||
|
"specifier": state.denormalize_specifier(specifier),
|
||||||
|
"span": span,
|
||||||
|
"preferences": preferences,
|
||||||
|
})
|
||||||
|
}
|
||||||
RequestMethod::Restart => json!({
|
RequestMethod::Restart => json!({
|
||||||
"id": id,
|
"id": id,
|
||||||
"method": "restart",
|
"method": "restart",
|
||||||
|
|
|
@ -1071,6 +1071,213 @@ fn lsp_hover_disabled() {
|
||||||
shutdown(&mut client);
|
shutdown(&mut client);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn lsp_inlay_hints() {
|
||||||
|
let mut client = init("initialize_params_hints.json");
|
||||||
|
did_open(
|
||||||
|
&mut client,
|
||||||
|
json!({
|
||||||
|
"textDocument": {
|
||||||
|
"uri": "file:///a/file.ts",
|
||||||
|
"languageId": "typescript",
|
||||||
|
"version": 1,
|
||||||
|
"text": r#"function a(b: string) {
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
a("foo");
|
||||||
|
|
||||||
|
enum C {
|
||||||
|
A,
|
||||||
|
}
|
||||||
|
|
||||||
|
parseInt("123", 8);
|
||||||
|
|
||||||
|
const d = Date.now();
|
||||||
|
|
||||||
|
class E {
|
||||||
|
f = Date.now();
|
||||||
|
}
|
||||||
|
|
||||||
|
["a"].map((v) => v + v);
|
||||||
|
"#
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
let (maybe_res, maybe_err) = client
|
||||||
|
.write_request::<_, _, Value>(
|
||||||
|
"textDocument/inlayHint",
|
||||||
|
json!({
|
||||||
|
"textDocument": {
|
||||||
|
"uri": "file:///a/file.ts",
|
||||||
|
},
|
||||||
|
"range": {
|
||||||
|
"start": {
|
||||||
|
"line": 0,
|
||||||
|
"character": 0
|
||||||
|
},
|
||||||
|
"end": {
|
||||||
|
"line": 19,
|
||||||
|
"character": 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
assert!(maybe_err.is_none());
|
||||||
|
assert_eq!(
|
||||||
|
json!(maybe_res),
|
||||||
|
json!([
|
||||||
|
{
|
||||||
|
"position": {
|
||||||
|
"line": 0,
|
||||||
|
"character": 21
|
||||||
|
},
|
||||||
|
"label": ": string",
|
||||||
|
"kind": 1,
|
||||||
|
"paddingLeft": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"position": {
|
||||||
|
"line": 4,
|
||||||
|
"character": 10
|
||||||
|
},
|
||||||
|
"label": "b:",
|
||||||
|
"kind": 2,
|
||||||
|
"paddingRight": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"position": {
|
||||||
|
"line": 7,
|
||||||
|
"character": 11
|
||||||
|
},
|
||||||
|
"label": "= 0",
|
||||||
|
"paddingLeft": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"position": {
|
||||||
|
"line": 10,
|
||||||
|
"character": 17
|
||||||
|
},
|
||||||
|
"label": "string:",
|
||||||
|
"kind": 2,
|
||||||
|
"paddingRight": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"position": {
|
||||||
|
"line": 10,
|
||||||
|
"character": 24
|
||||||
|
},
|
||||||
|
"label": "radix:",
|
||||||
|
"kind": 2,
|
||||||
|
"paddingRight": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"position": {
|
||||||
|
"line": 12,
|
||||||
|
"character": 15
|
||||||
|
},
|
||||||
|
"label": ": number",
|
||||||
|
"kind": 1,
|
||||||
|
"paddingLeft": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"position": {
|
||||||
|
"line": 15,
|
||||||
|
"character": 11
|
||||||
|
},
|
||||||
|
"label": ": number",
|
||||||
|
"kind": 1,
|
||||||
|
"paddingLeft": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"position": {
|
||||||
|
"line": 18,
|
||||||
|
"character": 18
|
||||||
|
},
|
||||||
|
"label": "callbackfn:",
|
||||||
|
"kind": 2,
|
||||||
|
"paddingRight": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"position": {
|
||||||
|
"line": 18,
|
||||||
|
"character": 20
|
||||||
|
},
|
||||||
|
"label": ": string",
|
||||||
|
"kind": 1,
|
||||||
|
"paddingLeft": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"position": {
|
||||||
|
"line": 18,
|
||||||
|
"character": 21
|
||||||
|
},
|
||||||
|
"label": ": string",
|
||||||
|
"kind": 1,
|
||||||
|
"paddingLeft": true
|
||||||
|
}
|
||||||
|
])
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn lsp_inlay_hints_not_enabled() {
|
||||||
|
let mut client = init("initialize_params.json");
|
||||||
|
did_open(
|
||||||
|
&mut client,
|
||||||
|
json!({
|
||||||
|
"textDocument": {
|
||||||
|
"uri": "file:///a/file.ts",
|
||||||
|
"languageId": "typescript",
|
||||||
|
"version": 1,
|
||||||
|
"text": r#"function a(b: string) {
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
a("foo");
|
||||||
|
|
||||||
|
enum C {
|
||||||
|
A,
|
||||||
|
}
|
||||||
|
|
||||||
|
parseInt("123", 8);
|
||||||
|
|
||||||
|
const d = Date.now();
|
||||||
|
|
||||||
|
class E {
|
||||||
|
f = Date.now();
|
||||||
|
}
|
||||||
|
|
||||||
|
["a"].map((v) => v + v);
|
||||||
|
"#
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
let (maybe_res, maybe_err) = client
|
||||||
|
.write_request::<_, _, Value>(
|
||||||
|
"textDocument/inlayHint",
|
||||||
|
json!({
|
||||||
|
"textDocument": {
|
||||||
|
"uri": "file:///a/file.ts",
|
||||||
|
},
|
||||||
|
"range": {
|
||||||
|
"start": {
|
||||||
|
"line": 0,
|
||||||
|
"character": 0
|
||||||
|
},
|
||||||
|
"end": {
|
||||||
|
"line": 19,
|
||||||
|
"character": 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
assert!(maybe_err.is_none());
|
||||||
|
assert_eq!(json!(maybe_res), json!(null));
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn lsp_workspace_enable_paths() {
|
fn lsp_workspace_enable_paths() {
|
||||||
let mut params: lsp::InitializeParams = serde_json::from_value(load_fixture(
|
let mut params: lsp::InitializeParams = serde_json::from_value(load_fixture(
|
||||||
|
|
102
cli/tests/testdata/lsp/initialize_params_hints.json
vendored
Normal file
102
cli/tests/testdata/lsp/initialize_params_hints.json
vendored
Normal file
|
@ -0,0 +1,102 @@
|
||||||
|
{
|
||||||
|
"processId": 0,
|
||||||
|
"clientInfo": {
|
||||||
|
"name": "test-harness",
|
||||||
|
"version": "1.0.0"
|
||||||
|
},
|
||||||
|
"rootUri": null,
|
||||||
|
"initializationOptions": {
|
||||||
|
"enable": true,
|
||||||
|
"cache": null,
|
||||||
|
"certificateStores": null,
|
||||||
|
"codeLens": {
|
||||||
|
"implementations": true,
|
||||||
|
"references": true,
|
||||||
|
"test": true
|
||||||
|
},
|
||||||
|
"config": null,
|
||||||
|
"importMap": null,
|
||||||
|
"inlayHints": {
|
||||||
|
"parameterNames": {
|
||||||
|
"enabled": "all"
|
||||||
|
},
|
||||||
|
"parameterTypes": {
|
||||||
|
"enabled": true
|
||||||
|
},
|
||||||
|
"variableTypes": {
|
||||||
|
"enabled": true
|
||||||
|
},
|
||||||
|
"propertyDeclarationTypes": {
|
||||||
|
"enabled": true
|
||||||
|
},
|
||||||
|
"functionLikeReturnTypes": {
|
||||||
|
"enabled": true
|
||||||
|
},
|
||||||
|
"enumMemberValues": {
|
||||||
|
"enabled": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"lint": true,
|
||||||
|
"suggest": {
|
||||||
|
"autoImports": true,
|
||||||
|
"completeFunctionCalls": false,
|
||||||
|
"names": true,
|
||||||
|
"paths": true,
|
||||||
|
"imports": {
|
||||||
|
"hosts": {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"testing": {
|
||||||
|
"args": [
|
||||||
|
"--allow-all"
|
||||||
|
],
|
||||||
|
"enable": true
|
||||||
|
},
|
||||||
|
"tlsCertificate": null,
|
||||||
|
"unsafelyIgnoreCertificateErrors": null,
|
||||||
|
"unstable": false
|
||||||
|
},
|
||||||
|
"capabilities": {
|
||||||
|
"textDocument": {
|
||||||
|
"codeAction": {
|
||||||
|
"codeActionLiteralSupport": {
|
||||||
|
"codeActionKind": {
|
||||||
|
"valueSet": [
|
||||||
|
"quickfix",
|
||||||
|
"refactor"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"isPreferredSupport": true,
|
||||||
|
"dataSupport": true,
|
||||||
|
"disabledSupport": true,
|
||||||
|
"resolveSupport": {
|
||||||
|
"properties": [
|
||||||
|
"edit"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"completion": {
|
||||||
|
"completionItem": {
|
||||||
|
"snippetSupport": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"foldingRange": {
|
||||||
|
"lineFoldingOnly": true
|
||||||
|
},
|
||||||
|
"synchronization": {
|
||||||
|
"dynamicRegistration": true,
|
||||||
|
"willSave": true,
|
||||||
|
"willSaveWaitUntil": true,
|
||||||
|
"didSave": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"workspace": {
|
||||||
|
"configuration": true,
|
||||||
|
"workspaceFolders": true
|
||||||
|
},
|
||||||
|
"experimental": {
|
||||||
|
"testingApi": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -898,6 +898,15 @@ delete Object.prototype.__proto__;
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
case "provideInlayHints":
|
||||||
|
return respond(
|
||||||
|
id,
|
||||||
|
languageService.provideInlayHints(
|
||||||
|
request.specifier,
|
||||||
|
request.span,
|
||||||
|
request.preferences,
|
||||||
|
),
|
||||||
|
);
|
||||||
default:
|
default:
|
||||||
throw new TypeError(
|
throw new TypeError(
|
||||||
// @ts-ignore exhausted case statement sets type to never
|
// @ts-ignore exhausted case statement sets type to never
|
||||||
|
|
10
cli/tsc/compiler.d.ts
vendored
10
cli/tsc/compiler.d.ts
vendored
|
@ -77,7 +77,8 @@ declare global {
|
||||||
| GetTypeDefinitionRequest
|
| GetTypeDefinitionRequest
|
||||||
| PrepareCallHierarchy
|
| PrepareCallHierarchy
|
||||||
| ProvideCallHierarchyIncomingCalls
|
| ProvideCallHierarchyIncomingCalls
|
||||||
| ProvideCallHierarchyOutgoingCalls;
|
| ProvideCallHierarchyOutgoingCalls
|
||||||
|
| ProvideInlayHints;
|
||||||
|
|
||||||
interface BaseLanguageServerRequest {
|
interface BaseLanguageServerRequest {
|
||||||
id: number;
|
id: number;
|
||||||
|
@ -255,6 +256,13 @@ declare global {
|
||||||
position: number;
|
position: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface ProvideInlayHints extends BaseLanguageServerRequest {
|
||||||
|
method: "provideInlayHints";
|
||||||
|
specifier: string;
|
||||||
|
span: ts.TextSpan;
|
||||||
|
preferences?: ts.UserPreferences;
|
||||||
|
}
|
||||||
|
|
||||||
interface Restart extends BaseLanguageServerRequest {
|
interface Restart extends BaseLanguageServerRequest {
|
||||||
method: "restart";
|
method: "restart";
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue