1 use crate::assist_context::{AssistContext, Assists};
4 assists::{AssistId, AssistKind},
8 ast::{self, edit::IndentLevel},
12 // Assist: generate_constant
14 // Generate a named constant.
17 // struct S { i: usize }
18 // impl S { pub fn new(n: usize) {} }
20 // let v = S::new(CAPA$0CITY);
25 // struct S { i: usize }
26 // impl S { pub fn new(n: usize) {} }
28 // const CAPACITY: usize = $0;
29 // let v = S::new(CAPACITY);
33 pub(crate) fn generate_constant(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
34 let statement = ctx.find_node_at_offset::<ast::Stmt>()?;
35 let arg_list = ctx.find_node_at_offset::<ast::ArgList>()?;
36 let expr = ctx.find_node_at_offset::<ast::Expr>()?;
37 let constant_token = ctx.find_node_at_offset::<ast::NameRef>()?;
38 let ty = ctx.sema.type_of_expr(&expr)?;
39 let scope = ctx.sema.scope(statement.syntax());
40 let module = scope.module()?;
41 let type_name = ty.original().display_source_code(ctx.db(), module.into()).ok()?;
42 let indent = IndentLevel::from_node(statement.syntax());
43 if !arg_list.syntax().text_range().contains_range(constant_token.syntax().text_range()) {
46 if constant_token.to_string().chars().any(|it| !(it.is_uppercase() || it == '_')) {
47 cov_mark::hit!(not_constant_name);
50 if NameRefClass::classify(&ctx.sema, &constant_token).is_some() {
51 cov_mark::hit!(already_defined);
54 let target = statement.syntax().parent()?.text_range();
55 let statement_syntax = statement.syntax().clone_for_update();
57 AssistId("generate_constant", AssistKind::QuickFix),
62 statement.syntax().text_range(),
64 "const {}: {} = $0;\n{}{}",
68 statement_syntax.text()
78 use crate::tests::{check_assist, check_assist_not_applicable};
84 r#"struct S { i: usize }
86 pub fn new(n: usize) {}
89 let v = S::new(CAPA$0CITY);
91 r#"struct S { i: usize }
93 pub fn new(n: usize) {}
96 const CAPACITY: usize = $0;
97 let v = S::new(CAPACITY);
102 fn test_wont_apply_when_defined() {
103 cov_mark::check!(already_defined);
104 check_assist_not_applicable(
106 r#"struct S { i: usize }
108 pub fn new(n: usize) {}
111 const CAPACITY: usize = 10;
112 let v = S::new(CAPAC$0ITY);
117 fn test_wont_apply_when_maybe_not_constant() {
118 cov_mark::check!(not_constant_name);
119 check_assist_not_applicable(
121 r#"struct S { i: usize }
123 pub fn new(n: usize) {}
126 let v = S::new(capa$0city);