mirror of
https://github.com/zed-industries/zed.git
synced 2024-12-27 07:32:02 +03:00
Add docs for buffer.rs
Co-authored-by: Antonio <antonio@zed.dev>
This commit is contained in:
parent
ebe2c3658c
commit
6457ccf9ec
@ -60,12 +60,15 @@ pub use {tree_sitter_rust, tree_sitter_typescript};
|
|||||||
pub use lsp::DiagnosticSeverity;
|
pub use lsp::DiagnosticSeverity;
|
||||||
|
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
pub static ref BUFFER_DIFF_TASK: TaskLabel = TaskLabel::new();
|
static ref BUFFER_DIFF_TASK: TaskLabel = TaskLabel::new();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Indicate whether a [Buffer] has permissions to edit.
|
||||||
#[derive(PartialEq, Clone, Copy, Debug)]
|
#[derive(PartialEq, Clone, Copy, Debug)]
|
||||||
pub enum Capability {
|
pub enum Capability {
|
||||||
|
/// The buffer is a mutable replica.
|
||||||
ReadWrite,
|
ReadWrite,
|
||||||
|
/// The buffer is a read-only replica.
|
||||||
ReadOnly,
|
ReadOnly,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -107,11 +110,11 @@ pub struct Buffer {
|
|||||||
capability: Capability,
|
capability: Capability,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// An immutable, cheaply cloneable representation of a certain
|
/// An immutable, cheaply cloneable representation of a fixed
|
||||||
/// state of a buffer.
|
/// state of a buffer.
|
||||||
pub struct BufferSnapshot {
|
pub struct BufferSnapshot {
|
||||||
text: text::BufferSnapshot,
|
text: text::BufferSnapshot,
|
||||||
pub git_diff: git::diff::BufferDiff,
|
git_diff: git::diff::BufferDiff,
|
||||||
pub(crate) syntax: SyntaxSnapshot,
|
pub(crate) syntax: SyntaxSnapshot,
|
||||||
file: Option<Arc<dyn File>>,
|
file: Option<Arc<dyn File>>,
|
||||||
diagnostics: SmallVec<[(LanguageServerId, DiagnosticSet); 2]>,
|
diagnostics: SmallVec<[(LanguageServerId, DiagnosticSet); 2]>,
|
||||||
@ -128,25 +131,33 @@ pub struct BufferSnapshot {
|
|||||||
/// assumes that indentation is all the same character.
|
/// assumes that indentation is all the same character.
|
||||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Default)]
|
#[derive(Clone, Copy, Debug, PartialEq, Eq, Default)]
|
||||||
pub struct IndentSize {
|
pub struct IndentSize {
|
||||||
|
/// The number of bytes that comprise the indentation.
|
||||||
pub len: u32,
|
pub len: u32,
|
||||||
|
/// The kind of whitespace used for indentation.
|
||||||
pub kind: IndentKind,
|
pub kind: IndentKind,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A whitespace character that's used for indentation.
|
/// A whitespace character that's used for indentation.
|
||||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Default)]
|
#[derive(Clone, Copy, Debug, PartialEq, Eq, Default)]
|
||||||
pub enum IndentKind {
|
pub enum IndentKind {
|
||||||
|
/// An ASCII space character.
|
||||||
#[default]
|
#[default]
|
||||||
Space,
|
Space,
|
||||||
|
/// An ASCII tab chracter.
|
||||||
Tab,
|
Tab,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The shape of a selection cursor.
|
/// The shape of a selection cursor.
|
||||||
#[derive(Copy, Clone, PartialEq, Eq, Debug, Default)]
|
#[derive(Copy, Clone, PartialEq, Eq, Debug, Default)]
|
||||||
pub enum CursorShape {
|
pub enum CursorShape {
|
||||||
|
/// A vertical bar
|
||||||
#[default]
|
#[default]
|
||||||
Bar,
|
Bar,
|
||||||
|
/// A block that surrounds the following character
|
||||||
Block,
|
Block,
|
||||||
|
/// An underline that runs along the following character
|
||||||
Underscore,
|
Underscore,
|
||||||
|
/// A box drawn around the following character
|
||||||
Hollow,
|
Hollow,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -158,26 +169,40 @@ struct SelectionSet {
|
|||||||
lamport_timestamp: clock::Lamport,
|
lamport_timestamp: clock::Lamport,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
|
||||||
pub struct GroupId {
|
|
||||||
source: Arc<str>,
|
|
||||||
id: usize,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A diagnostic associated with a certain range of a buffer.
|
/// A diagnostic associated with a certain range of a buffer.
|
||||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||||
pub struct Diagnostic {
|
pub struct Diagnostic {
|
||||||
|
/// The name of the service that produced this diagnostic.
|
||||||
pub source: Option<String>,
|
pub source: Option<String>,
|
||||||
|
/// A machine-readable code that identifies this diagnostic.
|
||||||
pub code: Option<String>,
|
pub code: Option<String>,
|
||||||
|
/// Whether this diagnostic is a hint, warning, or error.
|
||||||
pub severity: DiagnosticSeverity,
|
pub severity: DiagnosticSeverity,
|
||||||
|
/// The human-readable message associated with this diagnostic.
|
||||||
pub message: String,
|
pub message: String,
|
||||||
|
/// An id that identifies the group to which this diagnostic belongs.
|
||||||
|
///
|
||||||
|
/// When a language server produces a diagnostic with
|
||||||
|
/// one or more associated diagnostics, those diagnostics are all
|
||||||
|
/// assigned a single group id.
|
||||||
pub group_id: usize,
|
pub group_id: usize,
|
||||||
pub is_valid: bool,
|
/// Whether this diagnostic is the primary diagnostic for its group.
|
||||||
|
///
|
||||||
|
/// In a given group, the primary diagnostic is the top-level diagnostic
|
||||||
|
/// returned by the language server. The non-primary diagnostics are the
|
||||||
|
/// associated diagnostics.
|
||||||
pub is_primary: bool,
|
pub is_primary: bool,
|
||||||
|
/// Whether this diagnostic is considered to originate from an analysis of
|
||||||
|
/// files on disk, as opposed to any unsaved buffer contents. This is a
|
||||||
|
/// property of a given diagnostic source, and is configured for a given
|
||||||
|
/// language server via the [LspAdapter::disk_based_diagnostic_sources] method
|
||||||
|
/// for the language server.
|
||||||
pub is_disk_based: bool,
|
pub is_disk_based: bool,
|
||||||
|
/// Whether this diagnostic marks unnecessary code.
|
||||||
pub is_unnecessary: bool,
|
pub is_unnecessary: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// TODO - move this into the `project` crate and make it private.
|
||||||
pub async fn prepare_completion_documentation(
|
pub async fn prepare_completion_documentation(
|
||||||
documentation: &lsp::Documentation,
|
documentation: &lsp::Documentation,
|
||||||
language_registry: &Arc<LanguageRegistry>,
|
language_registry: &Arc<LanguageRegistry>,
|
||||||
@ -209,77 +234,125 @@ pub async fn prepare_completion_documentation(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Documentation associated with a [Completion].
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub enum Documentation {
|
pub enum Documentation {
|
||||||
|
/// There is no documentation for this completion.
|
||||||
Undocumented,
|
Undocumented,
|
||||||
|
/// A single line of documentation.
|
||||||
SingleLine(String),
|
SingleLine(String),
|
||||||
|
/// Multiple lines of plain text documentation.
|
||||||
MultiLinePlainText(String),
|
MultiLinePlainText(String),
|
||||||
|
/// Markdown documentation.
|
||||||
MultiLineMarkdown(ParsedMarkdown),
|
MultiLineMarkdown(ParsedMarkdown),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A completion provided by a language server
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct Completion {
|
pub struct Completion {
|
||||||
|
/// The range of the buffer that will be replaced.
|
||||||
pub old_range: Range<Anchor>,
|
pub old_range: Range<Anchor>,
|
||||||
|
/// The new text that will be inserted.
|
||||||
pub new_text: String,
|
pub new_text: String,
|
||||||
|
/// A label for this completion that is shown in the menu.
|
||||||
pub label: CodeLabel,
|
pub label: CodeLabel,
|
||||||
|
/// The id of the language server that produced this completion.
|
||||||
pub server_id: LanguageServerId,
|
pub server_id: LanguageServerId,
|
||||||
|
/// The documentation for this completion.
|
||||||
pub documentation: Option<Documentation>,
|
pub documentation: Option<Documentation>,
|
||||||
|
/// The raw completion provided by the language server.
|
||||||
pub lsp_completion: lsp::CompletionItem,
|
pub lsp_completion: lsp::CompletionItem,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A code action provided by a language server.
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct CodeAction {
|
pub struct CodeAction {
|
||||||
|
/// The id of the language server that produced this code action.
|
||||||
pub server_id: LanguageServerId,
|
pub server_id: LanguageServerId,
|
||||||
|
/// The range of the buffer where this code action is applicable.
|
||||||
pub range: Range<Anchor>,
|
pub range: Range<Anchor>,
|
||||||
|
/// The raw code action provided by the language server.
|
||||||
pub lsp_action: lsp::CodeAction,
|
pub lsp_action: lsp::CodeAction,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// An operation used to synchronize this buffer with its other replicas.
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
pub enum Operation {
|
pub enum Operation {
|
||||||
|
/// A text operation.
|
||||||
Buffer(text::Operation),
|
Buffer(text::Operation),
|
||||||
|
|
||||||
|
/// An update to the buffer's diagnostics.
|
||||||
UpdateDiagnostics {
|
UpdateDiagnostics {
|
||||||
|
/// The id of the language server that produced the new diagnostics.
|
||||||
server_id: LanguageServerId,
|
server_id: LanguageServerId,
|
||||||
|
/// The diagnostics.
|
||||||
diagnostics: Arc<[DiagnosticEntry<Anchor>]>,
|
diagnostics: Arc<[DiagnosticEntry<Anchor>]>,
|
||||||
|
/// The buffer's lamport timestamp.
|
||||||
lamport_timestamp: clock::Lamport,
|
lamport_timestamp: clock::Lamport,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/// An update to the most recent selections in this buffer.
|
||||||
UpdateSelections {
|
UpdateSelections {
|
||||||
|
/// The selections.
|
||||||
selections: Arc<[Selection<Anchor>]>,
|
selections: Arc<[Selection<Anchor>]>,
|
||||||
|
/// The buffer's lamport timestamp.
|
||||||
lamport_timestamp: clock::Lamport,
|
lamport_timestamp: clock::Lamport,
|
||||||
|
/// Whether the selections are in 'line mode'.
|
||||||
line_mode: bool,
|
line_mode: bool,
|
||||||
|
/// The [CursorShape] associated with these selections.
|
||||||
cursor_shape: CursorShape,
|
cursor_shape: CursorShape,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/// An update to the characters that should trigger autocompletion
|
||||||
|
/// for this buffer.
|
||||||
UpdateCompletionTriggers {
|
UpdateCompletionTriggers {
|
||||||
|
/// The characters that trigger autocompletion.
|
||||||
triggers: Vec<String>,
|
triggers: Vec<String>,
|
||||||
|
/// The buffer's lamport timestamp.
|
||||||
lamport_timestamp: clock::Lamport,
|
lamport_timestamp: clock::Lamport,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// An event that occurs in a buffer.
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
pub enum Event {
|
pub enum Event {
|
||||||
|
/// The buffer was changed in a way that must be
|
||||||
|
/// propagated to its other replicas.
|
||||||
Operation(Operation),
|
Operation(Operation),
|
||||||
|
/// The buffer was edited.
|
||||||
Edited,
|
Edited,
|
||||||
|
/// The buffer's `dirty` bit changed.
|
||||||
DirtyChanged,
|
DirtyChanged,
|
||||||
|
/// The buffer was saved.
|
||||||
Saved,
|
Saved,
|
||||||
|
/// The buffer's file was changed on disk.
|
||||||
FileHandleChanged,
|
FileHandleChanged,
|
||||||
|
/// The buffer was reloaded.
|
||||||
Reloaded,
|
Reloaded,
|
||||||
|
/// The buffer's diff_base changed.
|
||||||
DiffBaseChanged,
|
DiffBaseChanged,
|
||||||
|
/// The buffer's language was changed.
|
||||||
LanguageChanged,
|
LanguageChanged,
|
||||||
|
/// The buffer's syntax trees were updated.
|
||||||
Reparsed,
|
Reparsed,
|
||||||
|
/// The buffer's diagnostics were updated.
|
||||||
DiagnosticsUpdated,
|
DiagnosticsUpdated,
|
||||||
|
/// The buffer was explicitly requested to close.
|
||||||
Closed,
|
Closed,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The file associated with a buffer.
|
/// The file associated with a buffer.
|
||||||
pub trait File: Send + Sync {
|
pub trait File: Send + Sync {
|
||||||
|
/// Returns the [LocalFile] associated with this file, if the
|
||||||
|
/// file is local.
|
||||||
fn as_local(&self) -> Option<&dyn LocalFile>;
|
fn as_local(&self) -> Option<&dyn LocalFile>;
|
||||||
|
|
||||||
|
/// Returns whether this file is local.
|
||||||
fn is_local(&self) -> bool {
|
fn is_local(&self) -> bool {
|
||||||
self.as_local().is_some()
|
self.as_local().is_some()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the file's mtime.
|
||||||
fn mtime(&self) -> SystemTime;
|
fn mtime(&self) -> SystemTime;
|
||||||
|
|
||||||
/// Returns the path of this file relative to the worktree's root directory.
|
/// Returns the path of this file relative to the worktree's root directory.
|
||||||
@ -298,10 +371,13 @@ pub trait File: Send + Sync {
|
|||||||
/// This is needed for looking up project-specific settings.
|
/// This is needed for looking up project-specific settings.
|
||||||
fn worktree_id(&self) -> usize;
|
fn worktree_id(&self) -> usize;
|
||||||
|
|
||||||
|
/// Returns whether the file has been deleted.
|
||||||
fn is_deleted(&self) -> bool;
|
fn is_deleted(&self) -> bool;
|
||||||
|
|
||||||
|
/// Converts this file into an [Any] trait object.
|
||||||
fn as_any(&self) -> &dyn Any;
|
fn as_any(&self) -> &dyn Any;
|
||||||
|
|
||||||
|
/// Converts this file into a protobuf message.
|
||||||
fn to_proto(&self) -> rpc::proto::File;
|
fn to_proto(&self) -> rpc::proto::File;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -310,8 +386,10 @@ pub trait LocalFile: File {
|
|||||||
/// Returns the absolute path of this file.
|
/// Returns the absolute path of this file.
|
||||||
fn abs_path(&self, cx: &AppContext) -> PathBuf;
|
fn abs_path(&self, cx: &AppContext) -> PathBuf;
|
||||||
|
|
||||||
|
/// Loads the file's contents from disk.
|
||||||
fn load(&self, cx: &AppContext) -> Task<Result<String>>;
|
fn load(&self, cx: &AppContext) -> Task<Result<String>>;
|
||||||
|
|
||||||
|
/// Called when the buffer is reloaded from disk.
|
||||||
fn buffer_reloaded(
|
fn buffer_reloaded(
|
||||||
&self,
|
&self,
|
||||||
buffer_id: u64,
|
buffer_id: u64,
|
||||||
@ -392,11 +470,18 @@ pub struct BufferChunks<'a> {
|
|||||||
/// diagnostic status.
|
/// diagnostic status.
|
||||||
#[derive(Clone, Copy, Debug, Default)]
|
#[derive(Clone, Copy, Debug, Default)]
|
||||||
pub struct Chunk<'a> {
|
pub struct Chunk<'a> {
|
||||||
|
/// The text of the chunk.
|
||||||
pub text: &'a str,
|
pub text: &'a str,
|
||||||
|
/// The syntax highlighting style of the chunk.
|
||||||
pub syntax_highlight_id: Option<HighlightId>,
|
pub syntax_highlight_id: Option<HighlightId>,
|
||||||
|
/// The highlight style that has been applied to this chunk in
|
||||||
|
/// the editor.
|
||||||
pub highlight_style: Option<HighlightStyle>,
|
pub highlight_style: Option<HighlightStyle>,
|
||||||
|
/// The severity of diagnostic associated with this chunk, if any.
|
||||||
pub diagnostic_severity: Option<DiagnosticSeverity>,
|
pub diagnostic_severity: Option<DiagnosticSeverity>,
|
||||||
|
/// Whether this chunk of text is marked as unnecessary.
|
||||||
pub is_unnecessary: bool,
|
pub is_unnecessary: bool,
|
||||||
|
/// Whether this chunk of text was originally a tab character.
|
||||||
pub is_tab: bool,
|
pub is_tab: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -418,21 +503,14 @@ pub(crate) struct DiagnosticEndpoint {
|
|||||||
/// A class of characters, used for characterizing a run of text.
|
/// A class of characters, used for characterizing a run of text.
|
||||||
#[derive(Copy, Clone, Eq, PartialEq, PartialOrd, Ord, Debug)]
|
#[derive(Copy, Clone, Eq, PartialEq, PartialOrd, Ord, Debug)]
|
||||||
pub enum CharKind {
|
pub enum CharKind {
|
||||||
|
/// Whitespace.
|
||||||
Whitespace,
|
Whitespace,
|
||||||
|
/// Punctuation.
|
||||||
Punctuation,
|
Punctuation,
|
||||||
|
/// Word.
|
||||||
Word,
|
Word,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CharKind {
|
|
||||||
pub fn coerce_punctuation(self, treat_punctuation_as_word: bool) -> Self {
|
|
||||||
if treat_punctuation_as_word && self == CharKind::Punctuation {
|
|
||||||
CharKind::Word
|
|
||||||
} else {
|
|
||||||
self
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Buffer {
|
impl Buffer {
|
||||||
/// Create a new buffer with the given base text.
|
/// Create a new buffer with the given base text.
|
||||||
pub fn new<T: Into<String>>(replica_id: ReplicaId, id: u64, base_text: T) -> Self {
|
pub fn new<T: Into<String>>(replica_id: ReplicaId, id: u64, base_text: T) -> Self {
|
||||||
@ -554,14 +632,17 @@ impl Buffer {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the [Capability] of this buffer.
|
||||||
pub fn capability(&self) -> Capability {
|
pub fn capability(&self) -> Capability {
|
||||||
self.capability
|
self.capability
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Whether this buffer can only be read.
|
||||||
pub fn read_only(&self) -> bool {
|
pub fn read_only(&self) -> bool {
|
||||||
self.capability == Capability::ReadOnly
|
self.capability == Capability::ReadOnly
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Builds a [Buffer] with the given underlying [TextBuffer], diff base, [File] and [Capability].
|
||||||
pub fn build(
|
pub fn build(
|
||||||
buffer: TextBuffer,
|
buffer: TextBuffer,
|
||||||
diff_base: Option<String>,
|
diff_base: Option<String>,
|
||||||
@ -675,6 +756,7 @@ impl Buffer {
|
|||||||
.set_language_registry(language_registry);
|
.set_language_registry(language_registry);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// This method is called to signal that the buffer has been saved.
|
||||||
pub fn did_save(
|
pub fn did_save(
|
||||||
&mut self,
|
&mut self,
|
||||||
version: clock::Global,
|
version: clock::Global,
|
||||||
@ -689,6 +771,7 @@ impl Buffer {
|
|||||||
cx.notify();
|
cx.notify();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Reloads the contents of the buffer from disk.
|
||||||
pub fn reload(
|
pub fn reload(
|
||||||
&mut self,
|
&mut self,
|
||||||
cx: &mut ModelContext<Self>,
|
cx: &mut ModelContext<Self>,
|
||||||
@ -737,6 +820,7 @@ impl Buffer {
|
|||||||
rx
|
rx
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// This method is called to signal that the buffer has been reloaded.
|
||||||
pub fn did_reload(
|
pub fn did_reload(
|
||||||
&mut self,
|
&mut self,
|
||||||
version: clock::Global,
|
version: clock::Global,
|
||||||
@ -763,6 +847,8 @@ impl Buffer {
|
|||||||
cx.notify();
|
cx.notify();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Updates the [File] backing this buffer. This should be called when
|
||||||
|
/// the file has changed or has been deleted.
|
||||||
pub fn file_updated(&mut self, new_file: Arc<dyn File>, cx: &mut ModelContext<Self>) {
|
pub fn file_updated(&mut self, new_file: Arc<dyn File>, cx: &mut ModelContext<Self>) {
|
||||||
let mut file_changed = false;
|
let mut file_changed = false;
|
||||||
|
|
||||||
@ -800,16 +886,20 @@ impl Buffer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the current diff base, see [Buffer::set_diff_base].
|
||||||
pub fn diff_base(&self) -> Option<&str> {
|
pub fn diff_base(&self) -> Option<&str> {
|
||||||
self.diff_base.as_deref()
|
self.diff_base.as_deref()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Sets the text that will be used to compute a Git diff
|
||||||
|
/// against the buffer text.
|
||||||
pub fn set_diff_base(&mut self, diff_base: Option<String>, cx: &mut ModelContext<Self>) {
|
pub fn set_diff_base(&mut self, diff_base: Option<String>, cx: &mut ModelContext<Self>) {
|
||||||
self.diff_base = diff_base;
|
self.diff_base = diff_base;
|
||||||
self.git_diff_recalc(cx);
|
self.git_diff_recalc(cx);
|
||||||
cx.emit(Event::DiffBaseChanged);
|
cx.emit(Event::DiffBaseChanged);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Recomputes the Git diff status.
|
||||||
pub fn git_diff_recalc(&mut self, cx: &mut ModelContext<Self>) -> Option<Task<()>> {
|
pub fn git_diff_recalc(&mut self, cx: &mut ModelContext<Self>) -> Option<Task<()>> {
|
||||||
let diff_base = self.diff_base.clone()?; // TODO: Make this an Arc
|
let diff_base = self.diff_base.clone()?; // TODO: Make this an Arc
|
||||||
let snapshot = self.snapshot();
|
let snapshot = self.snapshot();
|
||||||
@ -830,14 +920,12 @@ impl Buffer {
|
|||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn close(&mut self, cx: &mut ModelContext<Self>) {
|
/// Returns the primary [Language] assigned to this [Buffer].
|
||||||
cx.emit(Event::Closed);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn language(&self) -> Option<&Arc<Language>> {
|
pub fn language(&self) -> Option<&Arc<Language>> {
|
||||||
self.language.as_ref()
|
self.language.as_ref()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the [Language] at the given location.
|
||||||
pub fn language_at<D: ToOffset>(&self, position: D) -> Option<Arc<Language>> {
|
pub fn language_at<D: ToOffset>(&self, position: D) -> Option<Arc<Language>> {
|
||||||
let offset = position.to_offset(self);
|
let offset = position.to_offset(self);
|
||||||
self.syntax_map
|
self.syntax_map
|
||||||
@ -848,26 +936,32 @@ impl Buffer {
|
|||||||
.or_else(|| self.language.clone())
|
.or_else(|| self.language.clone())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The number of times the buffer was parsed.
|
||||||
pub fn parse_count(&self) -> usize {
|
pub fn parse_count(&self) -> usize {
|
||||||
self.parse_count
|
self.parse_count
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The number of times selections were updated.
|
||||||
pub fn selections_update_count(&self) -> usize {
|
pub fn selections_update_count(&self) -> usize {
|
||||||
self.selections_update_count
|
self.selections_update_count
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The number of times diagnostics were updated.
|
||||||
pub fn diagnostics_update_count(&self) -> usize {
|
pub fn diagnostics_update_count(&self) -> usize {
|
||||||
self.diagnostics_update_count
|
self.diagnostics_update_count
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The number of times the underlying file was updated.
|
||||||
pub fn file_update_count(&self) -> usize {
|
pub fn file_update_count(&self) -> usize {
|
||||||
self.file_update_count
|
self.file_update_count
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The number of times the git diff status was updated.
|
||||||
pub fn git_diff_update_count(&self) -> usize {
|
pub fn git_diff_update_count(&self) -> usize {
|
||||||
self.git_diff_update_count
|
self.git_diff_update_count
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Whether the buffer is being parsed in the background.
|
||||||
#[cfg(any(test, feature = "test-support"))]
|
#[cfg(any(test, feature = "test-support"))]
|
||||||
pub fn is_parsing(&self) -> bool {
|
pub fn is_parsing(&self) -> bool {
|
||||||
self.parsing_in_background
|
self.parsing_in_background
|
||||||
@ -2377,7 +2471,7 @@ impl BufferSnapshot {
|
|||||||
self.syntax.layers_for_range(0..self.len(), &self.text)
|
self.syntax.layers_for_range(0..self.len(), &self.text)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn syntax_layer_at<D: ToOffset>(&self, position: D) -> Option<SyntaxLayer> {
|
fn syntax_layer_at<D: ToOffset>(&self, position: D) -> Option<SyntaxLayer> {
|
||||||
let offset = position.to_offset(self);
|
let offset = position.to_offset(self);
|
||||||
self.syntax
|
self.syntax
|
||||||
.layers_for_range(offset..offset, &self.text)
|
.layers_for_range(offset..offset, &self.text)
|
||||||
@ -2385,12 +2479,14 @@ impl BufferSnapshot {
|
|||||||
.last()
|
.last()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the [Language] at the given location.
|
||||||
pub fn language_at<D: ToOffset>(&self, position: D) -> Option<&Arc<Language>> {
|
pub fn language_at<D: ToOffset>(&self, position: D) -> Option<&Arc<Language>> {
|
||||||
self.syntax_layer_at(position)
|
self.syntax_layer_at(position)
|
||||||
.map(|info| info.language)
|
.map(|info| info.language)
|
||||||
.or(self.language.as_ref())
|
.or(self.language.as_ref())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the settings for the language at the given location.
|
||||||
pub fn settings_at<'a, D: ToOffset>(
|
pub fn settings_at<'a, D: ToOffset>(
|
||||||
&self,
|
&self,
|
||||||
position: D,
|
position: D,
|
||||||
@ -2399,6 +2495,7 @@ impl BufferSnapshot {
|
|||||||
language_settings(self.language_at(position), self.file.as_ref(), cx)
|
language_settings(self.language_at(position), self.file.as_ref(), cx)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the [LanguageScope] at the given location.
|
||||||
pub fn language_scope_at<D: ToOffset>(&self, position: D) -> Option<LanguageScope> {
|
pub fn language_scope_at<D: ToOffset>(&self, position: D) -> Option<LanguageScope> {
|
||||||
let offset = position.to_offset(self);
|
let offset = position.to_offset(self);
|
||||||
let mut scope = None;
|
let mut scope = None;
|
||||||
@ -2443,6 +2540,8 @@ impl BufferSnapshot {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns a tuple of the range and character kind of the word
|
||||||
|
/// surrounding the given position.
|
||||||
pub fn surrounding_word<T: ToOffset>(&self, start: T) -> (Range<usize>, Option<CharKind>) {
|
pub fn surrounding_word<T: ToOffset>(&self, start: T) -> (Range<usize>, Option<CharKind>) {
|
||||||
let mut start = start.to_offset(self);
|
let mut start = start.to_offset(self);
|
||||||
let mut end = start;
|
let mut end = start;
|
||||||
@ -2475,6 +2574,7 @@ impl BufferSnapshot {
|
|||||||
(start..end, word_kind)
|
(start..end, word_kind)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the range for the closes syntax node enclosing the given range.
|
||||||
pub fn range_for_syntax_ancestor<T: ToOffset>(&self, range: Range<T>) -> Option<Range<usize>> {
|
pub fn range_for_syntax_ancestor<T: ToOffset>(&self, range: Range<T>) -> Option<Range<usize>> {
|
||||||
let range = range.start.to_offset(self)..range.end.to_offset(self);
|
let range = range.start.to_offset(self)..range.end.to_offset(self);
|
||||||
let mut result: Option<Range<usize>> = None;
|
let mut result: Option<Range<usize>> = None;
|
||||||
@ -2543,11 +2643,19 @@ impl BufferSnapshot {
|
|||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the outline for the buffer.
|
||||||
|
///
|
||||||
|
/// This method allows passing an optional [SyntaxTheme] to
|
||||||
|
/// syntax-highlight the returned symbols.
|
||||||
pub fn outline(&self, theme: Option<&SyntaxTheme>) -> Option<Outline<Anchor>> {
|
pub fn outline(&self, theme: Option<&SyntaxTheme>) -> Option<Outline<Anchor>> {
|
||||||
self.outline_items_containing(0..self.len(), true, theme)
|
self.outline_items_containing(0..self.len(), true, theme)
|
||||||
.map(Outline::new)
|
.map(Outline::new)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns all the symbols that contain the given position.
|
||||||
|
///
|
||||||
|
/// This method allows passing an optional [SyntaxTheme] to
|
||||||
|
/// syntax-highlight the returned symbols.
|
||||||
pub fn symbols_containing<T: ToOffset>(
|
pub fn symbols_containing<T: ToOffset>(
|
||||||
&self,
|
&self,
|
||||||
position: T,
|
position: T,
|
||||||
@ -2699,6 +2807,8 @@ impl BufferSnapshot {
|
|||||||
Some(items)
|
Some(items)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// For each grammar in the language, runs the provided
|
||||||
|
/// [tree_sitter::Query] against the given range.
|
||||||
pub fn matches(
|
pub fn matches(
|
||||||
&self,
|
&self,
|
||||||
range: Range<usize>,
|
range: Range<usize>,
|
||||||
@ -2755,6 +2865,7 @@ impl BufferSnapshot {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns selections for remote peers intersecting the given range.
|
||||||
#[allow(clippy::type_complexity)]
|
#[allow(clippy::type_complexity)]
|
||||||
pub fn remote_selections_in_range(
|
pub fn remote_selections_in_range(
|
||||||
&self,
|
&self,
|
||||||
@ -2793,6 +2904,13 @@ impl BufferSnapshot {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Whether the buffer contains any git changes.
|
||||||
|
pub fn has_git_diff(&self) -> bool {
|
||||||
|
!self.git_diff.is_empty()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns all the Git diff hunks intersecting the given
|
||||||
|
/// row range.
|
||||||
pub fn git_diff_hunks_in_row_range<'a>(
|
pub fn git_diff_hunks_in_row_range<'a>(
|
||||||
&'a self,
|
&'a self,
|
||||||
range: Range<u32>,
|
range: Range<u32>,
|
||||||
@ -2800,6 +2918,8 @@ impl BufferSnapshot {
|
|||||||
self.git_diff.hunks_in_row_range(range, self)
|
self.git_diff.hunks_in_row_range(range, self)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns all the Git diff hunks intersecting the given
|
||||||
|
/// range.
|
||||||
pub fn git_diff_hunks_intersecting_range<'a>(
|
pub fn git_diff_hunks_intersecting_range<'a>(
|
||||||
&'a self,
|
&'a self,
|
||||||
range: Range<Anchor>,
|
range: Range<Anchor>,
|
||||||
@ -2807,6 +2927,8 @@ impl BufferSnapshot {
|
|||||||
self.git_diff.hunks_intersecting_range(range, self)
|
self.git_diff.hunks_intersecting_range(range, self)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns all the Git diff hunks intersecting the given
|
||||||
|
/// range, in reverse order.
|
||||||
pub fn git_diff_hunks_intersecting_range_rev<'a>(
|
pub fn git_diff_hunks_intersecting_range_rev<'a>(
|
||||||
&'a self,
|
&'a self,
|
||||||
range: Range<Anchor>,
|
range: Range<Anchor>,
|
||||||
@ -2814,6 +2936,7 @@ impl BufferSnapshot {
|
|||||||
self.git_diff.hunks_intersecting_range_rev(range, self)
|
self.git_diff.hunks_intersecting_range_rev(range, self)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns all the diagnostics intersecting the given range.
|
||||||
pub fn diagnostics_in_range<'a, T, O>(
|
pub fn diagnostics_in_range<'a, T, O>(
|
||||||
&'a self,
|
&'a self,
|
||||||
search_range: Range<T>,
|
search_range: Range<T>,
|
||||||
@ -2843,6 +2966,9 @@ impl BufferSnapshot {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns all the diagnostic groups associated with the given
|
||||||
|
/// language server id. If no language server id is provided,
|
||||||
|
/// all diagnostics groups are returned.
|
||||||
pub fn diagnostic_groups(
|
pub fn diagnostic_groups(
|
||||||
&self,
|
&self,
|
||||||
language_server_id: Option<LanguageServerId>,
|
language_server_id: Option<LanguageServerId>,
|
||||||
@ -2873,6 +2999,7 @@ impl BufferSnapshot {
|
|||||||
groups
|
groups
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns an iterator over the diagnostics for the given group.
|
||||||
pub fn diagnostic_group<'a, O>(
|
pub fn diagnostic_group<'a, O>(
|
||||||
&'a self,
|
&'a self,
|
||||||
group_id: usize,
|
group_id: usize,
|
||||||
@ -2885,22 +3012,27 @@ impl BufferSnapshot {
|
|||||||
.flat_map(move |(_, set)| set.group(group_id, self))
|
.flat_map(move |(_, set)| set.group(group_id, self))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The number of times diagnostics were updated.
|
||||||
pub fn diagnostics_update_count(&self) -> usize {
|
pub fn diagnostics_update_count(&self) -> usize {
|
||||||
self.diagnostics_update_count
|
self.diagnostics_update_count
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The number of times the buffer was parsed.
|
||||||
pub fn parse_count(&self) -> usize {
|
pub fn parse_count(&self) -> usize {
|
||||||
self.parse_count
|
self.parse_count
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The number of times selections were updated.
|
||||||
pub fn selections_update_count(&self) -> usize {
|
pub fn selections_update_count(&self) -> usize {
|
||||||
self.selections_update_count
|
self.selections_update_count
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns a snapshot of underlying file.
|
||||||
pub fn file(&self) -> Option<&Arc<dyn File>> {
|
pub fn file(&self) -> Option<&Arc<dyn File>> {
|
||||||
self.file.as_ref()
|
self.file.as_ref()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Resolves the file path (relative to the worktree root) associated with the underlying file.
|
||||||
pub fn resolve_file_path(&self, cx: &AppContext, include_root: bool) -> Option<PathBuf> {
|
pub fn resolve_file_path(&self, cx: &AppContext, include_root: bool) -> Option<PathBuf> {
|
||||||
if let Some(file) = self.file() {
|
if let Some(file) = self.file() {
|
||||||
if file.path().file_name().is_none() || include_root {
|
if file.path().file_name().is_none() || include_root {
|
||||||
@ -2913,10 +3045,12 @@ impl BufferSnapshot {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The number of times the underlying file was updated.
|
||||||
pub fn file_update_count(&self) -> usize {
|
pub fn file_update_count(&self) -> usize {
|
||||||
self.file_update_count
|
self.file_update_count
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The number of times the git diff status was updated.
|
||||||
pub fn git_diff_update_count(&self) -> usize {
|
pub fn git_diff_update_count(&self) -> usize {
|
||||||
self.git_diff_update_count
|
self.git_diff_update_count
|
||||||
}
|
}
|
||||||
@ -2926,7 +3060,7 @@ fn indent_size_for_line(text: &text::BufferSnapshot, row: u32) -> IndentSize {
|
|||||||
indent_size_for_text(text.chars_at(Point::new(row, 0)))
|
indent_size_for_text(text.chars_at(Point::new(row, 0)))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn indent_size_for_text(text: impl Iterator<Item = char>) -> IndentSize {
|
fn indent_size_for_text(text: impl Iterator<Item = char>) -> IndentSize {
|
||||||
let mut result = IndentSize::spaces(0);
|
let mut result = IndentSize::spaces(0);
|
||||||
for c in text {
|
for c in text {
|
||||||
let kind = match c {
|
let kind = match c {
|
||||||
@ -3004,6 +3138,7 @@ impl<'a> BufferChunks<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Seeks to the given byte offset in the buffer.
|
||||||
pub fn seek(&mut self, offset: usize) {
|
pub fn seek(&mut self, offset: usize) {
|
||||||
self.range.start = offset;
|
self.range.start = offset;
|
||||||
self.chunks.seek(self.range.start);
|
self.chunks.seek(self.range.start);
|
||||||
@ -3027,6 +3162,7 @@ impl<'a> BufferChunks<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The current byte offset in the buffer.
|
||||||
pub fn offset(&self) -> usize {
|
pub fn offset(&self) -> usize {
|
||||||
self.range.start
|
self.range.start
|
||||||
}
|
}
|
||||||
@ -3179,7 +3315,6 @@ impl Default for Diagnostic {
|
|||||||
message: Default::default(),
|
message: Default::default(),
|
||||||
group_id: 0,
|
group_id: 0,
|
||||||
is_primary: false,
|
is_primary: false,
|
||||||
is_valid: true,
|
|
||||||
is_disk_based: false,
|
is_disk_based: false,
|
||||||
is_unnecessary: false,
|
is_unnecessary: false,
|
||||||
}
|
}
|
||||||
@ -3187,6 +3322,7 @@ impl Default for Diagnostic {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl IndentSize {
|
impl IndentSize {
|
||||||
|
/// Returns an [IndentSize] representing the given spaces.
|
||||||
pub fn spaces(len: u32) -> Self {
|
pub fn spaces(len: u32) -> Self {
|
||||||
Self {
|
Self {
|
||||||
len,
|
len,
|
||||||
@ -3194,6 +3330,7 @@ impl IndentSize {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns an [IndentSize] representing a tab.
|
||||||
pub fn tab() -> Self {
|
pub fn tab() -> Self {
|
||||||
Self {
|
Self {
|
||||||
len: 1,
|
len: 1,
|
||||||
@ -3201,10 +3338,12 @@ impl IndentSize {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// An iterator over the characters represented by this [IndentSize].
|
||||||
pub fn chars(&self) -> impl Iterator<Item = char> {
|
pub fn chars(&self) -> impl Iterator<Item = char> {
|
||||||
iter::repeat(self.char()).take(self.len as usize)
|
iter::repeat(self.char()).take(self.len as usize)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The character representation of this [IndentSize].
|
||||||
pub fn char(&self) -> char {
|
pub fn char(&self) -> char {
|
||||||
match self.kind {
|
match self.kind {
|
||||||
IndentKind::Space => ' ',
|
IndentKind::Space => ' ',
|
||||||
@ -3212,6 +3351,8 @@ impl IndentSize {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Consumes the current [IndentSize] and returns a new one that has
|
||||||
|
/// been shrunk or enlarged by the given size along the given direction.
|
||||||
pub fn with_delta(mut self, direction: Ordering, size: IndentSize) -> Self {
|
pub fn with_delta(mut self, direction: Ordering, size: IndentSize) -> Self {
|
||||||
match direction {
|
match direction {
|
||||||
Ordering::Less => {
|
Ordering::Less => {
|
||||||
@ -3233,6 +3374,8 @@ impl IndentSize {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Completion {
|
impl Completion {
|
||||||
|
/// A key that can be used to sort completions when displaying
|
||||||
|
/// them to the user.
|
||||||
pub fn sort_key(&self) -> (usize, &str) {
|
pub fn sort_key(&self) -> (usize, &str) {
|
||||||
let kind_key = match self.lsp_completion.kind {
|
let kind_key = match self.lsp_completion.kind {
|
||||||
Some(lsp::CompletionItemKind::VARIABLE) => 0,
|
Some(lsp::CompletionItemKind::VARIABLE) => 0,
|
||||||
@ -3241,12 +3384,13 @@ impl Completion {
|
|||||||
(kind_key, &self.label.text[self.label.filter_range.clone()])
|
(kind_key, &self.label.text[self.label.filter_range.clone()])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Whether this completion is a snippet.
|
||||||
pub fn is_snippet(&self) -> bool {
|
pub fn is_snippet(&self) -> bool {
|
||||||
self.lsp_completion.insert_text_format == Some(lsp::InsertTextFormat::SNIPPET)
|
self.lsp_completion.insert_text_format == Some(lsp::InsertTextFormat::SNIPPET)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn contiguous_ranges(
|
pub(crate) fn contiguous_ranges(
|
||||||
values: impl Iterator<Item = u32>,
|
values: impl Iterator<Item = u32>,
|
||||||
max_len: usize,
|
max_len: usize,
|
||||||
) -> impl Iterator<Item = Range<u32>> {
|
) -> impl Iterator<Item = Range<u32>> {
|
||||||
@ -3272,6 +3416,9 @@ pub fn contiguous_ranges(
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the [CharKind] for the given character. When a scope is provided,
|
||||||
|
/// the function checks if the character is considered a word character
|
||||||
|
/// based on the language scope's word character settings.
|
||||||
pub fn char_kind(scope: &Option<LanguageScope>, c: char) -> CharKind {
|
pub fn char_kind(scope: &Option<LanguageScope>, c: char) -> CharKind {
|
||||||
if c.is_whitespace() {
|
if c.is_whitespace() {
|
||||||
return CharKind::Whitespace;
|
return CharKind::Whitespace;
|
||||||
|
@ -223,7 +223,7 @@ pub fn serialize_diagnostics<'a>(
|
|||||||
} as i32,
|
} as i32,
|
||||||
group_id: entry.diagnostic.group_id as u64,
|
group_id: entry.diagnostic.group_id as u64,
|
||||||
is_primary: entry.diagnostic.is_primary,
|
is_primary: entry.diagnostic.is_primary,
|
||||||
is_valid: entry.diagnostic.is_valid,
|
is_valid: true,
|
||||||
code: entry.diagnostic.code.clone(),
|
code: entry.diagnostic.code.clone(),
|
||||||
is_disk_based: entry.diagnostic.is_disk_based,
|
is_disk_based: entry.diagnostic.is_disk_based,
|
||||||
is_unnecessary: entry.diagnostic.is_unnecessary,
|
is_unnecessary: entry.diagnostic.is_unnecessary,
|
||||||
@ -409,7 +409,6 @@ pub fn deserialize_diagnostics(
|
|||||||
message: diagnostic.message,
|
message: diagnostic.message,
|
||||||
group_id: diagnostic.group_id as usize,
|
group_id: diagnostic.group_id as usize,
|
||||||
code: diagnostic.code,
|
code: diagnostic.code,
|
||||||
is_valid: diagnostic.is_valid,
|
|
||||||
is_primary: diagnostic.is_primary,
|
is_primary: diagnostic.is_primary,
|
||||||
is_disk_based: diagnostic.is_disk_based,
|
is_disk_based: diagnostic.is_disk_based,
|
||||||
is_unnecessary: diagnostic.is_unnecessary,
|
is_unnecessary: diagnostic.is_unnecessary,
|
||||||
|
@ -3023,7 +3023,7 @@ impl MultiBufferSnapshot {
|
|||||||
|
|
||||||
pub fn has_git_diffs(&self) -> bool {
|
pub fn has_git_diffs(&self) -> bool {
|
||||||
for excerpt in self.excerpts.iter() {
|
for excerpt in self.excerpts.iter() {
|
||||||
if !excerpt.buffer.git_diff.is_empty() {
|
if excerpt.buffer.has_git_diff() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3912,7 +3912,6 @@ impl Project {
|
|||||||
message: diagnostic.message.clone(),
|
message: diagnostic.message.clone(),
|
||||||
group_id,
|
group_id,
|
||||||
is_primary: true,
|
is_primary: true,
|
||||||
is_valid: true,
|
|
||||||
is_disk_based,
|
is_disk_based,
|
||||||
is_unnecessary,
|
is_unnecessary,
|
||||||
},
|
},
|
||||||
@ -3930,7 +3929,6 @@ impl Project {
|
|||||||
message: info.message.clone(),
|
message: info.message.clone(),
|
||||||
group_id,
|
group_id,
|
||||||
is_primary: false,
|
is_primary: false,
|
||||||
is_valid: true,
|
|
||||||
is_disk_based,
|
is_disk_based,
|
||||||
is_unnecessary: false,
|
is_unnecessary: false,
|
||||||
},
|
},
|
||||||
|
@ -1471,7 +1471,10 @@ message Diagnostic {
|
|||||||
optional string code = 6;
|
optional string code = 6;
|
||||||
uint64 group_id = 7;
|
uint64 group_id = 7;
|
||||||
bool is_primary = 8;
|
bool is_primary = 8;
|
||||||
|
|
||||||
|
// TODO: remove this field
|
||||||
bool is_valid = 9;
|
bool is_valid = 9;
|
||||||
|
|
||||||
bool is_disk_based = 10;
|
bool is_disk_based = 10;
|
||||||
bool is_unnecessary = 11;
|
bool is_unnecessary = 11;
|
||||||
|
|
||||||
|
@ -681,8 +681,8 @@ pub(crate) fn next_word_start(
|
|||||||
for _ in 0..times {
|
for _ in 0..times {
|
||||||
let mut crossed_newline = false;
|
let mut crossed_newline = false;
|
||||||
point = movement::find_boundary(map, point, FindRange::MultiLine, |left, right| {
|
point = movement::find_boundary(map, point, FindRange::MultiLine, |left, right| {
|
||||||
let left_kind = char_kind(&scope, left).coerce_punctuation(ignore_punctuation);
|
let left_kind = coerce_punctuation(char_kind(&scope, left), ignore_punctuation);
|
||||||
let right_kind = char_kind(&scope, right).coerce_punctuation(ignore_punctuation);
|
let right_kind = coerce_punctuation(char_kind(&scope, right), ignore_punctuation);
|
||||||
let at_newline = right == '\n';
|
let at_newline = right == '\n';
|
||||||
|
|
||||||
let found = (left_kind != right_kind && right_kind != CharKind::Whitespace)
|
let found = (left_kind != right_kind && right_kind != CharKind::Whitespace)
|
||||||
@ -711,8 +711,8 @@ fn next_word_end(
|
|||||||
*point.column_mut() = 0;
|
*point.column_mut() = 0;
|
||||||
}
|
}
|
||||||
point = movement::find_boundary(map, point, FindRange::MultiLine, |left, right| {
|
point = movement::find_boundary(map, point, FindRange::MultiLine, |left, right| {
|
||||||
let left_kind = char_kind(&scope, left).coerce_punctuation(ignore_punctuation);
|
let left_kind = coerce_punctuation(char_kind(&scope, left), ignore_punctuation);
|
||||||
let right_kind = char_kind(&scope, right).coerce_punctuation(ignore_punctuation);
|
let right_kind = ccoerce_punctuation(har_kind(&scope, right), ignore_punctuation);
|
||||||
|
|
||||||
left_kind != right_kind && left_kind != CharKind::Whitespace
|
left_kind != right_kind && left_kind != CharKind::Whitespace
|
||||||
});
|
});
|
||||||
@ -744,8 +744,8 @@ fn previous_word_start(
|
|||||||
// cursor because the newline is checked only once.
|
// cursor because the newline is checked only once.
|
||||||
point =
|
point =
|
||||||
movement::find_preceding_boundary(map, point, FindRange::MultiLine, |left, right| {
|
movement::find_preceding_boundary(map, point, FindRange::MultiLine, |left, right| {
|
||||||
let left_kind = char_kind(&scope, left).coerce_punctuation(ignore_punctuation);
|
let left_kind = coerce_punctuation(char_kind(&scope, left), ignore_punctuation);
|
||||||
let right_kind = char_kind(&scope, right).coerce_punctuation(ignore_punctuation);
|
let right_kind = coerce_punctuation(char_kind(&scope, right), ignore_punctuation);
|
||||||
|
|
||||||
(left_kind != right_kind && !right.is_whitespace()) || left == '\n'
|
(left_kind != right_kind && !right.is_whitespace()) || left == '\n'
|
||||||
});
|
});
|
||||||
@ -952,6 +952,14 @@ pub(crate) fn next_line_end(
|
|||||||
end_of_line(map, false, point)
|
end_of_line(map, false, point)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn coerce_punctuation(kind: CharKind, treat_punctuation_as_word: bool) -> Self {
|
||||||
|
if treat_punctuation_as_word && kind == CharKind::Punctuation {
|
||||||
|
CharKind::Word
|
||||||
|
} else {
|
||||||
|
kind
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user