Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Detect duplicate messages and channels aspects #930

Closed
wants to merge 3 commits into from
Closed

Conversation

mhadhbir
Copy link

@mhadhbir mhadhbir commented Feb 9, 2022

xCloses #714

This commit introduces extra checks to avoid duplicate aspects for messages and channels.

Closes #714
rflx/specification/parser.py Outdated Show resolved Hide resolved
tests/unit/specification/parser_test.py Outdated Show resolved Hide resolved
@@ -533,10 +533,23 @@ def create_channel_decl(
filename: Path,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please also have a look at other uses of aspects. For example, messages can have Checksum aspects and transitions in sessions can have Desc aspects. Maybe we have the same issue there.

See #714 (comment).

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about the Desc aspect mentioned above? Please add a unit test, even if a duplicate aspect is already detected (even as a syntax error).

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't do anything for Desc as I think the code doesn't allow more than one Desc anyway, so I don't think it is necessary to add a test for this as I didn't implement it.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Even if it is not possible to have duplicate Desc aspects at the moment, this doesn't mean that this cannot be the case in the future. Unit test are used to prevent regressions. That is why it still makes sense to add a unit test, even if you did not change anything.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

test added.

Comment on lines 1958 to 2031
def test_parse_error_duplicate_channel_aspect_readable() -> None:
assert_error_string(
"""
package Test is

type M is
message
B : Opaque
with Size => 8;
end message;

generic
Channel : Channel with Readable, Writable, Readable;
session Session with
Initial => Start,
Final => Terminated
is
Message : M;
begin
state Start is
begin
Channel'Read (Message);
transition
goto Reply
if Message'Valid
goto Terminated
end Start;

state Reply is
begin
Channel'Write (Message);
transition
goto Terminated
end Reply;

state Terminated is null state;
end Session;

end Test;
""",
r'^<stdin>:11:62: parser: error: duplicate aspect "Readable"',
)


def test_parse_error_duplicate_channel_aspect_writable() -> None:
assert_error_string(
"""
package Test is

type M is
message
B : Opaque
with Size => 8;
end message;

generic
Channel : Channel with Readable, Writable, Writable;
session Session with
Initial => Start,
Final => Terminated
is
Message : M;
begin
state Start is
begin
Channel'Read (Message);
transition
goto Reply
if Message'Valid
goto Terminated
end Start;

state Reply is
begin
Channel'Write (Message);
transition
goto Terminated
end Reply;

state Terminated is null state;
end Session;

end Test;
""",
r'^<stdin>:11:62: parser: error: duplicate aspect "Writable"',
)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Duplicate code can be avoided by using @pytest.mark.parametrize.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

Comment on lines +2095 to +2087
Byte_Order => Low_Order_First,
Byte_Order => Low_Order_First;
end Test;
""",
r'^<stdin>:18:27: parser: error: duplicate aspect "ByteOrderAspect"',
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The aspect is called Byte_Order, not ByteOrderAspect.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's what the error message generates.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Then the error message needs to be changed.

Copy link
Author

@mhadhbir mhadhbir Feb 17, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That means changing aspect.kind_name, if you don't like the message I suggest you open a ticket to change the attribute _kind_name of the class ByteOrderAspect from librflxlang.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changing kind_name is not possible. Please find another solution.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In that case I think the error message should stay the same to keep the code consistent then.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The error messages are intended for users of the tool. Having a error message mentioning "ByteOrderAspect", while the aspect is actually called "Byte_Order" in the specification, is confusing. Keeping the code as it as, just because it is easier, is no option here.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

First, I don't think ByteOrderAspect is confusing, it literally literally has Byte Order and Aspect in it. and I already proposed a solution to change kind_name if you don't like the exact wording. I don't see another way to do it.

@@ -218,9 +219,10 @@ def create_session(
session: lang.SessionDecl,
package: ID,
filename: Path,
error: RecordFluxError,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All create_* functions, which had an error parameter before, had this as the first parameter. Could you please make that consistent to the existing code? A consistent order of parameters is especially relevant when function pointers are used, which is done in several cases here. I also would like to prevent confusions in the future.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

Comment on lines 1198 to 1220
checksum_parsed = False
checksum_result = {}
byte_order_parsed = False
byte_order_result = None
for aspect in aspects:
if isinstance(aspect, lang.ChecksumAspect):
if (isinstance(aspect, lang.ChecksumAspect) and checksum_parsed) or (
isinstance(aspect, lang.ByteOrderAspect) and byte_order_parsed
):
error.extend(
[
(
f'duplicate aspect "{aspect.kind_name}"',
Subsystem.PARSER,
Severity.ERROR,
node_location(aspect, filename),
)
],
)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are checksum_parsed and byte_order_parsed required? Couldn't just checksum_result and byte_order_result be used?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not really, fixed

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

using checksum_result is causing mypy to raise typing errors, I am putting checksum_parsed back

Comment on lines 1321 to 1381
raise NotImplementedError(
f"Enumeration kind {enumeration.f_elements.kind_name} unsupported"
)
raise NotImplementedError(f"Enmeration kind {enumeration.f_elements.kind_name} unsupported")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A typo is added here: Enmeration.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

Comment on lines 41 to 48
def parse_formal_declaration(data: str) -> decl.Declaration:
parser_declaration, filename = parse(data, lang.GrammarRule.session_parameter_rule)
assert isinstance(parser_declaration, lang.FormalDecl)
declaration = create_formal_declaration(parser_declaration, ID("Package"), filename)
error = RecordFluxError()
declaration = create_formal_declaration(parser_declaration, ID("Package"), filename, error)
assert isinstance(declaration, decl.Declaration)
return declaration
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

error.propagate() should be called after create_*, otherwise any error in create_* will be just ignored.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

Comment on lines 63 to 66
if diagnostics_to_error(unit.diagnostics, error, STDIN):
error.propagate()
assert isinstance(unit.root, lang.SessionDecl)
return create_session(unit.root, ID("Package"), Path("<stdin>"))
return create_session(unit.root, ID("Package"), Path("<stdin>"), error)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

error.propagate() should be called after create_*, otherwise any error in create_* will be just ignored.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

@@ -73,7 +74,7 @@ def parse_unproven_session(string: str) -> model.UnprovenSession:
if diagnostics_to_error(unit.diagnostics, error, STDIN):
error.propagate()
assert isinstance(unit.root, lang.SessionDecl)
return create_unproven_session(unit.root, ID("Package"), Path("<stdin>"))
return create_unproven_session(unit.root, ID("Package"), Path("<stdin>"), error)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

error.propagate() should be called after create_*, otherwise any error in create_* will be just ignored.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

Comment on lines +2114 to +2110
def test_parse_error_duplicate_size_aspect() -> None:
assert_error_string(
"""
package Test is
type T is (A, B) with Size => 12, Size => 10;
end Test;
""",
r'^<stdin>:3:50: parser: error: duplicate aspect "Size"',
)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are duplicate Size aspects also detected for range integers?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The logic of detecting duplicate Size aspects doesn't care about the format of the expression given to the aspect Size, so the answer to your question is Yes.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add a regression test nevertheless.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wouldn't be code duplication as well?

@mhadhbir mhadhbir marked this pull request as ready for review February 18, 2022 11:24
@senier senier closed this Apr 26, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants