zed/tooling/lints/ui/entity_update_in_render.rs
Miguel Raz Guzmán Macedo 4b7369481d
Add dylint lint library for Zed-specific patterns (#58496)
Adds a dylint library under tooling/lints that flags Zed-specific
anti-patterns:

* shared_string_from_str_literal, 
* async_block_without_await, 
* entity_update_in_render, 
* notify_in_render, 
* owned_string_into_shared, 
* len_in_loop_condition, and 
* blocking_io_on_foreground. 

Includes UI tests, a single-lint helper, and workspace.metadata.dylint
registration so cargo dylint --all discovers it. The library pins its
own nightly toolchain (kept out of the main workspace) and tracks dylint
6.

Release Notes:

- N/A

Self-Review Checklist:

- [ ] I've reviewed my own diff for quality, security, and reliability
- [ ] Unsafe blocks (if any) have justifying comments
- [ ] The content is consistent with the [UI/UX
checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
- [ ] Tests cover the new/changed behavior
- [ ] Performance impact has been considered and is acceptable

Closes #ISSUE

Release Notes:

- N/A or Added/Fixed/Improved ...
2026-07-03 22:05:34 +00:00

116 lines
2.8 KiB
Rust

// Tests for the `entity_update_in_render` lint.
#![allow(unused)]
extern crate gpui;
use gpui::*;
struct Counter {
value: i32,
}
// ============================================================
// SHOULD WARN — .update() returning () inside Render::render
// ============================================================
struct MutatingView {
counter: Entity<Counter>,
}
impl Render for MutatingView {
fn render(&mut self, _window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
self.counter.update(cx, |counter, _cx| {
counter.value += 1;
});
()
}
}
// WeakEntity::update returning Result<(), _> inside Render::render
struct WeakMutatingView {
counter: WeakEntity<Counter>,
}
impl Render for WeakMutatingView {
fn render(&mut self, _window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
let _ = self.counter.update(cx, |counter, _cx| {
counter.value += 1;
});
()
}
}
// Entity::update returning () inside RenderOnce::render
struct OnceMutatingView {
counter: Entity<Counter>,
}
impl RenderOnce for OnceMutatingView {
fn render(self, _window: &mut Window, cx: &mut App) -> impl IntoElement {
self.counter.update(cx, |counter, _cx| {
counter.value += 1;
});
()
}
}
// ============================================================
// SHOULD NOT WARN
// ============================================================
// .update() returning a value (reading, not mutating)
struct ReadingView {
counter: Entity<Counter>,
}
impl Render for ReadingView {
fn render(&mut self, _window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
let _val: i32 = self.counter.update(cx, |counter, _cx| counter.value);
()
}
}
// .update() inside a closure (e.g. event handler), not directly in render
struct ClosureView {
counter: Entity<Counter>,
}
impl Render for ClosureView {
fn render(&mut self, _window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
let counter = &self.counter;
let _handler = |cx: &mut App| {
counter.update(cx, |counter, _cx| {
counter.value += 1;
});
};
()
}
}
// .update() outside of render entirely
fn update_outside_render(entity: &Entity<Counter>, cx: &mut App) {
entity.update(cx, |counter, _cx| {
counter.value += 1;
});
}
// .update() on a non-gpui type (unrelated method named "update")
struct FakeEntity;
impl FakeEntity {
fn update(&self) {}
}
struct FakeView {
thing: FakeEntity,
}
impl Render for FakeView {
fn render(&mut self, _window: &mut Window, _cx: &mut Context<Self>) -> impl IntoElement {
self.thing.update();
()
}
}
fn main() {}