aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_ide_api/src/assists/fill_match_arm.rs
diff options
context:
space:
mode:
authorbors[bot] <bors[bot]@users.noreply.github.com>2019-02-05 13:21:42 +0000
committerbors[bot] <bors[bot]@users.noreply.github.com>2019-02-05 13:21:42 +0000
commit569e1e871e737ade80616288241d63e1531dbb8d (patch)
tree6f50440df7778581e7a16e6634ffa24e177efc8e /crates/ra_ide_api/src/assists/fill_match_arm.rs
parent41838254750fac3822bfe43b04158977e5355e42 (diff)
parente696342afad79b0aa7638a8c51ef3ce45489ed21 (diff)
Merge #746
746: Rename assits to assists r=kjeremy a=kjeremy Co-authored-by: Jeremy Kolb <[email protected]>
Diffstat (limited to 'crates/ra_ide_api/src/assists/fill_match_arm.rs')
-rw-r--r--crates/ra_ide_api/src/assists/fill_match_arm.rs157
1 files changed, 157 insertions, 0 deletions
diff --git a/crates/ra_ide_api/src/assists/fill_match_arm.rs b/crates/ra_ide_api/src/assists/fill_match_arm.rs
new file mode 100644
index 000000000..6ae829d85
--- /dev/null
+++ b/crates/ra_ide_api/src/assists/fill_match_arm.rs
@@ -0,0 +1,157 @@
1use std::fmt::Write;
2use hir::{
3 AdtDef,
4 source_binder,
5 Ty,
6 FieldSource,
7};
8use ra_ide_api_light::{
9 assists::{
10 Assist,
11 AssistBuilder
12 }
13};
14use ra_syntax::{
15 ast::{
16 self,
17 AstNode,
18 }
19};
20
21use crate::assists::AssistCtx;
22
23pub fn fill_match_arm(ctx: AssistCtx) -> Option<Assist> {
24 let match_expr = ctx.node_at_offset::<ast::MatchExpr>()?;
25
26 // We already have some match arms, so we don't provide any assists.
27 match match_expr.match_arm_list() {
28 Some(arm_list) if arm_list.arms().count() > 0 => {
29 return None;
30 }
31 _ => {}
32 }
33
34 let expr = match_expr.expr()?;
35 let function = source_binder::function_from_child_node(ctx.db, ctx.file_id, expr.syntax())?;
36 let infer_result = function.infer(ctx.db);
37 let syntax_mapping = function.body_syntax_mapping(ctx.db);
38 let node_expr = syntax_mapping.node_expr(expr)?;
39 let match_expr_ty = infer_result[node_expr].clone();
40 match match_expr_ty {
41 Ty::Adt { def_id, .. } => match def_id {
42 AdtDef::Enum(e) => {
43 let mut buf = format!("match {} {{\n", expr.syntax().text().to_string());
44 let variants = e.variants(ctx.db);
45 for variant in variants {
46 let name = variant.name(ctx.db)?;
47 write!(
48 &mut buf,
49 " {}::{}",
50 e.name(ctx.db)?.to_string(),
51 name.to_string()
52 )
53 .expect("write fmt");
54
55 let pat = variant
56 .fields(ctx.db)
57 .into_iter()
58 .map(|field| {
59 let name = field.name(ctx.db).to_string();
60 let (_, source) = field.source(ctx.db);
61 match source {
62 FieldSource::Named(_) => name,
63 FieldSource::Pos(_) => "_".to_string(),
64 }
65 })
66 .collect::<Vec<_>>();
67
68 match pat.first().map(|s| s.as_str()) {
69 Some("_") => write!(&mut buf, "({})", pat.join(", ")).expect("write fmt"),
70 Some(_) => write!(&mut buf, "{{{}}}", pat.join(", ")).expect("write fmt"),
71 None => (),
72 };
73
74 buf.push_str(" => (),\n");
75 }
76 buf.push_str("}");
77 ctx.build("fill match arms", |edit: &mut AssistBuilder| {
78 edit.replace_node_and_indent(match_expr.syntax(), buf);
79 })
80 }
81 _ => None,
82 },
83 _ => None,
84 }
85}
86
87#[cfg(test)]
88mod tests {
89 use insta::assert_debug_snapshot_matches;
90
91 use ra_syntax::{TextRange, TextUnit};
92
93 use crate::{
94 FileRange,
95 mock_analysis::{analysis_and_position, single_file_with_position}
96};
97 use ra_db::SourceDatabase;
98
99 fn test_assit(name: &str, code: &str) {
100 let (analysis, position) = if code.contains("//-") {
101 analysis_and_position(code)
102 } else {
103 single_file_with_position(code)
104 };
105 let frange = FileRange {
106 file_id: position.file_id,
107 range: TextRange::offset_len(position.offset, TextUnit::from(1)),
108 };
109 let source_file = analysis
110 .with_db(|db| db.parse(frange.file_id))
111 .expect("source file");
112 let ret = analysis
113 .with_db(|db| crate::assists::assists(db, frange.file_id, &source_file, frange.range))
114 .expect("assists");
115
116 assert_debug_snapshot_matches!(name, ret);
117 }
118
119 #[test]
120 fn test_fill_match_arm() {
121 test_assit(
122 "fill_match_arm1",
123 r#"
124 enum A {
125 As,
126 Bs,
127 Cs(String),
128 Ds(String, String),
129 Es{x: usize, y: usize}
130 }
131
132 fn main() {
133 let a = A::As;
134 match a<|>
135 }
136 "#,
137 );
138
139 test_assit(
140 "fill_match_arm2",
141 r#"
142 enum A {
143 As,
144 Bs,
145 Cs(String),
146 Ds(String, String),
147 Es{x: usize, y: usize}
148 }
149
150 fn main() {
151 let a = A::As;
152 match a<|> {}
153 }
154 "#,
155 );
156 }
157}