55 */
66#include " InstructionValidator.h"
77
8+ #include " GDCore/Events/Parsers/ExpressionParser2Node.h"
89#include " GDCore/Extensions/Metadata/AbstractFunctionMetadata.h"
910#include " GDCore/Extensions/Metadata/BehaviorMetadata.h"
1011#include " GDCore/Extensions/Metadata/InstructionMetadata.h"
2425
2526namespace gd {
2627
27- bool InstructionValidator::IsParameterValid (
28+ ParameterValidationResult InstructionValidator::ValidateParameter (
2829 const gd::Platform &platform,
2930 const gd::ProjectScopedContainers projectScopedContainers,
3031 const gd::Instruction &instruction, const InstructionMetadata &metadata,
3132 std::size_t parameterIndex, const gd::String &value) {
33+ ParameterValidationResult result;
34+
3235 if (parameterIndex >= instruction.GetParametersCount () ||
3336 parameterIndex >= metadata.GetParametersCount ()) {
34- return false ;
37+ result.isValid = false ;
38+ return result;
3539 }
40+
3641 const auto ¶meterMetadata = metadata.GetParameter (parameterIndex);
3742 // TODO Remove the ternary when all parameter declarations use
3843 // "number" instead of "expression".
3944 const auto ¶meterType = parameterMetadata.GetType () == " expression"
4045 ? " number"
4146 : parameterMetadata.GetType ();
47+
4248 bool shouldNotBeValidated = parameterType == " layer" && value.empty ();
4349 if (shouldNotBeValidated) {
44- return true ;
50+ return result; // Valid by default, no deprecation warning
4551 }
52+
4653 if (gd::ParameterMetadata::IsExpression (" number" , parameterType) ||
4754 gd::ParameterMetadata::IsExpression (" string" , parameterType) ||
4855 gd::ParameterMetadata::IsExpression (" variable" , parameterType)) {
@@ -52,13 +59,26 @@ bool InstructionValidator::IsParameterValid(
5259 parameterType,
5360 parameterMetadata.GetExtraInfo ());
5461 expressionNode.Visit (expressionValidator);
55- if (!expressionValidator.GetAllErrors ().empty ()) {
56- return false ;
62+
63+ // Check for fatal errors (validation)
64+ if (!expressionValidator.GetFatalErrors ().empty ()) {
65+ result.isValid = false ;
66+ }
67+
68+ // Check for deprecation warnings in the same pass
69+ const auto &allErrors = expressionValidator.GetAllErrors ();
70+ for (const auto *error : allErrors) {
71+ if (error->GetType () ==
72+ gd::ExpressionParserError::ErrorType::DeprecatedExpression) {
73+ result.hasDeprecationWarning = true ;
74+ break ;
75+ }
5776 }
77+
5878 // New object variable instructions require the variable to be
5979 // declared while legacy ones don't.
6080 // This is why it's done here instead of in the parser directly.
61- if (parameterType == " objectvar" &&
81+ if (result. isValid && parameterType == " objectvar" &&
6282 gd::VariableInstructionSwitcher::IsSwitchableVariableInstruction (
6383 instruction.GetType ())) {
6484 // Check at least the name of the root variable, it's the best we can
@@ -72,27 +92,39 @@ bool InstructionValidator::IsParameterValid(
7292 objectName,
7393 gd::InstructionValidator::GetRootVariableName (variableName)) ==
7494 gd::ObjectsContainersList::DoesNotExist) {
75- return false ;
95+ result. isValid = false ;
7696 }
7797 }
7898 } else if (gd::ParameterMetadata::IsObject (parameterType)) {
7999 const auto &objectOrGroupName =
80100 instruction.GetParameter (parameterIndex).GetPlainString ();
81101 const auto &objectsContainersList =
82102 projectScopedContainers.GetObjectsContainersList ();
83- return objectsContainersList.HasObjectOrGroupNamed (objectOrGroupName) &&
84- (parameterMetadata.GetExtraInfo ().empty () ||
85- objectsContainersList.GetTypeOfObject (objectOrGroupName) ==
86- parameterMetadata.GetExtraInfo ()) &&
87- InstructionValidator::HasRequiredBehaviors (
88- instruction, metadata, parameterIndex, objectsContainersList);
103+ result.isValid =
104+ objectsContainersList.HasObjectOrGroupNamed (objectOrGroupName) &&
105+ (parameterMetadata.GetExtraInfo ().empty () ||
106+ objectsContainersList.GetTypeOfObject (objectOrGroupName) ==
107+ parameterMetadata.GetExtraInfo ()) &&
108+ InstructionValidator::HasRequiredBehaviors (
109+ instruction, metadata, parameterIndex, objectsContainersList);
89110 } else if (gd::ParameterMetadata::IsExpression (" resource" , parameterType)) {
90111 const auto &resourceName =
91112 instruction.GetParameter (parameterIndex).GetPlainString ();
92- return projectScopedContainers.GetResourcesContainersList ()
93- .HasResourceNamed (resourceName);
113+ result. isValid = projectScopedContainers.GetResourcesContainersList ()
114+ .HasResourceNamed (resourceName);
94115 }
95- return true ;
116+
117+ return result;
118+ }
119+
120+ bool InstructionValidator::IsParameterValid (
121+ const gd::Platform &platform,
122+ const gd::ProjectScopedContainers projectScopedContainers,
123+ const gd::Instruction &instruction, const InstructionMetadata &metadata,
124+ std::size_t parameterIndex, const gd::String &value) {
125+ return ValidateParameter (platform, projectScopedContainers, instruction,
126+ metadata, parameterIndex, value)
127+ .isValid ;
96128}
97129
98130gd::String InstructionValidator::GetRootVariableName (const gd::String &name) {
@@ -107,6 +139,16 @@ gd::String InstructionValidator::GetRootVariableName(const gd::String &name) {
107139 : squareBracketPosition);
108140};
109141
142+ bool InstructionValidator::HasDeprecationWarnings (
143+ const gd::Platform &platform,
144+ const gd::ProjectScopedContainers projectScopedContainers,
145+ const gd::Instruction &instruction, const InstructionMetadata &metadata,
146+ std::size_t parameterIndex, const gd::String &value) {
147+ return ValidateParameter (platform, projectScopedContainers, instruction,
148+ metadata, parameterIndex, value)
149+ .hasDeprecationWarning ;
150+ }
151+
110152bool InstructionValidator::HasRequiredBehaviors (
111153 const gd::Instruction &instruction,
112154 const gd::InstructionMetadata &instructionMetadata,
0 commit comments