diff --git a/aas_core_codegen/python/transpilation.py b/aas_core_codegen/python/transpilation.py index 44acbc6e3..1f2af716c 100644 --- a/aas_core_codegen/python/transpilation.py +++ b/aas_core_codegen/python/transpilation.py @@ -965,6 +965,16 @@ def transform_name( def transform_not( self, node: parse_tree.Not ) -> Tuple[Optional[Stripped], Optional[Error]]: + # NOTE (mristin): + # We rewrite the negated nullness check into ``is not``, as linters such as + # ruff (E714) complain about it. + if isinstance(node.operand, parse_tree.IsNone): + return self.transform_is_not_none( + parse_tree.IsNotNone( + value=node.operand.value, original_node=node.original_node + ) + ) + operand, error = self.transform(node.operand) if error is not None: return None, error diff --git a/dev/test_data/common_meta_models/optional_arguments.py b/dev/test_data/common_meta_models/optional_arguments.py index 6f6d28307..70c83e636 100644 --- a/dev/test_data/common_meta_models/optional_arguments.py +++ b/dev/test_data/common_meta_models/optional_arguments.py @@ -37,6 +37,12 @@ def forwards_text(text: Optional[str]) -> bool: return text_is_not_banned(text) +@verification +def text_is_given(text: Optional[str]) -> bool: + """Check the negated nullness check of the optional argument.""" + return not (text is None) + + @verification def number_is_small(number: Optional[int]) -> bool: """Check the optional integer argument.""" diff --git a/dev/test_data/intermediate/common_meta_models/optional_arguments/expected_symbol_table.txt b/dev/test_data/intermediate/common_meta_models/optional_arguments/expected_symbol_table.txt index ac6cc64f1..efc3f8423 100644 --- a/dev/test_data/intermediate/common_meta_models/optional_arguments/expected_symbol_table.txt +++ b/dev/test_data/intermediate/common_meta_models/optional_arguments/expected_symbol_table.txt @@ -568,6 +568,35 @@ SymbolTable( postconditions=[]), parsed=..., arguments_by_name=...), + TranspilableVerification( + name='text_is_given', + visibility='PUBLIC', + arguments=[ + Argument( + name='text', + type_annotation=OptionalTypeAnnotation( + value=PrimitiveTypeAnnotation( + a_type='STR', + parsed=...), + parsed=...), + default=None, + mutable=False, + parsed=...)], + returns=PrimitiveTypeAnnotation( + a_type='BOOL', + parsed=...), + description=DescriptionOfSignature( + summary='Check the negated nullness check of the optional argument.', + remarks=[], + arguments_by_name=[], + returns=None, + parsed=...), + contracts=Contracts( + preconditions=[], + snapshots=[], + postconditions=[]), + parsed=..., + arguments_by_name=...), TranspilableVerification( name='number_is_small', visibility='PUBLIC', diff --git a/dev/test_data/main/cpp/expected/optional_arguments/expected_output/include/dummy/verification.hpp b/dev/test_data/main/cpp/expected/optional_arguments/expected_output/include/dummy/verification.hpp index f0a538e13..fc3171327 100644 --- a/dev/test_data/main/cpp/expected/optional_arguments/expected_output/include/dummy/verification.hpp +++ b/dev/test_data/main/cpp/expected/optional_arguments/expected_output/include/dummy/verification.hpp @@ -229,6 +229,11 @@ bool ForwardsText( const common::optional& text ); +/// \brief Check the negated nullness check of the optional argument. +bool TextIsGiven( + const common::optional& text +); + /// \brief Check the optional integer argument. bool NumberIsSmall( const common::optional& number diff --git a/dev/test_data/main/cpp/expected/optional_arguments/expected_output/src/verification.cpp b/dev/test_data/main/cpp/expected/optional_arguments/expected_output/src/verification.cpp index 7ce97d0f5..9ba66dd37 100644 --- a/dev/test_data/main/cpp/expected/optional_arguments/expected_output/src/verification.cpp +++ b/dev/test_data/main/cpp/expected/optional_arguments/expected_output/src/verification.cpp @@ -71,6 +71,12 @@ bool ForwardsText( ); } +bool TextIsGiven( + const common::optional& text +) { + return !(!(text.has_value())); +} + bool NumberIsSmall( const common::optional& number ) { diff --git a/dev/test_data/main/csharp/expected/optional_arguments/expected_output/dummy/verification.cs b/dev/test_data/main/csharp/expected/optional_arguments/expected_output/dummy/verification.cs index 65adde30d..9796206c2 100644 --- a/dev/test_data/main/csharp/expected/optional_arguments/expected_output/dummy/verification.cs +++ b/dev/test_data/main/csharp/expected/optional_arguments/expected_output/dummy/verification.cs @@ -63,6 +63,16 @@ public static bool ForwardsText( return Verification.TextIsNotBanned(text); } // public static bool ForwardsText + /// + /// Check the negated nullness check of the optional argument. + /// + public static bool TextIsGiven( + string? text + ) + { + return !(text == null); + } // public static bool TextIsGiven + /// /// Check the optional integer argument. /// diff --git a/dev/test_data/main/golang/expected/optional_arguments/expected_output/verification/verification.go b/dev/test_data/main/golang/expected/optional_arguments/expected_output/verification/verification.go index 3944758ce..8f1329528 100644 --- a/dev/test_data/main/golang/expected/optional_arguments/expected_output/verification/verification.go +++ b/dev/test_data/main/golang/expected/optional_arguments/expected_output/verification/verification.go @@ -68,6 +68,13 @@ func ForwardsText( return TextIsNotBanned(text) } +// Check the negated nullness check of the optional argument. +func TextIsGiven( + text *string, +) bool { + return !(text == nil) +} + // Check the optional integer argument. func NumberIsSmall( number *int64, diff --git a/dev/test_data/main/java/expected/optional_arguments/expected_output/src/main/java/dummy/verification/Verification.java b/dev/test_data/main/java/expected/optional_arguments/expected_output/src/main/java/dummy/verification/Verification.java index 4499e4a12..fa3f7aa24 100644 --- a/dev/test_data/main/java/expected/optional_arguments/expected_output/src/main/java/dummy/verification/Verification.java +++ b/dev/test_data/main/java/expected/optional_arguments/expected_output/src/main/java/dummy/verification/Verification.java @@ -57,6 +57,14 @@ public static Boolean forwardsText( return textIsNotBanned(text); } + /** + * Check the negated nullness check of the optional argument. + */ + public static Boolean textIsGiven( + Optional text) { + return !(!text.isPresent()); + } + /** * Check the optional integer argument. */ diff --git a/dev/test_data/main/python/expected/optional_arguments/expected_output/dummy/verification.py b/dev/test_data/main/python/expected/optional_arguments/expected_output/dummy/verification.py index b654310fa..4104807e6 100644 --- a/dev/test_data/main/python/expected/optional_arguments/expected_output/dummy/verification.py +++ b/dev/test_data/main/python/expected/optional_arguments/expected_output/dummy/verification.py @@ -93,6 +93,13 @@ def forwards_text( return text_is_not_banned(text) +def text_is_given( + text: Optional[str] +) -> bool: + """Check the negated nullness check of the optional argument.""" + return text is not None + + def number_is_small( number: Optional[int] ) -> bool: diff --git a/dev/test_data/main/typescript/expected/optional_arguments/expected_output/src/verification.ts b/dev/test_data/main/typescript/expected/optional_arguments/expected_output/src/verification.ts index a36c5f214..04520cd7f 100644 --- a/dev/test_data/main/typescript/expected/optional_arguments/expected_output/src/verification.ts +++ b/dev/test_data/main/typescript/expected/optional_arguments/expected_output/src/verification.ts @@ -222,6 +222,15 @@ export function forwardsText( return textIsNotBanned(text); } +/** + * Check the negated nullness check of the optional argument. + */ +export function textIsGiven( + text: string | null +): boolean { + return !(text === null); +} + /** * Check the optional integer argument. */ diff --git a/dev/test_data/parse/common_meta_models/optional_arguments/expected_symbol_table.txt b/dev/test_data/parse/common_meta_models/optional_arguments/expected_symbol_table.txt index 2a0cbc8e8..bd554f70b 100644 --- a/dev/test_data/parse/common_meta_models/optional_arguments/expected_symbol_table.txt +++ b/dev/test_data/parse/common_meta_models/optional_arguments/expected_symbol_table.txt @@ -518,6 +518,46 @@ UnverifiedSymbolTable( original_node=...)""")], node=..., arguments_by_name=...), + UnderstoodMethod( + name='text_is_given', + verification=True, + visibility='PUBLIC', + arguments=[ + Argument( + name='text', + type_annotation=SubscriptedTypeAnnotation( + identifier='Optional', + subscripts=[ + AtomicTypeAnnotation( + identifier='str', + node=...)], + node=...), + default=None, + node=...)], + returns=AtomicTypeAnnotation( + identifier='bool', + node=...), + description=Description( + document=..., + node=...), + contracts=Contracts( + preconditions=[], + snapshots=[], + postconditions=[]), + non_mutating=False, + body=[ + textwrap.dedent("""\ + Return( + value=Not( + operand=IsNone( + value=Name( + identifier='text', + original_node=...), + original_node=...), + original_node=...), + original_node=...)""")], + node=..., + arguments_by_name=...), UnderstoodMethod( name='number_is_small', verification=True,