Skip to content

Commit

Permalink
Validate no value for variable with variable array bounds
Browse files Browse the repository at this point in the history
Validate that there must be no value for a variable with variable array
bounds (i.e., "*"). Also add helper to properly check for variable
bounds in type declaration parser and improve regexes.
  • Loading branch information
mx990 authored and azoitl committed Jan 23, 2025
1 parent ef1094f commit cf02426
Show file tree
Hide file tree
Showing 11 changed files with 128 additions and 9 deletions.
5 changes: 5 additions & 0 deletions plugins/org.eclipse.fordiac.ide.model/model/fordiac.genmodel
Original file line number Diff line number Diff line change
Expand Up @@ -885,6 +885,11 @@
<genParameters ecoreParameter="lib.ecore#//VarDeclaration/validateNoValueForGenericTypeVariable/diagnostics"/>
<genParameters ecoreParameter="lib.ecore#//VarDeclaration/validateNoValueForGenericTypeVariable/context"/>
</genOperations>
<genOperations ecoreOperation="lib.ecore#//VarDeclaration/validateNoValueForVariableLengthArrayVariable"
body="return org.eclipse.fordiac.ide.model.libraryElement.impl.VarDeclarationAnnotations.validateNoValueForVariableLengthArrayVariable(this, diagnostics, context);">
<genParameters ecoreParameter="lib.ecore#//VarDeclaration/validateNoValueForVariableLengthArrayVariable/diagnostics"/>
<genParameters ecoreParameter="lib.ecore#//VarDeclaration/validateNoValueForVariableLengthArrayVariable/context"/>
</genOperations>
<genOperations ecoreOperation="lib.ecore#//VarDeclaration/validateValueForGenericInstanceVariable"
body="return org.eclipse.fordiac.ide.model.libraryElement.impl.VarDeclarationAnnotations.validateValueForGenericInstanceVariable(this, diagnostics, context);">
<genParameters ecoreParameter="lib.ecore#//VarDeclaration/validateValueForGenericInstanceVariable/diagnostics"/>
Expand Down
15 changes: 15 additions & 0 deletions plugins/org.eclipse.fordiac.ide.model/model/lib.ecore
Original file line number Diff line number Diff line change
Expand Up @@ -2312,6 +2312,21 @@
</eGenericType>
</eParameters>
</eOperations>
<eOperations name="validateNoValueForVariableLengthArrayVariable" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EBoolean">
<eAnnotations source="http://www.eclipse.org/emf/2002/Ecore">
<details key="invariant" value="true"/>
</eAnnotations>
<eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
<details key="body" value="return org.eclipse.fordiac.ide.model.libraryElement.impl.VarDeclarationAnnotations.validateNoValueForVariableLengthArrayVariable(this, diagnostics, context);"/>
</eAnnotations>
<eParameters name="diagnostics" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EDiagnosticChain"/>
<eParameters name="context">
<eGenericType eClassifier="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EMap">
<eTypeArguments eClassifier="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EJavaObject"/>
<eTypeArguments eClassifier="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EJavaObject"/>
</eGenericType>
</eParameters>
</eOperations>
<eOperations name="validateValueForGenericInstanceVariable" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EBoolean">
<eAnnotations source="http://www.eclipse.org/emf/2002/Ecore">
<details key="invariant" value="true"/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,14 @@ public interface VarDeclaration extends IInterfaceElement {
*/
boolean validateNoValueForGenericTypeVariable(DiagnosticChain diagnostics, Map<Object, Object> context);

/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @model annotation="http://www.eclipse.org/emf/2002/Ecore invariant='true'"
* @generated
*/
boolean validateNoValueForVariableLengthArrayVariable(DiagnosticChain diagnostics, Map<Object, Object> context);

/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5444,6 +5444,15 @@ public void initializePackageContents() {
g1.getETypeArguments().add(g2);
addEParameter(op, g1, "context", 0, 1, IS_UNIQUE, IS_ORDERED); //$NON-NLS-1$

op = addEOperation(varDeclarationEClass, ecorePackage.getEBoolean(), "validateNoValueForVariableLengthArrayVariable", 0, 1, IS_UNIQUE, IS_ORDERED); //$NON-NLS-1$
addEParameter(op, ecorePackage.getEDiagnosticChain(), "diagnostics", 0, 1, IS_UNIQUE, IS_ORDERED); //$NON-NLS-1$
g1 = createEGenericType(ecorePackage.getEMap());
g2 = createEGenericType(ecorePackage.getEJavaObject());
g1.getETypeArguments().add(g2);
g2 = createEGenericType(ecorePackage.getEJavaObject());
g1.getETypeArguments().add(g2);
addEParameter(op, g1, "context", 0, 1, IS_UNIQUE, IS_ORDERED); //$NON-NLS-1$

op = addEOperation(varDeclarationEClass, ecorePackage.getEBoolean(), "validateValueForGenericInstanceVariable", 0, 1, IS_UNIQUE, IS_ORDERED); //$NON-NLS-1$
addEParameter(op, ecorePackage.getEDiagnosticChain(), "diagnostics", 0, 1, IS_UNIQUE, IS_ORDERED); //$NON-NLS-1$
g1 = createEGenericType(ecorePackage.getEMap());
Expand Down Expand Up @@ -6318,6 +6327,12 @@ protected void createEcoreAnnotations() {
new String[] {
"invariant", "true" //$NON-NLS-1$ //$NON-NLS-2$
});
addAnnotation
(varDeclarationEClass.getEOperations().get(13),
source,
new String[] {
"invariant", "true" //$NON-NLS-1$ //$NON-NLS-2$
});
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -608,6 +608,16 @@ public boolean validateNoValueForGenericTypeVariable(final DiagnosticChain diagn
return org.eclipse.fordiac.ide.model.libraryElement.impl.VarDeclarationAnnotations.validateNoValueForGenericTypeVariable(this, diagnostics, context);
}

/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
@Override
public boolean validateNoValueForVariableLengthArrayVariable(final DiagnosticChain diagnostics, final Map<Object, Object> context) {
return org.eclipse.fordiac.ide.model.libraryElement.impl.VarDeclarationAnnotations.validateNoValueForVariableLengthArrayVariable(this, diagnostics, context);
}

/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -370,53 +370,61 @@ public class LibraryElementValidator extends EObjectValidator {
*/
public static final int VAR_DECLARATION__VALIDATE_NO_VALUE_FOR_GENERIC_TYPE_VARIABLE = 25;

/**
* The {@link org.eclipse.emf.common.util.Diagnostic#getCode() code} for constraint 'Validate No Value For Variable Length Array Variable' of 'Var Declaration'.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
public static final int VAR_DECLARATION__VALIDATE_NO_VALUE_FOR_VARIABLE_LENGTH_ARRAY_VARIABLE = 26;

/**
* The {@link org.eclipse.emf.common.util.Diagnostic#getCode() code} for constraint 'Validate Value For Generic Instance Variable' of 'Var Declaration'.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
public static final int VAR_DECLARATION__VALIDATE_VALUE_FOR_GENERIC_INSTANCE_VARIABLE = 26;
public static final int VAR_DECLARATION__VALIDATE_VALUE_FOR_GENERIC_INSTANCE_VARIABLE = 27;

/**
* The {@link org.eclipse.emf.common.util.Diagnostic#getCode() code} for constraint 'Validate Var In Out Source Type Is Well Defined' of 'Var Declaration'.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
public static final int VAR_DECLARATION__VALIDATE_VAR_IN_OUT_SOURCE_TYPE_IS_WELL_DEFINED = 27;
public static final int VAR_DECLARATION__VALIDATE_VAR_IN_OUT_SOURCE_TYPE_IS_WELL_DEFINED = 28;

/**
* The {@link org.eclipse.emf.common.util.Diagnostic#getCode() code} for constraint 'Validate Var In Out Is Withed' of 'Var Declaration'.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
public static final int VAR_DECLARATION__VALIDATE_VAR_IN_OUT_IS_WITHED = 28;
public static final int VAR_DECLARATION__VALIDATE_VAR_IN_OUT_IS_WITHED = 29;

/**
* The {@link org.eclipse.emf.common.util.Diagnostic#getCode() code} for constraint 'Validate Var In Out Subapp Interface' of 'Var Declaration'.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
public static final int VAR_DECLARATION__VALIDATE_VAR_IN_OUT_SUBAPP_INTERFACE = 29;
public static final int VAR_DECLARATION__VALIDATE_VAR_IN_OUT_SUBAPP_INTERFACE = 30;

/**
* The {@link org.eclipse.emf.common.util.Diagnostic#getCode() code} for constraint 'Validate Var In Out Subapp Network' of 'Var Declaration'.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
public static final int VAR_DECLARATION__VALIDATE_VAR_IN_OUT_SUBAPP_NETWORK = 30;
public static final int VAR_DECLARATION__VALIDATE_VAR_IN_OUT_SUBAPP_NETWORK = 31;

/**
* A constant with a fixed name that can be used as the base value for additional hand written constants.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
private static final int GENERATED_DIAGNOSTIC_CODE_COUNT = 30;
private static final int GENERATED_DIAGNOSTIC_CODE_COUNT = 31;

/**
* A constant with a fixed name that can be used as the base value for additional hand written constants in a derived class.
Expand Down Expand Up @@ -1989,6 +1997,7 @@ public boolean validateLocalVariable(LocalVariable localVariable, DiagnosticChai
if (result || diagnostics != null) result &= validateITypedElement_validateType(localVariable, diagnostics, context);
if (result || diagnostics != null) result &= validateVarDeclaration_validateMultipleInputConnections(localVariable, diagnostics, context);
if (result || diagnostics != null) result &= validateVarDeclaration_validateNoValueForGenericTypeVariable(localVariable, diagnostics, context);
if (result || diagnostics != null) result &= validateVarDeclaration_validateNoValueForVariableLengthArrayVariable(localVariable, diagnostics, context);
if (result || diagnostics != null) result &= validateVarDeclaration_validateValueForGenericInstanceVariable(localVariable, diagnostics, context);
if (result || diagnostics != null) result &= validateVarDeclaration_validateVarInOutSourceTypeIsWellDefined(localVariable, diagnostics, context);
if (result || diagnostics != null) result &= validateVarDeclaration_validateVarInOutIsWithed(localVariable, diagnostics, context);
Expand Down Expand Up @@ -2676,6 +2685,7 @@ public boolean validateVarDeclaration(VarDeclaration varDeclaration, DiagnosticC
if (result || diagnostics != null) result &= validateITypedElement_validateType(varDeclaration, diagnostics, context);
if (result || diagnostics != null) result &= validateVarDeclaration_validateMultipleInputConnections(varDeclaration, diagnostics, context);
if (result || diagnostics != null) result &= validateVarDeclaration_validateNoValueForGenericTypeVariable(varDeclaration, diagnostics, context);
if (result || diagnostics != null) result &= validateVarDeclaration_validateNoValueForVariableLengthArrayVariable(varDeclaration, diagnostics, context);
if (result || diagnostics != null) result &= validateVarDeclaration_validateValueForGenericInstanceVariable(varDeclaration, diagnostics, context);
if (result || diagnostics != null) result &= validateVarDeclaration_validateVarInOutSourceTypeIsWellDefined(varDeclaration, diagnostics, context);
if (result || diagnostics != null) result &= validateVarDeclaration_validateVarInOutIsWithed(varDeclaration, diagnostics, context);
Expand Down Expand Up @@ -2704,6 +2714,16 @@ public boolean validateVarDeclaration_validateNoValueForGenericTypeVariable(VarD
return varDeclaration.validateNoValueForGenericTypeVariable(diagnostics, context);
}

/**
* Validates the validateNoValueForVariableLengthArrayVariable constraint of '<em>Var Declaration</em>'.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
public boolean validateVarDeclaration_validateNoValueForVariableLengthArrayVariable(VarDeclaration varDeclaration, DiagnosticChain diagnostics, Map<Object, Object> context) {
return varDeclaration.validateNoValueForVariableLengthArrayVariable(diagnostics, context);
}

/**
* Validates the validateValueForGenericInstanceVariable constraint of '<em>Var Declaration</em>'.
* <!-- begin-user-doc -->
Expand Down Expand Up @@ -2791,6 +2811,7 @@ public boolean validateMemberVarDeclaration(MemberVarDeclaration memberVarDeclar
if (result || diagnostics != null) result &= validateITypedElement_validateType(memberVarDeclaration, diagnostics, context);
if (result || diagnostics != null) result &= validateVarDeclaration_validateMultipleInputConnections(memberVarDeclaration, diagnostics, context);
if (result || diagnostics != null) result &= validateVarDeclaration_validateNoValueForGenericTypeVariable(memberVarDeclaration, diagnostics, context);
if (result || diagnostics != null) result &= validateVarDeclaration_validateNoValueForVariableLengthArrayVariable(memberVarDeclaration, diagnostics, context);
if (result || diagnostics != null) result &= validateVarDeclaration_validateValueForGenericInstanceVariable(memberVarDeclaration, diagnostics, context);
if (result || diagnostics != null) result &= validateVarDeclaration_validateVarInOutSourceTypeIsWellDefined(memberVarDeclaration, diagnostics, context);
if (result || diagnostics != null) result &= validateVarDeclaration_validateVarInOutIsWithed(memberVarDeclaration, diagnostics, context);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,8 @@ public final class Messages extends NLS {
public static String VALIDATOR_UNKNOWN_LITERAL_TYPE;
public static String VarDeclarationAnnotations_MultipleInputConnections;

public static String VarDeclarationAnnotations_MustNotSpecifyValueForVariableWithVariableArrayBounds;

public static String VarDeclarationAnnotations_ShouldNotSpecifyValueForGenericVariableInType;

public static String VarDeclarationAnnotations_ShouldSpecifyValueForGenericVariableInInstance;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,9 @@
public final class TypeDeclarationParser {

private static final Pattern SIMPLE_SUBRANGE_PATTERN = Pattern
.compile("([\\+\\-]?\\d+)\\s*\\.\\.\\s*([\\+\\-]?\\d+)"); //$NON-NLS-1$
.compile("([\\+\\-]?+\\d++)\\s*+\\.\\.\\s*+([\\+\\-]?+\\d++)"); //$NON-NLS-1$
private static final Pattern SIMPLE_ARRAY_SIZE_PATTERN = Pattern
.compile(SIMPLE_SUBRANGE_PATTERN + "(?:\\s*,\\s*" + SIMPLE_SUBRANGE_PATTERN + ")*"); //$NON-NLS-1$ //$NON-NLS-2$
.compile(SIMPLE_SUBRANGE_PATTERN + "(?:\\s*+,\\s*+" + SIMPLE_SUBRANGE_PATTERN + ")*+"); //$NON-NLS-1$ //$NON-NLS-2$

public static DataType parseTypeDeclaration(final DataType baseType, final String arraySize) {
final DataType result = parseLegacyTypeDeclaration(baseType, arraySize);
Expand Down Expand Up @@ -67,6 +67,11 @@ public static boolean isSimpleTypeDeclaration(final String arraySize) {
|| SIMPLE_ARRAY_SIZE_PATTERN.matcher(arraySize.trim()).matches();
}

public static boolean isVariableArrayBounds(final String arraySize) {
return arraySize != null && !arraySize.isBlank()
&& splitString(arraySize).stream().map(String::strip).anyMatch("*"::equals); //$NON-NLS-1$
}

private static Subrange parseSimpleSubrange(final String text) {
final Matcher matcher = SIMPLE_SUBRANGE_PATTERN.matcher(text);
if (matcher.matches()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import org.eclipse.emf.common.util.DiagnosticChain;
import org.eclipse.fordiac.ide.model.Messages;
import org.eclipse.fordiac.ide.model.datatype.helper.IecTypes.GenericTypes;
import org.eclipse.fordiac.ide.model.datatype.helper.TypeDeclarationParser;
import org.eclipse.fordiac.ide.model.errormarker.FordiacMarkerHelper;
import org.eclipse.fordiac.ide.model.helpers.VarInOutHelper;
import org.eclipse.fordiac.ide.model.libraryElement.FB;
Expand Down Expand Up @@ -66,6 +67,21 @@ public static boolean validateNoValueForGenericTypeVariable(final VarDeclaration
return true;
}

public static boolean validateNoValueForVariableLengthArrayVariable(final VarDeclaration varDeclaration,
final DiagnosticChain diagnostics, final Map<Object, Object> context) {
if (varDeclaration.isArray() && hasValue(varDeclaration)
&& TypeDeclarationParser.isVariableArrayBounds(varDeclaration.getArraySize().getValue())) {
if (diagnostics != null) {
diagnostics.add(new BasicDiagnostic(Diagnostic.ERROR, LibraryElementValidator.DIAGNOSTIC_SOURCE,
LibraryElementValidator.VAR_DECLARATION__VALIDATE_NO_VALUE_FOR_VARIABLE_LENGTH_ARRAY_VARIABLE,
Messages.VarDeclarationAnnotations_MustNotSpecifyValueForVariableWithVariableArrayBounds,
FordiacMarkerHelper.getDiagnosticData(varDeclaration)));
}
return false;
}
return true;
}

public static boolean validateValueForGenericInstanceVariable(final VarDeclaration varDeclaration,
final DiagnosticChain diagnostics, final Map<Object, Object> context) {
if (varDeclaration.isIsInput() && varDeclaration.getInputConnections().isEmpty()
Expand All @@ -87,7 +103,8 @@ public static boolean validateVarInOutSourceTypeIsWellDefined(final VarDeclarati
final DiagnosticChain diagnostics, final Map<Object, Object> context) {
if (varDeclaration.isInOutVar() && varDeclaration.isIsInput() && varDeclaration.getFBNetworkElement() != null
&& varDeclaration.getInputConnections().isEmpty()
&& ((varDeclaration.isArray() && varDeclaration.getArraySize().getValue().contains("*")) //$NON-NLS-1$
&& ((varDeclaration.isArray()
&& TypeDeclarationParser.isVariableArrayBounds(varDeclaration.getArraySize().getValue()))
|| GenericTypes.isAnyType(varDeclaration.getType()))) {
// We have a VarInOut input on a FB instance which is an array of variable
// length or an ANY variable, so its not well defined
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ VALIDATOR_TypeNotSupported=Type {0} is not supported
VALIDATOR_UnevenlyQuotedStringLiteral=Unevenly quoted string literal: {0}
VALIDATOR_UNKNOWN_LITERAL_TYPE=Unknown literal type: {0}
VarDeclarationAnnotations_MultipleInputConnections=Multiple input connections on variable
VarDeclarationAnnotations_MustNotSpecifyValueForVariableWithVariableArrayBounds=Must not specify a value for variable with variable array bounds
VarDeclarationAnnotations_ShouldNotSpecifyValueForGenericVariableInType=Should not specify a value for variable of generic type in defining type
VarDeclarationAnnotations_ShouldSpecifyValueForGenericVariableInInstance=Should specify a value for unconnected variable of generic type in instance
VarDeclarationAnnotations_VarInOutLeftNotConnected=VAR_IN_OUT ''{0}'' must be connected on the left, since it is connected on the inside
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,26 @@ void testCheckSimpleTypeDeclaration() {
assertFalse(TypeDeclarationParser.isSimpleTypeDeclaration("(()))")); //$NON-NLS-1$
}

@Test
void testCheckVariableArrayBounds() {
assertFalse(TypeDeclarationParser.isVariableArrayBounds(null));
assertFalse(TypeDeclarationParser.isVariableArrayBounds("")); //$NON-NLS-1$
assertFalse(TypeDeclarationParser.isVariableArrayBounds("17")); //$NON-NLS-1$
assertFalse(TypeDeclarationParser.isVariableArrayBounds("17, 4")); //$NON-NLS-1$
assertFalse(TypeDeclarationParser.isVariableArrayBounds("17 + 4 * 2, 42")); //$NON-NLS-1$

assertFalse(TypeDeclarationParser.isVariableArrayBounds("0..17")); //$NON-NLS-1$
assertFalse(TypeDeclarationParser.isVariableArrayBounds("-10..10")); //$NON-NLS-1$
assertFalse(TypeDeclarationParser.isVariableArrayBounds("0..17,21..42")); //$NON-NLS-1$

assertFalse(TypeDeclarationParser.isVariableArrayBounds("0..17*4")); //$NON-NLS-1$
assertFalse(TypeDeclarationParser.isVariableArrayBounds("0..17*4, 1..VAR")); //$NON-NLS-1$

assertTrue(TypeDeclarationParser.isVariableArrayBounds("*")); //$NON-NLS-1$
assertTrue(TypeDeclarationParser.isVariableArrayBounds("*,*")); //$NON-NLS-1$
assertTrue(TypeDeclarationParser.isVariableArrayBounds("0..17, *")); //$NON-NLS-1$
}

protected void assertTypeNameEquals(final String expected, final DataType type) {
assertNotNull(type);
assertEquals(expected, type.getName());
Expand Down

0 comments on commit cf02426

Please sign in to comment.