mirror of
https://github.com/Myriad-Dreamin/tinymist.git
synced 2025-07-18 18:25:00 +00:00
dev: process overlapping cases in line folding only mode
This commit is contained in:
parent
a92d477d88
commit
3ab4fa625f
15 changed files with 476 additions and 177 deletions
|
@ -58,7 +58,7 @@ insta.workspace = true
|
||||||
serde.workspace = true
|
serde.workspace = true
|
||||||
serde_json.workspace = true
|
serde_json.workspace = true
|
||||||
typst-assets = { workspace = true, features = ["fonts"] }
|
typst-assets = { workspace = true, features = ["fonts"] }
|
||||||
reflexo-typst.workspace = true
|
reflexo-typst = { workspace = true, features = ["no-content-hint"] }
|
||||||
sha2 = { version = "0.10" }
|
sha2 = { version = "0.10" }
|
||||||
hex = { version = "0.4" }
|
hex = { version = "0.4" }
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
#let slides(..args) = args
|
||||||
|
#slides()[
|
||||||
|
= Heading
|
||||||
|
][
|
||||||
|
|
||||||
|
]
|
|
@ -0,0 +1,6 @@
|
||||||
|
#let slides(..args) = args
|
||||||
|
#slides[
|
||||||
|
|
||||||
|
][
|
||||||
|
|
||||||
|
]
|
|
@ -0,0 +1,6 @@
|
||||||
|
#let slides(..args) = args
|
||||||
|
#slides()[
|
||||||
|
|
||||||
|
][
|
||||||
|
|
||||||
|
]
|
|
@ -1,9 +1,10 @@
|
||||||
---
|
---
|
||||||
source: crates/tinymist-query/src/folding_range.rs
|
source: crates/tinymist-query/src/folding_range.rs
|
||||||
expression: "JsonRepr::new_pure(result.unwrap())"
|
expression: "JsonRepr::new_pure(json!({ \"false\": result_false, \"true\": result_true, }))"
|
||||||
input_file: crates/tinymist-query/src/fixtures/folding_range/array_folding.typ
|
input_file: crates/tinymist-query/src/fixtures/folding_range/array_folding.typ
|
||||||
---
|
---
|
||||||
[
|
{
|
||||||
|
"false": [
|
||||||
{
|
{
|
||||||
"collapsedText": "",
|
"collapsedText": "",
|
||||||
"endCharacter": 1,
|
"endCharacter": 1,
|
||||||
|
@ -11,4 +12,12 @@ input_file: crates/tinymist-query/src/fixtures/folding_range/array_folding.typ
|
||||||
"startCharacter": 1,
|
"startCharacter": 1,
|
||||||
"startLine": 0
|
"startLine": 0
|
||||||
}
|
}
|
||||||
|
],
|
||||||
|
"true": [
|
||||||
|
{
|
||||||
|
"collapsedText": "",
|
||||||
|
"endLine": 4,
|
||||||
|
"startLine": 0
|
||||||
|
}
|
||||||
]
|
]
|
||||||
|
}
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
---
|
---
|
||||||
source: crates/tinymist-query/src/folding_range.rs
|
source: crates/tinymist-query/src/folding_range.rs
|
||||||
expression: "JsonRepr::new_pure(result.unwrap())"
|
expression: "JsonRepr::new_pure(json!({ \"false\": result_false, \"true\": result_true, }))"
|
||||||
input_file: crates/tinymist-query/src/fixtures/folding_range/base.typ
|
input_file: crates/tinymist-query/src/fixtures/folding_range/base.typ
|
||||||
---
|
---
|
||||||
[
|
{
|
||||||
|
"false": [
|
||||||
{
|
{
|
||||||
"collapsedText": "Heading 2",
|
"collapsedText": "Heading 2",
|
||||||
"endCharacter": 12,
|
"endCharacter": 12,
|
||||||
|
@ -32,4 +33,22 @@ input_file: crates/tinymist-query/src/fixtures/folding_range/base.typ
|
||||||
"startCharacter": 2,
|
"startCharacter": 2,
|
||||||
"startLine": 4
|
"startLine": 4
|
||||||
}
|
}
|
||||||
|
],
|
||||||
|
"true": [
|
||||||
|
{
|
||||||
|
"collapsedText": "Heading 1",
|
||||||
|
"endLine": 3,
|
||||||
|
"startLine": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"collapsedText": "",
|
||||||
|
"endLine": 9,
|
||||||
|
"startLine": 6
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"collapsedText": "Heading 3",
|
||||||
|
"endLine": 9,
|
||||||
|
"startLine": 4
|
||||||
|
}
|
||||||
]
|
]
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,49 @@
|
||||||
|
---
|
||||||
|
source: crates/tinymist-query/src/folding_range.rs
|
||||||
|
expression: "JsonRepr::new_pure(json!({ \"false\": result_false, \"true\": result_true, }))"
|
||||||
|
input_file: crates/tinymist-query/src/fixtures/folding_range/heading-in-multiple-content.typ
|
||||||
|
---
|
||||||
|
{
|
||||||
|
"false": [
|
||||||
|
{
|
||||||
|
"collapsedText": "Heading",
|
||||||
|
"endCharacter": 11,
|
||||||
|
"endLine": 3,
|
||||||
|
"startCharacter": 4,
|
||||||
|
"startLine": 2
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"collapsedText": "",
|
||||||
|
"endCharacter": 1,
|
||||||
|
"endLine": 3,
|
||||||
|
"startCharacter": 9,
|
||||||
|
"startLine": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"collapsedText": "",
|
||||||
|
"endCharacter": 1,
|
||||||
|
"endLine": 5,
|
||||||
|
"startCharacter": 1,
|
||||||
|
"startLine": 3
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"collapsedText": "",
|
||||||
|
"endCharacter": 1,
|
||||||
|
"endLine": 5,
|
||||||
|
"startCharacter": 7,
|
||||||
|
"startLine": 1
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"true": [
|
||||||
|
{
|
||||||
|
"collapsedText": "",
|
||||||
|
"endLine": 5,
|
||||||
|
"startLine": 3
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"collapsedText": "",
|
||||||
|
"endLine": 5,
|
||||||
|
"startLine": 1
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
|
@ -1,9 +1,10 @@
|
||||||
---
|
---
|
||||||
source: crates/tinymist-query/src/folding_range.rs
|
source: crates/tinymist-query/src/folding_range.rs
|
||||||
expression: "JsonRepr::new_pure(result.unwrap())"
|
expression: "JsonRepr::new_pure(json!({ \"false\": result_false, \"true\": result_true, }))"
|
||||||
input_file: crates/tinymist-query/src/fixtures/folding_range/headings-in-blocks.typ
|
input_file: crates/tinymist-query/src/fixtures/folding_range/headings-in-blocks.typ
|
||||||
---
|
---
|
||||||
[
|
{
|
||||||
|
"false": [
|
||||||
{
|
{
|
||||||
"collapsedText": "",
|
"collapsedText": "",
|
||||||
"endCharacter": 11,
|
"endCharacter": 11,
|
||||||
|
@ -46,4 +47,27 @@ input_file: crates/tinymist-query/src/fixtures/folding_range/headings-in-blocks.
|
||||||
"startCharacter": 9,
|
"startCharacter": 9,
|
||||||
"startLine": 0
|
"startLine": 0
|
||||||
}
|
}
|
||||||
|
],
|
||||||
|
"true": [
|
||||||
|
{
|
||||||
|
"collapsedText": "Heading 2",
|
||||||
|
"endLine": 8,
|
||||||
|
"startLine": 5
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"collapsedText": "",
|
||||||
|
"endLine": 7,
|
||||||
|
"startLine": 3
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"collapsedText": "Heading 1",
|
||||||
|
"endLine": 8,
|
||||||
|
"startLine": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"collapsedText": "",
|
||||||
|
"endLine": 8,
|
||||||
|
"startLine": 0
|
||||||
|
}
|
||||||
]
|
]
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,42 @@
|
||||||
|
---
|
||||||
|
source: crates/tinymist-query/src/folding_range.rs
|
||||||
|
expression: "JsonRepr::new_pure(json!({ \"false\": result_false, \"true\": result_true, }))"
|
||||||
|
input_file: crates/tinymist-query/src/fixtures/folding_range/multiple-content-2.typ
|
||||||
|
---
|
||||||
|
{
|
||||||
|
"false": [
|
||||||
|
{
|
||||||
|
"collapsedText": "",
|
||||||
|
"endCharacter": 1,
|
||||||
|
"endLine": 3,
|
||||||
|
"startCharacter": 7,
|
||||||
|
"startLine": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"collapsedText": "",
|
||||||
|
"endCharacter": 1,
|
||||||
|
"endLine": 5,
|
||||||
|
"startCharacter": 1,
|
||||||
|
"startLine": 3
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"collapsedText": "",
|
||||||
|
"endCharacter": 1,
|
||||||
|
"endLine": 5,
|
||||||
|
"startCharacter": 7,
|
||||||
|
"startLine": 1
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"true": [
|
||||||
|
{
|
||||||
|
"collapsedText": "",
|
||||||
|
"endLine": 5,
|
||||||
|
"startLine": 3
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"collapsedText": "",
|
||||||
|
"endLine": 5,
|
||||||
|
"startLine": 1
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
|
@ -0,0 +1,42 @@
|
||||||
|
---
|
||||||
|
source: crates/tinymist-query/src/folding_range.rs
|
||||||
|
expression: "JsonRepr::new_pure(json!({ \"false\": result_false, \"true\": result_true, }))"
|
||||||
|
input_file: crates/tinymist-query/src/fixtures/folding_range/multiple-content.typ
|
||||||
|
---
|
||||||
|
{
|
||||||
|
"false": [
|
||||||
|
{
|
||||||
|
"collapsedText": "",
|
||||||
|
"endCharacter": 1,
|
||||||
|
"endLine": 3,
|
||||||
|
"startCharacter": 9,
|
||||||
|
"startLine": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"collapsedText": "",
|
||||||
|
"endCharacter": 1,
|
||||||
|
"endLine": 5,
|
||||||
|
"startCharacter": 1,
|
||||||
|
"startLine": 3
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"collapsedText": "",
|
||||||
|
"endCharacter": 1,
|
||||||
|
"endLine": 5,
|
||||||
|
"startCharacter": 7,
|
||||||
|
"startLine": 1
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"true": [
|
||||||
|
{
|
||||||
|
"collapsedText": "",
|
||||||
|
"endLine": 5,
|
||||||
|
"startLine": 3
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"collapsedText": "",
|
||||||
|
"endLine": 5,
|
||||||
|
"startLine": 1
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
|
@ -1,9 +1,10 @@
|
||||||
---
|
---
|
||||||
source: crates/tinymist-query/src/folding_range.rs
|
source: crates/tinymist-query/src/folding_range.rs
|
||||||
expression: "JsonRepr::new_pure(result.unwrap())"
|
expression: "JsonRepr::new_pure(json!({ \"false\": result_false, \"true\": result_true, }))"
|
||||||
input_file: crates/tinymist-query/src/fixtures/folding_range/nested-blocks.typ
|
input_file: crates/tinymist-query/src/fixtures/folding_range/nested-blocks.typ
|
||||||
---
|
---
|
||||||
[
|
{
|
||||||
|
"false": [
|
||||||
{
|
{
|
||||||
"collapsedText": "",
|
"collapsedText": "",
|
||||||
"endCharacter": 5,
|
"endCharacter": 5,
|
||||||
|
@ -67,4 +68,47 @@ input_file: crates/tinymist-query/src/fixtures/folding_range/nested-blocks.typ
|
||||||
"startCharacter": 9,
|
"startCharacter": 9,
|
||||||
"startLine": 0
|
"startLine": 0
|
||||||
}
|
}
|
||||||
|
],
|
||||||
|
"true": [
|
||||||
|
{
|
||||||
|
"collapsedText": "",
|
||||||
|
"endLine": 4,
|
||||||
|
"startLine": 2
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"collapsedText": "",
|
||||||
|
"endLine": 5,
|
||||||
|
"startLine": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"collapsedText": "",
|
||||||
|
"endLine": 8,
|
||||||
|
"startLine": 6
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"collapsedText": "",
|
||||||
|
"endLine": 11,
|
||||||
|
"startLine": 10
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"collapsedText": "",
|
||||||
|
"endLine": 14,
|
||||||
|
"startLine": 12
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"collapsedText": "",
|
||||||
|
"endLine": 15,
|
||||||
|
"startLine": 9
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"collapsedText": "",
|
||||||
|
"endLine": 17,
|
||||||
|
"startLine": 16
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"collapsedText": "",
|
||||||
|
"endLine": 18,
|
||||||
|
"startLine": 0
|
||||||
|
}
|
||||||
]
|
]
|
||||||
|
}
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
---
|
---
|
||||||
source: crates/tinymist-query/src/folding_range.rs
|
source: crates/tinymist-query/src/folding_range.rs
|
||||||
expression: "JsonRepr::new_pure(result.unwrap())"
|
expression: "JsonRepr::new_pure(json!({ \"false\": result_false, \"true\": result_true, }))"
|
||||||
input_file: crates/tinymist-query/src/fixtures/folding_range/paren_folding.typ
|
input_file: crates/tinymist-query/src/fixtures/folding_range/paren_folding.typ
|
||||||
---
|
---
|
||||||
[
|
{
|
||||||
|
"false": [
|
||||||
{
|
{
|
||||||
"collapsedText": "",
|
"collapsedText": "",
|
||||||
"endCharacter": 1,
|
"endCharacter": 1,
|
||||||
|
@ -11,4 +12,12 @@ input_file: crates/tinymist-query/src/fixtures/folding_range/paren_folding.typ
|
||||||
"startCharacter": 1,
|
"startCharacter": 1,
|
||||||
"startLine": 0
|
"startLine": 0
|
||||||
}
|
}
|
||||||
|
],
|
||||||
|
"true": [
|
||||||
|
{
|
||||||
|
"collapsedText": "",
|
||||||
|
"endLine": 2,
|
||||||
|
"startLine": 0
|
||||||
|
}
|
||||||
]
|
]
|
||||||
|
}
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
use hashbrown::HashSet;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
prelude::*,
|
prelude::*,
|
||||||
syntax::{get_lexical_hierarchy, LexicalHierarchy, LexicalKind, LexicalScopeKind},
|
syntax::{get_lexical_hierarchy, LexicalHierarchy, LexicalKind, LexicalScopeKind},
|
||||||
|
@ -42,12 +44,45 @@ impl SyntaxRequest for FoldingRangeRequest {
|
||||||
&symbols,
|
&symbols,
|
||||||
source,
|
source,
|
||||||
position_encoding,
|
position_encoding,
|
||||||
line_folding_only,
|
|
||||||
loc,
|
loc,
|
||||||
loc,
|
loc,
|
||||||
true,
|
true,
|
||||||
&mut results,
|
&mut results,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Generally process of folding ranges with line_folding_only
|
||||||
|
if line_folding_only {
|
||||||
|
let mut max_line = 0;
|
||||||
|
for r in &mut results {
|
||||||
|
r.start_character = None;
|
||||||
|
r.end_character = None;
|
||||||
|
max_line = max_line.max(r.end_line);
|
||||||
|
}
|
||||||
|
let mut line_coverage = vec![false; max_line as usize + 1];
|
||||||
|
let mut pair_coverage = HashSet::new();
|
||||||
|
results.reverse();
|
||||||
|
results.retain_mut(|r| {
|
||||||
|
if pair_coverage.contains(&(r.start_line, r.end_line)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if line_coverage[r.start_line as usize] {
|
||||||
|
r.start_line += 1;
|
||||||
|
}
|
||||||
|
if line_coverage[r.end_line as usize] {
|
||||||
|
r.end_line = r.end_line.saturating_sub(1);
|
||||||
|
}
|
||||||
|
if r.start_line >= r.end_line {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
line_coverage[r.start_line as usize] = true;
|
||||||
|
pair_coverage.insert((r.start_line, r.end_line));
|
||||||
|
true
|
||||||
|
});
|
||||||
|
results.reverse();
|
||||||
|
}
|
||||||
|
|
||||||
if false {
|
if false {
|
||||||
trace!("FoldingRangeRequest(line_folding_only={line_folding_only}) symbols: {symbols:#?} results: {results:#?}");
|
trace!("FoldingRangeRequest(line_folding_only={line_folding_only}) symbols: {symbols:#?} results: {results:#?}");
|
||||||
}
|
}
|
||||||
|
@ -58,13 +93,10 @@ impl SyntaxRequest for FoldingRangeRequest {
|
||||||
|
|
||||||
type LoC = (u32, Option<u32>);
|
type LoC = (u32, Option<u32>);
|
||||||
|
|
||||||
#[allow(clippy::too_many_arguments)]
|
|
||||||
#[allow(deprecated)]
|
|
||||||
fn calc_folding_range(
|
fn calc_folding_range(
|
||||||
symbols: &[LexicalHierarchy],
|
symbols: &[LexicalHierarchy],
|
||||||
source: &Source,
|
source: &Source,
|
||||||
position_encoding: PositionEncoding,
|
position_encoding: PositionEncoding,
|
||||||
line_folding_only: bool,
|
|
||||||
parent_last_loc: LoC,
|
parent_last_loc: LoC,
|
||||||
last_loc: LoC,
|
last_loc: LoC,
|
||||||
is_last_range: bool,
|
is_last_range: bool,
|
||||||
|
@ -79,7 +111,7 @@ fn calc_folding_range(
|
||||||
start_line: rng.start.line,
|
start_line: rng.start.line,
|
||||||
start_character: Some(rng.start.character),
|
start_character: Some(rng.start.character),
|
||||||
end_line: rng.end.line,
|
end_line: rng.end.line,
|
||||||
end_character: line_folding_only.then_some(rng.end.character),
|
end_character: Some(rng.end.character),
|
||||||
kind: None,
|
kind: None,
|
||||||
collapsed_text: Some(e.info.name.clone()),
|
collapsed_text: Some(e.info.name.clone()),
|
||||||
};
|
};
|
||||||
|
@ -113,7 +145,6 @@ fn calc_folding_range(
|
||||||
ch,
|
ch,
|
||||||
source,
|
source,
|
||||||
position_encoding,
|
position_encoding,
|
||||||
line_folding_only,
|
|
||||||
parent_last_loc,
|
parent_last_loc,
|
||||||
last_loc,
|
last_loc,
|
||||||
!is_not_final_last_range,
|
!is_not_final_last_range,
|
||||||
|
@ -133,15 +164,23 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn test() {
|
fn test() {
|
||||||
snapshot_testing("folding_range", &|world, path| {
|
snapshot_testing("folding_range", &|world, path| {
|
||||||
|
let mut r = |line_folding_only| {
|
||||||
let request = FoldingRangeRequest {
|
let request = FoldingRangeRequest {
|
||||||
path: path.clone(),
|
path: path.clone(),
|
||||||
line_folding_only: true,
|
line_folding_only,
|
||||||
};
|
};
|
||||||
|
|
||||||
let source = world.source_by_path(&path).unwrap();
|
let source = world.source_by_path(&path).unwrap();
|
||||||
|
|
||||||
let result = request.request(&source, PositionEncoding::Utf16);
|
request.request(&source, PositionEncoding::Utf16)
|
||||||
assert_snapshot!(JsonRepr::new_pure(result.unwrap()));
|
};
|
||||||
|
|
||||||
|
let result_false = r(false);
|
||||||
|
let result_true = r(true);
|
||||||
|
assert_snapshot!(JsonRepr::new_pure(json!({
|
||||||
|
"false": result_false,
|
||||||
|
"true": result_true,
|
||||||
|
})));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,7 @@ use typst::{diag::PackageError, foundations::Bytes};
|
||||||
pub use insta::assert_snapshot;
|
pub use insta::assert_snapshot;
|
||||||
pub use reflexo_typst::TypstSystemWorld;
|
pub use reflexo_typst::TypstSystemWorld;
|
||||||
pub use serde::Serialize;
|
pub use serde::Serialize;
|
||||||
|
pub use serde_json::json;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
analysis::{Analysis, AnalysisResources},
|
analysis::{Analysis, AnalysisResources},
|
||||||
|
|
|
@ -100,7 +100,10 @@ embed-fonts = ["typst-assets/fonts"]
|
||||||
|
|
||||||
# Disable the default content hint.
|
# Disable the default content hint.
|
||||||
# This requires modifying typst.
|
# This requires modifying typst.
|
||||||
no-content-hint = ["reflexo-typst/no-content-hint"]
|
no-content-hint = [
|
||||||
|
"reflexo-typst/no-content-hint",
|
||||||
|
"reflexo-vec2svg/no-content-hint",
|
||||||
|
]
|
||||||
|
|
||||||
preview = [
|
preview = [
|
||||||
"typst-preview",
|
"typst-preview",
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue