diff --git a/crates/language/src/buffer.rs b/crates/language/src/buffer.rs index d9472e8a77afc2dc7222d003aa23f513448ed661..f4917780b318e7e3cc4d0e81eac5656822d17e6d 100644 --- a/crates/language/src/buffer.rs +++ b/crates/language/src/buffer.rs @@ -42,7 +42,13 @@ use std::{ }; use sum_tree::TreeMap; use text::operation_queue::OperationQueue; -pub use text::{Buffer as TextBuffer, BufferSnapshot as TextBufferSnapshot, *}; +use text::*; +pub use text::{ + Anchor, Bias, Buffer as TextBuffer, BufferSnapshot as TextBufferSnapshot, Edit, OffsetRangeExt, + OffsetUtf16, Patch, Point, PointUtf16, Rope, RopeFingerprint, Selection, SelectionGoal, + Subscription, TextDimension, TextSummary, ToOffset, ToOffsetUtf16, ToPoint, ToPointUtf16, + Transaction, TransactionId, Unclipped, +}; use theme::SyntaxTheme; #[cfg(any(test, feature = "test-support"))] use util::RandomCharIter; @@ -63,6 +69,7 @@ pub enum Capability { ReadOnly, } +/// An in-memory representation of a source code file. pub struct Buffer { text: TextBuffer, diff_base: Option, @@ -99,6 +106,8 @@ pub struct Buffer { capability: Capability, } +/// An immutable, cheaply cloneable representation of a certain +/// state of a buffer. pub struct BufferSnapshot { text: text::BufferSnapshot, pub git_diff: git::diff::BufferDiff, @@ -150,6 +159,7 @@ pub struct GroupId { id: usize, } +/// A diagnostic associated with a certain range of a buffer. #[derive(Clone, Debug, PartialEq, Eq)] pub struct Diagnostic { pub source: Option, @@ -257,6 +267,7 @@ pub enum Event { Closed, } +/// The file associated with a buffer. pub trait File: Send + Sync { fn as_local(&self) -> Option<&dyn LocalFile>; @@ -306,6 +317,10 @@ pub trait LocalFile: File { ); } +/// The auto-indent behavior associated with an editing operation. +/// For some editing operations, each affected line of text has its +/// indentation recomputed. For other operations, the entire block +/// of edited text is adjusted uniformly. #[derive(Clone, Debug)] pub enum AutoindentMode { /// Indent each line of inserted text. @@ -353,6 +368,8 @@ struct BufferChunkHighlights<'a> { highlight_maps: Vec, } +/// An iterator that yields chunks of a buffer's text, along with their +/// syntax highlights and diagnostic status. pub struct BufferChunks<'a> { range: Range, chunks: text::Chunks<'a>, @@ -365,6 +382,8 @@ pub struct BufferChunks<'a> { highlights: Option>, } +/// A chunk of a buffer's text, along with its syntax highlight and +/// diagnostic status. #[derive(Clone, Copy, Debug, Default)] pub struct Chunk<'a> { pub text: &'a str, @@ -375,6 +394,7 @@ pub struct Chunk<'a> { pub is_tab: bool, } +/// A set of edits to a given version of a buffer, computed asynchronously. pub struct Diff { pub(crate) base_version: clock::Global, line_ending: LineEnding, @@ -407,6 +427,7 @@ impl CharKind { } impl Buffer { + /// Create a new buffer with the given base text. pub fn new>(replica_id: ReplicaId, id: u64, base_text: T) -> Self { Self::build( TextBuffer::new(replica_id, id, base_text.into()), @@ -416,6 +437,7 @@ impl Buffer { ) } + /// Create a new buffer that is a replica of a remote buffer. pub fn remote( remote_id: u64, replica_id: ReplicaId, @@ -430,6 +452,8 @@ impl Buffer { ) } + /// Create a new buffer that is a replica of a remote buffer, populating its + /// state from the given protobuf message. pub fn from_proto( replica_id: ReplicaId, capability: Capability, @@ -456,6 +480,7 @@ impl Buffer { Ok(this) } + /// Serialize the buffer's state to a protobuf message. pub fn to_proto(&self) -> proto::BufferState { proto::BufferState { id: self.remote_id(), @@ -469,6 +494,7 @@ impl Buffer { } } + /// Serialize as protobufs all of the changes to the buffer since the given version. pub fn serialize_ops( &self, since: Option, @@ -515,6 +541,7 @@ impl Buffer { }) } + /// Assign a language to the buffer, returning the buffer. pub fn with_language(mut self, language: Arc, cx: &mut ModelContext) -> Self { self.set_language(Some(language), cx); self @@ -572,6 +599,8 @@ impl Buffer { } } + /// Retrieve a snapshot of the buffer's current state. This is computationally + /// cheap, and allows reading from the buffer on a background thread. pub fn snapshot(&self) -> BufferSnapshot { let text = self.text.snapshot(); let mut syntax_map = self.syntax_map.lock(); @@ -594,18 +623,22 @@ impl Buffer { } } - pub fn as_text_snapshot(&self) -> &text::BufferSnapshot { + pub(crate) fn as_text_snapshot(&self) -> &text::BufferSnapshot { &self.text } + /// Retrieve a snapshot of the buffer's raw text, without any + /// language-related state like the syntax tree or diagnostics. pub fn text_snapshot(&self) -> text::BufferSnapshot { self.text.snapshot() } + /// The file associated with the buffer, if any. pub fn file(&self) -> Option<&Arc> { self.file.as_ref() } + /// The version of the buffer that was last saved or reloaded from disk. pub fn saved_version(&self) -> &clock::Global { &self.saved_version } @@ -614,10 +647,12 @@ impl Buffer { self.file_fingerprint } + /// The mtime of the buffer's file when the buffer was last saved or reloaded from disk. pub fn saved_mtime(&self) -> SystemTime { self.saved_mtime } + /// Assign a language to the buffer. pub fn set_language(&mut self, language: Option>, cx: &mut ModelContext) { self.syntax_map.lock().clear(); self.language = language; @@ -625,6 +660,8 @@ impl Buffer { cx.emit(Event::LanguageChanged); } + /// Assign a language registry to the buffer. This allows the buffer to retrieve + /// other languages if parts of the buffer are written in different languages. pub fn set_language_registry(&mut self, language_registry: Arc) { self.syntax_map .lock() @@ -935,6 +972,7 @@ impl Buffer { cx.notify(); } + /// Assign to the buffer a set of diagnostics created by a given language server. pub fn update_diagnostics( &mut self, server_id: LanguageServerId, @@ -1164,9 +1202,9 @@ impl Buffer { self.edit(edits, None, cx); } - // Create a minimal edit that will cause the the given row to be indented - // with the given size. After applying this edit, the length of the line - // will always be at least `new_size.len`. + /// Create a minimal edit that will cause the the given row to be indented + /// with the given size. After applying this edit, the length of the line + /// will always be at least `new_size.len`. pub fn edit_for_indent_size_adjustment( row: u32, current_size: IndentSize, @@ -1201,6 +1239,8 @@ impl Buffer { } } + /// Spawns a background task that asynchronously computes a `Diff` between the buffer's text + /// and the given new text. pub fn diff(&self, mut new_text: String, cx: &AppContext) -> Task { let old_text = self.as_rope().clone(); let base_version = self.version(); @@ -1272,7 +1312,7 @@ impl Buffer { }) } - /// Spawn a background task that searches the buffer for any whitespace + /// Spawns a background task that searches the buffer for any whitespace /// at the ends of a lines, and returns a `Diff` that removes that whitespace. pub fn remove_trailing_whitespace(&self, cx: &AppContext) -> Task { let old_text = self.as_rope().clone(); @@ -1292,7 +1332,7 @@ impl Buffer { }) } - /// Ensure that the buffer ends with a single newline character, and + /// Ensures that the buffer ends with a single newline character, and /// no other whitespace. pub fn ensure_final_newline(&mut self, cx: &mut ModelContext) { let len = self.len(); @@ -1313,7 +1353,7 @@ impl Buffer { self.edit([(offset..len, "\n")], None, cx); } - /// Apply a diff to the buffer. If the buffer has changed since the given diff was + /// Applies a diff to the buffer. If the buffer has changed since the given diff was /// calculated, then adjust the diff to account for those changes, and discard any /// parts of the diff that conflict with those changes. pub fn apply_diff(&mut self, diff: Diff, cx: &mut ModelContext) -> Option { @@ -1352,11 +1392,14 @@ impl Buffer { self.end_transaction(cx) } + /// Checks if the buffer has unsaved changes. pub fn is_dirty(&self) -> bool { self.file_fingerprint != self.as_rope().fingerprint() || self.file.as_ref().map_or(false, |file| file.is_deleted()) } + /// Checks if the buffer and its file have both changed since the buffer + /// was last saved or reloaded. pub fn has_conflict(&self) -> bool { self.file_fingerprint != self.as_rope().fingerprint() && self @@ -1365,14 +1408,23 @@ impl Buffer { .map_or(false, |file| file.mtime() > self.saved_mtime) } + /// Gets a [`Subscription`] that tracks all of the changes to the buffer's text. pub fn subscribe(&mut self) -> Subscription { self.text.subscribe() } + /// Starts a transaction, if one is not already in-progress. When undoing or + /// redoing edits, all of the edits performed within a transaction are undone + /// or redone together. pub fn start_transaction(&mut self) -> Option { self.start_transaction_at(Instant::now()) } + /// Starts a transaction, providing the current time. Subsequent transactions + /// that occur within a short period of time will be grouped together. This + /// is controlled by the buffer's undo grouping duration. + /// + /// See [`Buffer::set_group_interval`]. pub fn start_transaction_at(&mut self, now: Instant) -> Option { self.transaction_depth += 1; if self.was_dirty_before_starting_transaction.is_none() { @@ -1381,10 +1433,16 @@ impl Buffer { self.text.start_transaction_at(now) } + /// Terminates the current transaction, if this is the outermost transaction. pub fn end_transaction(&mut self, cx: &mut ModelContext) -> Option { self.end_transaction_at(Instant::now(), cx) } + /// Terminates the current transaction, providing the current time. Subsequent transactions + /// that occur within a short period of time will be grouped together. This + /// is controlled by the buffer's undo grouping duration. + /// + /// See [`Buffer::set_group_interval`]. pub fn end_transaction_at( &mut self, now: Instant, @@ -1405,26 +1463,33 @@ impl Buffer { } } + /// Manually add a transaction to the buffer's undo history. pub fn push_transaction(&mut self, transaction: Transaction, now: Instant) { self.text.push_transaction(transaction, now); } + /// Prevent the last transaction from being grouped with any subsequent transactions, + /// even if they occur with the buffer's undo grouping duration. pub fn finalize_last_transaction(&mut self) -> Option<&Transaction> { self.text.finalize_last_transaction() } + /// Manually group all changes since a given transaction. pub fn group_until_transaction(&mut self, transaction_id: TransactionId) { self.text.group_until_transaction(transaction_id); } + /// Manually remove a transaction from the buffer's undo history pub fn forget_transaction(&mut self, transaction_id: TransactionId) { self.text.forget_transaction(transaction_id); } + /// Manually merge two adjacent transactions in the buffer's undo history. pub fn merge_transactions(&mut self, transaction: TransactionId, destination: TransactionId) { self.text.merge_transactions(transaction, destination); } + /// Waits for the buffer to receive operations with the given timestamps. pub fn wait_for_edits( &mut self, edit_ids: impl IntoIterator, @@ -1432,6 +1497,7 @@ impl Buffer { self.text.wait_for_edits(edit_ids) } + /// Waits for the buffer to receive the operations necessary for resolving the given anchors. pub fn wait_for_anchors( &mut self, anchors: impl IntoIterator, @@ -1439,14 +1505,18 @@ impl Buffer { self.text.wait_for_anchors(anchors) } + /// Waits for the buffer to receive operations up to the given version. pub fn wait_for_version(&mut self, version: clock::Global) -> impl Future> { self.text.wait_for_version(version) } + /// Forces all futures returned by [`Buffer::wait_for_version`], [`Buffer::wait_for_edits`], or + /// [`Buffer::wait_for_version`] to resolve with an error. pub fn give_up_waiting(&mut self) { self.text.give_up_waiting(); } + /// Stores a set of selections that should be broadcasted to all of the buffer's replicas. pub fn set_active_selections( &mut self, selections: Arc<[Selection]>, @@ -1475,6 +1545,8 @@ impl Buffer { ); } + /// Clears the selections, so that other replicas of the buffer do not see any selections for + /// this replica. pub fn remove_active_selections(&mut self, cx: &mut ModelContext) { if self .remote_selections @@ -1485,6 +1557,7 @@ impl Buffer { } } + /// Replaces the buffer's entire text. pub fn set_text(&mut self, text: T, cx: &mut ModelContext) -> Option where T: Into>, @@ -1493,6 +1566,15 @@ impl Buffer { self.edit([(0..self.len(), text)], None, cx) } + /// Applies the given edits to the buffer. Each edit is specified as a range of text to + /// delete, and a string of text to insert at that location. + /// + /// If an [`AutoindentMode`] is provided, then the buffer will enqueue an auto-indent + /// request for the edited ranges, which will be processed when the buffer finishes + /// parsing. + /// + /// Parsing takes place at the end of a transaction, and may compute synchronously + /// or asynchronously, depending on the changes. pub fn edit( &mut self, edits_iter: I, @@ -1626,6 +1708,7 @@ impl Buffer { cx.notify(); } + /// Applies the given remote operations to the buffer. pub fn apply_ops>( &mut self, ops: I, @@ -1773,11 +1856,13 @@ impl Buffer { cx.emit(Event::Operation(operation)); } + /// Removes the selections for a given peer. pub fn remove_peer(&mut self, replica_id: ReplicaId, cx: &mut ModelContext) { self.remote_selections.remove(&replica_id); cx.notify(); } + /// Undoes the most recent transaction. pub fn undo(&mut self, cx: &mut ModelContext) -> Option { let was_dirty = self.is_dirty(); let old_version = self.version.clone(); @@ -1791,6 +1876,7 @@ impl Buffer { } } + /// Manually undoes a specific transaction in the buffer's undo history. pub fn undo_transaction( &mut self, transaction_id: TransactionId, @@ -1807,6 +1893,7 @@ impl Buffer { } } + /// Manually undoes all changes after a given transaction in the buffer's undo history. pub fn undo_to_transaction( &mut self, transaction_id: TransactionId, diff --git a/crates/language/src/language.rs b/crates/language/src/language.rs index 366d2b0098ca36437252044c50825bceaed96081..df12a270c95f64cd15bc5d4fb73908d0b4f3f9a3 100644 --- a/crates/language/src/language.rs +++ b/crates/language/src/language.rs @@ -1,3 +1,7 @@ +//! The `language` crate provides... ??? + +#![warn(missing_docs)] + mod buffer; mod diagnostic_set; mod highlight_map; @@ -58,6 +62,9 @@ pub use syntax_map::{OwnedSyntaxLayerInfo, SyntaxLayerInfo}; pub use text::LineEnding; pub use tree_sitter::{Parser, Tree}; +/// Initializes the `language` crate. +/// +/// This should be called before making use of items from the create. pub fn init(cx: &mut AppContext) { language_settings::init(cx); } @@ -90,7 +97,7 @@ thread_local! { } lazy_static! { - pub static ref NEXT_GRAMMAR_ID: AtomicUsize = Default::default(); + pub(crate) static ref NEXT_GRAMMAR_ID: AtomicUsize = Default::default(); pub static ref PLAIN_TEXT: Arc = Arc::new(Language::new( LanguageConfig { name: "Plain Text".into(), @@ -358,14 +365,22 @@ pub struct CodeLabel { #[derive(Clone, Deserialize)] pub struct LanguageConfig { + /// Human-readable name of the language. pub name: Arc, + // The name of the grammar in a WASM bundle. pub grammar_name: Option>, + /// Given a list of `LanguageConfig`'s, the language of a file can be determined based on the path extension matching any of the `path_suffixes`. pub path_suffixes: Vec, + /// List of pub brackets: BracketPairConfig, + /// A regex pattern that determines whether the language should be assigned to a file or not. #[serde(default, deserialize_with = "deserialize_regex")] pub first_line_pattern: Option, + /// If set to true, auto indentation uses last non empty line to determine + /// the indentation level for a new line. #[serde(default = "auto_indent_using_last_non_empty_line_default")] pub auto_indent_using_last_non_empty_line: bool, + /// A regex that is used to determine whether the #[serde(default, deserialize_with = "deserialize_regex")] pub increase_indent_pattern: Option, #[serde(default, deserialize_with = "deserialize_regex")] @@ -382,12 +397,16 @@ pub struct LanguageConfig { pub scope_opt_in_language_servers: Vec, #[serde(default)] pub overrides: HashMap, + /// A list of characters that Zed should treat as word characters for the + /// purpose of features that operate on word boundaries, like 'move to next word end' + /// or a whole-word search in buffer search. #[serde(default)] pub word_characters: HashSet, #[serde(default)] pub prettier_parser_name: Option, } +/// Tree-sitter language queries for a given language. #[derive(Debug, Default)] pub struct LanguageQueries { pub highlights: Option>, @@ -399,6 +418,9 @@ pub struct LanguageQueries { pub overrides: Option>, } +/// Represents a language for the given range. Some languages (e.g. HTML) +/// interleave several languages together, thus a single buffer might actually contain +/// several nested scopes. #[derive(Clone, Debug)] pub struct LanguageScope { language: Arc, @@ -491,7 +513,10 @@ pub struct FakeLspAdapter { #[derive(Clone, Debug, Default)] pub struct BracketPairConfig { + /// A list of character pairs that should be treated as brackets in the context of a given language. pub pairs: Vec, + /// A list of tree-sitter scopes for which a given bracket should not be active. + /// N-th entry in `[Self::disabled_scopes_by_bracket_ix]` contains a list of disabled scopes for an n-th entry in `[Self::pairs]` pub disabled_scopes_by_bracket_ix: Vec>, } @@ -1641,6 +1666,8 @@ impl LanguageScope { self.language.config.collapsed_placeholder.as_ref() } + /// Returns line prefix that is inserted in e.g. line continuations or + /// in `toggle comments` action. pub fn line_comment_prefix(&self) -> Option<&Arc> { Override::as_option( self.config_override().map(|o| &o.line_comment), @@ -1656,6 +1683,11 @@ impl LanguageScope { .map(|e| (&e.0, &e.1)) } + /// Returns a list of language-specific word characters. + /// + /// By default, Zed treats alphanumeric characters (and '_') as word characters for + /// the purpose of actions like 'move to next word end` or whole-word search. + /// It additionally accounts for language's additional word characters. pub fn word_characters(&self) -> Option<&HashSet> { Override::as_option( self.config_override().map(|o| &o.word_characters), @@ -1663,6 +1695,8 @@ impl LanguageScope { ) } + /// Returns a list of bracket pairs for a given language with an additional + /// piece of information about whether the particular bracket pair is currently active for a given language. pub fn brackets(&self) -> impl Iterator { let mut disabled_ids = self .config_override() diff --git a/crates/language/src/language_settings.rs b/crates/language/src/language_settings.rs index 5359d184d65a9249f8fc82b1eae9c95d71beda6c..3ac8842243abf28823db57c9b9d15eec29bc9c6c 100644 --- a/crates/language/src/language_settings.rs +++ b/crates/language/src/language_settings.rs @@ -1,3 +1,5 @@ +//! Provides `language`-related settings. + use crate::{File, Language}; use anyhow::Result; use collections::{HashMap, HashSet}; @@ -11,10 +13,12 @@ use serde::{Deserialize, Serialize}; use settings::Settings; use std::{num::NonZeroU32, path::Path, sync::Arc}; -pub fn init(cx: &mut AppContext) { +/// Initializes the language settings. +pub(crate) fn init(cx: &mut AppContext) { AllLanguageSettings::register(cx); } +/// Returns the settings for the specified language from the provided file. pub fn language_settings<'a>( language: Option<&Arc>, file: Option<&Arc>, @@ -24,6 +28,7 @@ pub fn language_settings<'a>( all_language_settings(file, cx).language(language_name.as_deref()) } +/// Returns the settings for all languages from the provided file. pub fn all_language_settings<'a>( file: Option<&Arc>, cx: &'a AppContext, @@ -32,36 +37,68 @@ pub fn all_language_settings<'a>( AllLanguageSettings::get(location, cx) } +/// The settings for all languages. #[derive(Debug, Clone)] pub struct AllLanguageSettings { + /// The settings for GitHub Copilot. pub copilot: CopilotSettings, defaults: LanguageSettings, languages: HashMap, LanguageSettings>, } +/// The settings for a particular language. #[derive(Debug, Clone, Deserialize)] pub struct LanguageSettings { + /// How many columns a tab should occupy. pub tab_size: NonZeroU32, + /// Whether to indent lines using tab characters, as opposed to multiple + /// spaces. pub hard_tabs: bool, + /// How to soft-wrap long lines of text. pub soft_wrap: SoftWrap, + /// The column at which to soft-wrap lines, for buffers where soft-wrap + /// is enabled. pub preferred_line_length: u32, + /// Whether to show wrap guides in the editor. Setting this to true will + /// show a guide at the 'preferred_line_length' value if softwrap is set to + /// 'preferred_line_length', and will show any additional guides as specified + /// by the 'wrap_guides' setting. pub show_wrap_guides: bool, + /// Character counts at which to show wrap guides in the editor. pub wrap_guides: Vec, + /// Whether or not to perform a buffer format before saving. pub format_on_save: FormatOnSave, + /// Whether or not to remove any trailing whitespace from lines of a buffer + /// before saving it. pub remove_trailing_whitespace_on_save: bool, + /// Whether or not to ensure there's a single newline at the end of a buffer + /// when saving it. pub ensure_final_newline_on_save: bool, + /// How to perform a buffer format. pub formatter: Formatter, + /// Zed's Prettier integration settings. + /// If Prettier is enabled, Zed will use this its Prettier instance for any applicable file, if + /// the project has no other Prettier installed. pub prettier: HashMap, + /// Whether to use language servers to provide code intelligence. pub enable_language_server: bool, + /// Controls whether Copilot provides suggestion immediately (true) + /// or waits for a `copilot::Toggle` (false). pub show_copilot_suggestions: bool, + /// Whether to show tabs and spaces in the editor. pub show_whitespaces: ShowWhitespaceSetting, + /// Whether to start a new line with a comment when a previous line is a comment as well. pub extend_comment_on_newline: bool, + /// Inlay hint related settings. pub inlay_hints: InlayHintSettings, } +/// The settings for [GitHub Copilot](https://github.com/features/copilot). #[derive(Clone, Debug, Default)] pub struct CopilotSettings { + /// Whether Copilit is enabled. pub feature_enabled: bool, + /// A list of globs representing files that Copilot should be disabled for. pub disabled_globs: Vec, } @@ -138,7 +175,7 @@ pub struct LanguageSettingsContent { pub formatter: Option, /// Zed's Prettier integration settings. /// If Prettier is enabled, Zed will use this its Prettier instance for any applicable file, if - /// project has no other Prettier installed. + /// the project has no other Prettier installed. /// /// Default: {} #[serde(default)] @@ -148,7 +185,7 @@ pub struct LanguageSettingsContent { /// Default: true #[serde(default)] pub enable_language_server: Option, - /// Controls whether copilot provides suggestion immediately (true) + /// Controls whether Copilot provides suggestion immediately (true) /// or waits for a `copilot::Toggle` (false). /// /// Default: true @@ -176,9 +213,11 @@ pub struct CopilotSettingsContent { #[derive(Clone, Default, Serialize, Deserialize, JsonSchema)] #[serde(rename_all = "snake_case")] pub struct FeaturesContent { + /// Whether the GitHub Copilot feature is enabled. pub copilot: Option, } +/// Controls the soft-wrapping behavior in the editor. #[derive(Copy, Clone, Debug, Serialize, Deserialize, PartialEq, Eq, JsonSchema)] #[serde(rename_all = "snake_case")] pub enum SoftWrap { @@ -190,14 +229,20 @@ pub enum SoftWrap { PreferredLineLength, } +/// Controls the behavior of formatting files when they are saved. #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, JsonSchema)] #[serde(rename_all = "snake_case")] pub enum FormatOnSave { + /// Files should be formatted on save. On, + /// Files should not be formatted on save. Off, LanguageServer, + /// The external program to use to format the files on save. External { + /// The external program to run. command: Arc, + /// The arguments to pass to the program. arguments: Arc<[String]>, }, } @@ -231,6 +276,7 @@ pub enum Formatter { }, } +/// The settings for inlay hints. #[derive(Copy, Clone, Debug, Serialize, Deserialize, JsonSchema, PartialEq, Eq)] pub struct InlayHintSettings { /// Global switch to toggle hints on and off. @@ -238,10 +284,19 @@ pub struct InlayHintSettings { /// Default: false #[serde(default)] pub enabled: bool, + /// Whether type hints should be shown. + /// + /// Default: true #[serde(default = "default_true")] pub show_type_hints: bool, + /// Whether parameter hints should be shown. + /// + /// Default: true #[serde(default = "default_true")] pub show_parameter_hints: bool, + /// Whether other hints should be shown. + /// + /// Default: true #[serde(default = "default_true")] pub show_other_hints: bool, } @@ -251,6 +306,7 @@ fn default_true() -> bool { } impl InlayHintSettings { + /// Returns the kinds of inlay hints that are enabled based on the settings. pub fn enabled_inlay_hint_kinds(&self) -> HashSet> { let mut kinds = HashSet::default(); if self.show_type_hints { diff --git a/crates/language/src/markdown.rs b/crates/language/src/markdown.rs index df75b610ef844ec858d74ae7a3a8bafa5a59edbe..863f38667f27c4124dc76702cffd12ed0a8ad0be 100644 --- a/crates/language/src/markdown.rs +++ b/crates/language/src/markdown.rs @@ -1,3 +1,5 @@ +//! Provides Markdown-related constructs. + use std::sync::Arc; use std::{ops::Range, path::PathBuf}; @@ -5,21 +7,30 @@ use crate::{HighlightId, Language, LanguageRegistry}; use gpui::{px, FontStyle, FontWeight, HighlightStyle, UnderlineStyle}; use pulldown_cmark::{CodeBlockKind, Event, Options, Parser, Tag}; +/// Parsed Markdown content. #[derive(Debug, Clone)] pub struct ParsedMarkdown { + /// The Markdown text. pub text: String, + /// The list of highlights contained in the Markdown document. pub highlights: Vec<(Range, MarkdownHighlight)>, + /// The regions of the various ranges in the Markdown document. pub region_ranges: Vec>, + /// The regions of the Markdown document. pub regions: Vec, } +/// A run of highlighted Markdown text. #[derive(Debug, Clone, PartialEq, Eq)] pub enum MarkdownHighlight { + /// A styled Markdown highlight. Style(MarkdownHighlightStyle), + /// A highlighted code block. Code(HighlightId), } impl MarkdownHighlight { + /// Converts this [`MarkdownHighlight`] to a [`HighlightStyle`]. pub fn to_highlight_style(&self, theme: &theme::SyntaxTheme) -> Option { match self { MarkdownHighlight::Style(style) => { @@ -48,23 +59,39 @@ impl MarkdownHighlight { } } +/// The style for a Markdown highlight. #[derive(Debug, Clone, Default, PartialEq, Eq)] pub struct MarkdownHighlightStyle { + /// Whether the text should be italicized. pub italic: bool, + /// Whether the text should be underlined. pub underline: bool, + /// The weight of the text. pub weight: FontWeight, } +/// A parsed region in a Markdown document. #[derive(Debug, Clone)] pub struct ParsedRegion { + /// Whether the region is a code block. pub code: bool, + /// The link contained in this region, if it has one. pub link: Option, } +/// A Markdown link. #[derive(Debug, Clone)] pub enum Link { - Web { url: String }, - Path { path: PathBuf }, + /// A link to a webpage. + Web { + /// The URL of the webpage. + url: String, + }, + /// A link to a path on the filesystem. + Path { + /// The path to the item. + path: PathBuf, + }, } impl Link { @@ -82,6 +109,7 @@ impl Link { } } +/// Parses a string of Markdown. pub async fn parse_markdown( markdown: &str, language_registry: &Arc, @@ -111,6 +139,7 @@ pub async fn parse_markdown( } } +/// Parses a Markdown block. pub async fn parse_markdown_block( markdown: &str, language_registry: &Arc, @@ -261,6 +290,7 @@ pub async fn parse_markdown_block( } } +/// Appends a highlighted run of text to the provided `text` buffer. pub fn highlight_code( text: &mut String, highlights: &mut Vec<(Range, MarkdownHighlight)>, @@ -275,6 +305,7 @@ pub fn highlight_code( } } +/// Appends a new paragraph to the provided `text` buffer. pub fn new_paragraph(text: &mut String, list_stack: &mut Vec<(Option, bool)>) { let mut is_subsequent_paragraph_of_list = false; if let Some((_, has_content)) = list_stack.last_mut() { diff --git a/crates/language/src/proto.rs b/crates/language/src/proto.rs index 957f4ee7fbc4da251698fd640d33d37d5cf4a06b..8d71e6e397af8ff11c24e3ba2b7c322395952d93 100644 --- a/crates/language/src/proto.rs +++ b/crates/language/src/proto.rs @@ -1,3 +1,5 @@ +//! Handles conversions of `language` items to and from the [`rpc`] protocol. + use crate::{ diagnostic_set::DiagnosticEntry, CodeAction, CodeLabel, Completion, CursorShape, Diagnostic, Language, @@ -11,15 +13,18 @@ use text::*; pub use proto::{BufferState, Operation}; +/// Serializes a [`RopeFingerprint`] to be sent over the wire. pub fn serialize_fingerprint(fingerprint: RopeFingerprint) -> String { fingerprint.to_hex() } +/// Deserializes a [`RopeFingerprint`] from the wire format. pub fn deserialize_fingerprint(fingerprint: &str) -> Result { RopeFingerprint::from_hex(fingerprint) .map_err(|error| anyhow!("invalid fingerprint: {}", error)) } +/// Deserializes a `[text::LineEnding]` from the wire format. pub fn deserialize_line_ending(message: proto::LineEnding) -> text::LineEnding { match message { proto::LineEnding::Unix => text::LineEnding::Unix, @@ -27,6 +32,7 @@ pub fn deserialize_line_ending(message: proto::LineEnding) -> text::LineEnding { } } +/// Serializes a [`text::LineEnding`] to be sent over the wire. pub fn serialize_line_ending(message: text::LineEnding) -> proto::LineEnding { match message { text::LineEnding::Unix => proto::LineEnding::Unix, @@ -34,6 +40,7 @@ pub fn serialize_line_ending(message: text::LineEnding) -> proto::LineEnding { } } +/// Serializes a [`crate::Operation`] to be sent over the wire. pub fn serialize_operation(operation: &crate::Operation) -> proto::Operation { proto::Operation { variant: Some(match operation { @@ -96,6 +103,7 @@ pub fn serialize_operation(operation: &crate::Operation) -> proto::Operation { } } +/// Serializes an [`operation::EditOperation`] to be sent over the wire. pub fn serialize_edit_operation(operation: &EditOperation) -> proto::operation::Edit { proto::operation::Edit { replica_id: operation.timestamp.replica_id as u32, @@ -110,6 +118,7 @@ pub fn serialize_edit_operation(operation: &EditOperation) -> proto::operation:: } } +/// Serializes an entry in the undo map to be sent over the wire. pub fn serialize_undo_map_entry( (edit_id, counts): (&clock::Lamport, &[(clock::Lamport, u32)]), ) -> proto::UndoMapEntry {