From b3517c7f93bf57b0100b8285b132d38ec1995064 Mon Sep 17 00:00:00 2001 From: Corentin Machu Date: Thu, 4 Jul 2024 16:55:50 +0200 Subject: [PATCH] Improve format of error when type is not compatible Ref. eng/recordflux/RecordFlux#1720 --- rflx/typing_.py | 19 ++-- tests/integration/specification_model_test.py | 92 ++++++++++++++++++- tests/unit/expr_test.py | 36 ++++---- tests/unit/model/message_test.py | 20 ++-- tests/unit/model/session_test.py | 24 ++--- tests/unit/typing__test.py | 8 +- 6 files changed, 145 insertions(+), 54 deletions(-) diff --git a/rflx/typing_.py b/rflx/typing_.py index a5f8f7e2a..fe4e7ecd6 100644 --- a/rflx/typing_.py +++ b/rflx/typing_.py @@ -397,13 +397,16 @@ def check_type( f"expected {desc}", Severity.ERROR, location, - annotations=[ - Annotation( - f"found {actual}", - Severity.NOTE, - location, - ), - ], + annotations=( + [ + Annotation( + f"found {actual}", + Severity.ERROR, + location, + ), + ] + ), + generate_default_annotation=False, ), ) @@ -435,7 +438,7 @@ def check_type_instance( f"expected {desc}", Severity.ERROR, location, - annotations=[Annotation(f"found {actual}", Severity.NOTE, location)], + annotations=[Annotation(f"found {actual}", Severity.ERROR, location)], generate_default_annotation=False, ), ) diff --git a/tests/integration/specification_model_test.py b/tests/integration/specification_model_test.py index 1a9a76e14..1a549d394 100644 --- a/tests/integration/specification_model_test.py +++ b/tests/integration/specification_model_test.py @@ -1975,8 +1975,96 @@ def test_incompatible_type_link_condition( 5 | with Size => 8 6 | then F2 7 | if F1 = 32; - | ^^ - | -- note: found type universal integer (32) + | ^^ found type universal integer (32) + | + """, + ), + capfd, + ) + + +def test_aggregate_type_in_condition( + tmp_path: Path, + capfd: pytest.CaptureFixture[str], +) -> None: + file_path = tmp_path / "test.rflx" + file_path.write_text( + textwrap.dedent( + """\ + package Test is + type I is range 0 .. 255 with Size => 8; + type M (A : I) is + message + X : Boolean + then Z + if [1, 2, 3] = A; + Z : Opaque + with Size => 8; + end message; + end Test; + """, + ), + ) + assert_error_full_message( + file_path, + textwrap.dedent( + f"""\ + info: Parsing {file_path} + info: Processing Test + info: Verifying __BUILTINS__::Boolean + info: Verifying __INTERNAL__::Opaque + info: Verifying Test::I + info: Verifying Test::M + error: expected aggregate with element type universal integer (1 .. 3) + --> {file_path}:7:31 + | + 5 | X : Boolean + | - note: on path "X" + 6 | then Z + 7 | if [1, 2, 3] = A; + | ^ found integer type "Test::I" (0 .. 255) + | + """, + ), + capfd, + ) + + +def test_aggregate_type_in_size( + tmp_path: Path, + capfd: pytest.CaptureFixture[str], +) -> None: + file_path = tmp_path / "test.rflx" + file_path.write_text( + textwrap.dedent( + """\ + package Test is + type I is range 0 .. 255 with Size => 8; + type M is + message + Z : Opaque + with Size => 1 + [1, 2, 3]; + end message; + end Test; + """, + ), + ) + assert_error_full_message( + file_path, + textwrap.dedent( + f"""\ + info: Parsing {file_path} + info: Processing Test + info: Verifying __BUILTINS__::Boolean + info: Verifying __INTERNAL__::Opaque + info: Verifying Test::I + info: Verifying Test::M + error: expected integer type + --> {file_path}:6:30 + | + 6 | with Size => 1 + [1, 2, 3]; + | ^^^^^^^^^ found aggregate with element type universal \ +integer (1 .. 3) | """, ), diff --git a/tests/unit/expr_test.py b/tests/unit/expr_test.py index 7f6b281e8..1bd0aae31 100644 --- a/tests/unit/expr_test.py +++ b/tests/unit/expr_test.py @@ -133,7 +133,7 @@ def test_not_type_error() -> None: assert_type_error( Not(Variable("X", type_=rty.BaseInteger(), location=Location((10, 20)))), r'^:10:20: error: expected enumeration type "__BUILTINS__::Boolean"\n' - r":10:20: note: found integer type$", + r":10:20: error: found integer type$", ) @@ -402,9 +402,9 @@ def test_bool_expr_type_error(operation: Callable[[Expr, Expr], Expr]) -> None: Number(1, location=Location((10, 30))), ), r'^:10:20: error: expected enumeration type "__BUILTINS__::Boolean"\n' - r':10:20: note: found integer type "A" \(0 .. 100\)\n' + r':10:20: error: found integer type "A" \(0 .. 100\)\n' r':10:30: error: expected enumeration type "__BUILTINS__::Boolean"\n' - r":10:30: note: found type universal integer \(1\)$", + r":10:30: error: found type universal integer \(1\)$", ) @@ -633,9 +633,9 @@ def test_math_expr_type_error(operation: Callable[[Expr, Expr], Expr]) -> None: Variable("True", type_=rty.BOOLEAN, location=Location((10, 30))), ), r"^:10:20: error: expected integer type\n" - r':10:20: note: found enumeration type "__BUILTINS__::Boolean"\n' + r':10:20: error: found enumeration type "__BUILTINS__::Boolean"\n' r":10:30: error: expected integer type\n" - r':10:30: note: found enumeration type "__BUILTINS__::Boolean"$', + r':10:30: error: found enumeration type "__BUILTINS__::Boolean"$', ) @@ -655,7 +655,7 @@ def test_neg_type_error() -> None: assert_type_error( Neg(Variable("X", type_=rty.BOOLEAN, location=Location((10, 20)))), r"^:10:20: error: expected integer type\n" - r':10:20: note: found enumeration type "__BUILTINS__::Boolean"$', + r':10:20: error: found enumeration type "__BUILTINS__::Boolean"$', ) @@ -1173,7 +1173,7 @@ def test_relation_integer_type_error(relation: Callable[[Expr, Expr], Expr]) -> Variable("True", type_=rty.BOOLEAN, location=Location((10, 30))), ), r"^:10:30: error: expected integer type\n" - r':10:30: note: found enumeration type "__BUILTINS__::Boolean"$', + r':10:30: error: found enumeration type "__BUILTINS__::Boolean"$', ) @@ -1197,7 +1197,7 @@ def test_relation_composite_type_error(relation: Callable[[Expr, Expr], Expr]) - ), r"^:10:30: error: expected aggregate" r" with element integer type\n" - r':10:30: note: found enumeration type "__BUILTINS__::Boolean"$', + r':10:30: error: found enumeration type "__BUILTINS__::Boolean"$', ) assert_type_error( relation( @@ -1206,7 +1206,7 @@ def test_relation_composite_type_error(relation: Callable[[Expr, Expr], Expr]) - ), r"^:10:30: error: expected aggregate" r" with element integer type\n" - r':10:30: note: found sequence type "A"' + r':10:30: error: found sequence type "A"' r' with element enumeration type "__BUILTINS__::Boolean"$', ) @@ -1474,9 +1474,9 @@ def test_value_range_type_error() -> None: location=Location((10, 20)), ), r"^:10:30: error: expected integer type\n" - r':10:30: note: found enumeration type "__BUILTINS__::Boolean"\n' + r':10:30: error: found enumeration type "__BUILTINS__::Boolean"\n' r":10:40: error: expected integer type\n" - r':10:40: note: found sequence type "A" with element integer type$', + r':10:40: error: found sequence type "A" with element integer type$', ) @@ -1527,21 +1527,21 @@ def test_quantified_expression_type(expr: Callable[[str, Expr, Expr], Expr]) -> Variable("Y", type_=rty.BOOLEAN, location=Location((10, 30))), Variable("Z", type_=rty.Sequence("A", rty.BaseInteger()), location=Location((10, 40))), r"^:10:30: error: expected composite type\n" - r':10:30: note: found enumeration type "__BUILTINS__::Boolean"\n' + r':10:30: error: found enumeration type "__BUILTINS__::Boolean"\n' r':10:40: error: expected enumeration type "__BUILTINS__::Boolean"\n' - r':10:40: note: found sequence type "A" with element integer type$', + r':10:40: error: found sequence type "A" with element integer type$', ), ( Variable("Y", type_=rty.BOOLEAN, location=Location((10, 30))), Equal(Variable("X"), Number(1)), r"^:10:30: error: expected composite type\n" - r':10:30: note: found enumeration type "__BUILTINS__::Boolean"$', + r':10:30: error: found enumeration type "__BUILTINS__::Boolean"$', ), ( Variable("Y", type_=rty.Sequence("A", rty.BOOLEAN)), Equal(Variable("X"), Number(1, location=Location((10, 30)))), r'^:10:30: error: expected enumeration type "__BUILTINS__::Boolean"\n' - r":10:30: note: found type universal integer \(1\)$", + r":10:30: error: found type universal integer \(1\)$", ), ], ) @@ -1842,7 +1842,7 @@ def test_selected_type() -> None: ( Selected(Variable("X", type_=rty.BOOLEAN, location=Location((10, 20))), "Y"), r"^:10:20: error: expected message type\n" - r':10:20: note: found enumeration type "__BUILTINS__::Boolean"$', + r':10:20: error: found enumeration type "__BUILTINS__::Boolean"$', ), ( Selected( @@ -1949,9 +1949,9 @@ def test_call_type_error() -> None: ], ), r'^:10:30: error: expected enumeration type "__BUILTINS__::Boolean"\n' - r":10:30: note: found integer type\n" + r":10:30: error: found integer type\n" r":10:40: error: expected integer type\n" - r':10:40: note: found enumeration type "__BUILTINS__::Boolean"$', + r':10:40: error: found enumeration type "__BUILTINS__::Boolean"$', ) diff --git a/tests/unit/model/message_test.py b/tests/unit/model/message_test.py index 96d80d167..abd1dd961 100644 --- a/tests/unit/model/message_test.py +++ b/tests/unit/model/message_test.py @@ -1135,7 +1135,7 @@ def test_invalid_relation_to_opaque() -> None: types, r'^:10:20: error: expected sequence type "__INTERNAL__::Opaque"' r' with element integer type "Byte" \(0 .. 255\)\n' - r":10:20: note: found type universal integer \(42\)\n" + r":10:20: error: found type universal integer \(42\)\n" r':1:1: note: on path "Length"\n' r':2:3: note: on path "Data"$', ) @@ -1158,11 +1158,11 @@ def test_invalid_relation_to_aggregate() -> None: structure, types, r"^:10:20: error: expected integer type\n" - r':10:20: note: found sequence type "__INTERNAL__::Opaque"' + r':10:20: error: found sequence type "__INTERNAL__::Opaque"' r' with element integer type "Byte" \(0 .. 255\)\n' r':1:1: note: on path "F1"\n' r":10:30: error: expected integer type\n" - r":10:30: note: found aggregate" + r":10:30: error: found aggregate" r" with element type universal integer \(1 .. 2\)\n" r':1:1: note: on path "F1"$', ) @@ -1186,7 +1186,7 @@ def test_invalid_element_in_relation_to_aggregate(lower: Number) -> None: structure, types, rf'^:10:20: error: expected integer type "P::Integer" \({lower} .. 255\)\n' - r":10:20: note: found aggregate with element type universal integer" + r":10:20: error: found aggregate with element type universal integer" r" \(1 .. 2\)\n" r':1:2: note: on path "F1"$', ) @@ -1214,7 +1214,7 @@ def test_opaque_aggregate_out_of_range() -> None: types, r'^:10:20: error: expected sequence type "__INTERNAL__::Opaque"' r' with element integer type "Byte" \(0 .. 255\)\n' - r":10:20: note: found aggregate" + r":10:20: error: found aggregate" r" with element type universal integer \(1 .. 256\)\n" r':1:2: note: on path "F"$', ) @@ -1247,7 +1247,7 @@ def test_sequence_aggregate_out_of_range() -> None: types, r'^:10:20: error: expected sequence type "P::Sequence"' r' with element integer type "P::Element" \(0 .. 63\)\n' - r":10:20: note: found aggregate" + r":10:20: error: found aggregate" r" with element type universal integer \(1 .. 64\)\n" r':1:2: note: on path "F"$', ) @@ -1285,7 +1285,7 @@ def test_sequence_aggregate_invalid_element_type() -> None: types, r'^:10:20: error: expected sequence type "P::Sequence"' r' with element message type "P::I"\n' - r":10:20: note: found aggregate with element type universal integer" + r":10:20: error: found aggregate with element type universal integer" r" \(1 .. 64\)\n" r':1:2: note: on path "F"$', ) @@ -2062,7 +2062,7 @@ def test_invalid_type_condition_enum() -> None: structure, types, r'^:10:20: error: expected enumeration type "P::E1"\n' - r':10:20: note: found enumeration type "P::E2"\n' + r':10:20: error: found enumeration type "P::E2"\n' r':1:1: note: on path "F1"$', ) @@ -5872,7 +5872,7 @@ def test_merge_message_with_illegal_condition_on_message_type_field() -> None: match=( "^" ':1:2: error: expected enumeration type "__BUILTINS__::Boolean"\n' - r":1:2: note: found type universal integer \(1\)" + r":1:2: error: found type universal integer \(1\)" "$" ), ): @@ -6296,7 +6296,7 @@ def test_refinement_type_error_in_condition() -> None: match=( r"^" r':10:20: error: expected integer type "P::T" \(0 \.\. 255\)\n' - r':10:20: note: found enumeration type "__BUILTINS__::Boolean"' + r':10:20: error: found enumeration type "__BUILTINS__::Boolean"' r"$" ), ): diff --git a/tests/unit/model/session_test.py b/tests/unit/model/session_test.py index b9e94f428..9ad89162f 100644 --- a/tests/unit/model/session_test.py +++ b/tests/unit/model/session_test.py @@ -811,7 +811,7 @@ def test_reset_incompatible() -> None: types=[BOOLEAN], regex=( r"^:10:20: error: expected sequence type or message type\n" - r':10:20: note: found enumeration type "__BUILTINS__::Boolean"$' + r':10:20: error: found enumeration type "__BUILTINS__::Boolean"$' ), ) @@ -911,7 +911,7 @@ def test_call_invalid_argument_type() -> None: regex=( r"^" r':10:20: error: expected enumeration type "__BUILTINS__::Boolean"\n' - r":10:20: note: found readable channel" + r":10:20: error: found readable channel" "$" ), ) @@ -1062,9 +1062,9 @@ def test_channel_read_invalid_type() -> None: r"^" r":10:20: error: channel parameter must be a variable\n" r":10:20: error: expected readable channel\n" - r':10:20: note: found message type "TLV::Message"\n' + r':10:20: error: found message type "TLV::Message"\n' r":10:30: error: expected message type\n" - r":10:30: note: found type universal integer \(0\)" + r":10:30: error: found type universal integer \(0\)" r"$" ), ) @@ -1092,7 +1092,7 @@ def test_channel_read_invalid_mode() -> None: regex=( r"^" r":10:20: error: expected readable channel\n" - r":10:20: note: found writable channel" + r":10:20: error: found writable channel" r"$" ), ) @@ -1120,7 +1120,7 @@ def test_channel_write_invalid_mode() -> None: regex=( r"^" r":10:20: error: expected writable channel\n" - r":10:20: note: found readable channel" + r":10:20: error: found readable channel" r"$" ), ) @@ -1463,7 +1463,7 @@ def test_append_incompatible() -> None: types=[BOOLEAN], regex=( r"^:10:20: error: expected sequence type\n" - r':10:20: note: found enumeration type "__BUILTINS__::Boolean"$' + r':10:20: error: found enumeration type "__BUILTINS__::Boolean"$' ), ) @@ -1533,7 +1533,7 @@ def test_extend_incompatible() -> None: types=[BOOLEAN], regex=( r"^:10:20: error: expected sequence type\n" - r':10:20: note: found enumeration type "__BUILTINS__::Boolean"$' + r':10:20: error: found enumeration type "__BUILTINS__::Boolean"$' ), ) @@ -1770,7 +1770,7 @@ def test_message_field_assignment_with_incompatible_field_type() -> None: regex=( r"^" r':1:2: error: expected enumeration type "TLV::Tag"\n' - r":1:2: note: found type universal integer \(42\)" + r":1:2: error: found type universal integer \(42\)" r"$" ), ) @@ -1801,7 +1801,7 @@ def test_message_field_assignment_with_incompatible_variable_type() -> None: regex=( r"^" r":1:2: error: expected message type\n" - r':1:2: note: found enumeration type "TLV::Tag"' + r':1:2: error: found enumeration type "TLV::Tag"' r"$" ), ) @@ -2081,7 +2081,7 @@ def test_type_error_in_variable_declaration() -> None: regex=( r"^" r':10:20: error: expected enumeration type "__BUILTINS__::Boolean"\n' - r":10:20: note: found type universal integer \(1\)" + r":10:20: error: found type universal integer \(1\)" r"$" ), ) @@ -2116,7 +2116,7 @@ def test_type_error_in_renaming_declaration() -> None: regex=( r"^" r":10:20: error: expected message type\n" - r":10:20: note: found type universal integer \(1\)" + r":10:20: error: found type universal integer \(1\)" r"$" ), ) diff --git a/tests/unit/typing__test.py b/tests/unit/typing__test.py index 6dd68ea55..030a2b79f 100644 --- a/tests/unit/typing__test.py +++ b/tests/unit/typing__test.py @@ -700,13 +700,13 @@ def test_check_type(actual: Type, expected: Type) -> None: Message("A"), Channel(readable=False, writable=True), r"^:10:20: error: expected writable channel\n" - r':10:20: note: found message type "A"$', + r':10:20: error: found message type "A"$', ), ( BaseInteger(), Message("A"), r'^:10:20: error: expected message type "A"\n' - r":10:20: note: found integer type$", + r":10:20: error: found integer type$", ), ( Undefined(), @@ -743,13 +743,13 @@ def test_check_type_instance( Message("M"), Channel, r"^:10:20: error: expected channel\n" - r':10:20: note: found message type "M"$', + r':10:20: error: found message type "M"$', ), ( BaseInteger(), (Sequence, Message), r"^:10:20: error: expected sequence type or message type\n" - r":10:20: note: found integer type$", + r":10:20: error: found integer type$", ), ( Undefined(),