Remove restriction on concatenating Tany with a string
[hiphop-php.git] / hphp / hack / src / utils / errors.ml
blob7af4c83fdc056a13e82d1173a0df863f63580ce5
1 (**
2 * Copyright (c) 2014, Facebook, Inc.
3 * All rights reserved.
5 * This source code is licensed under the BSD-style license found in the
6 * LICENSE file in the "hack" directory of this source tree. An additional grant
7 * of patent rights can be found in the PATENTS file in the same directory.
9 *)
11 open Utils
13 (*****************************************************************************)
14 (* Errors accumulator. *)
15 (*****************************************************************************)
17 type error = (Pos.t * string) list
18 type t = error list
20 let (error_list: t ref) = ref []
22 let add pos msg =
23 error_list := [pos, msg] :: !error_list
25 let add_list pos_msg_l =
26 error_list := pos_msg_l :: !error_list
28 let add_error error =
29 error_list := error :: !error_list
31 let to_list (error: error) = (error: (Pos.t * string) list)
32 let get_pos (error: error) = fst (List.hd error)
33 let filename (error: error) = Pos.filename (get_pos error)
34 let make_error (x: (Pos.t * string) list) = (x: error)
36 (*****************************************************************************)
37 (* Lexer error *)
38 (*****************************************************************************)
40 let fixme_format pos =
41 add pos "HH_FIXME wrong format, expected '/* HH_FIXME[ERROR_NUMBER] */'"
43 let alok (pos, x) =
44 add pos (
45 "You probably forgot to bind this type parameter right?\nAdd <"^x^
46 "> somewhere (after the function name definition, or after the class name)\nExamples: "^"function foo<T> or class A<T>")
48 let unexpected_eof pos =
49 add pos "Unexpected end of file"
51 let missing_field pos1 pos2 name =
52 add_list
53 [pos1, "The field '"^name^"' is missing";
54 pos2, "The field '"^name^"' is defined"]
56 let generic_class_var pos =
57 add pos "A class variable cannot be generic"
59 let explain_constraint pos name (error: error) =
60 add_list (
61 error @
62 [pos, "Considering the constraint on the type '"^name^"'"]
65 let unexpected_arrow pos cname =
66 add pos ("Keys may not be specified for " ^ cname ^ " initialization")
68 let missing_arrow pos cname =
69 add pos ("Keys must be specified for " ^ cname ^ " initialization")
71 let disallowed_xhp_type pos name =
72 add pos (name ^ " is not a valid type. Use :xhp or XHPChild.")
74 let overflow p =
75 add p "Value is too large"
77 let unterminated_comment pos =
78 add pos "unterminated comment"
80 let unterminated_xhp_comment pos =
81 add pos "unterminated xhp comment"
83 let name_already_bound x p1 p2 =
84 let x = Utils.strip_ns x in
85 add_list [
86 p1, "Name already bound: "^x;
87 p2, "Previous definition is here"
90 let method_name_already_bound p name =
91 add p ("Method name already bound: "^name)
93 let error_name_already_bound hhi_root name name_prev p p_prev =
94 (* hhi_root = *)
95 let name = Utils.strip_ns name in
96 let name_prev = Utils.strip_ns name_prev in
97 let errs = [
98 p, "Name already bound: "^name;
99 p_prev, (if String.compare name name_prev == 0
100 then "Previous definition is here"
101 else "Previous definition "^name_prev^" differs only in capitalization ")
102 ] in
103 let hhi_msg =
104 "This appears to be defined in an hhi file included in your project "^
105 "root. The hhi files for the standard library are now a part of the "^
106 "typechecker and must be removed from your project. Typically, you can "^
107 "do this by deleting the \"hhi\" directory you copied into your "^
108 "project when first starting with Hack." in
109 (* unsafe_opt since init stack will refuse to continue if we don't have an
110 * hhi root. *)
111 let errs =
112 if str_starts_with p.Pos.pos_file hhi_root
113 then errs @ [p_prev, hhi_msg]
114 else if str_starts_with p_prev.Pos.pos_file hhi_root
115 then errs @ [p, hhi_msg]
116 else errs in
117 add_list errs
119 let unbound_name p x =
120 add p ("Unbound name: "^(strip_ns x))
122 let different_scope p x p' =
123 add_list [p, ("The variable "^ x ^" is defined");
124 p', ("But in a different scope")]
126 let undefined p x =
127 add p ("Undefined variable: "^x)
129 let this_reserved pos =
130 add pos "The type parameter \"this\" is reserved"
132 let start_with_T pos =
133 add pos
134 "Please make your type parameter start with the letter T (capital)"
136 let already_bound pos x =
137 add pos ("Argument already bound: "^x)
139 let unexpected_typedef pos def_pos =
140 add_list [
141 pos, "Unexpected typedef";
142 def_pos, "Definition is here";
145 let fd_name_already_bound pos =
146 add pos "Field name already bound"
148 let primitive_toplevel p =
149 add p ("Primitive type annotations are always available and may no \
150 longer be referred to in the toplevel namespace.")
152 let integer_instead_of_int p =
153 add p "Invalid Hack type. Using \"integer\" in Hack is considered \
154 an error. Use \"int\" instead, to keep the codebase \
155 consistent."
157 let boolean_instead_of_bool p =
158 add p "Invalid Hack type. Using \"boolean\" in Hack is considered \
159 an error. Use \"bool\" instead, to keep the codebase \
160 consistent."
162 let double_instead_of_float p =
163 add p "Invalid Hack type. Using \"double\" in Hack is considered \
164 an error. Use \"float\" instead. They are equivalent data types \
165 and the codebase remains consistent."
167 let real_instead_of_float p =
168 add p "Invalid Hack type. Using \"real\" in Hack is considered \
169 an error. Use \"float\" instead. They are equivalent data types and \
170 the codebase remains consistent."
172 let this_no_argument p =
173 add p "\"this\" expects no arguments"
175 let this_outside_of_class p =
176 add p "Cannot use \"this\" outside of a class"
178 let this_must_be_return p =
179 add p "The type \"this\" can only be used as a return type, \
180 to instantiate a covariant type variable, \
181 or as a private non-static member variable"
183 let lowercase_this p x =
184 add p ("Invalid Hack type \""^x^"\". Use \"this\" instead")
186 let tparam_with_tparam p x =
187 add p (Printf.sprintf "%s is a type parameter. Type parameters cannot \
188 themselves take type parameters (e.g. %s<int> doesn't make sense)" x x)
190 let shadowed_type_param p pos name =
191 add_list [
192 p, Printf.sprintf "You cannot re-bind the type parameter %s" name;
193 pos, Printf.sprintf "%s is already bound here" name
196 let missing_typehint p =
197 add p "Please add a type hint"
199 let expected_variable p =
200 add p "Was expecting a variable name"
202 let naming_too_few_arguments p =
203 add p "Too few arguments"
205 let naming_too_many_arguments p =
206 add p "Too many arguments"
208 let expected_collection p cn =
209 add p ("Unexpected collection type " ^ (Utils.strip_ns cn))
211 let illegal_CLASS p =
212 add p "Using __CLASS__ outside a class"
214 let dynamic_method_call p =
215 add p "Dynamic method call"
217 let illegal_fun p =
218 let msg = "The argument to fun() must be a single-quoted, constant "^
219 "literal string representing a valid function name." in
220 add p msg
222 let illegal_meth_fun p =
223 let msg = "String argument to fun() contains ':';"^
224 " for static class methods, use"^
225 " class_meth(Cls::class, 'method_name'), not fun('Cls::method_name')" in
226 add p msg
228 let illegal_inst_meth p =
229 let msg = "The argument to inst_meth() must be an expression and a "^
230 "constant literal string representing a valid method name." in
231 add p msg
233 let illegal_meth_caller p =
234 let msg =
235 "The two arguments to meth_caller() must be:"
236 ^"\n - first: ClassOrInterface::class"
237 ^"\n - second: a single-quoted string literal containing the name"
238 ^" of a non-static method of that class" in
239 add p msg
241 let illegal_class_meth p =
242 let msg =
243 "The two arguments to class_meth() must be:"
244 ^"\n - first: ValidClassname::class"
245 ^"\n - second: a single-quoted string literal containing the name"
246 ^" of a static method of that class" in
247 add p msg
249 let assert_arity p =
250 add p "assert expects exactly one argument"
252 let gena_arity p =
253 add p "gena() expects exactly 1 argument"
255 let genva_arity p =
256 add p "genva() expects at least 1 argument"
258 let gen_array_rec_arity p =
259 add p "gen_array_rec() expects exactly 1 argument"
261 let gen_array_va_rec_arity p =
262 add p
263 "gen_array_va_rec_DEPRECATED() expects at least 1 argument"
265 let dynamic_class p =
266 add p "Don't use dynamic classes"
268 let typedef_constraint pos =
269 add pos "Constraints on typedefs are not supported"
271 let add_a_typehint pos =
272 add pos "Please add a type hint"
274 let local_const var_pos =
275 add var_pos "You cannot use a local variable in a constant definition"
277 let illegal_constant pos =
278 add pos "Illegal constant value"
280 let cyclic_constraint p =
281 add p "Cyclic constraint"
283 let parsing_error (p, msg) =
284 add p msg
286 let format_string pos snippet s class_pos fname class_suggest =
287 add_list [
288 (pos, "I don't understand the format string " ^ snippet ^ " in " ^ s);
289 (class_pos,
290 "You can add a new format specifier by adding "
291 ^fname^"() to "^class_suggest)]
293 let expected_literal_string pos =
294 add pos "This argument must be a literal string"
296 let generic_array_strict p =
297 add p "You cannot have an array without generics in strict mode"
299 let nullable_void p =
300 add p "?void is a nonsensical typehint"
302 let tuple_syntax p =
303 add p ("Did you want a tuple? Try (X,Y), not tuple<X,Y>")
305 let class_arity pos class_name arity =
306 add pos ("The class "^(Utils.strip_ns class_name)^" expects "^
307 soi arity^" arguments")
309 let dynamic_yield_private pos =
310 add_list
311 [pos, "DynamicYield cannot see private methods in subclasses"]
313 let expecting_type_hint p =
314 add p "Was expecting a type hint"
316 let expecting_type_hint_suggest p ty =
317 add p ("Was expecting a type hint (what about: "^ty^")")
319 let expecting_return_type_hint p =
320 add p "Was expecting a return type hint"
322 let expecting_return_type_hint_suggest p ty =
323 add p ("Was expecting a return type hint (what about: ': "^ty^"')")
325 let field_kinds p1 p2 =
326 add_list [p1, "You cannot use this kind of field (value)";
327 p2, "Mixed with this kind of field (key => value)"]
329 let unbound_name_typing pos name =
330 add pos ("Unbound name, Typing: "^(strip_ns name))
332 let did_you_mean_naming pos name suggest_pos suggest_name =
333 add_list [pos, "Could not find "^(strip_ns name) ;
334 suggest_pos, "Did you mean "^(strip_ns suggest_name)^"?"]
336 let previous_default p =
337 add p
338 ("A previous parameter has a default value.\n"^
339 "Remove all the default values for the preceding parameters,\n"^
340 "or add a default value to this one.")
342 let void_parameter p =
343 add p "Cannot have a void parameter"
345 let nullable_parameter pos =
346 add pos "Please add a ?, this argument can be null"
348 let return_in_void p1 p2 =
349 add_list [
351 "You cannot return a value";
353 "This is a void function"
356 let this_in_static p =
357 add p "Don't use $this in a static method"
359 let this_outside_class p =
360 add p "Can't use $this outside of a class"
362 let unbound_global cst_pos =
363 add cst_pos "Unbound global constant (Typing)"
365 let private_inst_meth method_pos p =
366 add_list [
367 method_pos, "This is a private method";
368 p, "you cannot use it with inst_meth (whether you are in the same class or not)."
371 let protected_inst_meth method_pos p =
372 add_list [
373 method_pos, "This is a protected method";
374 p, "you cannot use it with inst_meth (whether you are in the same class hierarchy or not)."
377 let private_class_meth p1 p2 =
378 add_list [
379 p1, "This is a private method";
380 p2, "you cannot use it with class_meth (whether you are in the same class or not)."
383 let protected_class_meth p1 p2 =
384 add_list [
385 p1, "This is a protected method";
386 p2, "you cannot use it with class_meth (whether you are in the same class hierarchy or not)."
389 let array_cast p =
390 add p "(array) cast forbidden in strict mode; arrays with unspecified \
391 key and value types are not allowed"
393 let anonymous_recursive p =
394 add p "Anonymous functions cannot be recursive"
396 let new_static_outside_class p =
397 add p "Can't use new static() outside of a class"
399 let new_self_outside_class p =
400 add p "Can't use new self() outside of a class"
402 let abstract_instantiate p cname =
403 add p ("Can't instantiate " ^ Utils.strip_ns cname)
405 let pair_arity p =
406 add p "A pair has exactly 2 elements"
408 let tuple_arity p2 size2 p1 size1 =
409 add_list [
410 p2, "This tuple has "^ string_of_int size2^" elements";
411 p1, string_of_int size1 ^ " were expected"]
413 let undefined_parent pos =
414 add pos "The parent class is undefined"
416 let parent_construct_in_trait pos =
417 add pos "Don't call parent::__construct from a trait"
419 let parent_outside_class pos =
420 add pos "parent is undefined outside of a class"
422 let dont_use_isset p =
423 add p "Don't use isset!"
425 let array_get_arity p1 name p2 =
426 add_list [
427 p1, "You cannot use this "^(Utils.strip_ns name);
428 p2, "It is missing its type parameters"
431 let static_overflow p =
432 add p "Static integer overflow"
434 let typing_error p msg =
435 add p msg
437 let typing_error_l err =
438 add_error err
440 let undefined_field p name =
441 add p ("The field "^name^" is undefined")
443 let shape_access p =
444 add p "Was expecting a constant string (for shape access)"
446 let array_access p1 p2 ty =
447 add_list ((p1, "This is not a container, this is "^ty) ::
448 if p2 != Pos.none
449 then [p2, "You might want to check this out"]
450 else [])
452 let array_append p1 p2 ty =
453 add_list ((p1, ty^" does not allow array append") ::
454 if p2 != Pos.none
455 then [p2, "You might want to check this out"]
456 else [])
458 let const_mutation p1 p2 ty =
459 add_list ((p1, "You cannot mutate this") ::
460 if p2 != Pos.none
461 then [(p2, "This is " ^ ty)]
462 else [])
464 let negative_tuple_index p =
465 add p "You cannot use a negative value here"
467 let tuple_index_too_large p =
468 add p "Cannot access this field"
470 let expected_static_int p =
471 add p "Please use a static integer"
473 let expected_class p =
474 add p "Was expecting a class"
476 let snot_found_hint = function
477 | `no_hint ->
479 | `closest (pos, v) ->
480 [pos, "The closest thing is "^v^" but it's not a static method"]
481 | `did_you_mean (pos, v) ->
482 [pos, "Did you mean: "^v]
484 let string_of_class_member_kind = function
485 | `class_constant -> "class constant"
486 | `static_method -> "static method"
487 | `class_variable -> "class variable"
489 let smember_not_found kind pos member_name hint =
490 let kind = string_of_class_member_kind kind in
491 add_list ((pos, "Could not find "^kind^" "^member_name)
492 :: snot_found_hint hint)
494 let not_found_hint = function
495 | `no_hint ->
497 | `closest (pos, v) ->
498 [pos, "The closest thing is "^v^" but it's a static method"]
499 | `did_you_mean (pos, v) ->
500 [pos, "Did you mean: "^v]
502 let member_not_found kind pos (cpos, class_name) member_name hint =
503 let kind =
504 match kind with
505 | `method_ -> "method "
506 | `member -> "member "
508 let msg = "The "^kind^member_name^" is undefined "
509 ^"in an object of type "^(strip_ns class_name)
511 add_list
512 ((pos, msg) :: (cpos, "Check this out") ::
513 not_found_hint hint)
515 let parent_in_trait p =
516 add p
517 ("parent:: inside a trait is undefined"
518 ^" without 'require extends' of a class defined in <?hh")
520 let parent_undefined p =
521 add p "parent is undefined"
523 let constructor_no_args p =
524 add p "This constructor expects no argument"
526 let visibility p msg1 p_vis msg2 =
527 add_list [p, msg1; p_vis, msg2]
529 let typing_too_many_args pos pos_def =
530 add_list [pos, "Too many arguments"; pos_def, "Definition is here"]
532 let typing_too_few_args pos pos_def =
533 add_list [pos, "Too few arguments"; pos_def, "Definition is here"]
535 let anonymous_recursive_call pos =
536 add pos "recursive call to anonymous function"
538 let bad_call p ty =
539 add p ("This call is invalid, this is not a function, it is "^ty)
541 let sketchy_null_check p =
542 add p ("You are using a sketchy null check ...\n"^
543 "Use is_null, or $x === null instead")
545 let sketchy_null_check_primitive p =
546 add p
547 ("You are using a sketchy null check on a primitive type ...\n"^
548 "Use is_null, or $x === null instead")
550 let extend_final position =
551 add position "You cannot extend a class declared as final"
553 let read_before_write (p, v) =
554 add p (
556 "Read access to $this->"; v; " before initialization"
559 let interface_final pos =
560 add pos "Interfaces cannot be final"
562 let abstract_class_final pos =
563 add pos "Abstract classes cannot be final"
565 let trait_final pos =
566 add pos "Traits cannot be final"
568 let implement_abstract p1 p2 x =
569 let s_meth = "abstract method "^x in
570 add_list [p1, "This class must provide an implementation for the "^s_meth;
571 p2, "The "^s_meth^" is defined here"]
573 let generic_static p x =
574 add p ("This static variable cannot use the type parameter "^x^".")
576 let fun_too_many_args p1 p2 =
577 add_list [p1, "Too many mandatory arguments";
578 p2, "Because of this definition"]
580 let fun_too_few_args p1 p2 =
581 add_list [p1, "Too few arguments";
582 p2, "Because of this definition"]
584 let fun_unexpected_nonvariadic p1 p2 =
585 add_list [p1, "Should have a variadic argument";
586 p2, "Because of this definition"]
588 let fun_variadicity_hh_vs_php56 p1 p2 =
589 add_list [p1, "Variadic arguments: ...-style is not a subtype of ...$args";
590 p2, "Because of this definition"]
592 let expected_tparam pos n =
593 add pos ("Expected " ^
594 (match n with
595 | 0 -> "no type parameter"
596 | 1 -> "a type parameter"
597 | n -> string_of_int n ^ " type parameters"
600 let field_missing k p1 p2 =
601 add_list [p2, "The field '"^k^"' is defined";
602 p1, "The field '"^k^"' is missing"]
604 let object_string p1 p2 =
605 add_list [
606 p1, "You cannot use this object as a string";
607 p2, "This object doesn't implement __toString"]
609 let type_param_arity pos x n =
610 add pos ("The type "^x^" expects "^n^" parameters")
612 let cyclic_typedef p =
613 add p "Cyclic typedef"
615 let type_arity_mismatch p1 n1 p2 n2 =
616 add_list [p1, "This type has "^n1^" arguments";
617 p2, "This one has "^n2]
619 let this_final id p2 (error: error) =
620 let n = Utils.strip_ns (snd id) in
621 let message1 = "Since "^n^" is not final" in
622 let message2 = "this might not be a "^n in
623 add_list (error @ [(fst id, message1); (p2, message2)])
625 let tuple_arity_mismatch p1 n1 p2 n2 =
626 add_list [p1, "This tuple has "^n1^" elements";
627 p2, "This one has "^n2^" elements"]
629 let fun_arity_mismatch p1 p2 =
630 add_list [p1, "Number of arguments doesn't match";
631 p2, "Because of this definition"]
633 let discarded_awaitable p1 p2 =
634 add_list [
635 p1, "This expression is of type Awaitable, but it's "^
636 "either being discarded or used in a dangerous way before "^
637 "being awaited";
638 p2, "This is why I think it is Awaitable"
641 let gena_expects_array p1 p2 ty_str =
642 add_list [
643 p1, "gena expects an array";
644 p2, "It is incompatible with " ^ ty_str;
647 let unify_error left right =
648 add_list (left @ right)
650 let static_dynamic static_position dyn_position method_name =
651 let msg_static = "The function "^method_name^" is static" in
652 let msg_dynamic = "It is defined as dynamic here" in
653 add_list [static_position, msg_static; dyn_position, msg_dynamic]
655 let null_member s p r =
656 add_list ([
658 "You are trying to access the member "^s^
659 " but this object can be null. "
660 ] @ r
663 let non_object_member s p1 ty p2 =
664 add_list [p1,
665 ("You are trying to access the member "^s^
666 " but this is not an object, it is "^
667 ty);
669 "Check this out"]
671 let null_container p null_witness =
672 add_list (
675 "You are trying to access an element of this container"^
676 " but the container could be null. "
677 ] @ null_witness)
679 let option_mixed pos =
680 add pos "?mixed is a redundant typehint - just use mixed"
682 (*****************************************************************************)
683 (* Typing decl errors *)
684 (*****************************************************************************)
686 let wrong_extend_kind child_pos child parent_pos parent =
687 let msg1 = child_pos, child^" cannot extend "^parent in
688 let msg2 = parent_pos, "This is "^parent in
689 add_list [msg1; msg2]
691 let unsatisfied_req parent_pos req_name req_pos =
692 let s1 = "Failure to satisfy requirement: "^(Utils.strip_ns req_name) in
693 let s2 = "Required here" in
694 if req_pos = parent_pos then add parent_pos s1
695 else add_list [parent_pos, s1; req_pos, s2]
697 let cyclic_class_def stack pos =
698 let stack = SSet.fold (fun x y -> (Utils.strip_ns x)^" "^y) stack "" in
699 add pos ("Cyclic class definition : "^stack)
701 let override_final ~parent ~child =
702 add_list [child, "You cannot override this method";
703 parent, "It was declared as final"]
705 let should_be_override pos class_id id =
706 add pos
707 ((Utils.strip_ns class_id)^"::"^id^"() is marked as override; \
708 no non-private parent definition found \
709 or overridden parent is defined in non-<?hh code")
711 let override_per_trait class_name id m_pos =
712 let c_pos, c_name = class_name in
713 let err_msg =
714 ("Method "^(Utils.strip_ns c_name)^"::"^id^" is should be an override \
715 per the declaring trait; no non-private parent definition found \
716 or overridden parent is defined in non-<?hh code")
717 in add_list [
718 c_pos, err_msg;
719 m_pos, "Declaration of "^id^"() is here"
722 let missing_assign pos =
723 add pos "Please assign a value"
725 let private_override pos class_id id =
726 add pos ((Utils.strip_ns class_id)^"::"^id
727 ^": combining private and override is nonsensical")
729 (*****************************************************************************)
730 (* Init check errors *)
731 (*****************************************************************************)
733 let no_construct_parent p =
734 add p (sl["You are extending a class that needs to be initialized\n";
735 "Make sure you call parent::__construct.\n"
738 let not_initialized (p, c) =
739 if c = "parent::__construct" then no_construct_parent p else
740 add p (sl[
741 "The class member "; c;" is not always properly initialized\n";
742 "Make sure you systematically set $this->"; c;
743 " when the method __construct is called\n";
744 "Alternatively, you can define the type as optional (?...)\n"
747 let call_before_init p cv =
748 add p (
749 sl([
750 "Until the initialization of $this is over,";
751 " you can only call private methods\n";
752 "The initialization is not over because ";
754 if cv = "parent::__construct"
755 then ["you forgot to call parent::__construct"]
756 else ["$this->"; cv; " can still potentially be null"])
759 (*****************************************************************************)
760 (* Nast errors check *)
761 (*****************************************************************************)
763 let type_arity pos name nargs =
764 add pos
765 (sl ["The type ";(Utils.strip_ns name);" expects ";nargs;" type parameter(s)"])
767 let abstract_outside (p, _) =
768 add p
769 "This method is declared as abstract, in a class that isn't"
771 let invalid_req_implements p =
772 add p "Only traits may use 'require implements'"
774 let invalid_req_extends p =
775 add p "Only traits and interfaces may use 'require extends'"
777 let interface_with_body (p, _) =
778 add p
779 "A method cannot have a body in an interface"
781 let abstract_with_body (p, _) =
782 add p
783 "This method is declared as abstract, but has a body"
785 let not_abstract_without_body (p, _) =
786 add p
787 "This method is not declared as abstract, it must have a body"
789 let return_in_gen p =
790 add p
791 ("Don't use return in a generator (a generator"^
792 " is a function that uses yield)")
794 let return_in_finally p =
795 add p
796 ("Don't use return in a finally block;"^
797 " there's nothing to receive the return value")
799 let yield_in_async_function p =
800 add p
801 "Don't use yield in an async function"
803 let await_in_sync_function p =
804 add p
805 "await can only be used inside async functions"
807 let magic (p, s) =
808 add p
809 ("Don't call "^s^" it's one of these magic things we want to avoid")
811 let non_interface (p : Pos.t) (c2: string) (verb: string): 'a =
812 add p ("Cannot " ^ verb ^ " " ^ (strip_ns c2) ^ " - it is not an interface")
814 let toString_returns_string pos =
815 add pos "__toString should return a string"
817 let toString_visibility pos =
818 add pos "__toString must have public visibility and cannot be static"
820 let uses_non_trait (p: Pos.t) (n: string) (t: string) =
821 add p ((Utils.strip_ns n) ^ " is not a trait. It is " ^ t ^ ".")
823 let requires_non_class (p: Pos.t) (n: string) (t: string) =
824 add p ((Utils.strip_ns n) ^ " is not a class. It is " ^ t ^ ".")
826 let abstract_body pos =
827 add pos "This method shouldn't have a body"
829 let not_public_interface pos =
830 add pos "Access type for interface method must be public"
832 let interface_with_member_variable pos =
833 add pos "Interfaces cannot have member variables"
835 let interface_with_static_member_variable pos =
836 add pos "Interfaces cannot have static variables"
838 let dangerous_method_name p =
839 add p ("This is a dangerous method name, "^
840 "if you want to define a constructor, use "^
841 "__construct")
843 (*****************************************************************************)
844 (* Nast terminality *)
845 (*****************************************************************************)
847 let case_fallthrough p1 p2 =
848 add_list [
849 p1, ("This switch has a case that implicitly falls through and is "^
850 "not annotated with // FALLTHROUGH");
851 p2, "This case implicitly falls through"
854 let default_fallthrough p =
855 add p
856 ("This switch has a default case that implicitly falls "^
857 "through and is not annotated with // FALLTHROUGH")
859 (*****************************************************************************)
860 (* Typing inheritance *)
861 (*****************************************************************************)
863 let visibility_extends vis pos parent_pos parent_vis =
864 let msg1 = pos, "This member visibility is: " ^ vis in
865 let msg2 = parent_pos, parent_vis ^ " was expected" in
866 add_list [msg1; msg2]
868 let member_not_implemented member_name parent_pos pos defn_pos =
869 let msg1 = pos, "This object doesn't implement the method "^member_name in
870 let msg2 = parent_pos, "Which is required by this interface" in
871 let msg3 = defn_pos, "As defined here" in
872 add_list [msg1; msg2; msg3]
874 let override parent_pos parent_name pos name (error: error) =
875 let msg1 = pos, ("This object is of type "^(strip_ns name)) in
876 let msg2 = parent_pos,
877 ("It is incompatible with this object of type "^(strip_ns parent_name)^
878 "\nbecause some of their methods are incompatible."^
879 "\nRead the following to see why:"
880 ) in
881 (* This is a cascading error message *)
882 add_list (msg1 :: msg2 :: error)
884 let missing_constructor pos =
885 add pos "The constructor is not implemented"
887 (*****************************************************************************)
888 (* Enum checking *)
889 (*****************************************************************************)
891 let typedef_trail_entry pos = pos, "Typedef definition comes from here"
893 let add_with_trail errs trail =
894 add_list (errs @ List.map typedef_trail_entry trail)
896 let enum_constant_type_bad pos ty_pos ty trail =
897 add_with_trail
898 [pos, "Enum constants must be an int or string";
899 ty_pos, "Not " ^ ty]
900 trail
902 let enum_type_bad pos ty trail =
903 add_with_trail
904 [pos, "Enums must have int, string, or mixed type, not " ^ ty]
905 trail
907 let enum_type_typedef_mixed pos =
908 add pos "Can't use typedef that resolves to mixed in Enum"
910 (*****************************************************************************)
911 (* Shape checking *)
912 (*****************************************************************************)
913 let invalid_shape_field_name p =
914 add p
915 "Was expecting a constant string or class constant (for shape access)"
917 let invalid_shape_field_type pos ty_pos ty trail =
918 add_with_trail
919 [pos, "A shape field name must be an int or string";
920 ty_pos, "Not " ^ ty]
921 trail
923 let invalid_shape_field_literal key_pos witness_pos =
924 add_list [key_pos, "Shape uses literal string as field name";
925 witness_pos, "But expected a class constant"]
927 let invalid_shape_field_const key_pos witness_pos =
928 add_list [key_pos, "Shape uses class constant as field name";
929 witness_pos, "But expected a literal string"]
931 let shape_field_class_mismatch key_pos witness_pos key_class witness_class =
932 add_list
933 [key_pos, "Shape field name is class constant from " ^ key_class;
934 witness_pos, "But expected constant from " ^ witness_class]
936 let shape_field_type_mismatch key_pos witness_pos key_ty witness_ty =
937 add_list
938 [key_pos, "Shape field name is " ^ key_ty ^ " class constant";
939 witness_pos, "But expected " ^ witness_ty]
941 (*****************************************************************************)
942 (* Printing *)
943 (*****************************************************************************)
945 let to_json (e : error) = Hh_json.(
946 let elts = List.map (fun (p, w) ->
947 let line, scol, ecol = Pos.info_pos p in
948 JAssoc [ "descr", JString w;
949 "path", JString p.Pos.pos_file;
950 "line", JInt line;
951 "start", JInt scol;
952 "end", JInt ecol
956 JAssoc [ "message", JList elts ]
959 let to_string (e : error) : string =
960 let buf = Buffer.create 50 in
961 (match e with
962 | [] -> assert false
963 | (pos1, msg1) :: rest_of_error ->
964 Buffer.add_string buf begin
965 Printf.sprintf "%s\n%s\n" (Pos.string pos1) msg1
966 end;
967 List.iter begin fun (p, w) ->
968 let msg = Printf.sprintf "%s\n%s\n" (Pos.string p) w in
969 Buffer.add_string buf msg
970 end rest_of_error
972 Buffer.contents buf
974 (*****************************************************************************)
975 (* Try if errors. *)
976 (*****************************************************************************)
978 let try_ f1 f2 =
979 let error_list_copy = !error_list in
980 error_list := [];
981 let result = f1 () in
982 let errors = !error_list in
983 error_list := error_list_copy;
984 match List.rev errors with
985 | [] -> result
986 | l :: _ -> f2 l
988 let try_with_error f1 f2 =
989 try_ f1 (fun err -> add_error err; f2())
991 let try_add_err pos err f1 f2 =
992 try_ f1 begin fun l ->
993 add_list ((pos, err) :: l);
994 f2()
997 (*****************************************************************************)
998 (* Do. *)
999 (*****************************************************************************)
1001 let do_ f =
1002 let error_list_copy = !error_list in
1003 error_list := [];
1004 let result = f () in
1005 let out_errors = !error_list in
1006 error_list := error_list_copy;
1007 List.rev out_errors, result
1009 let try_when f ~when_ ~do_ =
1010 try_ f begin fun (error: error) ->
1011 if when_()
1012 then do_ error
1013 else add_error error