diff options
-rw-r--r-- | crates/ra_assists/src/handlers/add_function.rs | 69 | ||||
-rw-r--r-- | crates/ra_syntax/src/ast/make.rs | 4 |
2 files changed, 27 insertions, 46 deletions
diff --git a/crates/ra_assists/src/handlers/add_function.rs b/crates/ra_assists/src/handlers/add_function.rs index 9bd46f5dc..f185cffdb 100644 --- a/crates/ra_assists/src/handlers/add_function.rs +++ b/crates/ra_assists/src/handlers/add_function.rs | |||
@@ -81,6 +81,7 @@ struct FunctionBuilder { | |||
81 | type_params: Option<ast::TypeParamList>, | 81 | type_params: Option<ast::TypeParamList>, |
82 | params: ast::ParamList, | 82 | params: ast::ParamList, |
83 | file: AssistFile, | 83 | file: AssistFile, |
84 | needs_pub: bool, | ||
84 | } | 85 | } |
85 | 86 | ||
86 | impl FunctionBuilder { | 87 | impl FunctionBuilder { |
@@ -90,11 +91,12 @@ impl FunctionBuilder { | |||
90 | ctx: &AssistCtx, | 91 | ctx: &AssistCtx, |
91 | call: &ast::CallExpr, | 92 | call: &ast::CallExpr, |
92 | path: &ast::Path, | 93 | path: &ast::Path, |
93 | generate_in: Option<hir::InFile<hir::ModuleSource>>, | 94 | target_module: Option<hir::InFile<hir::ModuleSource>>, |
94 | ) -> Option<Self> { | 95 | ) -> Option<Self> { |
96 | let needs_pub = target_module.is_some(); | ||
95 | let mut file = AssistFile::default(); | 97 | let mut file = AssistFile::default(); |
96 | let target = if let Some(generate_in_module) = generate_in { | 98 | let target = if let Some(target_module) = target_module { |
97 | let (in_file, target) = next_space_for_fn_in_module(ctx.sema.db, generate_in_module)?; | 99 | let (in_file, target) = next_space_for_fn_in_module(ctx.sema.db, target_module)?; |
98 | file = in_file; | 100 | file = in_file; |
99 | target | 101 | target |
100 | } else { | 102 | } else { |
@@ -102,12 +104,16 @@ impl FunctionBuilder { | |||
102 | }; | 104 | }; |
103 | let fn_name = fn_name(&path)?; | 105 | let fn_name = fn_name(&path)?; |
104 | let (type_params, params) = fn_args(ctx, &call)?; | 106 | let (type_params, params) = fn_args(ctx, &call)?; |
105 | Some(Self { target, fn_name, type_params, params, file }) | 107 | Some(Self { target, fn_name, type_params, params, file, needs_pub }) |
106 | } | 108 | } |
109 | |||
107 | fn render(self) -> Option<FunctionTemplate> { | 110 | fn render(self) -> Option<FunctionTemplate> { |
108 | let placeholder_expr = ast::make::expr_todo(); | 111 | let placeholder_expr = ast::make::expr_todo(); |
109 | let fn_body = ast::make::block_expr(vec![], Some(placeholder_expr)); | 112 | let fn_body = ast::make::block_expr(vec![], Some(placeholder_expr)); |
110 | let fn_def = ast::make::fn_def(self.fn_name, self.type_params, self.params, fn_body); | 113 | let mut fn_def = ast::make::fn_def(self.fn_name, self.type_params, self.params, fn_body); |
114 | if self.needs_pub { | ||
115 | fn_def = ast::make::add_pub_crate_modifier(fn_def); | ||
116 | } | ||
111 | 117 | ||
112 | let (fn_def, insert_offset) = match self.target { | 118 | let (fn_def, insert_offset) = match self.target { |
113 | GeneratedFunctionTarget::BehindItem(it) => { | 119 | GeneratedFunctionTarget::BehindItem(it) => { |
@@ -116,15 +122,14 @@ impl FunctionBuilder { | |||
116 | (indented, it.text_range().end()) | 122 | (indented, it.text_range().end()) |
117 | } | 123 | } |
118 | GeneratedFunctionTarget::InEmptyItemList(it) => { | 124 | GeneratedFunctionTarget::InEmptyItemList(it) => { |
119 | let with_leading_newline = ast::make::add_leading_newlines(1, fn_def); | 125 | let indent_once = IndentLevel(1); |
120 | let indent = IndentLevel::from_node(it.syntax()).indented(); | 126 | let indent = IndentLevel::from_node(it.syntax()); |
121 | let mut indented = indent.increase_indent(with_leading_newline); | 127 | |
122 | if !item_list_has_whitespace(&it) { | 128 | let fn_def = ast::make::add_leading_newlines(1, fn_def); |
123 | // In this case we want to make sure there's a newline between the closing | 129 | let fn_def = indent_once.increase_indent(fn_def); |
124 | // function brace and the closing module brace (so it doesn't end in `}}`). | 130 | let fn_def = ast::make::add_trailing_newlines(1, fn_def); |
125 | indented = ast::make::add_trailing_newlines(1, indented); | 131 | let fn_def = indent.increase_indent(fn_def); |
126 | } | 132 | (fn_def, it.syntax().text_range().start() + TextUnit::from_usize(1)) |
127 | (indented, it.syntax().text_range().start() + TextUnit::from_usize(1)) | ||
128 | } | 133 | } |
129 | }; | 134 | }; |
130 | 135 | ||
@@ -140,11 +145,6 @@ impl FunctionBuilder { | |||
140 | } | 145 | } |
141 | } | 146 | } |
142 | 147 | ||
143 | /// Returns true if the given ItemList contains whitespace. | ||
144 | fn item_list_has_whitespace(it: &ast::ItemList) -> bool { | ||
145 | it.syntax().descendants_with_tokens().find(|it| it.kind() == SyntaxKind::WHITESPACE).is_some() | ||
146 | } | ||
147 | |||
148 | enum GeneratedFunctionTarget { | 148 | enum GeneratedFunctionTarget { |
149 | BehindItem(SyntaxNode), | 149 | BehindItem(SyntaxNode), |
150 | InEmptyItemList(ast::ItemList), | 150 | InEmptyItemList(ast::ItemList), |
@@ -803,29 +803,7 @@ fn foo() { | |||
803 | ", | 803 | ", |
804 | r" | 804 | r" |
805 | mod bar { | 805 | mod bar { |
806 | fn my_fn() { | 806 | pub(crate) fn my_fn() { |
807 | <|>todo!() | ||
808 | } | ||
809 | } | ||
810 | |||
811 | fn foo() { | ||
812 | bar::my_fn() | ||
813 | } | ||
814 | ", | ||
815 | ); | ||
816 | check_assist( | ||
817 | add_function, | ||
818 | r" | ||
819 | mod bar { | ||
820 | } | ||
821 | |||
822 | fn foo() { | ||
823 | bar::my_fn<|>() | ||
824 | } | ||
825 | ", | ||
826 | r" | ||
827 | mod bar { | ||
828 | fn my_fn() { | ||
829 | <|>todo!() | 807 | <|>todo!() |
830 | } | 808 | } |
831 | } | 809 | } |
@@ -854,7 +832,7 @@ fn foo() { | |||
854 | mod bar { | 832 | mod bar { |
855 | fn something_else() {} | 833 | fn something_else() {} |
856 | 834 | ||
857 | fn my_fn() { | 835 | pub(crate) fn my_fn() { |
858 | <|>todo!() | 836 | <|>todo!() |
859 | } | 837 | } |
860 | } | 838 | } |
@@ -872,8 +850,7 @@ fn foo() { | |||
872 | add_function, | 850 | add_function, |
873 | r" | 851 | r" |
874 | mod bar { | 852 | mod bar { |
875 | mod baz { | 853 | mod baz {} |
876 | } | ||
877 | } | 854 | } |
878 | 855 | ||
879 | fn foo() { | 856 | fn foo() { |
@@ -883,7 +860,7 @@ fn foo() { | |||
883 | r" | 860 | r" |
884 | mod bar { | 861 | mod bar { |
885 | mod baz { | 862 | mod baz { |
886 | fn my_fn() { | 863 | pub(crate) fn my_fn() { |
887 | <|>todo!() | 864 | <|>todo!() |
888 | } | 865 | } |
889 | } | 866 | } |
diff --git a/crates/ra_syntax/src/ast/make.rs b/crates/ra_syntax/src/ast/make.rs index b0f4803f3..ee0f5cc40 100644 --- a/crates/ra_syntax/src/ast/make.rs +++ b/crates/ra_syntax/src/ast/make.rs | |||
@@ -303,6 +303,10 @@ pub fn add_trailing_newlines(amount_of_newlines: usize, t: impl AstNode) -> ast: | |||
303 | ast_from_text(&format!("{}{}", t.syntax(), newlines)) | 303 | ast_from_text(&format!("{}{}", t.syntax(), newlines)) |
304 | } | 304 | } |
305 | 305 | ||
306 | pub fn add_pub_crate_modifier(fn_def: ast::FnDef) -> ast::FnDef { | ||
307 | ast_from_text(&format!("pub(crate) {}", fn_def)) | ||
308 | } | ||
309 | |||
306 | fn ast_from_text<N: AstNode>(text: &str) -> N { | 310 | fn ast_from_text<N: AstNode>(text: &str) -> N { |
307 | let parse = SourceFile::parse(text); | 311 | let parse = SourceFile::parse(text); |
308 | let node = parse.tree().syntax().descendants().find_map(N::cast).unwrap(); | 312 | let node = parse.tree().syntax().descendants().find_map(N::cast).unwrap(); |