]> git.lizzy.rs Git - rust.git/commitdiff
Merge #2043
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>
Tue, 22 Oct 2019 08:09:03 +0000 (08:09 +0000)
committerGitHub <noreply@github.com>
Tue, 22 Oct 2019 08:09:03 +0000 (08:09 +0000)
2043: Instructions for VS Code Remote Development r=matklad a=marcogroppo

`rust-analyzer` can be used with the Visual Studio Code Remote Development extension pack, but `cargo xtask install` is not enough, you have to install the `VSIX` package from VS Code.

These instructions have been added to the `README`.

Co-authored-by: Marco Groppo <marco.groppo@gmail.com>
crates/ra_lsp_server/src/conv.rs
crates/ra_lsp_server/src/main_loop.rs
crates/ra_lsp_server/src/main_loop/handlers.rs
crates/ra_lsp_server/src/world.rs

index 1318a17389f8140bd4c6dbe3fdb5efb1a8960d54..ee503633d7ee44e88fb66ae10fb9c952682a5631 100644 (file)
@@ -227,22 +227,57 @@ fn conv_with(
     }
 }
 
-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;
 
-    fn conv_with(self, line_index: &LineIndex) -> lsp_types::FoldingRange {
-        let range = self.range.conv_with(&line_index);
-        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: match self.kind {
-                FoldKind::Comment => Some(lsp_types::FoldingRangeKind::Comment),
-                FoldKind::Imports => Some(lsp_types::FoldingRangeKind::Imports),
-                FoldKind::Mods => None,
-                FoldKind::Block => None,
-            },
+    fn conv_with(self, ctx: &FoldConvCtx) -> lsp_types::FoldingRange {
+        let kind = match self.kind {
+            FoldKind::Comment => Some(lsp_types::FoldingRangeKind::Comment),
+            FoldKind::Imports => Some(lsp_types::FoldingRangeKind::Imports),
+            FoldKind::Mods => None,
+            FoldKind::Block => None,
+        };
+
+        let range = self.range.conv_with(&ctx.line_index);
+
+        if ctx.line_folding_only {
+            // 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,
+            }
         }
     }
 }
@@ -512,3 +547,46 @@ fn try_conv_with_to_vec(self, ctx: CTX) -> Result<Vec<Self::Output>> {
         self.map(|it| it.try_conv_with(ctx)).collect()
     }
 }
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+    use test_utils::extract_ranges;
+
+    #[test]
+    fn conv_fold_line_folding_only_fixup() {
+        let text = r#"<fold>mod a;
+mod b;
+mod c;</fold>
+
+fn main() <fold>{
+    if cond <fold>{
+        a::do_a();
+    }</fold> else <fold>{
+        b::do_b();
+    }</fold>
+}</fold>"#;
+
+        let (ranges, text) = extract_ranges(text, "fold");
+        assert_eq!(ranges.len(), 4);
+        let folds = vec![
+            Fold { range: ranges[0], kind: FoldKind::Mods },
+            Fold { range: ranges[1], kind: FoldKind::Block },
+            Fold { range: ranges[2], kind: FoldKind::Block },
+            Fold { range: ranges[3], kind: FoldKind::Block },
+        ];
+
+        let line_index = LineIndex::new(&text);
+        let ctx = FoldConvCtx { text: &text, line_index: &line_index, line_folding_only: true };
+        let converted: Vec<_> = folds.into_iter().map_conv_with(&ctx).collect();
+
+        let expected_lines = [(0, 2), (4, 10), (5, 6), (7, 9)];
+        assert_eq!(converted.len(), expected_lines.len());
+        for (folding_range, (start_line, end_line)) in converted.iter().zip(expected_lines.iter()) {
+            assert_eq!(folding_range.start_line, *start_line);
+            assert_eq!(folding_range.start_character, None);
+            assert_eq!(folding_range.end_line, *end_line);
+            assert_eq!(folding_range.end_character, None);
+        }
+    }
+}
index 35c35d32bb08ad5fcb9ca3cb9f34648f13fc42f8..0b5d9c44d40dff5eca6f203bb2a85b910fcdd6f2 100644 (file)
@@ -111,6 +111,21 @@ pub fn main_loop(
             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 mut ff = FeatureFlags::default();
             for (flag, value) in config.feature_flags {
@@ -133,14 +148,7 @@ pub fn main_loop(
             config.lru_capacity,
             &globs,
             Watch(!config.use_client_watching),
-            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),
-            },
+            options,
             feature_flags,
         )
     };
index 10e2713766a56e57d603519cefa60f06f2fa7756..af3cd04ea953e47700d4af6d728f760f37233254 100644 (file)
@@ -18,7 +18,7 @@
 
 use crate::{
     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},
     world::WorldSnapshot,
     LspError, Result,
@@ -383,8 +383,14 @@ pub fn handle_folding_range(
 ) -> Result<Option<Vec<FoldingRange>>> {
     let file_id = params.text_document.try_conv_with(&world)?;
     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 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)
 }
 
index 0eb684de5d41f4121cde7546eae1adb5318edff1..51824e7a352bda91a6da97d46422f6c632e5f3eb 100644 (file)
@@ -27,6 +27,7 @@
 pub struct Options {
     pub publish_decorations: bool,
     pub supports_location_link: bool,
+    pub line_folding_only: bool,
 }
 
 /// `WorldState` is the primary mutable state of the language server