bbnf_analysis/features/
code_actions.rs1use std::collections::HashMap;
2
3use ls_types::*;
4
5use crate::state::DocumentState;
6
7pub fn code_actions(
8 state: &DocumentState,
9 uri: &Uri,
10 range: Range,
11) -> CodeActionResponse {
12 let mut actions = Vec::new();
13
14 for diag in &state.info.diagnostics {
16 if diag.message.starts_with("Unused rule:") {
17 if diag.range.start.line >= range.start.line
19 && diag.range.end.line <= range.end.line
20 {
21 let name = diag
23 .message
24 .strip_prefix("Unused rule: `")
25 .and_then(|s| s.strip_suffix('`'));
26 if let Some(name) = name {
27 if let Some(&idx) = state.info.rule_index.get(name) {
28 let rule = &state.info.rules[idx];
29
30 let mut delete_end = rule.full_span.1;
32 while delete_end < state.text.len() {
34 let ch = state.text.as_bytes()[delete_end];
35 if ch == b';' || ch == b'.' {
36 delete_end += 1;
37 break;
38 }
39 delete_end += 1;
40 }
41 if delete_end < state.text.len()
43 && state.text.as_bytes()[delete_end] == b'\n'
44 {
45 delete_end += 1;
46 }
47
48 let mut changes = HashMap::new();
49 changes.insert(
50 uri.clone(),
51 vec![TextEdit {
52 range: state.line_index.span_to_range(rule.full_span.0, delete_end),
53 new_text: String::new(),
54 }],
55 );
56
57 actions.push(CodeActionOrCommand::CodeAction(CodeAction {
58 title: format!("Remove unused rule `{}`", name),
59 kind: Some(CodeActionKind::QUICKFIX),
60 diagnostics: Some(vec![diag.clone()]),
61 edit: Some(WorkspaceEdit {
62 changes: Some(changes),
63 ..Default::default()
64 }),
65 ..Default::default()
66 }));
67 }
68 }
69 }
70 }
71 }
72
73 for diag in &state.info.diagnostics {
75 if diag.message.starts_with("Undefined rule:")
76 && diag.range.start.line >= range.start.line
77 && diag.range.end.line <= range.end.line
78 {
79 let name = diag
80 .message
81 .strip_prefix("Undefined rule: `")
82 .and_then(|s| s.strip_suffix('`'));
83 if let Some(name) = name {
84 let insert_text = format!("\n{} = ;\n", name);
86 let end_pos = state.line_index.offset_to_position(state.text.len());
87
88 let mut changes = HashMap::new();
89 changes.insert(
90 uri.clone(),
91 vec![TextEdit {
92 range: Range::new(end_pos, end_pos),
93 new_text: insert_text,
94 }],
95 );
96
97 actions.push(CodeActionOrCommand::CodeAction(CodeAction {
98 title: format!("Define rule `{}`", name),
99 kind: Some(CodeActionKind::QUICKFIX),
100 diagnostics: Some(vec![diag.clone()]),
101 edit: Some(WorkspaceEdit {
102 changes: Some(changes),
103 ..Default::default()
104 }),
105 ..Default::default()
106 }));
107 }
108 }
109 }
110
111 actions
112}