diff --git a/src/extensions/score_metamodel/checks/graph_checks.py b/src/extensions/score_metamodel/checks/graph_checks.py index 2335db228..e056bf62f 100644 --- a/src/extensions/score_metamodel/checks/graph_checks.py +++ b/src/extensions/score_metamodel/checks/graph_checks.py @@ -13,6 +13,7 @@ import operator from collections.abc import Callable from functools import reduce +from itertools import chain from typing import Any, cast from score_metamodel import ( @@ -198,3 +199,32 @@ def check_metamodel_graph( f" Explanation: {explanation}" ) log.warning_for_need(need, msg) + + +@graph_check +def check_valid_only_links_to_valid( + app: Sphinx, + all_needs: NeedsView, + log: CheckLogger, +): + # Pre-Gather all *valid* need id's (external, & local) + valid_needs_id_all = set( + x.id for x in all_needs.values() if x.get("status") == "valid" + ) + # Pre-Gather all LOCAL *valid* id's to iterate over and check + valid_needs_local = [ + x + for x in all_needs.filter_is_external(False).values() + if x.get("status") == "valid" + ] + + for need in valid_needs_local: + # Using set comprehension here to enable faster computation for comparisons + all_linked_needs: set[str] = set( + x.id + for x in set(chain(*need._links.values())) # type: ignore + ) + invalid_needs = all_linked_needs.difference(valid_needs_id_all) + if invalid_needs: + msg = f"is valid but links to invalid need(s): {invalid_needs}" + log.warning_for_need(need, msg, is_new_check=True) diff --git a/src/extensions/score_metamodel/tests/rst/graph/test_invalid_graph.rst b/src/extensions/score_metamodel/tests/rst/graph/test_invalid_graph.rst new file mode 100644 index 000000000..581d3b8d1 --- /dev/null +++ b/src/extensions/score_metamodel/tests/rst/graph/test_invalid_graph.rst @@ -0,0 +1,32 @@ +.. + # ******************************************************************************* + # Copyright (c) 2026 Contributors to the Eclipse Foundation + # + # See the NOTICE file(s) distributed with this work for additional + # information regarding copyright ownership. + # + # This program and the accompanying materials are made available under the + # terms of the Apache License Version 2.0 which is available at + # https://www.apache.org/licenses/LICENSE-2.0 + # + # SPDX-License-Identifier: Apache-2.0 + # ******************************************************************************* + +#CHECK: check_valid_only_links_to_valid + +.. feat_req:: Parent requirement INVALID QM + :id: feat_req__parent__QM_invalid + :safety: QM + :status: invalid + +.. We can not yet enable this test. As the check is only an 'info' and not yet a true warning +.. Therefore the test is the inverse of what we will test once it is enabled. + +.. #EXPECT: comp_saf_fmea__child__16: is valid but links to invalid need(s): +#EXPECT-NOT: invalid need(s): + +.. comp_saf_fmea:: Child requirement + :id: comp_saf_fmea__child__1 + :safety: QM + :status: valid + :mitigated_by: feat_req__parent__QM_invalid