55//! original files. So we need to map the ranges.
66
77mod fixes;
8+ mod field_shorthand;
89
910use std:: cell:: RefCell ;
1011
@@ -15,7 +16,7 @@ use itertools::Itertools;
1516use rustc_hash:: FxHashSet ;
1617use syntax:: {
1718 ast:: { self , AstNode } ,
18- match_ast , SyntaxNode , TextRange , T ,
19+ SyntaxNode , TextRange , T ,
1920} ;
2021use text_edit:: TextEdit ;
2122
@@ -80,7 +81,7 @@ pub(crate) fn diagnostics(
8081
8182 for node in parse. tree ( ) . syntax ( ) . descendants ( ) {
8283 check_unnecessary_braces_in_use_statement ( & mut res, file_id, & node) ;
83- check_field_shorthand ( & mut res, file_id, & node) ;
84+ field_shorthand :: check ( & mut res, file_id, & node) ;
8485 }
8586 let res = RefCell :: new ( res) ;
8687 let sink_builder = DiagnosticSinkBuilder :: new ( )
@@ -188,100 +189,6 @@ fn text_edit_for_remove_unnecessary_braces_with_self_in_use_statement(
188189 None
189190}
190191
191- fn check_field_shorthand ( acc : & mut Vec < Diagnostic > , file_id : FileId , node : & SyntaxNode ) {
192- match_ast ! {
193- match node {
194- ast:: RecordExpr ( it) => check_expr_field_shorthand( acc, file_id, it) ,
195- ast:: RecordPat ( it) => check_pat_field_shorthand( acc, file_id, it) ,
196- _ => ( )
197- }
198- } ;
199- }
200-
201- fn check_expr_field_shorthand (
202- acc : & mut Vec < Diagnostic > ,
203- file_id : FileId ,
204- record_expr : ast:: RecordExpr ,
205- ) {
206- let record_field_list = match record_expr. record_expr_field_list ( ) {
207- Some ( it) => it,
208- None => return ,
209- } ;
210- for record_field in record_field_list. fields ( ) {
211- let ( name_ref, expr) = match record_field. name_ref ( ) . zip ( record_field. expr ( ) ) {
212- Some ( it) => it,
213- None => continue ,
214- } ;
215-
216- let field_name = name_ref. syntax ( ) . text ( ) . to_string ( ) ;
217- let field_expr = expr. syntax ( ) . text ( ) . to_string ( ) ;
218- let field_name_is_tup_index = name_ref. as_tuple_field ( ) . is_some ( ) ;
219- if field_name != field_expr || field_name_is_tup_index {
220- continue ;
221- }
222-
223- let mut edit_builder = TextEdit :: builder ( ) ;
224- edit_builder. delete ( record_field. syntax ( ) . text_range ( ) ) ;
225- edit_builder. insert ( record_field. syntax ( ) . text_range ( ) . start ( ) , field_name) ;
226- let edit = edit_builder. finish ( ) ;
227-
228- let field_range = record_field. syntax ( ) . text_range ( ) ;
229- acc. push ( Diagnostic {
230- // name: None,
231- range : field_range,
232- message : "Shorthand struct initialization" . to_string ( ) ,
233- severity : Severity :: WeakWarning ,
234- fix : Some ( Fix :: new (
235- "Use struct shorthand initialization" ,
236- SourceFileEdit { file_id, edit } . into ( ) ,
237- field_range,
238- ) ) ,
239- } ) ;
240- }
241- }
242-
243- fn check_pat_field_shorthand (
244- acc : & mut Vec < Diagnostic > ,
245- file_id : FileId ,
246- record_pat : ast:: RecordPat ,
247- ) {
248- let record_pat_field_list = match record_pat. record_pat_field_list ( ) {
249- Some ( it) => it,
250- None => return ,
251- } ;
252- for record_pat_field in record_pat_field_list. fields ( ) {
253- let ( name_ref, pat) = match record_pat_field. name_ref ( ) . zip ( record_pat_field. pat ( ) ) {
254- Some ( it) => it,
255- None => continue ,
256- } ;
257-
258- let field_name = name_ref. syntax ( ) . text ( ) . to_string ( ) ;
259- let field_pat = pat. syntax ( ) . text ( ) . to_string ( ) ;
260- let field_name_is_tup_index = name_ref. as_tuple_field ( ) . is_some ( ) ;
261- if field_name != field_pat || field_name_is_tup_index {
262- continue ;
263- }
264-
265- let mut edit_builder = TextEdit :: builder ( ) ;
266- edit_builder. delete ( record_pat_field. syntax ( ) . text_range ( ) ) ;
267- edit_builder. insert ( record_pat_field. syntax ( ) . text_range ( ) . start ( ) , field_name) ;
268- let edit = edit_builder. finish ( ) ;
269-
270- let field_range = record_pat_field. syntax ( ) . text_range ( ) ;
271- acc. push ( Diagnostic {
272- // name: None,
273- range : field_range,
274- message : "Shorthand struct pattern" . to_string ( ) ,
275- severity : Severity :: WeakWarning ,
276- fix : Some ( Fix :: new (
277- "Use struct field shorthand" ,
278- SourceFileEdit { file_id, edit } . into ( ) ,
279- field_range,
280- ) ) ,
281- } ) ;
282- }
283- }
284-
285192#[ cfg( test) ]
286193mod tests {
287194 use expect_test:: { expect, Expect } ;
@@ -295,7 +202,7 @@ mod tests {
295202 /// * a diagnostic is produced
296203 /// * this diagnostic fix trigger range touches the input cursor position
297204 /// * that the contents of the file containing the cursor match `after` after the diagnostic fix is applied
298- fn check_fix ( ra_fixture_before : & str , ra_fixture_after : & str ) {
205+ pub ( super ) fn check_fix ( ra_fixture_before : & str , ra_fixture_after : & str ) {
299206 let after = trim_indent ( ra_fixture_after) ;
300207
301208 let ( analysis, file_position) = fixture:: position ( ra_fixture_before) ;
@@ -377,7 +284,7 @@ mod tests {
377284
378285 /// Takes a multi-file input fixture with annotated cursor position and checks that no diagnostics
379286 /// apply to the file containing the cursor.
380- fn check_no_diagnostics ( ra_fixture : & str ) {
287+ pub ( crate ) fn check_no_diagnostics ( ra_fixture : & str ) {
381288 let ( analysis, files) = fixture:: files ( ra_fixture) ;
382289 let diagnostics = files
383290 . into_iter ( )
@@ -777,104 +684,6 @@ mod a {
777684 ) ;
778685 }
779686
780- #[ test]
781- fn test_check_expr_field_shorthand ( ) {
782- check_no_diagnostics (
783- r#"
784- struct A { a: &'static str }
785- fn main() { A { a: "hello" } }
786- "# ,
787- ) ;
788- check_no_diagnostics (
789- r#"
790- struct A(usize);
791- fn main() { A { 0: 0 } }
792- "# ,
793- ) ;
794-
795- check_fix (
796- r#"
797- struct A { a: &'static str }
798- fn main() {
799- let a = "haha";
800- A { a<|>: a }
801- }
802- "# ,
803- r#"
804- struct A { a: &'static str }
805- fn main() {
806- let a = "haha";
807- A { a }
808- }
809- "# ,
810- ) ;
811-
812- check_fix (
813- r#"
814- struct A { a: &'static str, b: &'static str }
815- fn main() {
816- let a = "haha";
817- let b = "bb";
818- A { a<|>: a, b }
819- }
820- "# ,
821- r#"
822- struct A { a: &'static str, b: &'static str }
823- fn main() {
824- let a = "haha";
825- let b = "bb";
826- A { a, b }
827- }
828- "# ,
829- ) ;
830- }
831-
832- #[ test]
833- fn test_check_pat_field_shorthand ( ) {
834- check_no_diagnostics (
835- r#"
836- struct A { a: &'static str }
837- fn f(a: A) { let A { a: hello } = a; }
838- "# ,
839- ) ;
840- check_no_diagnostics (
841- r#"
842- struct A(usize);
843- fn f(a: A) { let A { 0: 0 } = a; }
844- "# ,
845- ) ;
846-
847- check_fix (
848- r#"
849- struct A { a: &'static str }
850- fn f(a: A) {
851- let A { a<|>: a } = a;
852- }
853- "# ,
854- r#"
855- struct A { a: &'static str }
856- fn f(a: A) {
857- let A { a } = a;
858- }
859- "# ,
860- ) ;
861-
862- check_fix (
863- r#"
864- struct A { a: &'static str, b: &'static str }
865- fn f(a: A) {
866- let A { a<|>: a, b } = a;
867- }
868- "# ,
869- r#"
870- struct A { a: &'static str, b: &'static str }
871- fn f(a: A) {
872- let A { a, b } = a;
873- }
874- "# ,
875- ) ;
876- }
877-
878687 #[ test]
879688 fn test_add_field_from_usage ( ) {
880689 check_fix (
0 commit comments