Files
codex/prs/bolinfest/study/PR-2115-study.md
2025-09-02 15:17:45 -07:00

140 lines
4.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
**DOs**
- **Check Simple Conditions Before Locking:** Gate on cheap checks like `query.is_empty()` or identical queries without taking the mutex.
```rust
// Good: no lock held for trivial early-exit
if query.is_empty() {
let max_total = MAX_FILE_SEARCH_RESULTS.get();
let matches = collect_top_level_suggestions(&self.search_dir, max_total);
self.app_tx.send(AppEvent::FileSearchResult {
query: String::new(),
matches,
});
return;
}
// Only now take the lock
let mut st = self.state.lock().unwrap();
if query == st.latest_query {
return;
}
```
- **Model State Explicitly (avoid overloading):** Prefer clear flags or enums over `Option<String>` when representing “never shown” vs “empty string”.
```rust
// Prefer explicit fields
struct SearchState {
latest_query: String,
has_shown_popup: bool, // instead of latest_query: Option<String>
}
```
- **Keep Code Paths Symmetric:** Make empty and non-empty query flows update/search state consistently to preserve invariants.
```rust
fn handle_query(&self, query: String) {
if query.is_empty() {
self.finish_empty_query(&query); // updates scheduling state as needed
} else {
self.start_non_empty_search(query); // sets active_search + cancellation_token
}
}
fn finish_empty_query(&self, query: &str) {
// Clear any scheduled search consistently
let mut st = self.state.lock().unwrap();
st.is_search_scheduled = false;
st.active_search = None;
drop(st);
let max_total = MAX_FILE_SEARCH_RESULTS.get();
let matches = collect_top_level_suggestions(&self.search_dir, max_total);
self.app_tx.send(AppEvent::FileSearchResult {
query: query.to_string(),
matches,
});
}
```
- **Short-Circuit Unchanged Inputs:** Avoid re-scheduling when the query did not change; combine with the empty check if appropriate.
```rust
let unchanged = {
let st = self.state.lock().unwrap();
query == st.latest_query
};
if unchanged {
return;
}
```
- **Put Imports At The Top:** Keep `use` statements at module scope; use descriptive types.
```rust
use std::collections::HashSet;
use std::fs;
```
- **Use Descriptive Names:** Prefer self-explanatory identifiers over two-letter names in filesystem loops.
```rust
let mut seen: HashSet<String> = HashSet::new();
if let Ok(dir_iter) = fs::read_dir(cwd) {
for dir_entry in dir_iter.flatten() {
let entry_path = dir_entry.path();
let Some(name) = entry_path.strip_prefix(cwd).ok().and_then(|p| p.to_str()) else { continue };
// ...
}
}
```
**DONTs**
- **Dont Hold Locks During I/O or Heavy Work:** Copy out what you need, drop the lock, then perform filesystem or compute operations.
```rust
// Anti-pattern: lock held across I/O
let mut st = self.state.lock().unwrap();
for entry in std::fs::read_dir(&self.search_dir).unwrap() { /* ... */ }
// Better:
let search_dir = self.search_dir.clone();
drop(st);
for entry in std::fs::read_dir(search_dir).unwrap() { /* ... */ }
```
- **Dont Introduce APIs Without Clear Need:** Avoid adding methods like `reset()` unless theyre necessary, consistently used, and tested.
```rust
// Instead of adding a broad reset(), cancel the active search via existing state.
let mut st = self.state.lock().unwrap();
if let Some(active) = st.active_search.take() {
active.cancellation_token.store(true, std::sync::atomic::Ordering::Relaxed);
}
st.is_search_scheduled = false;
```
- **Dont Overload `Option<String>` For Multiple States:** `None` vs `Some("")` is ambiguous; model intent explicitly.
```rust
// Avoid:
latest_query: Option<String>
// Prefer:
latest_query: String,
has_shown_popup: bool,
```
- **Dont Put `use` Inside Functions For Common Types:** Keep module imports centralized; local `use` obscures dependencies.
```rust
// Avoid inside fn:
fn collect_top_level_suggestions(...) {
use std::collections::HashSet; // <-- move to top
}
```
- **Dont Diverge State Between Code Paths:** Ensure the “empty query” fast path doesnt skip essential bookkeeping done by the normal path.
```rust
// Avoid: empty path bypasses state updates
if query.is_empty() {
// send results and return; state not updated
return;
}
// Prefer: both paths maintain scheduler/active_search invariants
handle_query(query);
```