Start on adding support for editing via the assistant panel (#14795)
Note that this shouldn't have any visible user-facing behavior yet. The feature is incomplete but we wanna merge early to avoid a long-running branch. Release Notes: - N/A --------- Co-authored-by: Nathan <nathan@zed.dev>
This commit is contained in:
parent
87457f9ae8
commit
4d177918c1
44 changed files with 1999 additions and 968 deletions
|
@ -17,6 +17,7 @@ use crate::{
|
|||
LanguageScope, Outline, RunnableCapture, RunnableTag,
|
||||
};
|
||||
use anyhow::{anyhow, Context, Result};
|
||||
use async_watch as watch;
|
||||
pub use clock::ReplicaId;
|
||||
use futures::channel::oneshot;
|
||||
use gpui::{
|
||||
|
@ -32,7 +33,7 @@ use smol::future::yield_now;
|
|||
use std::{
|
||||
any::Any,
|
||||
cell::Cell,
|
||||
cmp::{self, Ordering},
|
||||
cmp::{self, Ordering, Reverse},
|
||||
collections::BTreeMap,
|
||||
ffi::OsStr,
|
||||
fmt,
|
||||
|
@ -104,6 +105,7 @@ pub struct Buffer {
|
|||
sync_parse_timeout: Duration,
|
||||
syntax_map: Mutex<SyntaxMap>,
|
||||
parsing_in_background: bool,
|
||||
parse_status: (watch::Sender<ParseStatus>, watch::Receiver<ParseStatus>),
|
||||
non_text_state_update_count: usize,
|
||||
diagnostics: SmallVec<[(LanguageServerId, DiagnosticSet); 2]>,
|
||||
remote_selections: TreeMap<ReplicaId, SelectionSet>,
|
||||
|
@ -119,6 +121,12 @@ pub struct Buffer {
|
|||
has_unsaved_edits: Cell<(clock::Global, bool)>,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||
pub enum ParseStatus {
|
||||
Idle,
|
||||
Parsing,
|
||||
}
|
||||
|
||||
/// An immutable, cheaply cloneable representation of a fixed
|
||||
/// state of a buffer.
|
||||
pub struct BufferSnapshot {
|
||||
|
@ -710,6 +718,7 @@ impl Buffer {
|
|||
parsing_in_background: false,
|
||||
non_text_state_update_count: 0,
|
||||
sync_parse_timeout: Duration::from_millis(1),
|
||||
parse_status: async_watch::channel(ParseStatus::Idle),
|
||||
autoindent_requests: Default::default(),
|
||||
pending_autoindent: Default::default(),
|
||||
language: None,
|
||||
|
@ -1059,6 +1068,7 @@ impl Buffer {
|
|||
}
|
||||
});
|
||||
|
||||
self.parse_status.0.send(ParseStatus::Parsing).unwrap();
|
||||
match cx
|
||||
.background_executor()
|
||||
.block_with_timeout(self.sync_parse_timeout, parse_task)
|
||||
|
@ -1101,10 +1111,15 @@ impl Buffer {
|
|||
self.non_text_state_update_count += 1;
|
||||
self.syntax_map.lock().did_parse(syntax_snapshot);
|
||||
self.request_autoindent(cx);
|
||||
self.parse_status.0.send(ParseStatus::Idle).unwrap();
|
||||
cx.emit(Event::Reparsed);
|
||||
cx.notify();
|
||||
}
|
||||
|
||||
pub fn parse_status(&self) -> watch::Receiver<ParseStatus> {
|
||||
self.parse_status.1.clone()
|
||||
}
|
||||
|
||||
/// Assign to the buffer a set of diagnostics created by a given language server.
|
||||
pub fn update_diagnostics(
|
||||
&mut self,
|
||||
|
@ -2749,7 +2764,6 @@ impl BufferSnapshot {
|
|||
.map(|g| g.outline_config.as_ref().unwrap())
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let mut stack = Vec::<Range<usize>>::new();
|
||||
let mut items = Vec::new();
|
||||
while let Some(mat) = matches.peek() {
|
||||
let config = &configs[mat.grammar_index];
|
||||
|
@ -2767,6 +2781,9 @@ impl BufferSnapshot {
|
|||
continue;
|
||||
}
|
||||
|
||||
let mut open_index = None;
|
||||
let mut close_index = None;
|
||||
|
||||
let mut buffer_ranges = Vec::new();
|
||||
for capture in mat.captures {
|
||||
let node_is_name;
|
||||
|
@ -2778,6 +2795,12 @@ impl BufferSnapshot {
|
|||
{
|
||||
node_is_name = false;
|
||||
} else {
|
||||
if Some(capture.index) == config.open_capture_ix {
|
||||
open_index = Some(capture.node.end_byte());
|
||||
} else if Some(capture.index) == config.close_capture_ix {
|
||||
close_index = Some(capture.node.start_byte());
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -2850,22 +2873,45 @@ impl BufferSnapshot {
|
|||
}
|
||||
|
||||
matches.advance();
|
||||
while stack.last().map_or(false, |prev_range| {
|
||||
prev_range.start > item_range.start || prev_range.end < item_range.end
|
||||
}) {
|
||||
stack.pop();
|
||||
}
|
||||
stack.push(item_range.clone());
|
||||
|
||||
items.push(OutlineItem {
|
||||
depth: stack.len() - 1,
|
||||
range: self.anchor_after(item_range.start)..self.anchor_before(item_range.end),
|
||||
depth: 0, // We'll calculate the depth later
|
||||
range: item_range,
|
||||
text,
|
||||
highlight_ranges,
|
||||
name_ranges,
|
||||
})
|
||||
body_range: open_index.zip(close_index).map(|(start, end)| start..end),
|
||||
});
|
||||
}
|
||||
Some(items)
|
||||
|
||||
items.sort_by_key(|item| (item.range.start, Reverse(item.range.end)));
|
||||
|
||||
// Assign depths based on containment relationships and convert to anchors.
|
||||
let mut item_ends_stack = Vec::<usize>::new();
|
||||
let mut anchor_items = Vec::new();
|
||||
for item in items {
|
||||
while let Some(last_end) = item_ends_stack.last().copied() {
|
||||
if last_end < item.range.end {
|
||||
item_ends_stack.pop();
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
anchor_items.push(OutlineItem {
|
||||
depth: item_ends_stack.len(),
|
||||
range: self.anchor_after(item.range.start)..self.anchor_before(item.range.end),
|
||||
text: item.text,
|
||||
highlight_ranges: item.highlight_ranges,
|
||||
name_ranges: item.name_ranges,
|
||||
body_range: item.body_range.map(|body_range| {
|
||||
self.anchor_after(body_range.start)..self.anchor_before(body_range.end)
|
||||
}),
|
||||
});
|
||||
item_ends_stack.push(item.range.end);
|
||||
}
|
||||
|
||||
Some(anchor_items)
|
||||
}
|
||||
|
||||
/// For each grammar in the language, runs the provided
|
||||
|
|
|
@ -2615,7 +2615,8 @@ fn rust_lang() -> Language {
|
|||
"impl" @context
|
||||
trait: (_)? @name
|
||||
"for"? @context
|
||||
type: (_) @name) @item
|
||||
type: (_) @name
|
||||
body: (_ "{" (_)* "}")) @item
|
||||
(function_item
|
||||
"fn" @context
|
||||
name: (_) @name) @item
|
||||
|
|
|
@ -867,6 +867,8 @@ pub struct OutlineConfig {
|
|||
pub name_capture_ix: u32,
|
||||
pub context_capture_ix: Option<u32>,
|
||||
pub extra_context_capture_ix: Option<u32>,
|
||||
pub open_capture_ix: Option<u32>,
|
||||
pub close_capture_ix: Option<u32>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
|
@ -1050,6 +1052,8 @@ impl Language {
|
|||
let mut name_capture_ix = None;
|
||||
let mut context_capture_ix = None;
|
||||
let mut extra_context_capture_ix = None;
|
||||
let mut open_capture_ix = None;
|
||||
let mut close_capture_ix = None;
|
||||
get_capture_indices(
|
||||
&query,
|
||||
&mut [
|
||||
|
@ -1057,6 +1061,8 @@ impl Language {
|
|||
("name", &mut name_capture_ix),
|
||||
("context", &mut context_capture_ix),
|
||||
("context.extra", &mut extra_context_capture_ix),
|
||||
("open", &mut open_capture_ix),
|
||||
("close", &mut close_capture_ix),
|
||||
],
|
||||
);
|
||||
if let Some((item_capture_ix, name_capture_ix)) = item_capture_ix.zip(name_capture_ix) {
|
||||
|
@ -1066,6 +1072,8 @@ impl Language {
|
|||
name_capture_ix,
|
||||
context_capture_ix,
|
||||
extra_context_capture_ix,
|
||||
open_capture_ix,
|
||||
close_capture_ix,
|
||||
});
|
||||
}
|
||||
Ok(self)
|
||||
|
|
|
@ -23,6 +23,7 @@ pub struct OutlineItem<T> {
|
|||
pub text: String,
|
||||
pub highlight_ranges: Vec<(Range<usize>, HighlightStyle)>,
|
||||
pub name_ranges: Vec<Range<usize>>,
|
||||
pub body_range: Option<Range<T>>,
|
||||
}
|
||||
|
||||
impl<T> Outline<T> {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue