소스 검색

[display] add FinalFields cause to generate missing ctors

Simon Krajewski 5 년 전
부모
커밋
10e5eb712a
3개의 변경된 파일28개의 추가작업 그리고 10개의 파일을 삭제
  1. 1 0
      src/context/common.ml
  2. 4 0
      src/context/display/diagnosticsPrinter.ml
  3. 23 10
      src/typing/typeloadFields.ml

+ 1 - 0
src/context/common.ml

@@ -251,6 +251,7 @@ type missing_field_cause =
 	| ImplementedInterface of tclass * tparams
 	| ImplementedInterface of tclass * tparams
 	| PropertyAccessor of tclass_field * bool (* true = getter *)
 	| PropertyAccessor of tclass_field * bool (* true = getter *)
 	| FieldAccess
 	| FieldAccess
+	| FinalFields of tclass_field list
 
 
 and missing_fields_diagnostics = {
 and missing_fields_diagnostics = {
 	mf_pos : pos;
 	mf_pos : pos;

+ 4 - 0
src/context/display/diagnosticsPrinter.ml

@@ -106,6 +106,10 @@ let json_of_diagnostics dctx =
 					]
 					]
 				| FieldAccess ->
 				| FieldAccess ->
 					"FieldAccess",jobject []
 					"FieldAccess",jobject []
+				| FinalFields cfl ->
+					"FinalFields",jobject [
+						"fields",jarray (List.map (fun cf -> generate_class_field jctx (scope cf) cf) cfl)
+					]
 			in
 			in
 			let current_fields = ref [] in
 			let current_fields = ref [] in
 			let map_field (cf,t,ct) =
 			let map_field (cf,t,ct) =

+ 23 - 10
src/typing/typeloadFields.ml

@@ -53,7 +53,7 @@ type class_init_ctx = {
 	mutable has_display_field : bool;
 	mutable has_display_field : bool;
 	mutable delayed_expr : (typer * tlazy ref option) list;
 	mutable delayed_expr : (typer * tlazy ref option) list;
 	mutable force_constructor : bool;
 	mutable force_constructor : bool;
-	mutable uninitialized_final : pos option;
+	mutable uninitialized_final : tclass_field list;
 }
 }
 
 
 type field_kind =
 type field_kind =
@@ -538,7 +538,7 @@ let create_class_context ctx c context_init p =
 		abstract = abstract;
 		abstract = abstract;
 		context_init = context_init;
 		context_init = context_init;
 		force_constructor = false;
 		force_constructor = false;
-		uninitialized_final = None;
+		uninitialized_final = [];
 		delayed_expr = [];
 		delayed_expr = [];
 		has_display_field = false;
 		has_display_field = false;
 	} in
 	} in
@@ -943,10 +943,6 @@ let create_variable (ctx,cctx,fctx) c f t eo p =
 	if fctx.is_abstract_member && not is_abstract_enum_field then error (fst f.cff_name ^ ": Cannot declare member variable in abstract") p;
 	if fctx.is_abstract_member && not is_abstract_enum_field then error (fst f.cff_name ^ ": Cannot declare member variable in abstract") p;
 	if fctx.is_inline && not fctx.is_static then error (fst f.cff_name ^ ": Inline variable must be static") p;
 	if fctx.is_inline && not fctx.is_static then error (fst f.cff_name ^ ": Inline variable must be static") p;
 	if fctx.is_inline && eo = None then error (fst f.cff_name ^ ": Inline variable must be initialized") p;
 	if fctx.is_inline && eo = None then error (fst f.cff_name ^ ": Inline variable must be initialized") p;
-	if fctx.is_final && not (fctx.is_extern || (has_class_flag c CExtern) || (has_class_flag c CInterface))  && eo = None then begin
-		if fctx.is_static then error (fst f.cff_name ^ ": Static final variable must be initialized") p
-		else cctx.uninitialized_final <- Some f.cff_pos;
-	end;
 	let t = (match t with
 	let t = (match t with
 		| None when eo = None ->
 		| None when eo = None ->
 			error ("Variable requires type-hint or initialization") (pos f.cff_name);
 			error ("Variable requires type-hint or initialization") (pos f.cff_name);
@@ -968,7 +964,13 @@ let create_variable (ctx,cctx,fctx) c f t eo p =
 		cf_meta = f.cff_meta;
 		cf_meta = f.cff_meta;
 		cf_kind = Var kind;
 		cf_kind = Var kind;
 	} in
 	} in
-	if fctx.is_final then add_class_field_flag cf CfFinal;
+	if fctx.is_final then begin
+		if not (fctx.is_extern || (has_class_flag c CExtern) || (has_class_flag c CInterface))  && eo = None then begin
+			if fctx.is_static then error (fst f.cff_name ^ ": Static final variable must be initialized") p
+			else cctx.uninitialized_final <- cf :: cctx.uninitialized_final;
+		end;
+		add_class_field_flag cf CfFinal;
+	end;
 	if fctx.is_extern then add_class_field_flag cf CfExtern;
 	if fctx.is_extern then add_class_field_flag cf CfExtern;
 	if fctx.is_abstract_member then begin
 	if fctx.is_abstract_member then begin
 		cf.cf_meta <- ((Meta.Custom ":impl"),[],null_pos) :: cf.cf_meta;
 		cf.cf_meta <- ((Meta.Custom ":impl"),[],null_pos) :: cf.cf_meta;
@@ -1676,9 +1678,20 @@ let init_class ctx c p context_init herits fields =
 		else
 		else
 			ensure_struct_init_constructor ctx c fields p;
 			ensure_struct_init_constructor ctx c fields p;
 	begin match cctx.uninitialized_final with
 	begin match cctx.uninitialized_final with
-		| Some pf when c.cl_constructor = None ->
-			display_error ctx "This class has uninitialized final vars, which requires a constructor" p;
-			display_error ctx "Example of an uninitialized final var" pf;
+		| cf :: cfl when c.cl_constructor = None ->
+			if Diagnostics.is_diagnostics_run ctx.com cf.cf_name_pos then begin
+				let diag = {
+					mf_pos = c.cl_name_pos;
+					mf_on = TClassDecl c;
+					mf_fields = [];
+					mf_cause = FinalFields (cf :: cfl);
+				} in
+				let display = ctx.com.display_information in
+				display.module_diagnostics <- MissingFields diag :: display.module_diagnostics
+			end else begin
+				display_error ctx "This class has uninitialized final vars, which requires a constructor" p;
+				display_error ctx "Example of an uninitialized final var" cf.cf_name_pos;
+			end
 		| _ ->
 		| _ ->
 			()
 			()
 	end;
 	end;