language: Update block_comment and documentation comment (#34861)

As suggested in https://github.com/zed-industries/zed/pull/34418, this
proposes various changes to language configs to make block comments and
doc-block-style comments more similar. In doing so, it introduces some
breaking changes into the extension schema.

This change is needed to support the changes I'm working on in #34418,
to be able to support `rewrap` in block comments like `/* really long
comment ... */`. As is, we can do this in C-style doc-block comments (eg
`/** ... */`) because of the config in `documentation`, but we can't do
this in regular block comments because we lack the info about what the
line prefix and indentation should be.

And while I was here, I did various other clean-ups, many of which feel
nice but are optional.

I would love special attention on the changes to the schema, version and
related changes; I'm totally unfamiliar with that part of Zed.

**Summary of changes**
- break: changes type of `block_comment` to same type as
`documentation_comment` (**this is the important change**)
- break: rename `documentation` to `documentation_comment` (optional,
but improves consistency w/ `line_comments` and `block_comment`)
- break/refactor?: removes some whitespace in the declaration of
`block_comment` delimiters (optional, may break things, need input; some
langs had no spaces, others did)
- refactor: change `tab_size` from `NonZeroU32` to just a `u32` (some
block comments don't seem to need/want indent past the initial
delimiter, so we need this be 0 sometimes)
- refactor: moves the `documentation_comment` declarations to appear
next to `block_comment`, rearranges the order of the fields in the TOML
for `documentation_comment`, rename backing `struct` (all optional)

**Future scope**
I believe that this will also allow us to extend regular block comments
on newline – as we do doc-block comments – but I haven't looked into
this yet. (eg, in JS try pressing enter in both of these: `/* */` and
`/** */`; the latter should extend w/ a `*` prefixed line, while the
former does not.)

Release Notes:

- BREAKING CHANGE: update extension schema version from 1 to 2, change
format of `block_comment` and rename `documentation_comment`

/cc @smitbarmase
This commit is contained in:
claytonrcarter 2025-07-23 11:08:52 -04:00 committed by GitHub
parent 14171e0721
commit 1f4c9b9427
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
18 changed files with 249 additions and 74 deletions

View file

@ -109,10 +109,10 @@ use inline_completion::{EditPredictionProvider, InlineCompletionProviderHandle};
pub use items::MAX_TAB_TITLE_LEN;
use itertools::Itertools;
use language::{
AutoindentMode, BracketMatch, BracketPair, Buffer, Capability, CharKind, CodeLabel,
CursorShape, DiagnosticEntry, DiffOptions, DocumentationConfig, EditPredictionsMode,
EditPreview, HighlightedText, IndentKind, IndentSize, Language, OffsetRangeExt, Point,
Selection, SelectionGoal, TextObject, TransactionId, TreeSitterOptions, WordsQuery,
AutoindentMode, BlockCommentConfig, BracketMatch, BracketPair, Buffer, Capability, CharKind,
CodeLabel, CursorShape, DiagnosticEntry, DiffOptions, EditPredictionsMode, EditPreview,
HighlightedText, IndentKind, IndentSize, Language, OffsetRangeExt, Point, Selection,
SelectionGoal, TextObject, TransactionId, TreeSitterOptions, WordsQuery,
language_settings::{
self, InlayHintSettings, LspInsertMode, RewrapBehavior, WordsCompletionMode,
all_language_settings, language_settings,
@ -4408,7 +4408,9 @@ impl Editor {
})
.max_by_key(|(_, len)| *len)?;
if let Some((block_start, _)) = language.block_comment_delimiters()
if let Some(BlockCommentConfig {
start: block_start, ..
}) = language.block_comment()
{
let block_start_trimmed = block_start.trim_end();
if block_start_trimmed.starts_with(delimiter.trim_end()) {
@ -4445,13 +4447,12 @@ impl Editor {
return None;
}
let DocumentationConfig {
let BlockCommentConfig {
start: start_tag,
end: end_tag,
prefix: delimiter,
tab_size: len,
} = language.documentation()?;
} = language.documentation_comment()?;
let is_within_block_comment = buffer
.language_scope_at(start_point)
.is_some_and(|scope| scope.override_name() == Some("comment"));
@ -4521,7 +4522,7 @@ impl Editor {
let cursor_is_at_start_of_end_tag =
column == end_tag_offset;
if cursor_is_at_start_of_end_tag {
indent_on_extra_newline.len = (*len).into();
indent_on_extra_newline.len = *len;
}
}
cursor_is_before_end_tag
@ -4534,7 +4535,7 @@ impl Editor {
&& cursor_is_before_end_tag_if_exists
{
if cursor_is_after_start_tag {
indent_on_newline.len = (*len).into();
indent_on_newline.len = *len;
}
Some(delimiter.clone())
} else {
@ -14349,8 +14350,11 @@ impl Editor {
(position..position, first_prefix.clone())
}));
}
} else if let Some((full_comment_prefix, comment_suffix)) =
language.block_comment_delimiters()
} else if let Some(BlockCommentConfig {
start: full_comment_prefix,
end: comment_suffix,
..
}) = language.block_comment()
{
let comment_prefix = full_comment_prefix.trim_end_matches(' ');
let comment_prefix_whitespace = &full_comment_prefix[comment_prefix.len()..];

View file

@ -2875,11 +2875,11 @@ async fn test_newline_documentation_comments(cx: &mut TestAppContext) {
let language = Arc::new(
Language::new(
LanguageConfig {
documentation: Some(language::DocumentationConfig {
documentation_comment: Some(language::BlockCommentConfig {
start: "/**".into(),
end: "*/".into(),
prefix: "* ".into(),
tab_size: NonZeroU32::new(1).unwrap(),
tab_size: 1,
}),
..LanguageConfig::default()
@ -3089,7 +3089,12 @@ async fn test_newline_comments_with_block_comment(cx: &mut TestAppContext) {
let lua_language = Arc::new(Language::new(
LanguageConfig {
line_comments: vec!["--".into()],
block_comment: Some(("--[[".into(), "]]".into())),
block_comment: Some(language::BlockCommentConfig {
start: "--[[".into(),
prefix: "".into(),
end: "]]".into(),
tab_size: 0,
}),
..LanguageConfig::default()
},
None,
@ -13806,7 +13811,12 @@ async fn test_toggle_block_comment(cx: &mut TestAppContext) {
Language::new(
LanguageConfig {
name: "HTML".into(),
block_comment: Some(("<!-- ".into(), " -->".into())),
block_comment: Some(BlockCommentConfig {
start: "<!-- ".into(),
prefix: "".into(),
end: " -->".into(),
tab_size: 0,
}),
..Default::default()
},
Some(tree_sitter_html::LANGUAGE.into()),

View file

@ -14,7 +14,8 @@ use futures::Future;
use gpui::{Context, Entity, Focusable as _, VisualTestContext, Window};
use indoc::indoc;
use language::{
FakeLspAdapter, Language, LanguageConfig, LanguageMatcher, LanguageQueries, point_to_lsp,
BlockCommentConfig, FakeLspAdapter, Language, LanguageConfig, LanguageMatcher, LanguageQueries,
point_to_lsp,
};
use lsp::{notification, request};
use multi_buffer::ToPointUtf16;
@ -269,7 +270,12 @@ impl EditorLspTestContext {
path_suffixes: vec!["html".into()],
..Default::default()
},
block_comment: Some(("<!-- ".into(), " -->".into())),
block_comment: Some(BlockCommentConfig {
start: "<!--".into(),
prefix: "".into(),
end: "-->".into(),
tab_size: 0,
}),
completion_query_characters: ['-'].into_iter().collect(),
..Default::default()
},