@@ -3,7 +3,10 @@ use hir::{
33 db:: { AstDatabase , HirDatabase } ,
44 known, AssocItem , HirDisplay , InFile , Type ,
55} ;
6- use ide_db:: { assists:: Assist , famous_defs:: FamousDefs , source_change:: SourceChange , FxHashMap } ;
6+ use ide_db:: {
7+ assists:: Assist , famous_defs:: FamousDefs , imports:: import_assets:: item_for_path_search,
8+ source_change:: SourceChange , FxHashMap ,
9+ } ;
710use stdx:: format_to;
811use syntax:: {
912 algo,
@@ -14,6 +17,58 @@ use text_edit::TextEdit;
1417
1518use crate :: { fix, Diagnostic , DiagnosticsContext } ;
1619
20+ // TODO: how to depupicate with `ide-assists/generate_new`
21+ pub fn use_trivial_constructor (
22+ db : & ide_db:: RootDatabase ,
23+ path : ast:: Path ,
24+ ty : & hir:: Type ,
25+ ) -> Option < ast:: Expr > {
26+ match ty. as_adt ( ) {
27+ Some ( hir:: Adt :: Enum ( x) ) => {
28+ let variants = x. variants ( db) ;
29+
30+ if variants. len ( ) == 1 {
31+ let variant = variants[ 0 ] ;
32+
33+ if variant. fields ( db) . is_empty ( ) {
34+ let path = ast:: make:: path_qualified (
35+ path,
36+ syntax:: ast:: make:: path_segment ( ast:: make:: name_ref (
37+ & variant. name ( db) . to_smol_str ( ) ,
38+ ) ) ,
39+ ) ;
40+
41+ use hir:: StructKind :: * ;
42+ let is_record = match variant. kind ( db) {
43+ Record => true ,
44+ Tuple => false ,
45+ Unit => false ,
46+ } ;
47+
48+ return Some ( if is_record {
49+ ast:: Expr :: RecordExpr ( syntax:: ast:: make:: record_expr (
50+ path,
51+ ast:: make:: record_expr_field_list ( std:: iter:: empty ( ) ) ,
52+ ) )
53+ } else {
54+ syntax:: ast:: make:: expr_path ( path)
55+ } ) ;
56+ }
57+ }
58+ }
59+ Some ( hir:: Adt :: Struct ( x) ) => {
60+ let fields = x. fields ( db) ;
61+
62+ if fields. is_empty ( ) {
63+ return Some ( syntax:: ast:: make:: expr_path ( path) ) ;
64+ }
65+ }
66+ _ => { }
67+ }
68+
69+ None
70+ }
71+
1772// Diagnostic: missing-fields
1873//
1974// This diagnostic is triggered if record lacks some fields that exist in the corresponding structure.
@@ -55,6 +110,11 @@ fn fixes(ctx: &DiagnosticsContext<'_>, d: &hir::MissingFields) -> Option<Vec<Ass
55110
56111 let root = ctx. sema . db . parse_or_expand ( d. file ) ?;
57112
113+ let current_module = match & d. field_list_parent {
114+ Either :: Left ( ptr) => ctx. sema . scope ( ptr. to_node ( & root) . syntax ( ) ) . unwrap ( ) . module ( ) ,
115+ Either :: Right ( ptr) => ctx. sema . scope ( ptr. to_node ( & root) . syntax ( ) ) . unwrap ( ) . module ( ) ,
116+ } ;
117+
58118 let build_text_edit = |parent_syntax, new_syntax : & SyntaxNode , old_syntax| {
59119 let edit = {
60120 let mut builder = TextEdit :: builder ( ) ;
@@ -110,7 +170,26 @@ fn fixes(ctx: &DiagnosticsContext<'_>, d: &hir::MissingFields) -> Option<Vec<Ass
110170 Some ( generate_fill_expr ( ty) )
111171 }
112172 } else {
113- Some ( generate_fill_expr ( ty) )
173+ let expr = ( || -> Option < ast:: Expr > {
174+ let item_in_ns = hir:: ItemInNs :: from ( hir:: ModuleDef :: from ( ty. as_adt ( ) ?) ) ;
175+
176+ let type_path = current_module. find_use_path (
177+ ctx. sema . db ,
178+ item_for_path_search ( ctx. sema . db , item_in_ns) ?,
179+ ) ?;
180+
181+ use_trivial_constructor (
182+ & ctx. sema . db ,
183+ ide_db:: helpers:: mod_path_to_ast ( & type_path) ,
184+ & ty,
185+ )
186+ } ) ( ) ;
187+
188+ if expr. is_some ( ) {
189+ expr
190+ } else {
191+ Some ( generate_fill_expr ( ty) )
192+ }
114193 } ;
115194 let field = make:: record_expr_field (
116195 make:: name_ref ( & f. name ( ctx. sema . db ) . to_smol_str ( ) ) ,
0 commit comments