Compare commits

...

22 Commits

Author SHA1 Message Date
Thorsten Ball
4003abcfbb zed 0.127.5 2024-03-26 09:08:42 +01:00
Thorsten Ball
df2d025a07 Update to vscode-eslint 2.4.4 & support flat config file extensions (#9708)
This upgrades to vscode-eslint 2.4.4 to support flat configs, in
multiple configuration files, ending in `.js`, `.cjs`, `.mjs`.

We changed the code to not use the GitHub release because we actually
don't need the artifacts of the release, we just need the source code,
which we compile anyway.

Fixes #7271.

Release Notes:

- Added support for ESLint flat config files.
([#7271](https://github.com/zed-industries/zed/issues/7271)).

Co-authored-by: Kristján Oddsson <koddsson@gmail.com>
2024-03-26 09:07:31 +01:00
Remco Smits
9446b044f6 Fix prettier-plugin-organize-imports plugin removes used imports (#9598)
So this pull request fixes an issue that was driven me crazy. The issue
was that when you use the `prettier-plugin-organize-imports` It would
remove some imports that should not be removed before they were used
inside the module itself.

You can reproduce it with the following `prettierrc.json` config and
source code. When you **save** the file, it would remove the `import
clsx from "clsx";` import from the file.

**Prettier config**
```json
{
  "semi": true,
  "tabWidth": 4,
  "trailingComma": "es5",
  "useTabs": true,
  "plugins": [
    "prettier-plugin-tailwindcss",
    "prettier-plugin-organize-imports"
  ]
}
```

**Source code**
```typescript
import clsx from "clsx";

export default function Home() {
  return (
      <main>
	      {clsx("asdjklasdjlkasd", "asdjlkasjdjlk")}
      </main>
  );
}
```

After a deep dive with @mrnugget, I was debugging deep down the prettier
plugin system and found the issue that was causing this issue. When I
was looking inside the
`node_modules/prettier-plugin-organize-imports/lib/organize.js`. I saw
the following code that looked strange to me because it falls back to
`file.ts` if `filepath` is not passed through inside the prettier config
options.

<img width="860" alt="Screenshot 2024-03-20 at 21 31 46"
src="https://github.com/zed-industries/zed/assets/62463826/47177fe5-e5a9-41d8-9f2f-0304b2c2159f">

So the issue was small, if you look at the following code, the `path`
key should be `filepath` inside the
`crates/prettier/src/prettier_server.js:205`
![Screenshot 2024-03-20 at 21 35
25](https://github.com/zed-industries/zed/assets/62463826/1eea0a88-c886-4632-9c69-9f3095126971)

Release Notes:

- Fixed prettier integration not using the correct filepath when
invoking prettier, which could lead to some prettier plugins failing to
format correctly.
([#9496](https://github.com/zed-industries/zed/issues/9496)).
2024-03-26 09:06:58 +01:00
Mikayla
e19b30ec33 zed 0.127.4 2024-03-24 09:23:29 -07:00
Conrad Irwin
96ac5b4044 Fix copilot modal (#9613)
Release Notes:

- Fixed copilot modal not responding
([#9596](https://github.com/zed-industries/zed/issues/9596)). (preview
only)
2024-03-24 09:22:34 -07:00
gcp-cherry-pick-bot[bot]
b6bf36b4a9 chat panel: Fix tooltips not working for links (cherry-pick #9691) (#9698)
Cherry-picked chat panel: Fix tooltips not working for links (#9691)

Closes #9418 

Noticed a difference in the `cx.set_tooltip(...)` calls between `div`
and `InteractiveText`. `div` calls `cx.set_tooltip(...)` inside
`after_layout`, but `InteractiveText` was calling this inside `paint`. I
believe as #9012 was merged, we need to call `cx.set_tooltip` inside
`after_layout`, as inserting inside `paint` does not seem to be
supported anymore.

I moved the code for setting the tooltip to `after_layout` and hovering
over links inside the chat seems to bring up the tooltips again.

Before:

See https://github.com/zed-industries/zed/issues/9418#issue-2189398784

After:



![image](https://github.com/zed-industries/zed/assets/53836821/a623164c-1ce0-40d7-bc53-020f176fba4a)


Release Notes:

- Fixed tooltip not showing up when hovering over links inside the chat
panel ([#9418](https://github.com/zed-industries/zed/issues/9418))

Co-authored-by: Bennet Bo Fenner <53836821+bennetbo@users.noreply.github.com>
2024-03-22 14:49:04 +01:00
Mikayla
7a704e5576 v0.127.x stable 2024-03-20 09:16:15 -07:00
gcp-cherry-pick-bot[bot]
59d86e66db Insert hitbox if div contains tooltip (cherry-pick #9545) (#9546)
Cherry-picked Insert hitbox if div contains tooltip (#9545)

Release Notes:

- Fixed a bug that would cause certain tooltips to not show up
(preview-only).

Co-authored-by: Antonio Scandurra <me@as-cii.com>
2024-03-19 19:03:20 +01:00
Conrad Irwin
8a7c340af5 zed 0.127.3 2024-03-18 15:11:07 -06:00
gcp-cherry-pick-bot[bot]
c3908b15be Upgrade Tree-sitter to handle high memory usage and memory errors in wasm parsers (cherry-pick #9518) (#9520)
Cherry-picked Upgrade Tree-sitter to handle high memory usage and memory
errors in wasm parsers (#9518)

Fixes #8528

Release Notes:

- Fixed a crash that could occur when editing certain SQL files.
- Fixed a general class of crashes that could occur due to bugs in
grammars added via extensions.

Co-authored-by: Marshall <marshall@zed.dev>

Co-authored-by: Max Brunsfeld <maxbrunsfeld@gmail.com>
Co-authored-by: Marshall <marshall@zed.dev>
2024-03-18 15:09:01 -06:00
gcp-cherry-pick-bot[bot]
cfdbfa927d Fix segfault in "install:cli" when app is not yet installed (cherry-pick #9427) (#9431)
Cherry-picked Fix segfault in "install:cli" when app is not yet
installed (#9427)

Release Notes:

- Fixed a panic running `cli: Install` or `cli: Register Zed Scheme`
before installing the app.

Co-authored-by: Conrad Irwin <conrad.irwin@gmail.com>
2024-03-18 14:53:47 -06:00
Conrad Irwin
1951f16fe5 Fix panic loading language queries (#9506)
Release Notes:

- Fixed a panic when loading a language with queries but no grammar
2024-03-18 14:47:01 -06:00
gcp-cherry-pick-bot[bot]
e6800bcc52 Don't panic on missing mtime (cherry-pick #9513) (#9514)
Cherry-picked Don't panic on missing mtime (#9513)

This is expected as of zed 0.128 when a new unsaved file is created

Release Notes:

- Fixed a panic when collaborating with newer zed versions

Co-authored-by: Conrad Irwin <conrad.irwin@gmail.com>
2024-03-18 14:37:26 -06:00
Antonio Scandurra
a24b8f2e09 zed 0.127.2 2024-03-18 18:35:25 +01:00
gcp-cherry-pick-bot[bot]
642fd36fdc Fix dispatching global actions from a window (cherry-pick #9502) (#9504)
Cherry-picked Fix dispatching global actions from a window (#9502)

Fixes https://github.com/zed-industries/zed/issues/9313

Release Notes:

- Fixed a regression that caused global actions to stop working when
invoked from a window (preview-only)
([#9313](https://github.com/zed-industries/zed/issues/9313)).

Co-authored-by: Conrad <conrad@zed.dev>

Co-authored-by: Antonio Scandurra <me@as-cii.com>
Co-authored-by: Conrad <conrad@zed.dev>
2024-03-18 18:33:36 +01:00
gcp-cherry-pick-bot[bot]
743760be87 Automatically create a hitbox for focusable elements (cherry-pick #9485) (#9486)
Cherry-picked Automatically create a hitbox for focusable elements
(#9485)

Closes #9462

This fixes the focus story in the storybook.

Release Notes:

- N/A

Co-authored-by: Antonio Scandurra <me@as-cii.com>
2024-03-18 09:59:07 +01:00
gcp-cherry-pick-bot[bot]
2db783ad04 Fix flickering when interacting with the language server logs (cherry-pick #9390) (#9435)
Cherry-picked Fix flickering when interacting with the language server
logs (#9390)

Fixes https://github.com/zed-industries/zed/issues/9340

The flickering was caused by the pane trying to restore focus on a
`FocusHandle` that wasn't being rendered anymore. This commit uses the
new `WeakFocusHandle` to avoid retaining a reference to focus handles
that don't exist anymore.

Release Notes:

- Fixed a bug that caused flickering when interacting with the language
server logs
([#9340](https://github.com/zed-industries/zed/issues/9340)).

Co-authored-by: Antonio Scandurra <me@as-cii.com>
2024-03-16 10:11:49 +01:00
Antonio Scandurra
597858ef99 zed 0.127.1 2024-03-14 09:47:22 +01:00
gcp-cherry-pick-bot[bot]
327879e054 Fix double-clicking titlebar to zoom (cherry-pick #9323) (#9327)
Cherry-picked Fix double-clicking titlebar to zoom (#9323)

Fixes https://github.com/zed-industries/zed/issues/9300

This was a regression caused by not inserting a hitbox when a div only
had click listeners on it.

Release Notes:

- Fixed a regression that disabled double-clicking on the titlebar to
zoom the window.
([#9300](https://github.com/zed-industries/zed/issues/9300))
(preview-only)

Co-authored-by: Antonio Scandurra <me@as-cii.com>
2024-03-14 09:38:05 +01:00
gcp-cherry-pick-bot[bot]
c1b4f3d817 Fix accidental leak of text stack between frames (cherry-pick #9297) (#9324)
Cherry-picked Fix accidental leak of text stack between frames (#9297)

Co-Authored-By: Max <max@zed.dev>
Co-Authored-By: Marshall <marshall@zed.dev>

Release Notes:

- Fixed a bug where text styles could leak between frames (preview only)

Co-authored-by: Max <max@zed.dev>
Co-authored-by: Marshall <marshall@zed.dev>

Co-authored-by: Conrad Irwin <conrad.irwin@gmail.com>
Co-authored-by: Max <max@zed.dev>
Co-authored-by: Marshall <marshall@zed.dev>
2024-03-14 09:34:20 +01:00
gcp-cherry-pick-bot[bot]
5bc4c4250c Automatically reset cursor style when hit test changes (cherry-pick #9289) (#9322)
Cherry-picked Automatically reset cursor style when hit test changes
(#9289)

Release Notes:

- N/A

Co-authored-by: Nathan Sobo <nathan@zed.dev>

Co-authored-by: Antonio Scandurra <me@as-cii.com>
Co-authored-by: Nathan Sobo <nathan@zed.dev>
2024-03-14 09:31:50 +01:00
Joseph T. Lyons
ced690dc0b v0.127.x preview 2024-03-13 11:57:21 -04:00
19 changed files with 268 additions and 167 deletions

18
Cargo.lock generated
View File

@@ -1860,10 +1860,11 @@ dependencies = [
[[package]]
name = "cc"
version = "1.0.88"
version = "1.0.90"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "02f341c093d19155a6e41631ce5971aac4e9a868262212153124c15fa22d1cdc"
checksum = "8cd6604a82acf3039f1144f54b8eb34e91ffba622051189e71b781822d5ee1f5"
dependencies = [
"jobserver",
"libc",
]
@@ -5061,6 +5062,15 @@ version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130"
[[package]]
name = "jobserver"
version = "0.1.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ab46a6e9526ddef3ae7f787c06f0f2600639ba80ea3eade3d8e670a2230f51d6"
dependencies = [
"libc",
]
[[package]]
name = "journal"
version = "0.1.0"
@@ -10313,7 +10323,7 @@ dependencies = [
[[package]]
name = "tree-sitter"
version = "0.20.100"
source = "git+https://github.com/tree-sitter/tree-sitter?rev=e4a23971ec3071a09c1e84816954c98f96e98e52#e4a23971ec3071a09c1e84816954c98f96e98e52"
source = "git+https://github.com/tree-sitter/tree-sitter?rev=4294e59279205f503eb14348dd5128bd5910c8fb#4294e59279205f503eb14348dd5128bd5910c8fb"
dependencies = [
"cc",
"regex",
@@ -12748,7 +12758,7 @@ dependencies = [
[[package]]
name = "zed"
version = "0.127.0"
version = "0.127.5"
dependencies = [
"activity_indicator",
"anyhow",

View File

@@ -354,7 +354,7 @@ features = [
]
[patch.crates-io]
tree-sitter = { git = "https://github.com/tree-sitter/tree-sitter", rev = "e4a23971ec3071a09c1e84816954c98f96e98e52" }
tree-sitter = { git = "https://github.com/tree-sitter/tree-sitter", rev = "4294e59279205f503eb14348dd5128bd5910c8fb" }
# Workaround for a broken nightly build of gpui: See #7644 and revisit once 0.5.3 is released.
pathfinder_simd = { git = "https://github.com/servo/pathfinder.git", rev = "e4fcda0d5259d0acf902aee6de7d2501f2bd6629" }

View File

@@ -194,9 +194,8 @@ impl Render for CopilotCodeVerification {
.on_action(cx.listener(|_, _: &menu::Cancel, cx| {
cx.emit(DismissEvent);
}))
.capture_any_mouse_down(cx.listener(|this, _: &MouseDownEvent, cx| {
.on_any_mouse_down(cx.listener(|this, _: &MouseDownEvent, cx| {
cx.focus(&this.focus_handle);
cx.stop_propagation();
}))
.child(
svg()

View File

@@ -1144,7 +1144,7 @@ impl AppContext {
}
}
pub(crate) fn dispatch_global_action(&mut self, action: &dyn Action) {
fn dispatch_global_action(&mut self, action: &dyn Action) {
self.propagate_event = true;
if let Some(mut global_listeners) = self

View File

@@ -1301,13 +1301,7 @@ impl Interactivity {
cx.with_text_style(style.text_style().cloned(), |cx| {
cx.with_content_mask(style.overflow_mask(bounds, cx.rem_size()), |cx| {
let hitbox = if self.occlude_mouse
|| style.mouse_cursor.is_some()
|| self.group.is_some()
|| self.has_hover_styles()
|| self.has_mouse_listeners()
|| self.scroll_offset.is_some()
{
let hitbox = if self.should_insert_hitbox(&style) {
Some(cx.insert_hitbox(bounds, self.occlude_mouse))
} else {
None
@@ -1322,17 +1316,22 @@ impl Interactivity {
)
}
fn has_hover_styles(&self) -> bool {
self.hover_style.is_some() || self.group_hover_style.is_some()
}
fn has_mouse_listeners(&self) -> bool {
!self.mouse_up_listeners.is_empty()
fn should_insert_hitbox(&self, style: &Style) -> bool {
self.occlude_mouse
|| style.mouse_cursor.is_some()
|| self.group.is_some()
|| self.scroll_offset.is_some()
|| self.tracked_focus_handle.is_some()
|| self.hover_style.is_some()
|| self.group_hover_style.is_some()
|| !self.mouse_up_listeners.is_empty()
|| !self.mouse_down_listeners.is_empty()
|| !self.mouse_move_listeners.is_empty()
|| !self.click_listeners.is_empty()
|| !self.scroll_wheel_listeners.is_empty()
|| self.drag_listener.is_some()
|| !self.drop_listeners.is_empty()
|| self.tooltip_builder.is_some()
}
fn clamp_scroll_position(

View File

@@ -415,8 +415,26 @@ impl Element for InteractiveText {
state: &mut Self::BeforeLayout,
cx: &mut ElementContext,
) -> Hitbox {
self.text.after_layout(bounds, state, cx);
cx.insert_hitbox(bounds, false)
cx.with_element_state::<InteractiveTextState, _>(
Some(self.element_id.clone()),
|interactive_state, cx| {
let interactive_state = interactive_state
.map(|interactive_state| interactive_state.unwrap_or_default());
if let Some(interactive_state) = interactive_state.as_ref() {
if let Some(active_tooltip) = interactive_state.active_tooltip.borrow().as_ref()
{
if let Some(tooltip) = active_tooltip.tooltip.clone() {
cx.set_tooltip(tooltip);
}
}
}
self.text.after_layout(bounds, state, cx);
let hitbox = cx.insert_hitbox(bounds, false);
(hitbox, interactive_state)
},
)
}
fn paint(
@@ -557,16 +575,6 @@ impl Element for InteractiveText {
cx.on_mouse_event(move |_: &MouseDownEvent, _, _| {
active_tooltip.take();
});
if let Some(tooltip) = interactive_state
.active_tooltip
.clone()
.borrow()
.as_ref()
.and_then(|at| at.tooltip.clone())
{
cx.set_tooltip(tooltip);
}
}
self.text.paint(bounds, text_state, &mut (), cx);

View File

@@ -552,6 +552,11 @@ impl Platform for MacPlatform {
let workspace: id = msg_send![class!(NSWorkspace), sharedWorkspace];
let scheme: id = ns_string(scheme);
let app: id = msg_send![workspace, URLForApplicationWithBundleIdentifier: bundle_id];
if app == nil {
return Task::ready(Err(anyhow!(
"Cannot register URL scheme until app is installed"
)));
}
let done_tx = Cell::new(Some(done_tx));
let block = ConcreteBlock::new(move |error: id| {
let result = if error == nil {

View File

@@ -29,7 +29,7 @@ use std::{
rc::Rc,
sync::{
atomic::{AtomicUsize, Ordering::SeqCst},
Arc,
Arc, Weak,
},
time::{Duration, Instant},
};
@@ -155,6 +155,14 @@ impl FocusHandle {
}
}
/// Converts this focus handle into a weak variant, which does not prevent it from being released.
pub fn downgrade(&self) -> WeakFocusHandle {
WeakFocusHandle {
id: self.id,
handles: Arc::downgrade(&self.handles),
}
}
/// Moves the focus to the element associated with this handle.
pub fn focus(&self, cx: &mut WindowContext) {
cx.focus(self)
@@ -207,6 +215,41 @@ impl Drop for FocusHandle {
}
}
/// A weak reference to a focus handle.
#[derive(Clone, Debug)]
pub struct WeakFocusHandle {
pub(crate) id: FocusId,
handles: Weak<RwLock<SlotMap<FocusId, AtomicUsize>>>,
}
impl WeakFocusHandle {
/// Attempts to upgrade the [WeakFocusHandle] to a [FocusHandle].
pub fn upgrade(&self) -> Option<FocusHandle> {
let handles = self.handles.upgrade()?;
FocusHandle::for_id(self.id, &handles)
}
}
impl PartialEq for WeakFocusHandle {
fn eq(&self, other: &WeakFocusHandle) -> bool {
self.id == other.id
}
}
impl Eq for WeakFocusHandle {}
impl PartialEq<FocusHandle> for WeakFocusHandle {
fn eq(&self, other: &FocusHandle) -> bool {
self.id == other.id
}
}
impl PartialEq<WeakFocusHandle> for FocusHandle {
fn eq(&self, other: &WeakFocusHandle) -> bool {
self.id == other.id
}
}
/// FocusableView allows users of your view to easily
/// focus it (using cx.focus_view(view))
pub trait FocusableView: 'static + Render {
@@ -653,7 +696,6 @@ impl<'a> WindowContext<'a> {
let window = self.window.handle;
self.app.defer(move |cx| {
cx.propagate_event = true;
window
.update(cx, |_, cx| {
let node_id = focus_handle
@@ -668,9 +710,6 @@ impl<'a> WindowContext<'a> {
cx.dispatch_action_on_node(node_id, action.as_ref());
})
.log_err();
if cx.propagate_event {
cx.dispatch_global_action(action.as_ref());
}
})
}
@@ -956,12 +995,6 @@ impl<'a> WindowContext<'a> {
self.window.next_frame.focus = self.window.focus;
self.window.next_frame.window_active = self.window.active.get();
// Set the cursor only if we're the active window.
if self.is_window_active() {
let cursor_style = self.compute_cursor_style().unwrap_or(CursorStyle::Arrow);
self.platform.set_cursor_style(cursor_style);
}
// Register requested input handler with the platform window.
if let Some(input_handler) = self.window.next_frame.input_handlers.pop() {
self.window
@@ -1017,6 +1050,8 @@ impl<'a> WindowContext<'a> {
.clone()
.retain(&(), |listener| listener(&event, self));
}
self.reset_cursor_style();
self.window.refreshing = false;
self.window.draw_phase = DrawPhase::None;
self.window.needs_present.set(true);
@@ -1031,16 +1066,20 @@ impl<'a> WindowContext<'a> {
profiling::finish_frame!();
}
fn compute_cursor_style(&mut self) -> Option<CursorStyle> {
// TODO: maybe we should have a HashMap keyed by HitboxId.
let request = self
.window
.next_frame
.cursor_styles
.iter()
.rev()
.find(|request| request.hitbox_id.is_hovered(self))?;
Some(request.style)
fn reset_cursor_style(&self) {
// Set the cursor only if we're the active window.
if self.is_window_active() {
let style = self
.window
.rendered_frame
.cursor_styles
.iter()
.rev()
.find(|request| request.hitbox_id.is_hovered(self))
.map(|request| request.style)
.unwrap_or(CursorStyle::Arrow);
self.platform.set_cursor_style(style);
}
}
/// Dispatch a given keystroke as though the user had typed it.
@@ -1175,7 +1214,11 @@ impl<'a> WindowContext<'a> {
}
fn dispatch_mouse_event(&mut self, event: &dyn Any) {
self.window.mouse_hit_test = self.window.rendered_frame.hit_test(self.mouse_position());
let hit_test = self.window.rendered_frame.hit_test(self.mouse_position());
if hit_test != self.window.mouse_hit_test {
self.window.mouse_hit_test = hit_test;
self.reset_cursor_style();
}
let mut mouse_listeners = mem::take(&mut self.window.rendered_frame.mouse_listeners);
self.with_element_context(|cx| {
@@ -1407,7 +1450,34 @@ impl<'a> WindowContext<'a> {
.dispatch_tree
.dispatch_path(node_id);
// Capture phase
// Capture phase for global actions.
self.propagate_event = true;
if let Some(mut global_listeners) = self
.global_action_listeners
.remove(&action.as_any().type_id())
{
for listener in &global_listeners {
listener(action.as_any(), DispatchPhase::Capture, self);
if !self.propagate_event {
break;
}
}
global_listeners.extend(
self.global_action_listeners
.remove(&action.as_any().type_id())
.unwrap_or_default(),
);
self.global_action_listeners
.insert(action.as_any().type_id(), global_listeners);
}
if !self.propagate_event {
return;
}
// Capture phase for window actions.
for node_id in &dispatch_path {
let node = self.window.rendered_frame.dispatch_tree.node(*node_id);
for DispatchActionListener {
@@ -1427,7 +1497,8 @@ impl<'a> WindowContext<'a> {
}
}
}
// Bubble phase
// Bubble phase for window actions.
for node_id in dispatch_path.iter().rev() {
let node = self.window.rendered_frame.dispatch_tree.node(*node_id);
for DispatchActionListener {
@@ -1449,6 +1520,30 @@ impl<'a> WindowContext<'a> {
}
}
}
// Bubble phase for global actions.
if let Some(mut global_listeners) = self
.global_action_listeners
.remove(&action.as_any().type_id())
{
for listener in global_listeners.iter().rev() {
self.propagate_event = false; // Actions stop propagation by default during the bubble phase
listener(action.as_any(), DispatchPhase::Bubble, self);
if !self.propagate_event {
break;
}
}
global_listeners.extend(
self.global_action_listeners
.remove(&action.as_any().type_id())
.unwrap_or_default(),
);
self.global_action_listeners
.insert(action.as_any().type_id(), global_listeners);
}
}
/// Register the given handler to be invoked whenever the global of the given type

View File

@@ -79,7 +79,7 @@ impl Hitbox {
}
}
#[derive(Default)]
#[derive(Default, Eq, PartialEq)]
pub(crate) struct HitTest(SmallVec<[HitboxId; 8]>);
pub(crate) struct DeferredDraw {
@@ -432,6 +432,7 @@ impl<'a> ElementContext<'a> {
);
self.window.next_frame.deferred_draws = deferred_draws;
self.window.element_id_stack.clear();
self.window.text_style_stack.clear();
}
fn paint_deferred_draws(&mut self, deferred_draw_indices: &[usize]) {

View File

@@ -940,13 +940,17 @@ impl Language {
}
pub fn with_highlights_query(mut self, source: &str) -> Result<Self> {
let grammar = self.grammar_mut();
let grammar = self
.grammar_mut()
.ok_or_else(|| anyhow!("cannot mutate grammar"))?;
grammar.highlights_query = Some(Query::new(&grammar.ts_language, source)?);
Ok(self)
}
pub fn with_outline_query(mut self, source: &str) -> Result<Self> {
let grammar = self.grammar_mut();
let grammar = self
.grammar_mut()
.ok_or_else(|| anyhow!("cannot mutate grammar"))?;
let query = Query::new(&grammar.ts_language, source)?;
let mut item_capture_ix = None;
let mut name_capture_ix = None;
@@ -974,7 +978,9 @@ impl Language {
}
pub fn with_embedding_query(mut self, source: &str) -> Result<Self> {
let grammar = self.grammar_mut();
let grammar = self
.grammar_mut()
.ok_or_else(|| anyhow!("cannot mutate grammar"))?;
let query = Query::new(&grammar.ts_language, source)?;
let mut item_capture_ix = None;
let mut name_capture_ix = None;
@@ -1005,7 +1011,9 @@ impl Language {
}
pub fn with_brackets_query(mut self, source: &str) -> Result<Self> {
let grammar = self.grammar_mut();
let grammar = self
.grammar_mut()
.ok_or_else(|| anyhow!("cannot mutate grammar"))?;
let query = Query::new(&grammar.ts_language, source)?;
let mut open_capture_ix = None;
let mut close_capture_ix = None;
@@ -1027,7 +1035,9 @@ impl Language {
}
pub fn with_indents_query(mut self, source: &str) -> Result<Self> {
let grammar = self.grammar_mut();
let grammar = self
.grammar_mut()
.ok_or_else(|| anyhow!("cannot mutate grammar"))?;
let query = Query::new(&grammar.ts_language, source)?;
let mut indent_capture_ix = None;
let mut start_capture_ix = None;
@@ -1055,7 +1065,9 @@ impl Language {
}
pub fn with_injection_query(mut self, source: &str) -> Result<Self> {
let grammar = self.grammar_mut();
let grammar = self
.grammar_mut()
.ok_or_else(|| anyhow!("cannot mutate grammar"))?;
let query = Query::new(&grammar.ts_language, source)?;
let mut language_capture_ix = None;
let mut content_capture_ix = None;
@@ -1095,7 +1107,13 @@ impl Language {
}
pub fn with_override_query(mut self, source: &str) -> anyhow::Result<Self> {
let query = Query::new(&self.grammar_mut().ts_language, source)?;
let query = {
let grammar = self
.grammar
.as_ref()
.ok_or_else(|| anyhow!("no grammar for language"))?;
Query::new(&grammar.ts_language, source)?
};
let mut override_configs_by_id = HashMap::default();
for (ix, name) in query.capture_names().iter().enumerate() {
@@ -1159,7 +1177,11 @@ impl Language {
}
self.config.brackets.disabled_scopes_by_bracket_ix.clear();
self.grammar_mut().override_config = Some(OverrideConfig {
let grammar = self
.grammar_mut()
.ok_or_else(|| anyhow!("cannot mutate grammar"))?;
grammar.override_config = Some(OverrideConfig {
query,
values: override_configs_by_id,
});
@@ -1167,7 +1189,10 @@ impl Language {
}
pub fn with_redaction_query(mut self, source: &str) -> anyhow::Result<Self> {
let grammar = self.grammar_mut();
let grammar = self
.grammar_mut()
.ok_or_else(|| anyhow!("cannot mutate grammar"))?;
let query = Query::new(&grammar.ts_language, source)?;
let mut redaction_capture_ix = None;
get_capture_indices(&query, &mut [("redact", &mut redaction_capture_ix)]);
@@ -1182,8 +1207,8 @@ impl Language {
Ok(self)
}
fn grammar_mut(&mut self) -> &mut Grammar {
Arc::get_mut(self.grammar.as_mut().unwrap()).unwrap()
fn grammar_mut(&mut self) -> Option<&mut Grammar> {
Arc::get_mut(self.grammar.as_mut()?)
}
pub fn name(&self) -> Arc<str> {

View File

@@ -431,15 +431,16 @@ impl LanguageRegistry {
let language = async {
let (config, queries) = (language.load)()?;
let grammar = if let Some(grammar) = config.grammar.clone() {
Some(this.get_or_load_grammar(grammar).await?)
if let Some(grammar) = config.grammar.clone() {
let grammar =
Some(this.get_or_load_grammar(grammar).await?);
Language::new_with_id(id, config, grammar)
.with_context_provider(provider)
.with_queries(queries)
} else {
None
};
Language::new_with_id(id, config, grammar)
.with_context_provider(provider)
.with_queries(queries)
Ok(Language::new_with_id(id, config, None)
.with_context_provider(provider))
}
}
.await;

View File

@@ -20,7 +20,7 @@ use std::{
use util::{
async_maybe,
fs::remove_matching,
github::{github_release_with_tag, GitHubLspBinaryVersion},
github::{build_tarball_url, GitHubLspBinaryVersion},
ResultExt,
};
@@ -216,9 +216,14 @@ pub struct EsLintLspAdapter {
}
impl EsLintLspAdapter {
const CURRENT_VERSION: &'static str = "release/2.4.4";
const SERVER_PATH: &'static str = "vscode-eslint/server/out/eslintServer.js";
const SERVER_NAME: &'static str = "eslint";
const FLAT_CONFIG_FILE_NAMES: &'static [&'static str] =
&["eslint.config.js", "eslint.config.mjs", "eslint.config.cjs"];
pub fn new(node: Arc<dyn NodeRuntime>) -> Self {
EsLintLspAdapter { node }
}
@@ -255,6 +260,9 @@ impl LspAdapter for EsLintLspAdapter {
}
let node_path = eslint_user_settings.get("nodePath").unwrap_or(&Value::Null);
let use_flat_config = Self::FLAT_CONFIG_FILE_NAMES
.iter()
.any(|file| workspace_root.join(file).is_file());
json!({
"": {
@@ -271,7 +279,7 @@ impl LspAdapter for EsLintLspAdapter {
"problems": {},
"codeActionOnSave": code_action_on_save,
"experimental": {
"useFlatConfig": workspace_root.join("eslint.config.js").is_file(),
"useFlatConfig": use_flat_config,
},
}
})
@@ -283,19 +291,13 @@ impl LspAdapter for EsLintLspAdapter {
async fn fetch_latest_server_version(
&self,
delegate: &dyn LspAdapterDelegate,
_delegate: &dyn LspAdapterDelegate,
) -> Result<Box<dyn 'static + Send + Any>> {
// We're using this hardcoded release tag, because ESLint's API changed with
// >= 2.3 and we haven't upgraded yet.
let release = github_release_with_tag(
"microsoft/vscode-eslint",
"release/2.2.20-Insider",
delegate.http_client(),
)
.await?;
let url = build_tarball_url("microsoft/vscode-eslint", Self::CURRENT_VERSION)?;
Ok(Box::new(GitHubLspBinaryVersion {
name: release.tag_name,
url: release.tarball_url,
name: Self::CURRENT_VERSION.into(),
url,
}))
}

View File

@@ -183,7 +183,7 @@ async function handleMessage(message, prettier) {
...resolvedConfig,
plugins,
parser: params.options.parser,
path: params.options.filepath,
filepath: params.options.filepath,
};
process.stderr.write(
`Resolved config: ${JSON.stringify(resolvedConfig)}, will format file '${

View File

@@ -7890,10 +7890,13 @@ impl Project {
}
let buffer_id = BufferId::new(state.id)?;
let buffer = cx.new_model(|_| {
Buffer::from_proto(this.replica_id(), this.capability(), state, buffer_file)
.unwrap()
});
let buffer = Buffer::from_proto(
this.replica_id(),
this.capability(),
state,
buffer_file,
)?;
let buffer = cx.new_model(|_| buffer);
this.incomplete_remote_buffers
.insert(buffer_id, Some(buffer));
}

View File

@@ -76,78 +76,33 @@ pub async fn latest_github_release(
.ok_or(anyhow!("Failed to find a release"))
}
pub async fn github_release_with_tag(
repo_name_with_owner: &str,
tag: &str,
http: Arc<dyn HttpClient>,
) -> Result<GithubRelease, anyhow::Error> {
let url = build_tagged_release_url(repo_name_with_owner, tag)?;
let mut response = http
.get(&url, Default::default(), true)
.await
.with_context(|| format!("error fetching release {} of {}", tag, repo_name_with_owner))?;
let mut body = Vec::new();
response
.body_mut()
.read_to_end(&mut body)
.await
.with_context(|| {
format!(
"error reading response body for release {} of {}",
tag, repo_name_with_owner
)
})?;
if response.status().is_client_error() {
let text = String::from_utf8_lossy(body.as_slice());
bail!(
"status error {}, response: {text:?}",
response.status().as_u16()
);
}
match serde_json::from_slice::<GithubRelease>(body.as_slice()) {
Ok(release) => Ok(release),
Err(err) => {
log::error!("Error deserializing: {:?}", err);
log::error!(
"GitHub API response text: {:?}",
String::from_utf8_lossy(body.as_slice())
);
Err(anyhow!(
"error deserializing release {} of {}",
tag,
repo_name_with_owner
))
}
}
}
fn build_tagged_release_url(repo_name_with_owner: &str, tag: &str) -> Result<String> {
pub fn build_tarball_url(repo_name_with_owner: &str, tag: &str) -> Result<String> {
let mut url = Url::parse(&format!(
"https://api.github.com/repos/{repo_name_with_owner}/releases/tags"
"https://github.com/{repo_name_with_owner}/archive/refs/tags",
))?;
// We're pushing this here, because tags may contain `/` and other characters
// that need to be escaped.
let tarball_filename = format!("{}.tar.gz", tag);
url.path_segments_mut()
.map_err(|_| anyhow!("cannot modify url path segments"))?
.push(tag);
.push(&tarball_filename);
Ok(url.to_string())
}
#[cfg(test)]
mod tests {
use super::build_tagged_release_url;
use crate::github::build_tarball_url;
#[test]
fn test_build_tagged_release_url() {
let tag = "release/2.2.20-Insider";
fn test_build_tarball_url() {
let tag = "release/2.3.5";
let repo_name_with_owner = "microsoft/vscode-eslint";
let have = build_tagged_release_url(repo_name_with_owner, tag).unwrap();
let have = build_tarball_url(repo_name_with_owner, tag).unwrap();
assert_eq!(have, "https://api.github.com/repos/microsoft/vscode-eslint/releases/tags/release%2F2.2.20-Insider");
assert_eq!(
have,
"https://github.com/microsoft/vscode-eslint/archive/refs/tags/release%2F2.3.5.tar.gz"
);
}
}

View File

@@ -12,7 +12,7 @@ use gpui::{
AsyncWindowContext, ClickEvent, DismissEvent, Div, DragMoveEvent, EntityId, EventEmitter,
ExternalPaths, FocusHandle, FocusableView, Model, MouseButton, NavigationDirection, Pixels,
Point, PromptLevel, Render, ScrollHandle, Subscription, Task, View, ViewContext, VisualContext,
WeakView, WindowContext,
WeakFocusHandle, WeakView, WindowContext,
};
use parking_lot::Mutex;
use project::{Project, ProjectEntryId, ProjectPath};
@@ -166,7 +166,7 @@ pub struct Pane {
zoomed: bool,
was_focused: bool,
active_item_index: usize,
last_focused_view_by_item: HashMap<EntityId, FocusHandle>,
last_focus_handle_by_item: HashMap<EntityId, WeakFocusHandle>,
nav_history: NavHistory,
toolbar: View<Toolbar>,
new_item_menu: Option<View<ContextMenu>>,
@@ -262,7 +262,7 @@ impl Pane {
was_focused: false,
zoomed: false,
active_item_index: 0,
last_focused_view_by_item: Default::default(),
last_focus_handle_by_item: Default::default(),
nav_history: NavHistory(Arc::new(Mutex::new(NavHistoryState {
mode: NavigationMode::Normal,
backward_stack: Default::default(),
@@ -380,18 +380,20 @@ impl Pane {
if self.focus_handle.is_focused(cx) {
// Pane was focused directly. We need to either focus a view inside the active item,
// or focus the active item itself
if let Some(weak_last_focused_view) =
self.last_focused_view_by_item.get(&active_item.item_id())
if let Some(weak_last_focus_handle) =
self.last_focus_handle_by_item.get(&active_item.item_id())
{
weak_last_focused_view.focus(cx);
return;
if let Some(focus_handle) = weak_last_focus_handle.upgrade() {
focus_handle.focus(cx);
return;
}
}
active_item.focus_handle(cx).focus(cx);
} else if let Some(focused) = cx.focused() {
if !self.context_menu_focused(cx) {
self.last_focused_view_by_item
.insert(active_item.item_id(), focused);
self.last_focus_handle_by_item
.insert(active_item.item_id(), focused.downgrade());
}
}
}

View File

@@ -941,8 +941,6 @@ mod element {
let flexes = self.flexes.clone();
let child_bounds = child.bounds;
let axis = self.axis;
let handle_hitbox = handle.hitbox.clone();
let was_hovered = handle_hitbox.is_hovered(cx);
move |e: &MouseMoveEvent, phase, cx| {
let dragged_handle = dragged_handle.borrow();
if phase.bubble() {
@@ -957,8 +955,6 @@ mod element {
workspace.clone(),
cx,
)
} else if was_hovered != handle_hitbox.is_hovered(cx) {
cx.refresh();
}
}
}

View File

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

View File

@@ -1 +1 @@
dev
stable