Compare commits

...

9 Commits

Author SHA1 Message Date
Thorsten Ball
6866187d1e zed 0.129.2 2024-04-04 11:46:19 +02:00
Thorsten Ball
0784e1c72f Improve handling of prettier errors on format (#10156)
When no formatter for a language is specified, Zed has the default
behaviour:

1. Attempt to format the buffer with `prettier`
2. If that doesn't work, use the language server.

The problem was that if `prettier` failed to format a buffer due to
legitimate syntax errors, we simply did a fallback to the language
server, which would then format over the syntax errors.

With JavaScript/React/TypeScript projects this could lead to a situation
where

1. Syntax error was introduced
2. Prettier fails
3. Zed ignores the error
4. typescript-language-server formats the buffer despite syntax errors

This would lead to some very weird formatting issues.

What this PR does is to fix the issue by handling `prettier` errors and
results in two user facing changes:

1. When no formatter is set (or set to `auto`) and if we attempted to
start a prettier instance to format, we will now display that error and
*not* fall back to language server formatting.
2. If the formatter is explicitly set to `prettier`, we will now show
errors if we failed to spawn prettier or failed to format with it.

This means that we now might show *more* errors than previously, but I
think that's better than not showing anything to the user at all.

And, of course, it also fixes the issue of invalid syntax being
formatted by the language server even though `prettier` failed with an
error.

Release Notes:

- Improved error handling when formatting buffers with `prettier`.
Previously `prettier` errors would be logged but ignored. Now `prettier`
errors are shown in the UI, just like language server errors when
formatting. And if no formatter is specified (or set to `"auto"`) and
Zed attempts to use `prettier` for formatting, then `prettier` errors
are no longer skipped. That fixes the issue of `prettier` not formatting
invalid syntax, but its error being skipped, leading to
`typescript-language-server` or another language server formatting
invalid syntax.
2024-04-04 11:45:28 +02:00
Marshall Bowers
9641ae0755 Remove basic.conf (#10120)
This PR removes the `basic.conf` file.

In #10099 we suppressed some typo warnings that had cropped up in this
file, but it turns out we don't need the file at all.

Release Notes:

- N/A
2024-04-03 12:32:47 -04:00
Kirill Bulatov
ce73ff9808 Avoid failing format test with current date (#10068)
Replace the test that tested with
`chrono::offset::Local::now().naive_local()` taken, failing the
formatting once per year at least.


Release Notes:

- N/A
2024-04-03 12:32:40 -04:00
Joseph T. Lyons
240db73199 v0.129.x stable 2024-04-03 12:11:10 -04:00
gcp-cherry-pick-bot[bot]
6b52917e75 Don't update active completion for editors that are not focused (cherry-pick #9904) (#9907)
Cherry-picked Don't update active completion for editors that are not
focused (#9904)

Release Notes:

- N/A

Co-authored-by: Antonio Scandurra <me@as-cii.com>
2024-03-28 10:52:33 +01:00
Marshall Bowers
f226a9932a zed 0.129.1 2024-03-27 13:50:53 -04:00
Marshall Bowers
a7915cb848 Look up extensions in the new index when reporting extension events (#9879)
This PR fixes a bug that was causing extension telemetry events to not
be reported.

We need to look up the extensions in the new index, as the extensions to
load won't be found in the old index.

Release Notes:

- N/A
2024-03-27 13:48:45 -04:00
Joseph T. Lyons
2d8288f076 v0.129.x preview 2024-03-27 10:52:55 -04:00
10 changed files with 68 additions and 71 deletions

2
Cargo.lock generated
View File

@@ -12457,7 +12457,7 @@ dependencies = [
[[package]]
name = "zed"
version = "0.129.0"
version = "0.129.2"
dependencies = [
"activity_indicator",
"anyhow",

View File

@@ -1,12 +0,0 @@
[Interface]
PrivateKey = B5Fp/yVfP0QYlb+YJv9ea+EMI1mWODPD3akh91cVjvc=
Address = fdaa:0:2ce3:a7b:bea:0:a:2/120
DNS = fdaa:0:2ce3::3
[Peer]
PublicKey = RKAYPljEJiuaELNDdQIEJmQienT9+LRISfIHwH45HAw=
AllowedIPs = fdaa:0:2ce3::/48
Endpoint = ord1.gateway.6pn.dev:51820
PersistentKeepalive = 15

View File

@@ -764,6 +764,7 @@ mod tests {
multibuffer
});
let editor = cx.add_window(|cx| Editor::for_multibuffer(multibuffer, None, cx));
editor.update(cx, |editor, cx| editor.focus(cx)).unwrap();
let copilot_provider = cx.new_model(|_| CopilotCompletionProvider::new(copilot));
editor
.update(cx, |editor, cx| {

View File

@@ -1676,7 +1676,9 @@ impl Editor {
) {
self.inline_completion_provider = Some(RegisteredInlineCompletionProvider {
_subscription: cx.observe(&provider, |this, _, cx| {
this.update_visible_inline_completion(cx);
if this.focus_handle.is_focused(cx) {
this.update_visible_inline_completion(cx);
}
}),
provider: Arc::new(provider),
});

View File

@@ -761,7 +761,7 @@ impl ExtensionStore {
if let Some(telemetry) = &self.telemetry {
for extension_id in &extensions_to_load {
if let Some(extension) = self.extension_index.extensions.get(extension_id) {
if let Some(extension) = new_index.extensions.get(extension_id) {
telemetry.report_extension_event(
extension_id.clone(),
extension.manifest.version.clone(),

View File

@@ -4,7 +4,7 @@ use std::{
sync::Arc,
};
use anyhow::Context;
use anyhow::{anyhow, Context, Result};
use collections::HashSet;
use fs::Fs;
use futures::{
@@ -44,51 +44,48 @@ pub(super) async fn format_with_prettier(
project: &WeakModel<Project>,
buffer: &Model<Buffer>,
cx: &mut AsyncAppContext,
) -> Option<FormatOperation> {
if let Some((prettier_path, prettier_task)) = project
) -> Option<Result<FormatOperation>> {
let prettier_instance = project
.update(cx, |project, cx| {
project.prettier_instance_for_buffer(buffer, cx)
})
.ok()?
.await
{
match prettier_task.await {
Ok(prettier) => {
let buffer_path = buffer
.update(cx, |buffer, cx| {
File::from_dyn(buffer.file()).map(|file| file.abs_path(cx))
})
.ok()?;
match prettier.format(buffer, buffer_path, cx).await {
Ok(new_diff) => return Some(FormatOperation::Prettier(new_diff)),
Err(e) => {
match prettier_path {
Some(prettier_path) => log::error!(
"Prettier instance from path {prettier_path:?} failed to format a buffer: {e:#}"
),
None => log::error!(
"Default prettier instance failed to format a buffer: {e:#}"
),
}
}
}
}
Err(e) => project
.await;
let Some((prettier_path, prettier_task)) = prettier_instance else {
return None;
};
let prettier_description = match prettier_path.as_ref() {
Some(path) => format!("prettier at {path:?}"),
None => "default prettier instance".to_string(),
};
match prettier_task.await {
Ok(prettier) => {
let buffer_path = buffer
.update(cx, |buffer, cx| {
File::from_dyn(buffer.file()).map(|file| file.abs_path(cx))
})
.ok()?;
let format_result = prettier
.format(buffer, buffer_path, cx)
.await
.map(FormatOperation::Prettier)
.with_context(|| format!("{} failed to format buffer", prettier_description));
Some(format_result)
}
Err(error) => {
project
.update(cx, |project, _| {
let instance_to_update = match prettier_path {
Some(prettier_path) => {
log::error!(
"Prettier instance from path {prettier_path:?} failed to spawn: {e:#}"
);
project.prettier_instances.get_mut(&prettier_path)
}
None => {
log::error!("Default prettier instance failed to spawn: {e:#}");
match &mut project.default_prettier.prettier {
PrettierInstallation::NotInstalled { .. } => None,
PrettierInstallation::Installed(instance) => Some(instance),
}
}
Some(prettier_path) => project.prettier_instances.get_mut(&prettier_path),
None => match &mut project.default_prettier.prettier {
PrettierInstallation::NotInstalled { .. } => None,
PrettierInstallation::Installed(instance) => Some(instance),
},
};
if let Some(instance) = instance_to_update {
@@ -96,11 +93,14 @@ pub(super) async fn format_with_prettier(
instance.prettier = None;
}
})
.ok()?,
.log_err();
Some(Err(anyhow!(
"{} failed to spawn: {error:#}",
prettier_description
)))
}
}
None
}
pub struct DefaultPrettier {

View File

@@ -4652,10 +4652,11 @@ impl Project {
}
}
(Formatter::Auto, FormatOnSave::On | FormatOnSave::Off) => {
if let Some(new_operation) =
prettier_support::format_with_prettier(&project, buffer, &mut cx).await
{
format_operation = Some(new_operation);
let prettier =
prettier_support::format_with_prettier(&project, buffer, &mut cx).await;
if let Some(operation) = prettier {
format_operation = Some(operation?);
} else if let Some((language_server, buffer_abs_path)) = server_and_buffer {
format_operation = Some(FormatOperation::Lsp(
Self::format_via_lsp(
@@ -4672,10 +4673,11 @@ impl Project {
}
}
(Formatter::Prettier, FormatOnSave::On | FormatOnSave::Off) => {
if let Some(new_operation) =
prettier_support::format_with_prettier(&project, buffer, &mut cx).await
{
format_operation = Some(new_operation);
let prettier =
prettier_support::format_with_prettier(&project, buffer, &mut cx).await;
if let Some(operation) = prettier {
format_operation = Some(operation?);
}
}
};

View File

@@ -296,15 +296,19 @@ mod tests {
}
#[test]
fn test_format_distance_from_now() {
fn test_format_distance_from_hms() {
let date = DateTimeType::Naive(
NaiveDateTime::parse_from_str("1969-07-20T00:00:00Z", "%Y-%m-%dT%H:%M:%SZ")
NaiveDateTime::parse_from_str("1969-07-20T11:22:33Z", "%Y-%m-%dT%H:%M:%SZ")
.expect("Invalid NaiveDateTime for date"),
);
let base_date = DateTimeType::Naive(
NaiveDateTime::parse_from_str("2024-02-01T00:00:00Z", "%Y-%m-%dT%H:%M:%SZ")
.expect("Invalid NaiveDateTime for base_date"),
);
assert_eq!(
"over 54 years ago",
format_distance_from_now(date, false, true, false)
format_distance(date, base_date.to_naive(), false, true, false)
);
}

View File

@@ -2,7 +2,7 @@
description = "The fast, collaborative code editor."
edition = "2021"
name = "zed"
version = "0.129.0"
version = "0.129.2"
publish = false
license = "GPL-3.0-or-later"
authors = ["Zed Team <hi@zed.dev>"]

View File

@@ -1 +1 @@
dev
stable