mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-10-01 14:21:44 +00:00
fixup folding ranges for "lineFoldingOnly" clients #2033
This commit is contained in:
parent
6b9bd7bdd2
commit
9d5e932626
4 changed files with 74 additions and 24 deletions
|
@ -227,22 +227,57 @@ impl ConvWith<(&LineIndex, LineEndings)> for &AtomTextEdit {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ConvWith<&LineIndex> for Fold {
|
pub(crate) struct FoldConvCtx<'a> {
|
||||||
|
pub(crate) text: &'a str,
|
||||||
|
pub(crate) line_index: &'a LineIndex,
|
||||||
|
pub(crate) line_folding_only: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ConvWith<&FoldConvCtx<'_>> for Fold {
|
||||||
type Output = lsp_types::FoldingRange;
|
type Output = lsp_types::FoldingRange;
|
||||||
|
|
||||||
fn conv_with(self, line_index: &LineIndex) -> lsp_types::FoldingRange {
|
fn conv_with(self, ctx: &FoldConvCtx) -> lsp_types::FoldingRange {
|
||||||
let range = self.range.conv_with(&line_index);
|
let kind = match self.kind {
|
||||||
lsp_types::FoldingRange {
|
FoldKind::Comment => Some(lsp_types::FoldingRangeKind::Comment),
|
||||||
start_line: range.start.line,
|
FoldKind::Imports => Some(lsp_types::FoldingRangeKind::Imports),
|
||||||
start_character: Some(range.start.character),
|
FoldKind::Mods => None,
|
||||||
end_line: range.end.line,
|
FoldKind::Block => None,
|
||||||
end_character: Some(range.end.character),
|
};
|
||||||
kind: match self.kind {
|
|
||||||
FoldKind::Comment => Some(lsp_types::FoldingRangeKind::Comment),
|
let range = self.range.conv_with(&ctx.line_index);
|
||||||
FoldKind::Imports => Some(lsp_types::FoldingRangeKind::Imports),
|
|
||||||
FoldKind::Mods => None,
|
if ctx.line_folding_only {
|
||||||
FoldKind::Block => None,
|
// Clients with line_folding_only == true (such as VSCode) will fold the whole end line
|
||||||
},
|
// even if it contains text not in the folding range. To prevent that we exclude
|
||||||
|
// range.end.line from the folding region if there is more text after range.end
|
||||||
|
// on the same line.
|
||||||
|
let has_more_text_on_end_line = ctx.text
|
||||||
|
[TextRange::from_to(self.range.end(), TextUnit::of_str(ctx.text))]
|
||||||
|
.chars()
|
||||||
|
.take_while(|it| *it != '\n')
|
||||||
|
.any(|it| !it.is_whitespace());
|
||||||
|
|
||||||
|
let end_line = if has_more_text_on_end_line {
|
||||||
|
range.end.line.saturating_sub(1)
|
||||||
|
} else {
|
||||||
|
range.end.line
|
||||||
|
};
|
||||||
|
|
||||||
|
lsp_types::FoldingRange {
|
||||||
|
start_line: range.start.line,
|
||||||
|
start_character: None,
|
||||||
|
end_line,
|
||||||
|
end_character: None,
|
||||||
|
kind,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
lsp_types::FoldingRange {
|
||||||
|
start_line: range.start.line,
|
||||||
|
start_character: Some(range.start.character),
|
||||||
|
end_line: range.end.line,
|
||||||
|
end_character: Some(range.end.character),
|
||||||
|
kind,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -111,6 +111,21 @@ pub fn main_loop(
|
||||||
connection.sender.send(request.into()).unwrap();
|
connection.sender.send(request.into()).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let options = {
|
||||||
|
let text_document_caps = client_caps.text_document.as_ref();
|
||||||
|
Options {
|
||||||
|
publish_decorations: config.publish_decorations,
|
||||||
|
supports_location_link: text_document_caps
|
||||||
|
.and_then(|it| it.definition)
|
||||||
|
.and_then(|it| it.link_support)
|
||||||
|
.unwrap_or(false),
|
||||||
|
line_folding_only: text_document_caps
|
||||||
|
.and_then(|it| it.folding_range.as_ref())
|
||||||
|
.and_then(|it| it.line_folding_only)
|
||||||
|
.unwrap_or(false),
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
let feature_flags = {
|
let feature_flags = {
|
||||||
let mut ff = FeatureFlags::default();
|
let mut ff = FeatureFlags::default();
|
||||||
for (flag, value) in config.feature_flags {
|
for (flag, value) in config.feature_flags {
|
||||||
|
@ -133,14 +148,7 @@ pub fn main_loop(
|
||||||
config.lru_capacity,
|
config.lru_capacity,
|
||||||
&globs,
|
&globs,
|
||||||
Watch(!config.use_client_watching),
|
Watch(!config.use_client_watching),
|
||||||
Options {
|
options,
|
||||||
publish_decorations: config.publish_decorations,
|
|
||||||
supports_location_link: client_caps
|
|
||||||
.text_document
|
|
||||||
.and_then(|it| it.definition)
|
|
||||||
.and_then(|it| it.link_support)
|
|
||||||
.unwrap_or(false),
|
|
||||||
},
|
|
||||||
feature_flags,
|
feature_flags,
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
|
@ -18,7 +18,7 @@ use serde_json::to_value;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
cargo_target_spec::{runnable_args, CargoTargetSpec},
|
cargo_target_spec::{runnable_args, CargoTargetSpec},
|
||||||
conv::{to_location, Conv, ConvWith, MapConvWith, TryConvWith, TryConvWithToVec},
|
conv::{to_location, Conv, ConvWith, FoldConvCtx, MapConvWith, TryConvWith, TryConvWithToVec},
|
||||||
req::{self, Decoration, InlayHint, InlayHintsParams, InlayKind},
|
req::{self, Decoration, InlayHint, InlayHintsParams, InlayKind},
|
||||||
world::WorldSnapshot,
|
world::WorldSnapshot,
|
||||||
LspError, Result,
|
LspError, Result,
|
||||||
|
@ -383,8 +383,14 @@ pub fn handle_folding_range(
|
||||||
) -> Result<Option<Vec<FoldingRange>>> {
|
) -> Result<Option<Vec<FoldingRange>>> {
|
||||||
let file_id = params.text_document.try_conv_with(&world)?;
|
let file_id = params.text_document.try_conv_with(&world)?;
|
||||||
let folds = world.analysis().folding_ranges(file_id)?;
|
let folds = world.analysis().folding_ranges(file_id)?;
|
||||||
|
let text = world.analysis().file_text(file_id)?;
|
||||||
let line_index = world.analysis().file_line_index(file_id)?;
|
let line_index = world.analysis().file_line_index(file_id)?;
|
||||||
let res = Some(folds.into_iter().map_conv_with(&*line_index).collect());
|
let ctx = FoldConvCtx {
|
||||||
|
text: &text,
|
||||||
|
line_index: &line_index,
|
||||||
|
line_folding_only: world.options.line_folding_only,
|
||||||
|
};
|
||||||
|
let res = Some(folds.into_iter().map_conv_with(&ctx).collect());
|
||||||
Ok(res)
|
Ok(res)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -27,6 +27,7 @@ use crate::{
|
||||||
pub struct Options {
|
pub struct Options {
|
||||||
pub publish_decorations: bool,
|
pub publish_decorations: bool,
|
||||||
pub supports_location_link: bool,
|
pub supports_location_link: bool,
|
||||||
|
pub line_folding_only: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// `WorldState` is the primary mutable state of the language server
|
/// `WorldState` is the primary mutable state of the language server
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue