Compare commits
6 Commits
scan-code
...
v0.112.2-p
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
67068faa1d | ||
|
|
1d175b4848 | ||
|
|
c51d54d86d | ||
|
|
dc55644e7d | ||
|
|
af9af3ff74 | ||
|
|
8539d97f43 |
2
Cargo.lock
generated
2
Cargo.lock
generated
@@ -11078,7 +11078,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "zed"
|
||||
version = "0.112.0"
|
||||
version = "0.112.2"
|
||||
dependencies = [
|
||||
"activity_indicator",
|
||||
"ai",
|
||||
|
||||
@@ -1692,14 +1692,25 @@ fn test_language_scope_at_with_javascript(cx: &mut AppContext) {
|
||||
r#"
|
||||
(jsx_element) @element
|
||||
(string) @string
|
||||
[
|
||||
(jsx_opening_element)
|
||||
(jsx_closing_element)
|
||||
(jsx_expression)
|
||||
] @default
|
||||
"#,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let text = r#"a["b"] = <C d="e"></C>;"#;
|
||||
let text = r#"
|
||||
a["b"] = <C d="e">
|
||||
<F></F>
|
||||
{ g() }
|
||||
</C>;
|
||||
"#
|
||||
.unindent();
|
||||
|
||||
let buffer =
|
||||
Buffer::new(0, cx.model_id() as u64, text).with_language(Arc::new(language), cx);
|
||||
Buffer::new(0, cx.model_id() as u64, &text).with_language(Arc::new(language), cx);
|
||||
let snapshot = buffer.snapshot();
|
||||
|
||||
let config = snapshot.language_scope_at(0).unwrap();
|
||||
@@ -1710,7 +1721,9 @@ fn test_language_scope_at_with_javascript(cx: &mut AppContext) {
|
||||
&[true, true]
|
||||
);
|
||||
|
||||
let string_config = snapshot.language_scope_at(3).unwrap();
|
||||
let string_config = snapshot
|
||||
.language_scope_at(text.find("b\"").unwrap())
|
||||
.unwrap();
|
||||
assert_eq!(string_config.line_comment_prefix().unwrap().as_ref(), "// ");
|
||||
// Second bracket pair is disabled
|
||||
assert_eq!(
|
||||
@@ -1718,18 +1731,49 @@ fn test_language_scope_at_with_javascript(cx: &mut AppContext) {
|
||||
&[true, false]
|
||||
);
|
||||
|
||||
let element_config = snapshot.language_scope_at(10).unwrap();
|
||||
// In between JSX tags: use the `element` override.
|
||||
let element_config = snapshot
|
||||
.language_scope_at(text.find("<F>").unwrap())
|
||||
.unwrap();
|
||||
assert_eq!(element_config.line_comment_prefix(), None);
|
||||
assert_eq!(
|
||||
element_config.block_comment_delimiters(),
|
||||
Some((&"{/*".into(), &"*/}".into()))
|
||||
);
|
||||
// Both bracket pairs are enabled
|
||||
assert_eq!(
|
||||
element_config.brackets().map(|e| e.1).collect::<Vec<_>>(),
|
||||
&[true, true]
|
||||
);
|
||||
|
||||
// Within a JSX tag: use the default config.
|
||||
let tag_config = snapshot
|
||||
.language_scope_at(text.find(" d=").unwrap() + 1)
|
||||
.unwrap();
|
||||
assert_eq!(tag_config.line_comment_prefix().unwrap().as_ref(), "// ");
|
||||
assert_eq!(
|
||||
tag_config.brackets().map(|e| e.1).collect::<Vec<_>>(),
|
||||
&[true, true]
|
||||
);
|
||||
|
||||
// In a JSX expression: use the default config.
|
||||
let expression_in_element_config = snapshot
|
||||
.language_scope_at(text.find("{").unwrap() + 1)
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
expression_in_element_config
|
||||
.line_comment_prefix()
|
||||
.unwrap()
|
||||
.as_ref(),
|
||||
"// "
|
||||
);
|
||||
assert_eq!(
|
||||
expression_in_element_config
|
||||
.brackets()
|
||||
.map(|e| e.1)
|
||||
.collect::<Vec<_>>(),
|
||||
&[true, true]
|
||||
);
|
||||
|
||||
buffer
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1696,14 +1696,25 @@ fn test_language_scope_at_with_javascript(cx: &mut AppContext) {
|
||||
r#"
|
||||
(jsx_element) @element
|
||||
(string) @string
|
||||
[
|
||||
(jsx_opening_element)
|
||||
(jsx_closing_element)
|
||||
(jsx_expression)
|
||||
] @default
|
||||
"#,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let text = r#"a["b"] = <C d="e"></C>;"#;
|
||||
let text = r#"
|
||||
a["b"] = <C d="e">
|
||||
<F></F>
|
||||
{ g() }
|
||||
</C>;
|
||||
"#
|
||||
.unindent();
|
||||
|
||||
let buffer =
|
||||
Buffer::new(0, cx.entity_id().as_u64(), text).with_language(Arc::new(language), cx);
|
||||
Buffer::new(0, cx.entity_id().as_u64(), &text).with_language(Arc::new(language), cx);
|
||||
let snapshot = buffer.snapshot();
|
||||
|
||||
let config = snapshot.language_scope_at(0).unwrap();
|
||||
@@ -1714,7 +1725,9 @@ fn test_language_scope_at_with_javascript(cx: &mut AppContext) {
|
||||
&[true, true]
|
||||
);
|
||||
|
||||
let string_config = snapshot.language_scope_at(3).unwrap();
|
||||
let string_config = snapshot
|
||||
.language_scope_at(text.find("b\"").unwrap())
|
||||
.unwrap();
|
||||
assert_eq!(string_config.line_comment_prefix().unwrap().as_ref(), "// ");
|
||||
// Second bracket pair is disabled
|
||||
assert_eq!(
|
||||
@@ -1722,18 +1735,49 @@ fn test_language_scope_at_with_javascript(cx: &mut AppContext) {
|
||||
&[true, false]
|
||||
);
|
||||
|
||||
let element_config = snapshot.language_scope_at(10).unwrap();
|
||||
// In between JSX tags: use the `element` override.
|
||||
let element_config = snapshot
|
||||
.language_scope_at(text.find("<F>").unwrap())
|
||||
.unwrap();
|
||||
assert_eq!(element_config.line_comment_prefix(), None);
|
||||
assert_eq!(
|
||||
element_config.block_comment_delimiters(),
|
||||
Some((&"{/*".into(), &"*/}".into()))
|
||||
);
|
||||
// Both bracket pairs are enabled
|
||||
assert_eq!(
|
||||
element_config.brackets().map(|e| e.1).collect::<Vec<_>>(),
|
||||
&[true, true]
|
||||
);
|
||||
|
||||
// Within a JSX tag: use the default config.
|
||||
let tag_config = snapshot
|
||||
.language_scope_at(text.find(" d=").unwrap() + 1)
|
||||
.unwrap();
|
||||
assert_eq!(tag_config.line_comment_prefix().unwrap().as_ref(), "// ");
|
||||
assert_eq!(
|
||||
tag_config.brackets().map(|e| e.1).collect::<Vec<_>>(),
|
||||
&[true, true]
|
||||
);
|
||||
|
||||
// In a JSX expression: use the default config.
|
||||
let expression_in_element_config = snapshot
|
||||
.language_scope_at(text.find("{").unwrap() + 1)
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
expression_in_element_config
|
||||
.line_comment_prefix()
|
||||
.unwrap()
|
||||
.as_ref(),
|
||||
"// "
|
||||
);
|
||||
assert_eq!(
|
||||
expression_in_element_config
|
||||
.brackets()
|
||||
.map(|e| e.1)
|
||||
.collect::<Vec<_>>(),
|
||||
&[true, true]
|
||||
);
|
||||
|
||||
buffer
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
use std::ops::ControlFlow;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::sync::Arc;
|
||||
|
||||
@@ -58,11 +59,17 @@ impl Prettier {
|
||||
fs: &dyn Fs,
|
||||
installed_prettiers: &HashSet<PathBuf>,
|
||||
locate_from: &Path,
|
||||
) -> anyhow::Result<Option<PathBuf>> {
|
||||
) -> anyhow::Result<ControlFlow<(), Option<PathBuf>>> {
|
||||
let mut path_to_check = locate_from
|
||||
.components()
|
||||
.take_while(|component| component.as_os_str().to_string_lossy() != "node_modules")
|
||||
.collect::<PathBuf>();
|
||||
if path_to_check != locate_from {
|
||||
log::debug!(
|
||||
"Skipping prettier location for path {path_to_check:?} that is inside node_modules"
|
||||
);
|
||||
return Ok(ControlFlow::Break(()));
|
||||
}
|
||||
let path_to_check_metadata = fs
|
||||
.metadata(&path_to_check)
|
||||
.await
|
||||
@@ -76,14 +83,14 @@ impl Prettier {
|
||||
loop {
|
||||
if installed_prettiers.contains(&path_to_check) {
|
||||
log::debug!("Found prettier path {path_to_check:?} in installed prettiers");
|
||||
return Ok(Some(path_to_check));
|
||||
return Ok(ControlFlow::Continue(Some(path_to_check)));
|
||||
} else if let Some(package_json_contents) =
|
||||
read_package_json(fs, &path_to_check).await?
|
||||
{
|
||||
if has_prettier_in_package_json(&package_json_contents) {
|
||||
if has_prettier_in_node_modules(fs, &path_to_check).await? {
|
||||
log::debug!("Found prettier path {path_to_check:?} in both package.json and node_modules");
|
||||
return Ok(Some(path_to_check));
|
||||
return Ok(ControlFlow::Continue(Some(path_to_check)));
|
||||
} else if project_path_with_prettier_dependency.is_none() {
|
||||
project_path_with_prettier_dependency = Some(path_to_check.clone());
|
||||
}
|
||||
@@ -109,7 +116,7 @@ impl Prettier {
|
||||
}) {
|
||||
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(Some(path_to_check));
|
||||
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:?}");
|
||||
}
|
||||
@@ -132,7 +139,7 @@ impl Prettier {
|
||||
}
|
||||
None => {
|
||||
log::debug!("Found no prettier in ancestors of {locate_from:?}");
|
||||
return Ok(None);
|
||||
return Ok(ControlFlow::Continue(None));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -497,37 +504,40 @@ mod tests {
|
||||
.await;
|
||||
|
||||
assert!(
|
||||
Prettier::locate_prettier_installation(
|
||||
fs.as_ref(),
|
||||
&HashSet::default(),
|
||||
Path::new("/root/.config/zed/settings.json"),
|
||||
)
|
||||
.await
|
||||
.unwrap()
|
||||
.is_none(),
|
||||
matches!(
|
||||
Prettier::locate_prettier_installation(
|
||||
fs.as_ref(),
|
||||
&HashSet::default(),
|
||||
Path::new("/root/.config/zed/settings.json"),
|
||||
)
|
||||
.await,
|
||||
Ok(ControlFlow::Continue(None))
|
||||
),
|
||||
"Should successfully find no prettier for path hierarchy without it"
|
||||
);
|
||||
assert!(
|
||||
Prettier::locate_prettier_installation(
|
||||
fs.as_ref(),
|
||||
&HashSet::default(),
|
||||
Path::new("/root/work/project/src/index.js")
|
||||
)
|
||||
.await
|
||||
.unwrap()
|
||||
.is_none(),
|
||||
matches!(
|
||||
Prettier::locate_prettier_installation(
|
||||
fs.as_ref(),
|
||||
&HashSet::default(),
|
||||
Path::new("/root/work/project/src/index.js")
|
||||
)
|
||||
.await,
|
||||
Ok(ControlFlow::Continue(None))
|
||||
),
|
||||
"Should successfully find no prettier for path hierarchy that has node_modules with prettier, but no package.json mentions of it"
|
||||
);
|
||||
assert!(
|
||||
Prettier::locate_prettier_installation(
|
||||
fs.as_ref(),
|
||||
&HashSet::default(),
|
||||
Path::new("/root/work/project/node_modules/expect/build/print.js")
|
||||
)
|
||||
.await
|
||||
.unwrap()
|
||||
.is_none(),
|
||||
"Even though it has package.json with prettier in it and no prettier on node_modules along the path, nothing should fail since declared inside node_modules"
|
||||
matches!(
|
||||
Prettier::locate_prettier_installation(
|
||||
fs.as_ref(),
|
||||
&HashSet::default(),
|
||||
Path::new("/root/work/project/node_modules/expect/build/print.js")
|
||||
)
|
||||
.await,
|
||||
Ok(ControlFlow::Break(()))
|
||||
),
|
||||
"Should not format files inside node_modules/"
|
||||
);
|
||||
}
|
||||
|
||||
@@ -580,7 +590,7 @@ mod tests {
|
||||
)
|
||||
.await
|
||||
.unwrap(),
|
||||
Some(PathBuf::from("/root/web_blog")),
|
||||
ControlFlow::Continue(Some(PathBuf::from("/root/web_blog"))),
|
||||
"Should find a preinstalled prettier in the project root"
|
||||
);
|
||||
assert_eq!(
|
||||
@@ -591,8 +601,8 @@ mod tests {
|
||||
)
|
||||
.await
|
||||
.unwrap(),
|
||||
Some(PathBuf::from("/root/web_blog")),
|
||||
"Should find a preinstalled prettier in the project root even for node_modules files"
|
||||
ControlFlow::Break(()),
|
||||
"Should not allow formatting node_modules/ contents"
|
||||
);
|
||||
}
|
||||
|
||||
@@ -604,6 +614,18 @@ mod tests {
|
||||
json!({
|
||||
"work": {
|
||||
"web_blog": {
|
||||
"node_modules": {
|
||||
"expect": {
|
||||
"build": {
|
||||
"print.js": "// print.js file contents",
|
||||
},
|
||||
"package.json": r#"{
|
||||
"devDependencies": {
|
||||
"prettier": "2.5.1"
|
||||
}
|
||||
}"#,
|
||||
},
|
||||
},
|
||||
"pages": {
|
||||
"[slug].tsx": "// [slug].tsx file contents",
|
||||
},
|
||||
@@ -624,33 +646,55 @@ mod tests {
|
||||
)
|
||||
.await;
|
||||
|
||||
let path = "/root/work/web_blog/node_modules/pages/[slug].tsx";
|
||||
match Prettier::locate_prettier_installation(
|
||||
fs.as_ref(),
|
||||
&HashSet::default(),
|
||||
Path::new(path)
|
||||
Path::new("/root/work/web_blog/pages/[slug].tsx")
|
||||
)
|
||||
.await {
|
||||
Ok(path) => panic!("Expected to fail for prettier in package.json but not in node_modules found, but got path {path:?}"),
|
||||
Err(e) => {
|
||||
let message = e.to_string();
|
||||
assert!(message.contains(path), "Error message should mention which start file was used for location");
|
||||
assert!(message.contains("/root/work/web_blog"), "Error message should mention potential candidates without prettier node_modules contents");
|
||||
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(),
|
||||
&HashSet::from_iter(
|
||||
[PathBuf::from("/root"), PathBuf::from("/root/work")].into_iter()
|
||||
),
|
||||
Path::new("/root/work/web_blog/node_modules/pages/[slug].tsx")
|
||||
Path::new("/root/work/web_blog/pages/[slug].tsx")
|
||||
)
|
||||
.await
|
||||
.unwrap(),
|
||||
Some(PathBuf::from("/root/work")),
|
||||
"Should return first cached value found without path checks"
|
||||
ControlFlow::Continue(Some(PathBuf::from("/root/work"))),
|
||||
"Should return closest cached value found without path checks"
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
Prettier::locate_prettier_installation(
|
||||
fs.as_ref(),
|
||||
&HashSet::default(),
|
||||
Path::new("/root/work/web_blog/node_modules/expect/build/print.js")
|
||||
)
|
||||
.await
|
||||
.unwrap(),
|
||||
ControlFlow::Break(()),
|
||||
"Should not allow formatting files inside node_modules/"
|
||||
);
|
||||
assert_eq!(
|
||||
Prettier::locate_prettier_installation(
|
||||
fs.as_ref(),
|
||||
&HashSet::from_iter(
|
||||
[PathBuf::from("/root"), PathBuf::from("/root/work")].into_iter()
|
||||
),
|
||||
Path::new("/root/work/web_blog/node_modules/expect/build/print.js")
|
||||
)
|
||||
.await
|
||||
.unwrap(),
|
||||
ControlFlow::Break(()),
|
||||
"Should ignore cache lookup for files inside node_modules/"
|
||||
);
|
||||
}
|
||||
|
||||
@@ -674,7 +718,9 @@ mod tests {
|
||||
},
|
||||
},
|
||||
},
|
||||
"node_modules": {},
|
||||
"node_modules": {
|
||||
"test.js": "// test.js contents",
|
||||
},
|
||||
"package.json": r#"{
|
||||
"devDependencies": {
|
||||
"prettier": "^3.0.3"
|
||||
@@ -703,9 +749,32 @@ mod tests {
|
||||
&HashSet::default(),
|
||||
Path::new("/root/work/full-stack-foundations/exercises/03.loading/01.problem.loader/app/routes/users+/$username_+/notes.tsx"),
|
||||
).await.unwrap(),
|
||||
Some(PathBuf::from("/root/work/full-stack-foundations")),
|
||||
ControlFlow::Continue(Some(PathBuf::from("/root/work/full-stack-foundations"))),
|
||||
"Should ascend to the multi-workspace root and find the prettier there",
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
Prettier::locate_prettier_installation(
|
||||
fs.as_ref(),
|
||||
&HashSet::default(),
|
||||
Path::new("/root/work/full-stack-foundations/node_modules/prettier/index.js")
|
||||
)
|
||||
.await
|
||||
.unwrap(),
|
||||
ControlFlow::Break(()),
|
||||
"Should not allow formatting files inside root node_modules/"
|
||||
);
|
||||
assert_eq!(
|
||||
Prettier::locate_prettier_installation(
|
||||
fs.as_ref(),
|
||||
&HashSet::default(),
|
||||
Path::new("/root/work/full-stack-foundations/exercises/03.loading/01.problem.loader/node_modules/test.js")
|
||||
)
|
||||
.await
|
||||
.unwrap(),
|
||||
ControlFlow::Break(()),
|
||||
"Should not allow formatting files inside submodule's node_modules/"
|
||||
);
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
|
||||
@@ -7,6 +7,7 @@ use lsp::{LanguageServer, LanguageServerId};
|
||||
use node_runtime::NodeRuntime;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::{
|
||||
ops::ControlFlow,
|
||||
path::{Path, PathBuf},
|
||||
sync::Arc,
|
||||
};
|
||||
@@ -58,11 +59,17 @@ impl Prettier {
|
||||
fs: &dyn Fs,
|
||||
installed_prettiers: &HashSet<PathBuf>,
|
||||
locate_from: &Path,
|
||||
) -> anyhow::Result<Option<PathBuf>> {
|
||||
) -> anyhow::Result<ControlFlow<(), Option<PathBuf>>> {
|
||||
let mut path_to_check = locate_from
|
||||
.components()
|
||||
.take_while(|component| component.as_os_str().to_string_lossy() != "node_modules")
|
||||
.collect::<PathBuf>();
|
||||
if path_to_check != locate_from {
|
||||
log::debug!(
|
||||
"Skipping prettier location for path {path_to_check:?} that is inside node_modules"
|
||||
);
|
||||
return Ok(ControlFlow::Break(()));
|
||||
}
|
||||
let path_to_check_metadata = fs
|
||||
.metadata(&path_to_check)
|
||||
.await
|
||||
@@ -76,14 +83,14 @@ impl Prettier {
|
||||
loop {
|
||||
if installed_prettiers.contains(&path_to_check) {
|
||||
log::debug!("Found prettier path {path_to_check:?} in installed prettiers");
|
||||
return Ok(Some(path_to_check));
|
||||
return Ok(ControlFlow::Continue(Some(path_to_check)));
|
||||
} else if let Some(package_json_contents) =
|
||||
read_package_json(fs, &path_to_check).await?
|
||||
{
|
||||
if has_prettier_in_package_json(&package_json_contents) {
|
||||
if has_prettier_in_node_modules(fs, &path_to_check).await? {
|
||||
log::debug!("Found prettier path {path_to_check:?} in both package.json and node_modules");
|
||||
return Ok(Some(path_to_check));
|
||||
return Ok(ControlFlow::Continue(Some(path_to_check)));
|
||||
} else if project_path_with_prettier_dependency.is_none() {
|
||||
project_path_with_prettier_dependency = Some(path_to_check.clone());
|
||||
}
|
||||
@@ -109,7 +116,7 @@ impl Prettier {
|
||||
}) {
|
||||
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(Some(path_to_check));
|
||||
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:?}");
|
||||
}
|
||||
@@ -132,7 +139,7 @@ impl Prettier {
|
||||
}
|
||||
None => {
|
||||
log::debug!("Found no prettier in ancestors of {locate_from:?}");
|
||||
return Ok(None);
|
||||
return Ok(ControlFlow::Continue(None));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -527,37 +534,40 @@ mod tests {
|
||||
.await;
|
||||
|
||||
assert!(
|
||||
Prettier::locate_prettier_installation(
|
||||
fs.as_ref(),
|
||||
&HashSet::default(),
|
||||
Path::new("/root/.config/zed/settings.json"),
|
||||
)
|
||||
.await
|
||||
.unwrap()
|
||||
.is_none(),
|
||||
matches!(
|
||||
Prettier::locate_prettier_installation(
|
||||
fs.as_ref(),
|
||||
&HashSet::default(),
|
||||
Path::new("/root/.config/zed/settings.json"),
|
||||
)
|
||||
.await,
|
||||
Ok(ControlFlow::Continue(None))
|
||||
),
|
||||
"Should successfully find no prettier for path hierarchy without it"
|
||||
);
|
||||
assert!(
|
||||
Prettier::locate_prettier_installation(
|
||||
fs.as_ref(),
|
||||
&HashSet::default(),
|
||||
Path::new("/root/work/project/src/index.js")
|
||||
)
|
||||
.await
|
||||
.unwrap()
|
||||
.is_none(),
|
||||
matches!(
|
||||
Prettier::locate_prettier_installation(
|
||||
fs.as_ref(),
|
||||
&HashSet::default(),
|
||||
Path::new("/root/work/project/src/index.js")
|
||||
)
|
||||
.await,
|
||||
Ok(ControlFlow::Continue(None))
|
||||
),
|
||||
"Should successfully find no prettier for path hierarchy that has node_modules with prettier, but no package.json mentions of it"
|
||||
);
|
||||
assert!(
|
||||
Prettier::locate_prettier_installation(
|
||||
fs.as_ref(),
|
||||
&HashSet::default(),
|
||||
Path::new("/root/work/project/node_modules/expect/build/print.js")
|
||||
)
|
||||
.await
|
||||
.unwrap()
|
||||
.is_none(),
|
||||
"Even though it has package.json with prettier in it and no prettier on node_modules along the path, nothing should fail since declared inside node_modules"
|
||||
matches!(
|
||||
Prettier::locate_prettier_installation(
|
||||
fs.as_ref(),
|
||||
&HashSet::default(),
|
||||
Path::new("/root/work/project/node_modules/expect/build/print.js")
|
||||
)
|
||||
.await,
|
||||
Ok(ControlFlow::Break(()))
|
||||
),
|
||||
"Should not format files inside node_modules/"
|
||||
);
|
||||
}
|
||||
|
||||
@@ -610,7 +620,7 @@ mod tests {
|
||||
)
|
||||
.await
|
||||
.unwrap(),
|
||||
Some(PathBuf::from("/root/web_blog")),
|
||||
ControlFlow::Continue(Some(PathBuf::from("/root/web_blog"))),
|
||||
"Should find a preinstalled prettier in the project root"
|
||||
);
|
||||
assert_eq!(
|
||||
@@ -621,8 +631,8 @@ mod tests {
|
||||
)
|
||||
.await
|
||||
.unwrap(),
|
||||
Some(PathBuf::from("/root/web_blog")),
|
||||
"Should find a preinstalled prettier in the project root even for node_modules files"
|
||||
ControlFlow::Break(()),
|
||||
"Should not allow formatting node_modules/ contents"
|
||||
);
|
||||
}
|
||||
|
||||
@@ -634,6 +644,18 @@ mod tests {
|
||||
json!({
|
||||
"work": {
|
||||
"web_blog": {
|
||||
"node_modules": {
|
||||
"expect": {
|
||||
"build": {
|
||||
"print.js": "// print.js file contents",
|
||||
},
|
||||
"package.json": r#"{
|
||||
"devDependencies": {
|
||||
"prettier": "2.5.1"
|
||||
}
|
||||
}"#,
|
||||
},
|
||||
},
|
||||
"pages": {
|
||||
"[slug].tsx": "// [slug].tsx file contents",
|
||||
},
|
||||
@@ -654,18 +676,16 @@ mod tests {
|
||||
)
|
||||
.await;
|
||||
|
||||
let path = "/root/work/web_blog/node_modules/pages/[slug].tsx";
|
||||
match Prettier::locate_prettier_installation(
|
||||
fs.as_ref(),
|
||||
&HashSet::default(),
|
||||
Path::new(path)
|
||||
Path::new("/root/work/web_blog/pages/[slug].tsx")
|
||||
)
|
||||
.await {
|
||||
Ok(path) => panic!("Expected to fail for prettier in package.json but not in node_modules found, but got path {path:?}"),
|
||||
Err(e) => {
|
||||
let message = e.to_string();
|
||||
assert!(message.contains(path), "Error message should mention which start file was used for location");
|
||||
assert!(message.contains("/root/work/web_blog"), "Error message should mention potential candidates without prettier node_modules contents");
|
||||
assert!(message.contains("/root/work/web_blog"), "Error message should mention which project had prettier defined");
|
||||
},
|
||||
};
|
||||
|
||||
@@ -675,12 +695,37 @@ mod tests {
|
||||
&HashSet::from_iter(
|
||||
[PathBuf::from("/root"), PathBuf::from("/root/work")].into_iter()
|
||||
),
|
||||
Path::new("/root/work/web_blog/node_modules/pages/[slug].tsx")
|
||||
Path::new("/root/work/web_blog/pages/[slug].tsx")
|
||||
)
|
||||
.await
|
||||
.unwrap(),
|
||||
Some(PathBuf::from("/root/work")),
|
||||
"Should return first cached value found without path checks"
|
||||
ControlFlow::Continue(Some(PathBuf::from("/root/work"))),
|
||||
"Should return closest cached value found without path checks"
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
Prettier::locate_prettier_installation(
|
||||
fs.as_ref(),
|
||||
&HashSet::default(),
|
||||
Path::new("/root/work/web_blog/node_modules/expect/build/print.js")
|
||||
)
|
||||
.await
|
||||
.unwrap(),
|
||||
ControlFlow::Break(()),
|
||||
"Should not allow formatting files inside node_modules/"
|
||||
);
|
||||
assert_eq!(
|
||||
Prettier::locate_prettier_installation(
|
||||
fs.as_ref(),
|
||||
&HashSet::from_iter(
|
||||
[PathBuf::from("/root"), PathBuf::from("/root/work")].into_iter()
|
||||
),
|
||||
Path::new("/root/work/web_blog/node_modules/expect/build/print.js")
|
||||
)
|
||||
.await
|
||||
.unwrap(),
|
||||
ControlFlow::Break(()),
|
||||
"Should ignore cache lookup for files inside node_modules/"
|
||||
);
|
||||
}
|
||||
|
||||
@@ -704,7 +749,9 @@ mod tests {
|
||||
},
|
||||
},
|
||||
},
|
||||
"node_modules": {},
|
||||
"node_modules": {
|
||||
"test.js": "// test.js contents",
|
||||
},
|
||||
"package.json": r#"{
|
||||
"devDependencies": {
|
||||
"prettier": "^3.0.3"
|
||||
@@ -733,9 +780,32 @@ mod tests {
|
||||
&HashSet::default(),
|
||||
Path::new("/root/work/full-stack-foundations/exercises/03.loading/01.problem.loader/app/routes/users+/$username_+/notes.tsx"),
|
||||
).await.unwrap(),
|
||||
Some(PathBuf::from("/root/work/full-stack-foundations")),
|
||||
ControlFlow::Continue(Some(PathBuf::from("/root/work/full-stack-foundations"))),
|
||||
"Should ascend to the multi-workspace root and find the prettier there",
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
Prettier::locate_prettier_installation(
|
||||
fs.as_ref(),
|
||||
&HashSet::default(),
|
||||
Path::new("/root/work/full-stack-foundations/node_modules/prettier/index.js")
|
||||
)
|
||||
.await
|
||||
.unwrap(),
|
||||
ControlFlow::Break(()),
|
||||
"Should not allow formatting files inside root node_modules/"
|
||||
);
|
||||
assert_eq!(
|
||||
Prettier::locate_prettier_installation(
|
||||
fs.as_ref(),
|
||||
&HashSet::default(),
|
||||
Path::new("/root/work/full-stack-foundations/exercises/03.loading/01.problem.loader/node_modules/test.js")
|
||||
)
|
||||
.await
|
||||
.unwrap(),
|
||||
ControlFlow::Break(()),
|
||||
"Should not allow formatting files inside submodule's node_modules/"
|
||||
);
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
|
||||
@@ -69,7 +69,7 @@ use std::{
|
||||
hash::Hash,
|
||||
mem,
|
||||
num::NonZeroU32,
|
||||
ops::Range,
|
||||
ops::{ControlFlow, Range},
|
||||
path::{self, Component, Path, PathBuf},
|
||||
process::Stdio,
|
||||
str,
|
||||
@@ -8442,7 +8442,10 @@ impl Project {
|
||||
})
|
||||
.await
|
||||
{
|
||||
Ok(None) => {
|
||||
Ok(ControlFlow::Break(())) => {
|
||||
return None;
|
||||
}
|
||||
Ok(ControlFlow::Continue(None)) => {
|
||||
let started_default_prettier =
|
||||
project.update(&mut cx, |project, _| {
|
||||
project
|
||||
@@ -8466,7 +8469,7 @@ impl Project {
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(Some(prettier_dir)) => {
|
||||
Ok(ControlFlow::Continue(Some(prettier_dir))) => {
|
||||
project.update(&mut cx, |project, _| {
|
||||
project
|
||||
.prettiers_per_worktree
|
||||
@@ -8593,7 +8596,7 @@ impl Project {
|
||||
.await
|
||||
})
|
||||
}
|
||||
None => Task::ready(Ok(None)),
|
||||
None => Task::ready(Ok(ControlFlow::Break(()))),
|
||||
};
|
||||
let mut plugins_to_install = prettier_plugins;
|
||||
let previous_installation_process =
|
||||
@@ -8622,8 +8625,9 @@ impl Project {
|
||||
.context("locate prettier installation")
|
||||
.map_err(Arc::new)?
|
||||
{
|
||||
Some(_non_default_prettier) => return Ok(()),
|
||||
None => {
|
||||
ControlFlow::Break(()) => return Ok(()),
|
||||
ControlFlow::Continue(Some(_non_default_prettier)) => return Ok(()),
|
||||
ControlFlow::Continue(None) => {
|
||||
let mut needs_install = match previous_installation_process {
|
||||
Some(previous_installation_process) => {
|
||||
previous_installation_process.await.is_err()
|
||||
|
||||
@@ -69,7 +69,7 @@ use std::{
|
||||
hash::Hash,
|
||||
mem,
|
||||
num::NonZeroU32,
|
||||
ops::Range,
|
||||
ops::{ControlFlow, Range},
|
||||
path::{self, Component, Path, PathBuf},
|
||||
process::Stdio,
|
||||
str,
|
||||
@@ -8488,7 +8488,10 @@ impl Project {
|
||||
})
|
||||
.await
|
||||
{
|
||||
Ok(None) => {
|
||||
Ok(ControlFlow::Break(())) => {
|
||||
return None;
|
||||
}
|
||||
Ok(ControlFlow::Continue(None)) => {
|
||||
match project.update(&mut cx, |project, _| {
|
||||
project
|
||||
.prettiers_per_worktree
|
||||
@@ -8520,7 +8523,7 @@ impl Project {
|
||||
.shared())),
|
||||
}
|
||||
}
|
||||
Ok(Some(prettier_dir)) => {
|
||||
Ok(ControlFlow::Continue(Some(prettier_dir))) => {
|
||||
match project.update(&mut cx, |project, _| {
|
||||
project
|
||||
.prettiers_per_worktree
|
||||
@@ -8662,7 +8665,7 @@ impl Project {
|
||||
.await
|
||||
})
|
||||
}
|
||||
None => Task::ready(Ok(None)),
|
||||
None => Task::ready(Ok(ControlFlow::Break(()))),
|
||||
};
|
||||
let mut plugins_to_install = prettier_plugins;
|
||||
let previous_installation_process =
|
||||
@@ -8692,8 +8695,9 @@ impl Project {
|
||||
.context("locate prettier installation")
|
||||
.map_err(Arc::new)?
|
||||
{
|
||||
Some(_non_default_prettier) => return Ok(()),
|
||||
None => {
|
||||
ControlFlow::Break(()) => return Ok(()),
|
||||
ControlFlow::Continue(Some(_non_default_prettier)) => return Ok(()),
|
||||
ControlFlow::Continue(None) => {
|
||||
let mut needs_install = match previous_installation_process {
|
||||
Some(previous_installation_process) => {
|
||||
previous_installation_process.await.is_err()
|
||||
|
||||
@@ -3,7 +3,7 @@ authors = ["Nathan Sobo <nathansobo@gmail.com>"]
|
||||
description = "The fast, collaborative code editor."
|
||||
edition = "2021"
|
||||
name = "zed"
|
||||
version = "0.112.0"
|
||||
version = "0.112.2"
|
||||
publish = false
|
||||
|
||||
[lib]
|
||||
|
||||
@@ -1 +1 @@
|
||||
dev
|
||||
preview
|
||||
@@ -8,6 +8,11 @@
|
||||
[
|
||||
(jsx_element)
|
||||
(jsx_fragment)
|
||||
] @element
|
||||
|
||||
[
|
||||
(jsx_opening_element)
|
||||
(jsx_closing_element)
|
||||
(jsx_self_closing_element)
|
||||
(jsx_expression)
|
||||
] @element
|
||||
] @default
|
||||
|
||||
@@ -8,6 +8,11 @@
|
||||
[
|
||||
(jsx_element)
|
||||
(jsx_fragment)
|
||||
] @element
|
||||
|
||||
[
|
||||
(jsx_opening_element)
|
||||
(jsx_closing_element)
|
||||
(jsx_self_closing_element)
|
||||
(jsx_expression)
|
||||
] @element
|
||||
] @default
|
||||
|
||||
@@ -2,6 +2,7 @@ use anyhow::{anyhow, Result};
|
||||
use async_compression::futures::bufread::GzipDecoder;
|
||||
use async_tar::Archive;
|
||||
use async_trait::async_trait;
|
||||
use collections::HashMap;
|
||||
use futures::{future::BoxFuture, FutureExt};
|
||||
use gpui::AppContext;
|
||||
use language::{LanguageServerName, LspAdapter, LspAdapterDelegate};
|
||||
@@ -20,12 +21,7 @@ use util::{fs::remove_matching, github::latest_github_release};
|
||||
use util::{github::GitHubLspBinaryVersion, ResultExt};
|
||||
|
||||
fn typescript_server_binary_arguments(server_path: &Path) -> Vec<OsString> {
|
||||
vec![
|
||||
server_path.into(),
|
||||
"--stdio".into(),
|
||||
"--tsserver-path".into(),
|
||||
"node_modules/typescript/lib".into(),
|
||||
]
|
||||
vec![server_path.into(), "--stdio".into()]
|
||||
}
|
||||
|
||||
fn eslint_server_binary_arguments(server_path: &Path) -> Vec<OsString> {
|
||||
@@ -158,9 +154,20 @@ impl LspAdapter for TypeScriptLspAdapter {
|
||||
|
||||
async fn initialization_options(&self) -> Option<serde_json::Value> {
|
||||
Some(json!({
|
||||
"provideFormatter": true
|
||||
"provideFormatter": true,
|
||||
"tsserver": {
|
||||
"path": "node_modules/typescript/lib",
|
||||
},
|
||||
}))
|
||||
}
|
||||
|
||||
async fn language_ids(&self) -> HashMap<String, String> {
|
||||
HashMap::from_iter([
|
||||
("TypeScript".into(), "typescript".into()),
|
||||
("JavaScript".into(), "javascript".into()),
|
||||
("TSX".into(), "typescriptreact".into()),
|
||||
])
|
||||
}
|
||||
}
|
||||
|
||||
async fn get_cached_ts_server_binary(
|
||||
|
||||
@@ -8,6 +8,11 @@
|
||||
[
|
||||
(jsx_element)
|
||||
(jsx_fragment)
|
||||
] @element
|
||||
|
||||
[
|
||||
(jsx_opening_element)
|
||||
(jsx_closing_element)
|
||||
(jsx_self_closing_element)
|
||||
(jsx_expression)
|
||||
] @element
|
||||
] @default
|
||||
|
||||
@@ -8,6 +8,11 @@
|
||||
[
|
||||
(jsx_element)
|
||||
(jsx_fragment)
|
||||
] @element
|
||||
|
||||
[
|
||||
(jsx_opening_element)
|
||||
(jsx_closing_element)
|
||||
(jsx_self_closing_element)
|
||||
(jsx_expression)
|
||||
] @element
|
||||
] @default
|
||||
|
||||
Reference in New Issue
Block a user