Remove 2 suffix for fs, db, semantic_index, prettier

Co-authored-by: Mikayla <mikayla@zed.dev>
This commit is contained in:
Max Brunsfeld 2024-01-03 12:09:08 -08:00
parent 324ac96977
commit 5ddd298b4d
75 changed files with 455 additions and 12973 deletions

View file

@ -15,7 +15,7 @@ test-support = []
client = { path = "../client" }
collections = { path = "../collections"}
language = { path = "../language" }
gpui = { path = "../gpui" }
gpui = { package = "gpui2", path = "../gpui2" }
fs = { path = "../fs" }
lsp = { path = "../lsp" }
node_runtime = { path = "../node_runtime"}
@ -31,5 +31,5 @@ parking_lot.workspace = true
[dev-dependencies]
language = { path = "../language", features = ["test-support"] }
gpui = { path = "../gpui", features = ["test-support"] }
gpui = { package = "gpui2", path = "../gpui2", features = ["test-support"] }
fs = { path = "../fs", features = ["test-support"] }

View file

@ -1,16 +1,16 @@
use std::ops::ControlFlow;
use std::path::{Path, PathBuf};
use std::sync::Arc;
use anyhow::Context;
use collections::{HashMap, HashSet};
use fs::Fs;
use gpui::{AsyncAppContext, ModelHandle};
use language::language_settings::language_settings;
use language::{Buffer, Diff};
use gpui::{AsyncAppContext, Model};
use language::{language_settings::language_settings, Buffer, Diff};
use lsp::{LanguageServer, LanguageServerId};
use node_runtime::NodeRuntime;
use serde::{Deserialize, Serialize};
use std::{
ops::ControlFlow,
path::{Path, PathBuf},
sync::Arc,
};
use util::paths::{PathMatcher, DEFAULT_PRETTIER_DIR};
#[derive(Clone)]
@ -100,39 +100,39 @@ impl Prettier {
}
} else {
match package_json_contents.get("workspaces") {
Some(serde_json::Value::Array(workspaces)) => {
match &project_path_with_prettier_dependency {
Some(project_path_with_prettier_dependency) => {
let subproject_path = project_path_with_prettier_dependency.strip_prefix(&path_to_check).expect("traversing path parents, should be able to strip prefix");
if workspaces.iter().filter_map(|value| {
if let serde_json::Value::String(s) = value {
Some(s.clone())
Some(serde_json::Value::Array(workspaces)) => {
match &project_path_with_prettier_dependency {
Some(project_path_with_prettier_dependency) => {
let subproject_path = project_path_with_prettier_dependency.strip_prefix(&path_to_check).expect("traversing path parents, should be able to strip prefix");
if workspaces.iter().filter_map(|value| {
if let serde_json::Value::String(s) = value {
Some(s.clone())
} else {
log::warn!("Skipping non-string 'workspaces' value: {value:?}");
None
}
}).any(|workspace_definition| {
if let Some(path_matcher) = PathMatcher::new(&workspace_definition).ok() {
path_matcher.is_match(subproject_path)
} else {
workspace_definition == subproject_path.to_string_lossy()
}
}) {
anyhow::ensure!(has_prettier_in_node_modules(fs, &path_to_check).await?, "Found prettier path {path_to_check:?} in the workspace root for project in {project_path_with_prettier_dependency:?}, but it's not installed into workspace root's node_modules");
log::info!("Found prettier path {path_to_check:?} in the workspace root for project in {project_path_with_prettier_dependency:?}");
return Ok(ControlFlow::Continue(Some(path_to_check)));
} else {
log::warn!("Skipping non-string 'workspaces' value: {value:?}");
None
log::warn!("Skipping path {path_to_check:?} that has prettier in its 'node_modules' subdirectory, but is not included in its package.json workspaces {workspaces:?}");
}
}).any(|workspace_definition| {
if let Some(path_matcher) = PathMatcher::new(&workspace_definition).ok() {
path_matcher.is_match(subproject_path)
} else {
workspace_definition == subproject_path.to_string_lossy()
}
}) {
anyhow::ensure!(has_prettier_in_node_modules(fs, &path_to_check).await?, "Found prettier path {path_to_check:?} in the workspace root for project in {project_path_with_prettier_dependency:?}, but it's not installed into workspace root's node_modules");
log::info!("Found prettier path {path_to_check:?} in the workspace root for project in {project_path_with_prettier_dependency:?}");
return Ok(ControlFlow::Continue(Some(path_to_check)));
} else {
log::warn!("Skipping path {path_to_check:?} that has prettier in its 'node_modules' subdirectory, but is not included in its package.json workspaces {workspaces:?}");
}
None => {
log::warn!("Skipping path {path_to_check:?} that has prettier in its 'node_modules' subdirectory, but has no prettier in its package.json");
}
}
None => {
log::warn!("Skipping path {path_to_check:?} that has prettier in its 'node_modules' subdirectory, but has no prettier in its package.json");
}
}
},
Some(unknown) => log::error!("Failed to parse workspaces for {path_to_check:?} from package.json, got {unknown:?}. Skipping."),
None => log::warn!("Skipping path {path_to_check:?} that has no prettier dependency and no workspaces section in its package.json"),
}
},
Some(unknown) => log::error!("Failed to parse workspaces for {path_to_check:?} from package.json, got {unknown:?}. Skipping."),
None => log::warn!("Skipping path {path_to_check:?} that has no prettier dependency and no workspaces section in its package.json"),
}
}
}
@ -172,7 +172,7 @@ impl Prettier {
) -> anyhow::Result<Self> {
use lsp::LanguageServerBinary;
let background = cx.background();
let executor = cx.background_executor().clone();
anyhow::ensure!(
prettier_dir.is_dir(),
"Prettier dir {prettier_dir:?} is not a directory"
@ -183,7 +183,7 @@ impl Prettier {
"no prettier server package found at {prettier_server:?}"
);
let node_path = background
let node_path = executor
.spawn(async move { node.binary_path().await })
.await?;
let server = LanguageServer::new(
@ -198,7 +198,7 @@ impl Prettier {
cx,
)
.context("prettier server creation")?;
let server = background
let server = executor
.spawn(server.initialize(None))
.await
.context("prettier server initialization")?;
@ -211,124 +211,154 @@ impl Prettier {
pub async fn format(
&self,
buffer: &ModelHandle<Buffer>,
buffer: &Model<Buffer>,
buffer_path: Option<PathBuf>,
cx: &AsyncAppContext,
cx: &mut AsyncAppContext,
) -> anyhow::Result<Diff> {
match self {
Self::Real(local) => {
let params = buffer.read_with(cx, |buffer, cx| {
let buffer_language = buffer.language();
let parser_with_plugins = buffer_language.and_then(|l| {
let prettier_parser = l.prettier_parser_name()?;
let mut prettier_plugins = l
.lsp_adapters()
.iter()
.flat_map(|adapter| adapter.prettier_plugins())
.collect::<Vec<_>>();
prettier_plugins.dedup();
Some((prettier_parser, prettier_plugins))
});
let params = buffer
.update(cx, |buffer, cx| {
let buffer_language = buffer.language();
let parser_with_plugins = buffer_language.and_then(|l| {
let prettier_parser = l.prettier_parser_name()?;
let mut prettier_plugins = l
.lsp_adapters()
.iter()
.flat_map(|adapter| adapter.prettier_plugins())
.collect::<Vec<_>>();
prettier_plugins.dedup();
Some((prettier_parser, prettier_plugins))
});
let prettier_node_modules = self.prettier_dir().join("node_modules");
anyhow::ensure!(prettier_node_modules.is_dir(), "Prettier node_modules dir does not exist: {prettier_node_modules:?}");
let plugin_name_into_path = |plugin_name: &str| {
let prettier_plugin_dir = prettier_node_modules.join(plugin_name);
for possible_plugin_path in [
prettier_plugin_dir.join("dist").join("index.mjs"),
prettier_plugin_dir.join("dist").join("index.js"),
prettier_plugin_dir.join("dist").join("plugin.js"),
prettier_plugin_dir.join("index.mjs"),
prettier_plugin_dir.join("index.js"),
prettier_plugin_dir.join("plugin.js"),
prettier_plugin_dir,
] {
if possible_plugin_path.is_file() {
return Some(possible_plugin_path);
}
}
None
};
let (parser, located_plugins) = match parser_with_plugins {
Some((parser, plugins)) => {
// Tailwind plugin requires being added last
// https://github.com/tailwindlabs/prettier-plugin-tailwindcss#compatibility-with-other-prettier-plugins
let mut add_tailwind_back = false;
let mut plugins = plugins.into_iter().filter(|&&plugin_name| {
if plugin_name == TAILWIND_PRETTIER_PLUGIN_PACKAGE_NAME {
add_tailwind_back = true;
false
} else {
true
let prettier_node_modules = self.prettier_dir().join("node_modules");
anyhow::ensure!(
prettier_node_modules.is_dir(),
"Prettier node_modules dir does not exist: {prettier_node_modules:?}"
);
let plugin_name_into_path = |plugin_name: &str| {
let prettier_plugin_dir = prettier_node_modules.join(plugin_name);
for possible_plugin_path in [
prettier_plugin_dir.join("dist").join("index.mjs"),
prettier_plugin_dir.join("dist").join("index.js"),
prettier_plugin_dir.join("dist").join("plugin.js"),
prettier_plugin_dir.join("index.mjs"),
prettier_plugin_dir.join("index.js"),
prettier_plugin_dir.join("plugin.js"),
prettier_plugin_dir,
] {
if possible_plugin_path.is_file() {
return Some(possible_plugin_path);
}
}).map(|plugin_name| (plugin_name, plugin_name_into_path(plugin_name))).collect::<Vec<_>>();
if add_tailwind_back {
plugins.push((&TAILWIND_PRETTIER_PLUGIN_PACKAGE_NAME, plugin_name_into_path(TAILWIND_PRETTIER_PLUGIN_PACKAGE_NAME)));
}
(Some(parser.to_string()), plugins)
},
None => (None, Vec::new()),
};
None
};
let (parser, located_plugins) = match parser_with_plugins {
Some((parser, plugins)) => {
// Tailwind plugin requires being added last
// https://github.com/tailwindlabs/prettier-plugin-tailwindcss#compatibility-with-other-prettier-plugins
let mut add_tailwind_back = false;
let prettier_options = if self.is_default() {
let language_settings = language_settings(buffer_language, buffer.file(), cx);
let mut options = language_settings.prettier.clone();
if !options.contains_key("tabWidth") {
options.insert(
"tabWidth".to_string(),
serde_json::Value::Number(serde_json::Number::from(
language_settings.tab_size.get(),
)),
);
}
if !options.contains_key("printWidth") {
options.insert(
"printWidth".to_string(),
serde_json::Value::Number(serde_json::Number::from(
language_settings.preferred_line_length,
)),
);
}
Some(options)
} else {
None
};
let mut plugins = plugins
.into_iter()
.filter(|&&plugin_name| {
if plugin_name == TAILWIND_PRETTIER_PLUGIN_PACKAGE_NAME {
add_tailwind_back = true;
false
} else {
true
}
})
.map(|plugin_name| {
(plugin_name, plugin_name_into_path(plugin_name))
})
.collect::<Vec<_>>();
if add_tailwind_back {
plugins.push((
&TAILWIND_PRETTIER_PLUGIN_PACKAGE_NAME,
plugin_name_into_path(
TAILWIND_PRETTIER_PLUGIN_PACKAGE_NAME,
),
));
}
(Some(parser.to_string()), plugins)
}
None => (None, Vec::new()),
};
let plugins = located_plugins.into_iter().filter_map(|(plugin_name, located_plugin_path)| {
match located_plugin_path {
Some(path) => Some(path),
None => {
log::error!("Have not found plugin path for {plugin_name:?} inside {prettier_node_modules:?}");
None},
}
}).collect();
log::debug!("Formatting file {:?} with prettier, plugins :{plugins:?}, options: {prettier_options:?}", buffer.file().map(|f| f.full_path(cx)));
let prettier_options = if self.is_default() {
let language_settings =
language_settings(buffer_language, buffer.file(), cx);
let mut options = language_settings.prettier.clone();
if !options.contains_key("tabWidth") {
options.insert(
"tabWidth".to_string(),
serde_json::Value::Number(serde_json::Number::from(
language_settings.tab_size.get(),
)),
);
}
if !options.contains_key("printWidth") {
options.insert(
"printWidth".to_string(),
serde_json::Value::Number(serde_json::Number::from(
language_settings.preferred_line_length,
)),
);
}
Some(options)
} else {
None
};
anyhow::Ok(FormatParams {
text: buffer.text(),
options: FormatOptions {
parser,
let plugins = located_plugins
.into_iter()
.filter_map(|(plugin_name, located_plugin_path)| {
match located_plugin_path {
Some(path) => Some(path),
None => {
log::error!(
"Have not found plugin path for {:?} inside {:?}",
plugin_name,
prettier_node_modules
);
None
}
}
})
.collect();
log::debug!(
"Formatting file {:?} with prettier, plugins :{:?}, options: {:?}",
plugins,
path: buffer_path,
prettier_options,
},
})
}).context("prettier params calculation")?;
buffer.file().map(|f| f.full_path(cx))
);
anyhow::Ok(FormatParams {
text: buffer.text(),
options: FormatOptions {
parser,
plugins,
path: buffer_path,
prettier_options,
},
})
})?
.context("prettier params calculation")?;
let response = local
.server
.request::<Format>(params)
.await
.context("prettier format request")?;
let diff_task = buffer.read_with(cx, |buffer, cx| buffer.diff(response.text, cx));
let diff_task = buffer.update(cx, |buffer, cx| buffer.diff(response.text, cx))?;
Ok(diff_task.await)
}
#[cfg(any(test, feature = "test-support"))]
Self::Test(_) => Ok(buffer
.read_with(cx, |buffer, cx| {
.update(cx, |buffer, cx| {
let formatted_text = buffer.text() + FORMAT_SUFFIX;
buffer.diff(formatted_text, cx)
})
})?
.await),
}
}
@ -471,7 +501,7 @@ mod tests {
#[gpui::test]
async fn test_prettier_lookup_finds_nothing(cx: &mut gpui::TestAppContext) {
let fs = FakeFs::new(cx.background());
let fs = FakeFs::new(cx.executor());
fs.insert_tree(
"/root",
json!({
@ -547,7 +577,7 @@ mod tests {
#[gpui::test]
async fn test_prettier_lookup_in_simple_npm_projects(cx: &mut gpui::TestAppContext) {
let fs = FakeFs::new(cx.background());
let fs = FakeFs::new(cx.executor());
fs.insert_tree(
"/root",
json!({
@ -612,7 +642,7 @@ mod tests {
#[gpui::test]
async fn test_prettier_lookup_for_not_installed(cx: &mut gpui::TestAppContext) {
let fs = FakeFs::new(cx.background());
let fs = FakeFs::new(cx.executor());
fs.insert_tree(
"/root",
json!({
@ -662,6 +692,7 @@ mod tests {
assert!(message.contains("/root/work/web_blog"), "Error message should mention which project had prettier defined");
},
};
assert_eq!(
Prettier::locate_prettier_installation(
fs.as_ref(),
@ -704,7 +735,7 @@ mod tests {
#[gpui::test]
async fn test_prettier_lookup_in_npm_workspaces(cx: &mut gpui::TestAppContext) {
let fs = FakeFs::new(cx.background());
let fs = FakeFs::new(cx.executor());
fs.insert_tree(
"/root",
json!({
@ -785,7 +816,7 @@ mod tests {
async fn test_prettier_lookup_in_npm_workspaces_for_not_installed(
cx: &mut gpui::TestAppContext,
) {
let fs = FakeFs::new(cx.background());
let fs = FakeFs::new(cx.executor());
fs.insert_tree(
"/root",
json!({