Represent empty position ranges as single character ranges when giving them to the...
commit5bb2000a593fdd40d76a40441bfbd503e589328c
authorJames Wu <jjwu@fb.com>
Fri, 3 Aug 2018 01:30:29 +0000 (2 18:30 -0700)
committerHhvm Bot <hhvm-bot@users.noreply.github.com>
Fri, 3 Aug 2018 01:41:49 +0000 (2 18:41 -0700)
treed6576a5eac36e01ad2319030281f2d9978b04b5c
parentc2b4b21692858a22bd6df0f6193532b79c4bd978
Represent empty position ranges as single character ranges when giving them to the user

Summary:
In the typechecker, we represent position ranges as [start, end) (that is, inclusive, exclusive). But when we want to go print them out to the user, we give them [start, end] (inclusive both sides). This makes it so that IDE behavior is correct, since they use inclusive character ranges.

But sometimes, the FFP will want to represent the empty character range. This is especially common with error messages that say "expected semicolon here", where we want to highlight the ending trivia after a token, but the token has no ending trivia. Then the expected range becomes an empty range.

This is all correct and dandy, *except* it has issues when we print it to the user. We calculate the inclusive range by essentially subtracting one from the end column number; this results in really bizarre error messages for empty ranges, where you would get characters 28-27 or characters 0--1.

To fix this, when we call Pos.info_pos on a character range that is empty, we instead highlight a single character rather than the empty range. This is preferable in all error messages rather than just an empty range, although it has the downside of sometimes looking a bit strange if it highlights only the first character of a token rather than the entire next token.

I could go in and try to make the parser much smarter about reading the next token in the case of empty trivia, but I think that this is a simpler change that still conveys decent error messages to the user.

Reviewed By: vassilmladenov

Differential Revision: D9137731

fbshipit-source-id: c141c007340b360fb4b8fe48e1a34a168d151060
58 files changed:
hphp/hack/src/utils/pos_embedded.ml
hphp/hack/test/typecheck/argument_unpacking/unpack_call10_unset.php.exp
hphp/hack/test/typecheck/argument_unpacking/unpack_call9_empty.php.exp
hphp/hack/test/typecheck/array/disallow_hetergeneous_inputs_for_darray.php.exp
hphp/hack/test/typecheck/array/disallow_hetergeneous_inputs_for_varray.php.exp
hphp/hack/test/typecheck/array/disallow_key_value_inputs_for_varray.php.exp
hphp/hack/test/typecheck/array/disallow_one_type_parameter_for_darray.php.exp
hphp/hack/test/typecheck/array/disallow_value_inputs_for_darray.php.exp
hphp/hack/test/typecheck/bad_function_hint2.php.exp
hphp/hack/test/typecheck/conditional_class_decl.php.exp
hphp/hack/test/typecheck/constraints/bad_contra_constraint.php.exp
hphp/hack/test/typecheck/constraints/constraint_override_bad.php.exp
hphp/hack/test/typecheck/constraints/constraint_override_bad2.php.exp
hphp/hack/test/typecheck/constructor_method_call.php.exp
hphp/hack/test/typecheck/decl_unclosed_xhp_nested.php.exp
hphp/hack/test/typecheck/dict_literal_mixed_brace.php.exp
hphp/hack/test/typecheck/dict_literal_mixed_brace2.php.exp
hphp/hack/test/typecheck/elseif3.php.exp
hphp/hack/test/typecheck/ffp/invalid_foreach_arrow1.php.exp
hphp/hack/test/typecheck/ffp/invalid_foreach_arrow2.php.exp
hphp/hack/test/typecheck/ffp/tuple_hints_broken.php.exp
hphp/hack/test/typecheck/fun_no_ret.php.exp
hphp/hack/test/typecheck/gen4.php.exp
hphp/hack/test/typecheck/goto_double_label.php.exp
hphp/hack/test/typecheck/goto_label_mid_statement.php.exp
hphp/hack/test/typecheck/heredoc_missing_end.php.exp
hphp/hack/test/typecheck/incorrect_darray.php.exp
hphp/hack/test/typecheck/lambda/lambda02.php.exp
hphp/hack/test/typecheck/legacy/heredoc_missing_identifier.php.exp
hphp/hack/test/typecheck/loop_forever_switch.php.exp
hphp/hack/test/typecheck/not_cast.php.exp
hphp/hack/test/typecheck/parse_error_visibility2.php.exp
hphp/hack/test/typecheck/parse_error_visibility3.php.exp
hphp/hack/test/typecheck/shape_type.php.exp
hphp/hack/test/typecheck/shape_typedef_with_multiple_optional_tokens.php.exp
hphp/hack/test/typecheck/shape_typedef_with_unknown_fields_not_at_end.php.exp
hphp/hack/test/typecheck/shape_usage_with_optional_field.php.exp
hphp/hack/test/typecheck/string_expressions17.php.exp
hphp/hack/test/typecheck/suggest_method_name.php.exp
hphp/hack/test/typecheck/suggest_method_name2.php.exp
hphp/hack/test/typecheck/suggest_method_name3.php.exp
hphp/hack/test/typecheck/typing_fail_abstract_method2.php.exp
hphp/hack/test/typecheck/typing_fail_cast.php.exp
hphp/hack/test/typecheck/typing_fail_list.php.exp
hphp/hack/test/typecheck/typing_fail_return_option.php.exp
hphp/hack/test/typecheck/typing_fail_string_null.php.exp
hphp/hack/test/typecheck/typing_fail_test.php.exp
hphp/hack/test/typecheck/typing_fail_visibility.php.exp
hphp/hack/test/typecheck/typing_fail_xhp.php.exp
hphp/hack/test/typecheck/unassigned_tconst.php.exp
hphp/hack/test/typecheck/using/using_as_function_name.php.exp
hphp/hack/test/typecheck/variadic_args7.php.exp
hphp/hack/test/typecheck/very_long_lines.php.exp
hphp/hack/test/typecheck/void_is_type_of_null/void_usage_2.php.exp
hphp/hack/test/typecheck/void_usage_2.php.exp
hphp/hack/test/typecheck/xhp_attr_11.php.exp
hphp/hack/test/unit/utils/diagnostic_subscription_test.ml
hphp/hack/test/unit/utils/errors_test.ml