Skip to content

Commit 76c48f3

Browse files
committed
support add import fold range
1 parent ee6057d commit 76c48f3

File tree

3 files changed

+99
-6
lines changed

3 files changed

+99
-6
lines changed

crates/emmylua_ls/src/handlers/fold_range/builder.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
1-
use code_analysis::LuaDocument;
1+
use code_analysis::{Emmyrc, LuaDocument};
22
use emmylua_parser::LuaChunk;
33
use lsp_types::{FoldingRange, FoldingRangeKind};
44
use rowan::TextRange;
55

6-
76
#[derive(Debug)]
87
pub struct FoldingRangeBuilder<'a> {
98
document: &'a LuaDocument<'a>,
@@ -65,4 +64,4 @@ impl FoldingRangeBuilder<'_> {
6564

6665
Some(())
6766
}
68-
}
67+
}
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
use code_analysis::Emmyrc;
2+
use emmylua_parser::{LuaAstNode, LuaChunk, LuaExpr, LuaStat};
3+
use lsp_types::{FoldingRange, FoldingRangeKind};
4+
use rowan::TextSize;
5+
6+
use super::builder::FoldingRangeBuilder;
7+
8+
9+
pub fn build_imports_fold_range(builder: &mut FoldingRangeBuilder, root: LuaChunk, emmyrc: &Emmyrc) -> Option<()> {
10+
let root_block = root.get_block()?;
11+
let require_like_func = &emmyrc.runtime.require_like_function;
12+
13+
let mut start: Option<TextSize> = None;
14+
let mut end: Option<TextSize> = None;
15+
for stat in root_block.get_stats() {
16+
if is_require_stat(stat.clone(), require_like_func).unwrap_or(false) {
17+
let range = stat.get_range();
18+
if start.is_none() {
19+
start = Some(range.start());
20+
}
21+
end = Some(range.end());
22+
} else if start.is_some() && end.is_some() {
23+
let start_pos = start.unwrap();
24+
let end_pos = end.unwrap();
25+
let docucment = builder.get_document();
26+
let start_line_col = docucment.get_line_col(start_pos)?;
27+
let end_line_col = docucment.get_line_col(end_pos)?;
28+
let fold_range = FoldingRange {
29+
start_line: start_line_col.0 as u32,
30+
start_character: Some(start_line_col.1 as u32),
31+
end_line: end_line_col.0 as u32,
32+
end_character: Some(end_line_col.1 as u32),
33+
kind: Some(FoldingRangeKind::Imports),
34+
collapsed_text: Some("imports ...".to_string()),
35+
};
36+
builder.push(fold_range);
37+
start = None;
38+
end = None;
39+
}
40+
}
41+
42+
// if just only require stat, then donot fold it
43+
Some(())
44+
}
45+
46+
47+
fn is_require_stat(stat: LuaStat, require_like_func: &Vec<String>) -> Option<bool> {
48+
match stat {
49+
LuaStat::LocalStat(local_stat) => {
50+
let exprs = local_stat.get_value_exprs();
51+
for expr in exprs {
52+
if is_require_expr(expr, require_like_func).unwrap_or(false) {
53+
return Some(true);
54+
}
55+
}
56+
}
57+
LuaStat::AssignStat(assign_stat) => {
58+
let (_, exprs) = assign_stat.get_var_and_expr_list();
59+
for expr in exprs {
60+
if is_require_expr(expr, require_like_func).unwrap_or(false) {
61+
return Some(true);
62+
}
63+
}
64+
}
65+
LuaStat::CallExprStat(call_expr_stat) => {
66+
let expr = call_expr_stat.get_call_expr()?;
67+
if is_require_expr(expr.into(), require_like_func).unwrap_or(false) {
68+
return Some(true);
69+
}
70+
}
71+
_ => {}
72+
}
73+
74+
Some(false)
75+
}
76+
77+
fn is_require_expr(expr: LuaExpr, require_like_func: &Vec<String>) -> Option<bool> {
78+
if let LuaExpr::CallExpr(call_expr) = expr {
79+
let name = call_expr.get_prefix_expr()?;
80+
if let LuaExpr::NameExpr(name_expr) = name {
81+
let name = name_expr.get_name_text()?;
82+
if require_like_func.contains(&name.to_string()) || name == "require" {
83+
return Some(true);
84+
}
85+
}
86+
}
87+
88+
Some(false)
89+
}

crates/emmylua_ls/src/handlers/fold_range/mod.rs

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,14 @@ mod builder;
22
mod comment;
33
mod expr;
44
mod stats;
5+
mod imports;
56

67
use builder::FoldingRangeBuilder;
8+
use code_analysis::Emmyrc;
79
use comment::build_comment_fold_range;
810
use emmylua_parser::{LuaAst, LuaAstNode};
911
use expr::{build_closure_expr_fold_range, build_string_fold_range, build_table_expr_fold_range};
12+
use imports::build_imports_fold_range;
1013
use lsp_types::{
1114
ClientCapabilities, FoldingRange, FoldingRangeParams, FoldingRangeProviderCapability,
1215
ServerCapabilities,
@@ -31,13 +34,13 @@ pub async fn on_folding_range_handler(
3134
let semantic_model = analysis.compilation.get_semantic_model(file_id)?;
3235
let document = semantic_model.get_document();
3336
let root = semantic_model.get_root();
34-
37+
let emmyrc = semantic_model.get_emmyrc();
3538
let mut builder = FoldingRangeBuilder::new(&document, root.clone());
36-
build_folding_ranges(&mut builder);
39+
build_folding_ranges(&mut builder, emmyrc);
3740
Some(builder.build())
3841
}
3942

40-
fn build_folding_ranges(builder: &mut FoldingRangeBuilder) {
43+
fn build_folding_ranges(builder: &mut FoldingRangeBuilder, emmyrc: &Emmyrc) {
4144
let root = builder.get_root().clone();
4245
for child in root.descendants::<LuaAst>() {
4346
match child {
@@ -80,6 +83,8 @@ fn build_folding_ranges(builder: &mut FoldingRangeBuilder) {
8083
_ => {}
8184
}
8285
}
86+
87+
build_imports_fold_range(builder, root, emmyrc);
8388
}
8489

8590
pub fn register_capabilities(

0 commit comments

Comments
 (0)