mirror of
https://github.com/denoland/deno.git
synced 2024-12-21 23:04:45 -05:00
feat(lsp): "deno/didRefreshDenoConfigurationTree" notifications (#26215)
This commit is contained in:
parent
f94cdd1723
commit
06778e4e9b
6 changed files with 304 additions and 13 deletions
|
@ -147,11 +147,11 @@ pub fn server_capabilities(
|
|||
moniker_provider: None,
|
||||
experimental: Some(json!({
|
||||
"denoConfigTasks": true,
|
||||
"testingApi":true,
|
||||
"testingApi": true,
|
||||
"didRefreshDenoConfigurationTreeNotifications": true,
|
||||
})),
|
||||
inlay_hint_provider: Some(OneOf::Left(true)),
|
||||
position_encoding: None,
|
||||
// TODO(nayeemrmn): Support pull-based diagnostics.
|
||||
diagnostic_provider: None,
|
||||
inline_value_provider: None,
|
||||
inline_completion_provider: None,
|
||||
|
|
|
@ -92,6 +92,19 @@ impl Client {
|
|||
});
|
||||
}
|
||||
|
||||
pub fn send_did_refresh_deno_configuration_tree_notification(
|
||||
&self,
|
||||
params: lsp_custom::DidRefreshDenoConfigurationTreeNotificationParams,
|
||||
) {
|
||||
// do on a task in case the caller currently is in the lsp lock
|
||||
let client = self.0.clone();
|
||||
spawn(async move {
|
||||
client
|
||||
.send_did_refresh_deno_configuration_tree_notification(params)
|
||||
.await;
|
||||
});
|
||||
}
|
||||
|
||||
pub fn send_did_change_deno_configuration_notification(
|
||||
&self,
|
||||
params: lsp_custom::DidChangeDenoConfigurationNotificationParams,
|
||||
|
@ -169,6 +182,10 @@ trait ClientTrait: Send + Sync {
|
|||
params: lsp_custom::DiagnosticBatchNotificationParams,
|
||||
);
|
||||
async fn send_test_notification(&self, params: TestingNotification);
|
||||
async fn send_did_refresh_deno_configuration_tree_notification(
|
||||
&self,
|
||||
params: lsp_custom::DidRefreshDenoConfigurationTreeNotificationParams,
|
||||
);
|
||||
async fn send_did_change_deno_configuration_notification(
|
||||
&self,
|
||||
params: lsp_custom::DidChangeDenoConfigurationNotificationParams,
|
||||
|
@ -249,6 +266,18 @@ impl ClientTrait for TowerClient {
|
|||
}
|
||||
}
|
||||
|
||||
async fn send_did_refresh_deno_configuration_tree_notification(
|
||||
&self,
|
||||
params: lsp_custom::DidRefreshDenoConfigurationTreeNotificationParams,
|
||||
) {
|
||||
self
|
||||
.0
|
||||
.send_notification::<lsp_custom::DidRefreshDenoConfigurationTreeNotification>(
|
||||
params,
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
async fn send_did_change_deno_configuration_notification(
|
||||
&self,
|
||||
params: lsp_custom::DidChangeDenoConfigurationNotificationParams,
|
||||
|
@ -366,6 +395,12 @@ impl ClientTrait for ReplClient {
|
|||
|
||||
async fn send_test_notification(&self, _params: TestingNotification) {}
|
||||
|
||||
async fn send_did_refresh_deno_configuration_tree_notification(
|
||||
&self,
|
||||
_params: lsp_custom::DidRefreshDenoConfigurationTreeNotificationParams,
|
||||
) {
|
||||
}
|
||||
|
||||
async fn send_did_change_deno_configuration_notification(
|
||||
&self,
|
||||
_params: lsp_custom::DidChangeDenoConfigurationNotificationParams,
|
||||
|
|
|
@ -50,6 +50,8 @@ use std::sync::Arc;
|
|||
use tower_lsp::lsp_types as lsp;
|
||||
|
||||
use super::logging::lsp_log;
|
||||
use super::lsp_custom;
|
||||
use super::urls::url_to_uri;
|
||||
use crate::args::discover_npmrc_from_workspace;
|
||||
use crate::args::has_flag_env_var;
|
||||
use crate::args::CliLockfile;
|
||||
|
@ -1716,14 +1718,14 @@ impl ConfigTree {
|
|||
.unwrap_or_else(|| Arc::new(FmtConfig::new_with_base(PathBuf::from("/"))))
|
||||
}
|
||||
|
||||
/// Returns (scope_uri, type).
|
||||
/// Returns (scope_url, type).
|
||||
pub fn watched_file_type(
|
||||
&self,
|
||||
specifier: &ModuleSpecifier,
|
||||
) -> Option<(&ModuleSpecifier, ConfigWatchedFileType)> {
|
||||
for (scope_uri, data) in self.scopes.iter() {
|
||||
for (scope_url, data) in self.scopes.iter() {
|
||||
if let Some(typ) = data.watched_files.get(specifier) {
|
||||
return Some((scope_uri, *typ));
|
||||
return Some((scope_url, *typ));
|
||||
}
|
||||
}
|
||||
None
|
||||
|
@ -1747,6 +1749,46 @@ impl ConfigTree {
|
|||
.any(|data| data.watched_files.contains_key(specifier))
|
||||
}
|
||||
|
||||
pub fn to_did_refresh_params(
|
||||
&self,
|
||||
) -> lsp_custom::DidRefreshDenoConfigurationTreeNotificationParams {
|
||||
let data = self
|
||||
.scopes
|
||||
.values()
|
||||
.filter_map(|data| {
|
||||
let workspace_root_scope_uri =
|
||||
Some(data.member_dir.workspace.root_dir())
|
||||
.filter(|s| *s != data.member_dir.dir_url())
|
||||
.and_then(|s| url_to_uri(s).ok());
|
||||
Some(lsp_custom::DenoConfigurationData {
|
||||
scope_uri: url_to_uri(&data.scope).ok()?,
|
||||
deno_json: data.maybe_deno_json().and_then(|c| {
|
||||
if workspace_root_scope_uri.is_some()
|
||||
&& Some(&c.specifier)
|
||||
== data
|
||||
.member_dir
|
||||
.workspace
|
||||
.root_deno_json()
|
||||
.map(|c| &c.specifier)
|
||||
{
|
||||
return None;
|
||||
}
|
||||
Some(lsp::TextDocumentIdentifier {
|
||||
uri: url_to_uri(&c.specifier).ok()?,
|
||||
})
|
||||
}),
|
||||
package_json: data.maybe_pkg_json().and_then(|p| {
|
||||
Some(lsp::TextDocumentIdentifier {
|
||||
uri: url_to_uri(&p.specifier()).ok()?,
|
||||
})
|
||||
}),
|
||||
workspace_root_scope_uri,
|
||||
})
|
||||
})
|
||||
.collect();
|
||||
lsp_custom::DidRefreshDenoConfigurationTreeNotificationParams { data }
|
||||
}
|
||||
|
||||
pub async fn refresh(
|
||||
&mut self,
|
||||
settings: &Settings,
|
||||
|
|
|
@ -963,6 +963,11 @@ impl Inner {
|
|||
.tree
|
||||
.refresh(&self.config.settings, &self.workspace_files, &file_fetcher)
|
||||
.await;
|
||||
self
|
||||
.client
|
||||
.send_did_refresh_deno_configuration_tree_notification(
|
||||
self.config.tree.to_did_refresh_params(),
|
||||
);
|
||||
for config_file in self.config.tree.config_files() {
|
||||
(|| {
|
||||
let compiler_options = config_file.to_compiler_options().ok()?.options;
|
||||
|
|
|
@ -46,6 +46,30 @@ pub struct DiagnosticBatchNotificationParams {
|
|||
pub messages_len: usize,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct DenoConfigurationData {
|
||||
pub scope_uri: lsp::Uri,
|
||||
pub workspace_root_scope_uri: Option<lsp::Uri>,
|
||||
pub deno_json: Option<lsp::TextDocumentIdentifier>,
|
||||
pub package_json: Option<lsp::TextDocumentIdentifier>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct DidRefreshDenoConfigurationTreeNotificationParams {
|
||||
pub data: Vec<DenoConfigurationData>,
|
||||
}
|
||||
|
||||
pub enum DidRefreshDenoConfigurationTreeNotification {}
|
||||
|
||||
impl lsp::notification::Notification
|
||||
for DidRefreshDenoConfigurationTreeNotification
|
||||
{
|
||||
type Params = DidRefreshDenoConfigurationTreeNotificationParams;
|
||||
const METHOD: &'static str = "deno/didRefreshDenoConfigurationTree";
|
||||
}
|
||||
|
||||
#[derive(Debug, Eq, Hash, PartialEq, Copy, Clone, Deserialize, Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub enum DenoConfigurationChangeType {
|
||||
|
@ -88,13 +112,15 @@ pub struct DidChangeDenoConfigurationNotificationParams {
|
|||
pub changes: Vec<DenoConfigurationChangeEvent>,
|
||||
}
|
||||
|
||||
// TODO(nayeemrmn): This is being replaced by
|
||||
// `DidRefreshDenoConfigurationTreeNotification` for Deno > v2.0.0. Remove it
|
||||
// soon.
|
||||
pub enum DidChangeDenoConfigurationNotification {}
|
||||
|
||||
impl lsp::notification::Notification
|
||||
for DidChangeDenoConfigurationNotification
|
||||
{
|
||||
type Params = DidChangeDenoConfigurationNotificationParams;
|
||||
|
||||
const METHOD: &'static str = "deno/didChangeDenoConfiguration";
|
||||
}
|
||||
|
||||
|
@ -102,7 +128,6 @@ pub enum DidUpgradeCheckNotification {}
|
|||
|
||||
impl lsp::notification::Notification for DidUpgradeCheckNotification {
|
||||
type Params = DidUpgradeCheckNotificationParams;
|
||||
|
||||
const METHOD: &'static str = "deno/didUpgradeCheck";
|
||||
}
|
||||
|
||||
|
@ -125,6 +150,5 @@ pub enum DiagnosticBatchNotification {}
|
|||
|
||||
impl lsp::notification::Notification for DiagnosticBatchNotification {
|
||||
type Params = DiagnosticBatchNotificationParams;
|
||||
|
||||
const METHOD: &'static str = "deno/internalTestDiagnosticBatch";
|
||||
}
|
||||
|
|
|
@ -1049,6 +1049,191 @@ fn lsp_workspace_enable_paths_no_workspace_configuration() {
|
|||
client.shutdown();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn lsp_did_refresh_deno_configuration_tree_notification() {
|
||||
let context = TestContextBuilder::new().use_temp_cwd().build();
|
||||
let temp_dir = context.temp_dir();
|
||||
temp_dir.create_dir_all("workspace/member1");
|
||||
temp_dir.create_dir_all("workspace/member2");
|
||||
temp_dir.create_dir_all("non_workspace1");
|
||||
temp_dir.create_dir_all("non_workspace2");
|
||||
temp_dir.write(
|
||||
"workspace/deno.json",
|
||||
json!({
|
||||
"workspace": [
|
||||
"member1",
|
||||
"member2",
|
||||
],
|
||||
})
|
||||
.to_string(),
|
||||
);
|
||||
temp_dir.write("workspace/member1/deno.json", json!({}).to_string());
|
||||
temp_dir.write("workspace/member1/package.json", json!({}).to_string());
|
||||
temp_dir.write("workspace/member2/package.json", json!({}).to_string());
|
||||
temp_dir.write("non_workspace1/deno.json", json!({}).to_string());
|
||||
let mut client = context.new_lsp_command().build();
|
||||
client.initialize_default();
|
||||
let res = client
|
||||
.read_notification_with_method::<Value>(
|
||||
"deno/didRefreshDenoConfigurationTree",
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
res,
|
||||
json!({
|
||||
"data": [
|
||||
{
|
||||
"scopeUri": temp_dir.url().join("non_workspace1/").unwrap(),
|
||||
"workspaceRootScopeUri": null,
|
||||
"denoJson": {
|
||||
"uri": temp_dir.url().join("non_workspace1/deno.json").unwrap(),
|
||||
},
|
||||
"packageJson": null,
|
||||
},
|
||||
{
|
||||
"scopeUri": temp_dir.url().join("workspace/").unwrap(),
|
||||
"workspaceRootScopeUri": null,
|
||||
"denoJson": {
|
||||
"uri": temp_dir.url().join("workspace/deno.json").unwrap(),
|
||||
},
|
||||
"packageJson": null,
|
||||
},
|
||||
{
|
||||
"scopeUri": temp_dir.url().join("workspace/member1/").unwrap(),
|
||||
"workspaceRootScopeUri": temp_dir.url().join("workspace/").unwrap(),
|
||||
"denoJson": {
|
||||
"uri": temp_dir.url().join("workspace/member1/deno.json").unwrap(),
|
||||
},
|
||||
"packageJson": {
|
||||
"uri": temp_dir.url().join("workspace/member1/package.json").unwrap(),
|
||||
},
|
||||
},
|
||||
{
|
||||
"scopeUri": temp_dir.url().join("workspace/member2/").unwrap(),
|
||||
"workspaceRootScopeUri": temp_dir.url().join("workspace/").unwrap(),
|
||||
"denoJson": null,
|
||||
"packageJson": {
|
||||
"uri": temp_dir.url().join("workspace/member2/package.json").unwrap(),
|
||||
},
|
||||
},
|
||||
],
|
||||
}),
|
||||
);
|
||||
temp_dir.write("non_workspace2/deno.json", json!({}).to_string());
|
||||
client.did_change_watched_files(json!({
|
||||
"changes": [{
|
||||
"uri": temp_dir.url().join("non_workspace2/deno.json").unwrap(),
|
||||
"type": 1,
|
||||
}],
|
||||
}));
|
||||
let res = client
|
||||
.read_notification_with_method::<Value>(
|
||||
"deno/didRefreshDenoConfigurationTree",
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
res,
|
||||
json!({
|
||||
"data": [
|
||||
{
|
||||
"scopeUri": temp_dir.url().join("non_workspace1/").unwrap(),
|
||||
"workspaceRootScopeUri": null,
|
||||
"denoJson": {
|
||||
"uri": temp_dir.url().join("non_workspace1/deno.json").unwrap(),
|
||||
},
|
||||
"packageJson": null,
|
||||
},
|
||||
{
|
||||
"scopeUri": temp_dir.url().join("non_workspace2/").unwrap(),
|
||||
"workspaceRootScopeUri": null,
|
||||
"denoJson": {
|
||||
"uri": temp_dir.url().join("non_workspace2/deno.json").unwrap(),
|
||||
},
|
||||
"packageJson": null,
|
||||
},
|
||||
{
|
||||
"scopeUri": temp_dir.url().join("workspace/").unwrap(),
|
||||
"workspaceRootScopeUri": null,
|
||||
"denoJson": {
|
||||
"uri": temp_dir.url().join("workspace/deno.json").unwrap(),
|
||||
},
|
||||
"packageJson": null,
|
||||
},
|
||||
{
|
||||
"scopeUri": temp_dir.url().join("workspace/member1/").unwrap(),
|
||||
"workspaceRootScopeUri": temp_dir.url().join("workspace/").unwrap(),
|
||||
"denoJson": {
|
||||
"uri": temp_dir.url().join("workspace/member1/deno.json").unwrap(),
|
||||
},
|
||||
"packageJson": {
|
||||
"uri": temp_dir.url().join("workspace/member1/package.json").unwrap(),
|
||||
},
|
||||
},
|
||||
{
|
||||
"scopeUri": temp_dir.url().join("workspace/member2/").unwrap(),
|
||||
"workspaceRootScopeUri": temp_dir.url().join("workspace/").unwrap(),
|
||||
"denoJson": null,
|
||||
"packageJson": {
|
||||
"uri": temp_dir.url().join("workspace/member2/package.json").unwrap(),
|
||||
},
|
||||
},
|
||||
],
|
||||
}),
|
||||
);
|
||||
client.change_configuration(json!({
|
||||
"deno": {
|
||||
"disablePaths": ["non_workspace1"],
|
||||
},
|
||||
}));
|
||||
let res = client
|
||||
.read_notification_with_method::<Value>(
|
||||
"deno/didRefreshDenoConfigurationTree",
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
res,
|
||||
json!({
|
||||
"data": [
|
||||
{
|
||||
"scopeUri": temp_dir.url().join("non_workspace2/").unwrap(),
|
||||
"workspaceRootScopeUri": null,
|
||||
"denoJson": {
|
||||
"uri": temp_dir.url().join("non_workspace2/deno.json").unwrap(),
|
||||
},
|
||||
"packageJson": null,
|
||||
},
|
||||
{
|
||||
"scopeUri": temp_dir.url().join("workspace/").unwrap(),
|
||||
"workspaceRootScopeUri": null,
|
||||
"denoJson": {
|
||||
"uri": temp_dir.url().join("workspace/deno.json").unwrap(),
|
||||
},
|
||||
"packageJson": null,
|
||||
},
|
||||
{
|
||||
"scopeUri": temp_dir.url().join("workspace/member1/").unwrap(),
|
||||
"workspaceRootScopeUri": temp_dir.url().join("workspace/").unwrap(),
|
||||
"denoJson": {
|
||||
"uri": temp_dir.url().join("workspace/member1/deno.json").unwrap(),
|
||||
},
|
||||
"packageJson": {
|
||||
"uri": temp_dir.url().join("workspace/member1/package.json").unwrap(),
|
||||
},
|
||||
},
|
||||
{
|
||||
"scopeUri": temp_dir.url().join("workspace/member2/").unwrap(),
|
||||
"workspaceRootScopeUri": temp_dir.url().join("workspace/").unwrap(),
|
||||
"denoJson": null,
|
||||
"packageJson": {
|
||||
"uri": temp_dir.url().join("workspace/member2/package.json").unwrap(),
|
||||
},
|
||||
},
|
||||
],
|
||||
}),
|
||||
);
|
||||
client.shutdown();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn lsp_did_change_deno_configuration_notification() {
|
||||
let context = TestContextBuilder::new().use_temp_cwd().build();
|
||||
|
@ -9403,14 +9588,15 @@ fn lsp_auto_discover_registry() {
|
|||
"triggerCharacter": "@"
|
||||
}),
|
||||
);
|
||||
let (method, res) = client.read_notification();
|
||||
assert_eq!(method, "deno/registryState");
|
||||
let res = client
|
||||
.read_notification_with_method::<Value>("deno/registryState")
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
res,
|
||||
Some(json!({
|
||||
json!({
|
||||
"origin": "http://localhost:4545",
|
||||
"suggestions": true,
|
||||
}))
|
||||
}),
|
||||
);
|
||||
client.shutdown();
|
||||
}
|
||||
|
@ -10117,7 +10303,6 @@ fn lsp_diagnostics_refresh_dependents() {
|
|||
assert_eq!(json!(diagnostics.all()), json!([])); // no diagnostics now
|
||||
|
||||
client.shutdown();
|
||||
assert_eq!(client.queue_len(), 0);
|
||||
}
|
||||
|
||||
// Regression test for https://github.com/denoland/deno/issues/10897.
|
||||
|
|
Loading…
Reference in a new issue