diff --git a/ba/org.osate.xtext.aadl2.ba.tests/models/issue3244/.gitignore b/ba/org.osate.xtext.aadl2.ba.tests/models/issue3244/.gitignore
new file mode 100644
index 0000000000..afce51184c
--- /dev/null
+++ b/ba/org.osate.xtext.aadl2.ba.tests/models/issue3244/.gitignore
@@ -0,0 +1,2 @@
+/.aadlbin-gen/
+/instances/
diff --git a/ba/org.osate.xtext.aadl2.ba.tests/models/issue3244/.project b/ba/org.osate.xtext.aadl2.ba.tests/models/issue3244/.project
new file mode 100644
index 0000000000..89e2bf8155
--- /dev/null
+++ b/ba/org.osate.xtext.aadl2.ba.tests/models/issue3244/.project
@@ -0,0 +1,16 @@
+
+
+ issue3244
+
+
+
+
+ org.eclipse.xtext.ui.shared.xtextBuilder
+
+
+
+
+ org.osate.core.aadlnature
+ org.eclipse.xtext.ui.shared.xtextNature
+
+
diff --git a/ba/org.osate.xtext.aadl2.ba.tests/models/issue3244/Issue3244.aadl b/ba/org.osate.xtext.aadl2.ba.tests/models/issue3244/Issue3244.aadl
new file mode 100644
index 0000000000..e03e867172
--- /dev/null
+++ b/ba/org.osate.xtext.aadl2.ba.tests/models/issue3244/Issue3244.aadl
@@ -0,0 +1,64 @@
+-- Copyright (c) 2004-2026 Carnegie Mellon University and others. (see Contributors file).
+-- All Rights Reserved.
+--
+-- NO WARRANTY. ALL MATERIAL IS FURNISHED ON AN "AS-IS" BASIS. CARNEGIE MELLON UNIVERSITY MAKES NO WARRANTIES OF ANY
+-- KIND, EITHER EXPRESSED OR IMPLIED, AS TO ANY MATTER INCLUDING, BUT NOT LIMITED TO, WARRANTY OF FITNESS FOR PURPOSE
+-- OR MERCHANTABILITY, EXCLUSIVITY, OR RESULTS OBTAINED FROM USE OF THE MATERIAL. CARNEGIE MELLON UNIVERSITY DOES NOT
+-- MAKE ANY WARRANTY OF ANY KIND WITH RESPECT TO FREEDOM FROM PATENT, TRADEMARK, OR COPYRIGHT INFRINGEMENT.
+--
+-- This program and the accompanying materials are made available under the terms of the Eclipse Public License 2.0
+-- which is available at https://www.eclipse.org/legal/epl-2.0/
+-- SPDX-License-Identifier: EPL-2.0
+--
+-- Created, in part, with funding and support from the United States Government. (see Acknowledgments file).
+--
+-- This program includes and/or can make use of certain third party source code, object code, documentation and other
+-- files ("Third Party Software"). The Third Party Software that is used by this program is dependent upon your system
+-- configuration. By using this program, You agree to comply with any and all relevant Third Party Software terms and
+-- conditions contained in any such Third Party Software or separate license file distributed with such Third Party
+-- Software. The parties who own the Third Party Software ("Third Party Licensors") are intended third party benefici-
+-- aries to this license with respect to the terms applicable to their Third Party Software. Third Party Software li-
+-- censes only apply to the Third Party Software and not any other portion of this program or this program as a whole.
+
+package Issue3244
+public
+ with Base_Types;
+
+ thread worker
+ features
+ outgoing : out event port;
+ end worker;
+
+ thread implementation worker.invalid
+ annex behavior_specification {**
+ variables
+ amount : Base_Types::Integer;
+ values[amount] : Base_Types::Integer;
+ flag : Base_Types::Boolean;
+ states
+ start : initial state;
+ done : complete final state;
+ transitions
+ start -[]-> done {
+ for (i : Base_Types::Integer in 0 .. 2) {
+ i := 1;
+ forall (j : Base_Types::Integer in 0 .. 2) {
+ j := 1;
+ flag := outgoing'fresh;
+ amount := #Issue3244Properties::Size
+ }
+ }
+ };
+ **};
+ end worker.invalid;
+
+ thread implementation worker.valid
+ annex behavior_specification {**
+ states
+ start : initial state;
+ done : complete final state;
+ transitions
+ start -[]-> done;
+ **};
+ end worker.valid;
+end Issue3244;
diff --git a/ba/org.osate.xtext.aadl2.ba.tests/models/issue3244/Issue3244Properties.aadl b/ba/org.osate.xtext.aadl2.ba.tests/models/issue3244/Issue3244Properties.aadl
new file mode 100644
index 0000000000..fefc939e6e
--- /dev/null
+++ b/ba/org.osate.xtext.aadl2.ba.tests/models/issue3244/Issue3244Properties.aadl
@@ -0,0 +1,25 @@
+-- Copyright (c) 2004-2026 Carnegie Mellon University and others. (see Contributors file).
+-- All Rights Reserved.
+--
+-- NO WARRANTY. ALL MATERIAL IS FURNISHED ON AN "AS-IS" BASIS. CARNEGIE MELLON UNIVERSITY MAKES NO WARRANTIES OF ANY
+-- KIND, EITHER EXPRESSED OR IMPLIED, AS TO ANY MATTER INCLUDING, BUT NOT LIMITED TO, WARRANTY OF FITNESS FOR PURPOSE
+-- OR MERCHANTABILITY, EXCLUSIVITY, OR RESULTS OBTAINED FROM USE OF THE MATERIAL. CARNEGIE MELLON UNIVERSITY DOES NOT
+-- MAKE ANY WARRANTY OF ANY KIND WITH RESPECT TO FREEDOM FROM PATENT, TRADEMARK, OR COPYRIGHT INFRINGEMENT.
+--
+-- This program and the accompanying materials are made available under the terms of the Eclipse Public License 2.0
+-- which is available at https://www.eclipse.org/legal/epl-2.0/
+-- SPDX-License-Identifier: EPL-2.0
+--
+-- Created, in part, with funding and support from the United States Government. (see Acknowledgments file).
+--
+-- This program includes and/or can make use of certain third party source code, object code, documentation and other
+-- files ("Third Party Software"). The Third Party Software that is used by this program is dependent upon your system
+-- configuration. By using this program, You agree to comply with any and all relevant Third Party Software terms and
+-- conditions contained in any such Third Party Software or separate license file distributed with such Third Party
+-- Software. The parties who own the Third Party Software ("Third Party Licensors") are intended third party benefici-
+-- aries to this license with respect to the terms applicable to their Third Party Software. Third Party Software li-
+-- censes only apply to the Third Party Software and not any other portion of this program or this program as a whole.
+
+property set Issue3244Properties is
+ Size : aadlinteger units AADL_Project::Size_Units applies to (all);
+end Issue3244Properties;
diff --git a/ba/org.osate.xtext.aadl2.ba.tests/src/org/osate/xtext/aadl2/ba/tests/Issue3244Test.java b/ba/org.osate.xtext.aadl2.ba.tests/src/org/osate/xtext/aadl2/ba/tests/Issue3244Test.java
new file mode 100644
index 0000000000..b51bd77cc7
--- /dev/null
+++ b/ba/org.osate.xtext.aadl2.ba.tests/src/org/osate/xtext/aadl2/ba/tests/Issue3244Test.java
@@ -0,0 +1,69 @@
+/**
+ * Copyright (c) 2004-2026 Carnegie Mellon University and others. (see Contributors file).
+ * All Rights Reserved.
+ *
+ * NO WARRANTY. ALL MATERIAL IS FURNISHED ON AN "AS-IS" BASIS. CARNEGIE MELLON UNIVERSITY MAKES NO WARRANTIES OF ANY
+ * KIND, EITHER EXPRESSED OR IMPLIED, AS TO ANY MATTER INCLUDING, BUT NOT LIMITED TO, WARRANTY OF FITNESS FOR PURPOSE
+ * OR MERCHANTABILITY, EXCLUSIVITY, OR RESULTS OBTAINED FROM USE OF THE MATERIAL. CARNEGIE MELLON UNIVERSITY DOES NOT
+ * MAKE ANY WARRANTY OF ANY KIND WITH RESPECT TO FREEDOM FROM PATENT, TRADEMARK, OR COPYRIGHT INFRINGEMENT.
+ *
+ * This program and the accompanying materials are made available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Created, in part, with funding and support from the United States Government. (see Acknowledgments file).
+ *
+ * This program includes and/or can make use of certain third party source code, object code, documentation and other
+ * files ("Third Party Software"). The Third Party Software that is used by this program is dependent upon your system
+ * configuration. By using this program, You agree to comply with any and all relevant Third Party Software terms and
+ * conditions contained in any such Third Party Software or separate license file distributed with such Third Party
+ * Software. The parties who own the Third Party Software ("Third Party Licensors") are intended third party benefici-
+ * aries to this license with respect to the terms applicable to their Third Party Software. Third Party Software li-
+ * censes only apply to the Third Party Software and not any other portion of this program or this program as a whole.
+ */
+package org.osate.xtext.aadl2.ba.tests;
+
+import static org.junit.Assert.assertEquals;
+
+import java.util.List;
+
+import org.eclipse.xtext.diagnostics.Severity;
+import org.eclipse.xtext.nodemodel.util.NodeModelUtils;
+import org.eclipse.xtext.testing.InjectWith;
+import org.eclipse.xtext.testing.XtextRunner;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.osate.aadl2.AadlPackage;
+import org.osate.testsupport.TestHelper;
+import org.osate.xtext.aadl2.ba.validation.BehaviorAnnexValidator;
+
+import com.google.inject.Inject;
+
+/** Characterizes independent diagnostics and annex isolation while consolidating validator traversals. */
+@RunWith(XtextRunner.class)
+@InjectWith(BehaviorAnnexEmbeddedInjectorProvider.class)
+public class Issue3244Test {
+ private static final String MODEL_DIRECTORY = "org.osate.xtext.aadl2.ba.tests/models/issue3244/";
+
+ @Inject
+ private TestHelper testHelper;
+
+ @Test
+ public void reportsIndependentChecksInNestedActionsAfterAnInvalidArraySize() throws Exception {
+ var result = testHelper.testFile(MODEL_DIRECTORY + "Issue3244.aadl",
+ MODEL_DIRECTORY + "Issue3244Properties.aadl");
+ var source = NodeModelUtils.getNode(result.getResource().getContents().getFirst()).getRootNode().getText();
+ // The invalid dimension gates the strict analyzers, but all source checks and both property checks must run.
+ // A second, valid annex in the same file must not inherit the first annex's pending checks.
+ var expected = List.of(BehaviorAnnexValidator.ARRAY_SIZE + ": amount",
+ BehaviorAnnexValidator.ITERATIVE_VARIABLE_TARGET + ": i",
+ BehaviorAnnexValidator.ITERATIVE_VARIABLE_TARGET + ": j",
+ BehaviorAnnexValidator.PORT_STATUS_DIRECTION + ": outgoing'fresh",
+ BehaviorAnnexValidator.PROPERTY_REFERENCE_VALUE + ": #Issue3244Properties::Size",
+ BehaviorAnnexValidator.PROPERTY_REFERENCE_UNITS + ": #Issue3244Properties::Size");
+ assertEquals(expected.stream().sorted().toList(), result.getIssues().stream().map(issue -> {
+ assertEquals(result.getSummary(), Severity.ERROR, issue.getSeverity());
+ return issue.getCode() + ": " + source.substring(issue.getOffset(), issue.getOffset() + issue.getLength());
+ }).sorted().toList());
+ }
+}
diff --git a/ba/org.osate.xtext.aadl2.ba/src/org/osate/xtext/aadl2/ba/validation/BehaviorAnnexValidator.java b/ba/org.osate.xtext.aadl2.ba/src/org/osate/xtext/aadl2/ba/validation/BehaviorAnnexValidator.java
index 7f3370ec39..3fac7ef7a7 100644
--- a/ba/org.osate.xtext.aadl2.ba/src/org/osate/xtext/aadl2/ba/validation/BehaviorAnnexValidator.java
+++ b/ba/org.osate.xtext.aadl2.ba/src/org/osate/xtext/aadl2/ba/validation/BehaviorAnnexValidator.java
@@ -30,6 +30,7 @@
import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;
+import java.util.function.Predicate;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EObject;
@@ -67,17 +68,21 @@
import org.osate.ba.aadlba.ForOrForAllStatement;
import org.osate.ba.aadlba.PropertyReference;
import org.osate.ba.aadlba.PropertySetPropertyReference;
+import org.osate.ba.aadlba.util.AadlBaSwitch;
import org.osate.ba.analyzers.AadlBaInitializationChecker;
import org.osate.ba.analyzers.AadlBaRulesCheckersDriver;
import org.osate.ba.analyzers.AadlBaTypeChecker;
import org.osate.ba.analyzers.AdaLikeDataTypeChecker;
import org.osate.ba.utils.AadlBaUtils;
-import org.osate.xtext.aadl2.ba.behaviorAnnex.AssignmentAction;
import org.osate.xtext.aadl2.ba.behaviorAnnex.ArrayDimension;
+import org.osate.xtext.aadl2.ba.behaviorAnnex.AssignmentAction;
import org.osate.xtext.aadl2.ba.behaviorAnnex.BehaviorAnnex;
import org.osate.xtext.aadl2.ba.behaviorAnnex.BehaviorAnnexPackage;
import org.osate.xtext.aadl2.ba.behaviorAnnex.BehaviorIntegerLiteral;
+import org.osate.xtext.aadl2.ba.behaviorAnnex.BehaviorState;
+import org.osate.xtext.aadl2.ba.behaviorAnnex.BehaviorStateGroup;
import org.osate.xtext.aadl2.ba.behaviorAnnex.BehaviorTransition;
+import org.osate.xtext.aadl2.ba.behaviorAnnex.BehaviorVariable;
import org.osate.xtext.aadl2.ba.behaviorAnnex.CommunicationAction;
import org.osate.xtext.aadl2.ba.behaviorAnnex.DispatchTriggerCondition;
import org.osate.xtext.aadl2.ba.behaviorAnnex.ForStatement;
@@ -88,6 +93,7 @@
import org.osate.xtext.aadl2.ba.behaviorAnnex.ReferenceSegment;
import org.osate.xtext.aadl2.ba.behaviorAnnex.UnaryExpression;
import org.osate.xtext.aadl2.ba.behaviorAnnex.UnindexedReferenceExpression;
+import org.osate.xtext.aadl2.ba.behaviorAnnex.util.BehaviorAnnexSwitch;
import org.osate.xtext.aadl2.ba.translation.DeclarativeToStrictTranslator;
import org.osate.xtext.aadl2.ba.translation.DeclarativeToStrictTranslator.TranslationResult;
@@ -136,29 +142,33 @@ public boolean isLanguageSpecific() {
@Check(CheckType.NORMAL)
public void checkBehaviorAnnex(final BehaviorAnnex source) {
- if (!(source.getContainingClassifier() instanceof ComponentClassifier owner)
- || !checkDeclarationNames(source, owner) || hasSyntaxOrLinkingErrors(source)
- || !checkCompleteModeStates(source, owner)) {
+ if (!(source.getContainingClassifier() instanceof ComponentClassifier owner)) {
+ return;
+ }
+ var checks = new DeclarativeChecks(source);
+ checks.doSwitch(source);
+ for (var contents = source.eAllContents(); contents.hasNext();) {
+ checks.doSwitch(contents.next());
+ }
+ var parseResult = ParseResultHolder.Factory.INSTANCE.adapt(source).getParseResult();
+ if (!checkDeclarationNames(checks.declarations, owner) || parseResult != null && parseResult.hasSyntaxErrors()
+ || checks.hasUnresolvedReference || !checkCompleteModeStates(source, checks.completeStates, owner)) {
return;
}
var translation = translator.translate(source, owner);
// Each check describes a use no strict checker can reject, and a model can get each one wrong independently,
// so report them all before deciding whether the strict checkers have a model to work on.
- var representable = checkArraySizes(source);
- representable &= checkIteratorClassifiers(source);
- representable &= checkInternalPortUses(source, translation);
- representable &= checkInternalConditionPorts(source, translation);
- representable &= checkExternalConditionTriggers(source, translation);
- representable &= checkTimeoutResetPorts(source, translation);
- representable &= checkIteratorTargets(source, translation);
- representable &= checkIteratedValues(source, translation);
- checkPortStatusValues(source, translation);
- checkExternalConditionsInModes(source);
+ var representable = true;
+ for (var check : checks.pendingChecks) {
+ representable &= check.test(translation);
+ }
// The strict model does carry a property reference that denotes no value, so this one is not a gate: the strict
// checkers keep their model and whatever else they have to say about it.
- checkPropertyReferenceValues(translation);
- checkPropertyReferenceUnits(translation);
+ var propertyChecks = new PropertyReferenceChecks(translation);
+ for (var contents = translation.getStrictAnnex().eAllContents(); contents.hasNext();) {
+ propertyChecks.doSwitch(contents.next());
+ }
if (!representable) {
return;
}
@@ -185,6 +195,169 @@ public void checkBehaviorAnnex(final BehaviorAnnex source) {
}
}
+ /**
+ * Collects checks during the one source-model walk. Translation must wait until all declarations and unresolved
+ * links have been checked, so the switch queues node-local checks rather than running them while visiting.
+ * The caller owns containment traversal; switch results never prune children.
+ */
+ private final class DeclarativeChecks extends BehaviorAnnexSwitch {
+ private final List declarations = new ArrayList<>();
+ private final List completeStates = new ArrayList<>();
+ private final List> pendingChecks = new ArrayList<>();
+ private final boolean inModes;
+ private boolean hasUnresolvedReference;
+
+ private DeclarativeChecks(final BehaviorAnnex source) {
+ inModes = DeclarativeToStrictTranslator.hasInModes(source);
+ }
+
+ @Override
+ public Void doSwitch(final EObject object) {
+ hasUnresolvedReference = hasUnresolvedReference || hasUnresolvedCrossReference(object);
+ return super.doSwitch(object);
+ }
+
+ @Override
+ public Void caseBehaviorVariable(final BehaviorVariable variable) {
+ declarations.add(new Declaration(variable.getName(), variable,
+ BehaviorAnnexPackage.eINSTANCE.getBehaviorVariable_Name(), false));
+ return null;
+ }
+
+ @Override
+ public Void caseBehaviorState(final BehaviorState state) {
+ var complete = state.eContainer() instanceof BehaviorStateGroup group && group.isComplete();
+ declarations.add(new Declaration(state.getName(), state,
+ BehaviorAnnexPackage.eINSTANCE.getBehaviorState_Name(), complete));
+ if (complete) {
+ completeStates.add(state);
+ }
+ return null;
+ }
+
+ @Override
+ public Void caseBehaviorTransition(final BehaviorTransition transition) {
+ declarations.add(new Declaration(transition.getName(), transition,
+ BehaviorAnnexPackage.eINSTANCE.getBehaviorTransition_Name(), false));
+ if (inModes) {
+ pendingChecks.add(translation -> {
+ checkExternalConditionInModes(transition);
+ return true;
+ });
+ }
+ return null;
+ }
+
+ @Override
+ public Void caseArrayDimension(final ArrayDimension dimension) {
+ pendingChecks.add(translation -> checkArraySize(dimension));
+ return null;
+ }
+
+ @Override
+ public Void caseForStatement(final ForStatement loop) {
+ pendingChecks.add(translation -> checkIteratorClassifier(loop));
+ pendingChecks.add(translation -> checkIteratedValues(loop, translation));
+ return null;
+ }
+
+ @Override
+ public Void caseReference(final Reference reference) {
+ pendingChecks.add(translation -> checkInternalPortUse(reference, translation));
+ return null;
+ }
+
+ @Override
+ public Void caseInternalCondition(final InternalCondition condition) {
+ pendingChecks.add(translation -> checkInternalConditionPorts(condition, translation));
+ return null;
+ }
+
+ @Override
+ public Void caseModeSwitchTrigger(final ModeSwitchTrigger trigger) {
+ pendingChecks.add(translation -> checkExternalConditionTrigger(trigger, translation));
+ return null;
+ }
+
+ @Override
+ public Void caseDispatchTriggerCondition(final DispatchTriggerCondition timeout) {
+ pendingChecks.add(translation -> checkTimeoutResetPorts(timeout, translation));
+ return null;
+ }
+
+ @Override
+ public Void caseAssignmentAction(final AssignmentAction action) {
+ pendingChecks.add(translation -> checkIteratorTarget(action.getTarget(), translation));
+ return null;
+ }
+
+ @Override
+ public Void caseCommunicationAction(final CommunicationAction action) {
+ if (action.isDequeue()) {
+ pendingChecks.add(translation -> checkIteratorTarget(action.getTarget(), translation));
+ }
+ return null;
+ }
+
+ @Override
+ public Void caseReferenceExpression(final ReferenceExpression expression) {
+ if (expression.isCount() || expression.isFresh() || expression.isUpdated()) {
+ pendingChecks.add(translation -> {
+ checkPortStatusValue(expression, expression.getReference(), translation);
+ return true;
+ });
+ }
+ return null;
+ }
+
+ @Override
+ public Void caseUnindexedReferenceExpression(final UnindexedReferenceExpression expression) {
+ if (expression.isCount() || expression.isFresh() || expression.isUpdated()) {
+ pendingChecks.add(translation -> {
+ checkPortStatusValue(expression, expression.getReference(), translation);
+ return true;
+ });
+ }
+ return null;
+ }
+ }
+
+ /** Checks property values and units together during the one strict-model walk owned by this adapter. */
+ private final class PropertyReferenceChecks extends AadlBaSwitch {
+ private final TranslationResult translation;
+ private final Set reportedUnits = new HashSet<>();
+
+ private PropertyReferenceChecks(final TranslationResult translation) {
+ this.translation = translation;
+ }
+
+ @Override
+ public Void casePropertySetPropertyReference(final PropertySetPropertyReference reference) {
+ checkPropertyReferenceValue(reference, translation);
+ // Continue to casePropertyReference so this same reference is also checked for units.
+ return null;
+ }
+
+ @Override
+ public Void casePropertyReference(final PropertyReference reference) {
+ if (!reference.getProperties().isEmpty()) {
+ checkPropertyReferenceUnits(reference,
+ AadlBaUtils.getPropertyType(reference.getProperties().getLast().getProperty()), translation,
+ reportedUnits);
+ }
+ return null;
+ }
+
+ @Override
+ public Void caseBehaviorPropertyConstant(final BehaviorPropertyConstant constant) {
+ if (constant.getProperty() != null) {
+ checkPropertyReferenceUnits(constant, constant.getProperty().getPropertyType(), translation,
+ reportedUnits);
+ }
+ return null;
+ }
+ }
+
/**
* AS5506/3 Rev A D.3 requires each behavior-variable array size to be the integer value constant of D.7: an integer
* literal or a property reference. The shared integer-value grammar also accepts an ordinary reference expression,
@@ -193,23 +366,17 @@ public void checkBehaviorAnnex(final BehaviorAnnex source) {
* reference denotes belongs to a component instance, so whether it can be read from the declarative model says
* nothing about the legality of the declaration and is not checked here.
*
- * @return {@code true} when every declared array size is an integer value constant
+ * @return {@code true} when the declared array size is an integer value constant
*/
- private boolean checkArraySizes(final BehaviorAnnex source) {
- var accepted = true;
- for (var contents = source.eAllContents(); contents.hasNext();) {
- if (!(contents.next() instanceof ArrayDimension dimension)) {
- continue;
- }
- var size = dimension.getSize();
- if (size instanceof ReferenceExpression reference && reference.getProperty() == null) {
- var written = NodeModelUtils.getTokenText(NodeModelUtils.findActualNodeFor(size));
- error("Array size '" + written + "' must be an integer literal or a property reference", size, null,
- ValidationMessageAcceptor.INSIGNIFICANT_INDEX, ARRAY_SIZE);
- accepted = false;
- }
+ private boolean checkArraySize(final ArrayDimension dimension) {
+ var size = dimension.getSize();
+ if (size instanceof ReferenceExpression reference && reference.getProperty() == null) {
+ var written = NodeModelUtils.getTokenText(NodeModelUtils.findActualNodeFor(size));
+ error("Array size '" + written + "' must be an integer literal or a property reference", size, null,
+ ValidationMessageAcceptor.INSIGNIFICANT_INDEX, ARRAY_SIZE);
+ return false;
}
- return accepted;
+ return true;
}
/**
@@ -219,22 +386,17 @@ private boolean checkArraySizes(final BehaviorAnnex source) {
* classifier out altogether, letting it pass would not leave the declaration rejected either: the iterated values
* would supply the iterator's type as if nothing had been written. Report it on the reference the loop writes.
*
- * @return {@code true} when every written iterator classifier is a data classifier
+ * @return {@code true} when the written iterator classifier is a data classifier
*/
- private boolean checkIteratorClassifiers(final BehaviorAnnex source) {
- var accepted = true;
- for (var contents = source.eAllContents(); contents.hasNext();) {
- if (!(contents.next() instanceof ForStatement loop) || loop.getDataClassifier() == null
- || loop.getDataClassifier() instanceof DataClassifier) {
- continue;
- }
+ private boolean checkIteratorClassifier(final ForStatement loop) {
+ if (loop.getDataClassifier() != null && !(loop.getDataClassifier() instanceof DataClassifier)) {
error("'" + loop.getDataClassifier().getName() + "' is not a data classifier: a for or forall iterator can"
+ " only name a data component classifier", loop,
BehaviorAnnexPackage.eINSTANCE.getForStatement_DataClassifier(),
ValidationMessageAcceptor.INSIGNIFICANT_INDEX, ITERATOR_CLASSIFIER);
- accepted = false;
+ return false;
}
- return accepted;
+ return true;
}
/**
@@ -243,27 +405,14 @@ private boolean checkIteratorClassifiers(final BehaviorAnnex source) {
* three suffixes, and neither D.5 nor D.7 states a corresponding legality rule. Enforce the semantics shared by the
* three definitions, while accepting both incoming and bidirectional ports because both are frozen on input.
*/
- private void checkPortStatusValues(final BehaviorAnnex source, final TranslationResult translation) {
- for (var contents = source.eAllContents(); contents.hasNext();) {
- var value = contents.next();
- final EObject reference;
- if (value instanceof ReferenceExpression expression
- && (expression.isCount() || expression.isFresh() || expression.isUpdated())) {
- reference = expression.getReference();
- } else if (value instanceof UnindexedReferenceExpression expression
- && (expression.isCount() || expression.isFresh() || expression.isUpdated())) {
- reference = expression.getReference();
- } else {
- continue;
- }
-
- if (translation.getResolvedReference(reference) instanceof Port port
- && AadlBaUtils.getDirectionType(port) == DirectionType.OUT) {
- var written = NodeModelUtils.getTokenText(NodeModelUtils.findActualNodeFor(value));
- error("Port status value '" + written + "' is defined only for a port that is frozen on input, but '"
- + port.getName() + "' is an outgoing port. AS5506/3 Rev. A states no corresponding legality rule.",
- value, null, ValidationMessageAcceptor.INSIGNIFICANT_INDEX, PORT_STATUS_DIRECTION);
- }
+ private void checkPortStatusValue(final EObject value, final EObject reference,
+ final TranslationResult translation) {
+ if (translation.getResolvedReference(reference) instanceof Port port
+ && AadlBaUtils.getDirectionType(port) == DirectionType.OUT) {
+ var written = NodeModelUtils.getTokenText(NodeModelUtils.findActualNodeFor(value));
+ error("Port status value '" + written + "' is defined only for a port that is frozen on input, but '"
+ + port.getName() + "' is an outgoing port. AS5506/3 Rev. A states no corresponding legality rule.",
+ value, null, ValidationMessageAcceptor.INSIGNIFICANT_INDEX, PORT_STATUS_DIRECTION);
}
}
@@ -275,21 +424,19 @@ private void checkPortStatusValues(final BehaviorAnnex source, final Translation
* value at all, and no strict checker rejects it. Report the reference as written. A reference that names a property
* type keeps its own value, an enumeration literal, so it is not one of these.
*/
- private void checkPropertyReferenceValues(final TranslationResult translation) {
- for (var contents = translation.getStrictAnnex().eAllContents(); contents.hasNext();) {
- // A property-set property reference is the translation of the alternative that names no element, and its
- // first property name holds the default value when the property has one.
- if (!(contents.next() instanceof PropertySetPropertyReference reference)
- || reference.getProperties().isEmpty()
- || !(reference.getProperties().getFirst().getProperty().getElement() instanceof Property property)) {
- continue;
- }
- var written = sourceFor(reference, translation);
- error("Property reference '" + NodeModelUtils.getTokenText(NodeModelUtils.findActualNodeFor(written))
- + "' has no value: property '" + property.getName() + "' has no default value and the reference"
- + " names no element that has a value for it", written, null,
- ValidationMessageAcceptor.INSIGNIFICANT_INDEX, PROPERTY_REFERENCE_VALUE);
+ private void checkPropertyReferenceValue(final PropertySetPropertyReference reference,
+ final TranslationResult translation) {
+ // A property-set property reference is the translation of the alternative that names no element, and its
+ // first property name holds the default value when the property has one.
+ if (reference.getProperties().isEmpty()
+ || !(reference.getProperties().getFirst().getProperty().getElement() instanceof Property property)) {
+ return;
}
+ var written = sourceFor(reference, translation);
+ error("Property reference '" + NodeModelUtils.getTokenText(NodeModelUtils.findActualNodeFor(written))
+ + "' has no value: property '" + property.getName() + "' has no default value and the reference"
+ + " names no element that has a value for it", written, null,
+ ValidationMessageAcceptor.INSIGNIFICANT_INDEX, PROPERTY_REFERENCE_VALUE);
}
/**
@@ -297,33 +444,22 @@ private void checkPropertyReferenceValues(final TranslationResult translation) {
* or record field, including when its holder carries a default expression. Prefixed references stay symbolic:
* neither an effective instance value nor its written unit is needed to check the declared units type.
*/
- private void checkPropertyReferenceUnits(final TranslationResult translation) {
- var reported = new HashSet();
- for (var contents = translation.getStrictAnnex().eAllContents(); contents.hasNext();) {
- var value = contents.next();
- final PropertyType declaredType;
- if (value instanceof PropertyReference reference && !reference.getProperties().isEmpty()) {
- declaredType = AadlBaUtils.getPropertyType(reference.getProperties().getLast().getProperty());
- } else if (value instanceof BehaviorPropertyConstant constant && constant.getProperty() != null) {
- declaredType = constant.getProperty().getPropertyType();
- } else {
- continue;
- }
- var type = AadlUtil.getBasePropertyType(declaredType);
- if (type instanceof RangeType range) {
- type = range.getNumberType();
- }
- if (!(type instanceof NumberType number)) {
- continue;
- }
- var units = number.getUnitsType();
- if (units != null && !"AADL_Project::Time_Units".equalsIgnoreCase(units.getQualifiedName())) {
- var source = sourceFor(value, translation);
- // Translation can copy a condition for multiple source states; report the written reference once.
- if (reported.add(source)) {
- error("Behavior Annex property references must be unitless or use AADL_Project::Time_Units", source,
- null, ValidationMessageAcceptor.INSIGNIFICANT_INDEX, PROPERTY_REFERENCE_UNITS);
- }
+ private void checkPropertyReferenceUnits(final EObject value, final PropertyType declaredType,
+ final TranslationResult translation, final Set reported) {
+ var type = AadlUtil.getBasePropertyType(declaredType);
+ if (type instanceof RangeType range) {
+ type = range.getNumberType();
+ }
+ if (!(type instanceof NumberType number)) {
+ return;
+ }
+ var units = number.getUnitsType();
+ if (units != null && !"AADL_Project::Time_Units".equalsIgnoreCase(units.getQualifiedName())) {
+ var source = sourceFor(value, translation);
+ // Translation can copy a condition for multiple source states; report the written reference once.
+ if (reported.add(source)) {
+ error("Behavior Annex property references must be unitless or use AADL_Project::Time_Units", source,
+ null, ValidationMessageAcceptor.INSIGNIFICANT_INDEX, PROPERTY_REFERENCE_UNITS);
}
}
}
@@ -335,21 +471,17 @@ private void checkPropertyReferenceUnits(final TranslationResult translation) {
* it. Report each such reference and leave the strict-model checkers out of it, the way a linking failure already
* gates them.
*
- * @return {@code true} when the annex uses every internal port it names as the standard admits
+ * @return {@code true} when the reference uses an internal port as the standard admits
*/
- private boolean checkInternalPortUses(final BehaviorAnnex source, final TranslationResult translation) {
- var accepted = true;
- for (var contents = source.eAllContents(); contents.hasNext();) {
- if (contents.next() instanceof Reference reference
- && translation.getResolvedReference(reference) instanceof InternalFeature internalPort
- && !isStandardInternalPortUse(reference)) {
- error("'" + internalPort.getName() + "' is an internal port: it can only be an assignment or dequeue"
- + " target, the port of a send action, or a port of an internal condition", reference, null,
- ValidationMessageAcceptor.INSIGNIFICANT_INDEX, INTERNAL_PORT_USE);
- accepted = false;
- }
+ private boolean checkInternalPortUse(final Reference reference, final TranslationResult translation) {
+ if (translation.getResolvedReference(reference) instanceof InternalFeature internalPort
+ && !isStandardInternalPortUse(reference)) {
+ error("'" + internalPort.getName() + "' is an internal port: it can only be an assignment or dequeue"
+ + " target, the port of a send action, or a port of an internal condition", reference, null,
+ ValidationMessageAcceptor.INSIGNIFICANT_INDEX, INTERNAL_PORT_USE);
+ return false;
}
- return accepted;
+ return true;
}
private static boolean isStandardInternalPortUse(final Reference reference) {
@@ -370,22 +502,18 @@ private static boolean isStandardInternalPortUse(final Reference reference) {
* condition would otherwise reach the strict checkers silently short of the ports the user wrote. Report the name
* as written, since an unresolved one has no element to name.
*
- * @return {@code true} when every internal condition in the annex lists internal ports only
+ * @return {@code true} when the internal condition lists internal ports only
*/
- private boolean checkInternalConditionPorts(final BehaviorAnnex source, final TranslationResult translation) {
+ private boolean checkInternalConditionPorts(final InternalCondition condition,
+ final TranslationResult translation) {
var accepted = true;
- for (var contents = source.eAllContents(); contents.hasNext();) {
- if (!(contents.next() instanceof InternalCondition condition)) {
- continue;
- }
- for (var port : condition.getInternalPorts()) {
- if (!(translation.getResolvedReference(port) instanceof InternalFeature)) {
- error("'" + NodeModelUtils.getTokenText(NodeModelUtils.findActualNodeFor(port)) + "' is not an"
- + " internal port: an internal condition can only list internal event or internal event data"
- + " features", port, null, ValidationMessageAcceptor.INSIGNIFICANT_INDEX,
- INTERNAL_CONDITION_PORT);
- accepted = false;
- }
+ for (var port : condition.getInternalPorts()) {
+ if (!(translation.getResolvedReference(port) instanceof InternalFeature)) {
+ error("'" + NodeModelUtils.getTokenText(NodeModelUtils.findActualNodeFor(port)) + "' is not an"
+ + " internal port: an internal condition can only list internal event or internal event data"
+ + " features", port, null, ValidationMessageAcceptor.INSIGNIFICANT_INDEX,
+ INTERNAL_CONDITION_PORT);
+ accepted = false;
}
}
return accepted;
@@ -396,32 +524,30 @@ private boolean checkInternalConditionPorts(final BehaviorAnnex source, final Tr
* subcomponent, retaining that subcomponent as the strict port holder's context. Invalid names and reference
* paths cannot be represented faithfully, so report every written trigger and gate the strict checkers.
*/
- private boolean checkExternalConditionTriggers(final BehaviorAnnex source, final TranslationResult translation) {
- var representable = true;
- for (var contents = source.eAllContents(); contents.hasNext();) {
- if (!(contents.next() instanceof ModeSwitchTrigger trigger) || trigger.getReference() == null) {
- continue;
- }
+ private boolean checkExternalConditionTrigger(final ModeSwitchTrigger trigger,
+ final TranslationResult translation) {
+ if (trigger.getReference() != null) {
var reference = trigger.getReference();
var kind = externalConditionTriggerKind(reference, translation);
if (kind != ExternalTriggerKind.VALID) {
error("'" + NodeModelUtils.getTokenText(NodeModelUtils.findActualNodeFor(reference))
+ "' is not an external-condition trigger: expected an incoming event or event data port"
- + " of the component, or an outgoing event or event data port of a subcomponent",
- reference, null, ValidationMessageAcceptor.INSIGNIFICANT_INDEX, EXTERNAL_CONDITION_TRIGGER);
+ + " of the component, or an outgoing event or event data port of a subcomponent", reference,
+ null, ValidationMessageAcceptor.INSIGNIFICANT_INDEX, EXTERNAL_CONDITION_TRIGGER);
// A wrong-direction port is still represented completely. Keep independent strict diagnostics,
// including the prohibition on external conditions in subprograms, whose event ports are all out.
- representable &= kind != ExternalTriggerKind.UNREPRESENTABLE;
+ return kind != ExternalTriggerKind.UNREPRESENTABLE;
}
}
- return representable;
+ return true;
}
private enum ExternalTriggerKind {
VALID, WRONG_DIRECTION, UNREPRESENTABLE
}
- private static ExternalTriggerKind externalConditionTriggerKind(Reference reference, TranslationResult translation) {
+ private static ExternalTriggerKind externalConditionTriggerKind(Reference reference,
+ TranslationResult translation) {
var resolved = translation.getResolvedReference(reference);
if (!(resolved instanceof EventPort) && !(resolved instanceof EventDataPort)) {
return ExternalTriggerKind.UNREPRESENTABLE;
@@ -465,30 +591,28 @@ private static ExternalTriggerKind externalConditionTriggerKind(Reference refere
* with no time to keep them beside. Report either, and leave the strict-model checkers out of a timeout short of the
* ports the user wrote. Report a name as written, since an unresolved one has no element to name.
*
- * @return {@code true} when every reset-port list in the annex belongs to a completion relative timeout and lists
+ * @return {@code true} when the reset-port list belongs to a completion relative timeout and lists
* event or event data ports only
*/
- private boolean checkTimeoutResetPorts(final BehaviorAnnex source, final TranslationResult translation) {
+ private boolean checkTimeoutResetPorts(final DispatchTriggerCondition timeout,
+ final TranslationResult translation) {
+ if (timeout.getResetPorts().isEmpty()) {
+ return true;
+ }
var accepted = true;
- for (var contents = source.eAllContents(); contents.hasNext();) {
- if (!(contents.next() instanceof DispatchTriggerCondition timeout) || timeout.getResetPorts().isEmpty()) {
- continue;
- }
- if (timeout.getTime() == null) {
- error("A timeout with reset ports is a completion relative timeout, which must specify a behavior time",
- timeout, null, ValidationMessageAcceptor.INSIGNIFICANT_INDEX, TIMEOUT_RESET_PORT_TIME);
+ if (timeout.getTime() == null) {
+ error("A timeout with reset ports is a completion relative timeout, which must specify a behavior time",
+ timeout, null, ValidationMessageAcceptor.INSIGNIFICANT_INDEX, TIMEOUT_RESET_PORT_TIME);
+ accepted = false;
+ }
+ for (var port : timeout.getResetPorts()) {
+ var resolved = translation.getResolvedReference(port);
+ if (!(resolved instanceof EventPort) && !(resolved instanceof EventDataPort)) {
+ error("'" + NodeModelUtils.getTokenText(NodeModelUtils.findActualNodeFor(port)) + "' is not a"
+ + " timeout reset port: a completion relative timeout can only list event or event data"
+ + " ports", port, null, ValidationMessageAcceptor.INSIGNIFICANT_INDEX, TIMEOUT_RESET_PORT);
accepted = false;
}
- for (var port : timeout.getResetPorts()) {
- var resolved = translation.getResolvedReference(port);
- if (!(resolved instanceof EventPort) && !(resolved instanceof EventDataPort)) {
- error("'" + NodeModelUtils.getTokenText(NodeModelUtils.findActualNodeFor(port)) + "' is not a"
- + " timeout reset port: a completion relative timeout can only list event or event data"
- + " ports", port, null, ValidationMessageAcceptor.INSIGNIFICANT_INDEX,
- TIMEOUT_RESET_PORT);
- accepted = false;
- }
- }
}
return accepted;
}
@@ -502,24 +626,20 @@ private boolean checkTimeoutResetPorts(final BehaviorAnnex source, final Transla
* component references that type check. Only the first segment of a target can name an iterator, and it is the
* segment the rule constrains, since writing one data element of the iterator writes part of the iterator.
*
- * @return {@code true} when no assignment or dequeue in the annex targets an iterator
+ * @return {@code true} when the assignment or dequeue target does not name an iterator
*/
- private boolean checkIteratorTargets(final BehaviorAnnex source, final TranslationResult translation) {
- var accepted = true;
- for (var contents = source.eAllContents(); contents.hasNext();) {
- var target = writtenTarget(contents.next());
- if (target == null || target.getSegments().isEmpty()) {
- continue;
- }
- var name = target.getSegments().get(0);
- if (translation.getResolvedReference(name) instanceof ForStatement loop) {
- error("Iterative variable '" + loop.getVariable()
- + "' cannot be an assignment target: Behavior Annex D.6.(L2) legality rule failed.", name, null,
- ValidationMessageAcceptor.INSIGNIFICANT_INDEX, ITERATIVE_VARIABLE_TARGET);
- accepted = false;
- }
+ private boolean checkIteratorTarget(final Reference target, final TranslationResult translation) {
+ if (target == null || target.getSegments().isEmpty()) {
+ return true;
}
- return accepted;
+ var name = target.getSegments().get(0);
+ if (translation.getResolvedReference(name) instanceof ForStatement loop) {
+ error("Iterative variable '" + loop.getVariable()
+ + "' cannot be an assignment target: Behavior Annex D.6.(L2) legality rule failed.", name, null,
+ ValidationMessageAcceptor.INSIGNIFICANT_INDEX, ITERATIVE_VARIABLE_TARGET);
+ return false;
+ }
+ return true;
}
/**
@@ -533,33 +653,18 @@ private boolean checkIteratorTargets(final BehaviorAnnex source, final Translati
* nothing at all. Report the values as written, since an integer range never fails here and everything else is one
* expression.
*
- * @return {@code true} when every loop in the annex iterates values the strict model can carry
+ * @return {@code true} when the loop iterates values the strict model can carry
*/
- private boolean checkIteratedValues(final BehaviorAnnex source, final TranslationResult translation) {
- var accepted = true;
- for (var contents = source.eAllContents(); contents.hasNext();) {
- if (!(contents.next() instanceof ForStatement loop) || loop.getValues() == null
- || !(translation.getStrict(loop) instanceof ForOrForAllStatement strict)
- || strict.getIteratedValues() != null) {
- continue;
- }
- error("'" + NodeModelUtils.getTokenText(NodeModelUtils.findActualNodeFor(loop.getValues()))
- + "' cannot be iterated: a for or forall iterates an integer range, an event data port, a parameter,"
- + " or an array data component reference", loop.getValues(), null,
- ValidationMessageAcceptor.INSIGNIFICANT_INDEX, ITERATED_VALUES);
- accepted = false;
- }
- return accepted;
- }
-
- /** The target an action writes, which the assignment action and the dequeue action spell the same way. */
- private static Reference writtenTarget(final EObject action) {
- if (action instanceof AssignmentAction assignment) {
- return assignment.getTarget();
+ private boolean checkIteratedValues(final ForStatement loop, final TranslationResult translation) {
+ if (loop.getValues() == null || !(translation.getStrict(loop) instanceof ForOrForAllStatement strict)
+ || strict.getIteratedValues() != null) {
+ return true;
}
- return action instanceof CommunicationAction communication && communication.isDequeue()
- ? communication.getTarget()
- : null;
+ error("'" + NodeModelUtils.getTokenText(NodeModelUtils.findActualNodeFor(loop.getValues()))
+ + "' cannot be iterated: a for or forall iterates an integer range, an event data port, a parameter,"
+ + " or an array data component reference", loop.getValues(), null,
+ ValidationMessageAcceptor.INSIGNIFICANT_INDEX, ITERATED_VALUES);
+ return false;
}
/**
@@ -567,25 +672,7 @@ private static Reference writtenTarget(final EObject action) {
* Check the declarations before resolving references so missing classifiers cannot hide duplicate names, and
* skip the strict checkers when names are ambiguous instead of validating an arbitrary resolution.
*/
- private boolean checkDeclarationNames(final BehaviorAnnex source, final ComponentClassifier owner) {
- var declarations = new ArrayList();
- for (var group : source.getVariableGroups()) {
- for (var variable : group.getVariables()) {
- declarations.add(new Declaration(variable.getName(), variable,
- BehaviorAnnexPackage.eINSTANCE.getBehaviorVariable_Name(), false));
- }
- }
- for (var group : source.getStateGroups()) {
- for (var state : group.getStates()) {
- declarations.add(new Declaration(state.getName(), state,
- BehaviorAnnexPackage.eINSTANCE.getBehaviorState_Name(), group.isComplete()));
- }
- }
- for (var transition : source.getTransitions()) {
- declarations.add(new Declaration(transition.getName(), transition,
- BehaviorAnnexPackage.eINSTANCE.getBehaviorTransition_Name(), false));
- }
-
+ private boolean checkDeclarationNames(final List declarations, final ComponentClassifier owner) {
Map> byName = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
for (var declaration : declarations) {
// Transitions need not have a label; partially edited declarations may also lack a name.
@@ -617,8 +704,8 @@ private boolean checkDeclarationNames(final BehaviorAnnex source, final Componen
for (var sameName : byName.values()) {
for (var declaration : sameName) {
if (sameName.size() > 1) {
- error("Duplicate Behavior Annex identifier '" + declaration.name() + "'",
- declaration.source(), declaration.feature(), DECLARATION_NAME);
+ error("Duplicate Behavior Annex identifier '" + declaration.name() + "'", declaration.source(),
+ declaration.feature(), DECLARATION_NAME);
valid = false;
}
// A complete state may represent a same-named mode, but cannot reuse a feature or data name.
@@ -628,7 +715,8 @@ private boolean checkDeclarationNames(final BehaviorAnnex source, final Componen
}
if (enclosingKind != null) {
error("Behavior Annex identifier '" + declaration.name() + "' conflicts with an enclosing "
- + enclosingKind + " identifier", declaration.source(), declaration.feature(), DECLARATION_NAME);
+ + enclosingKind + " identifier", declaration.source(), declaration.feature(),
+ DECLARATION_NAME);
valid = false;
}
}
@@ -640,7 +728,8 @@ private boolean checkDeclarationNames(final BehaviorAnnex source, final Componen
* In a subclause without an {@code in modes} statement, one complete state that names a mode makes the subclause a
* mode refinement. D.3 then requires every complete state in that subclause to name a mode.
*/
- private boolean checkCompleteModeStates(final BehaviorAnnex source, final ComponentClassifier owner) {
+ private boolean checkCompleteModeStates(final BehaviorAnnex source, final List completeStates,
+ final ComponentClassifier owner) {
if (!DeclarativeToStrictTranslator.canRefineModes(source)) {
return true;
}
@@ -648,8 +737,6 @@ private boolean checkCompleteModeStates(final BehaviorAnnex source, final Compon
for (var mode : owner.getAllModes()) {
modeNames.add(mode.getName());
}
- var completeStates = source.getStateGroups().stream().filter(group -> group.isComplete())
- .flatMap(group -> group.getStates().stream()).toList();
var firstModeState = completeStates.stream().filter(state -> modeNames.contains(state.getName())).findFirst();
if (firstModeState.isEmpty()) {
return true;
@@ -673,17 +760,12 @@ private boolean checkCompleteModeStates(final BehaviorAnnex source, final Compon
* statement on the enclosing subclause and the strict model does not carry it, so this rule is checked here, like
* the complete-state mode-refinement rule, rather than by the strict-model checkers.
*/
- private void checkExternalConditionsInModes(final BehaviorAnnex source) {
- if (!DeclarativeToStrictTranslator.hasInModes(source)) {
- return;
- }
- for (var transition : source.getTransitions()) {
- var condition = transition.getCondition();
- if (condition != null && condition.getModeSwitch() != null) {
- error("A Behavior Annex subclause with an in modes statement cannot use an external condition:"
- + " Behavior Annex D.3 consistency rule failed.", condition, null,
- ValidationMessageAcceptor.INSIGNIFICANT_INDEX, EXTERNAL_CONDITION_IN_MODES);
- }
+ private void checkExternalConditionInModes(final BehaviorTransition transition) {
+ var condition = transition.getCondition();
+ if (condition != null && condition.getModeSwitch() != null) {
+ error("A Behavior Annex subclause with an in modes statement cannot use an external condition:"
+ + " Behavior Annex D.3 consistency rule failed.", condition, null,
+ ValidationMessageAcceptor.INSIGNIFICANT_INDEX, EXTERNAL_CONDITION_IN_MODES);
}
}
@@ -728,19 +810,6 @@ private void checkIntegerLiteral(final String value, final EObject owner, final
}
}
- private static boolean hasSyntaxOrLinkingErrors(final BehaviorAnnex source) {
- var parseResult = ParseResultHolder.Factory.INSTANCE.adapt(source).getParseResult();
- if ((parseResult != null && parseResult.hasSyntaxErrors()) || hasUnresolvedCrossReference(source)) {
- return true;
- }
- for (var contents = source.eAllContents(); contents.hasNext();) {
- if (hasUnresolvedCrossReference(contents.next())) {
- return true;
- }
- }
- return false;
- }
-
private static boolean hasUnresolvedCrossReference(final EObject object) {
for (var reference : object.eClass().getEAllReferences()) {
if (reference.isContainment() || reference.isContainer()) {