diff --git a/Core/GDCore/Events/CodeGeneration/ExpressionCodeGenerator.cpp b/Core/GDCore/Events/CodeGeneration/ExpressionCodeGenerator.cpp index 86aca52b5f..e0d327b6eb 100644 --- a/Core/GDCore/Events/CodeGeneration/ExpressionCodeGenerator.cpp +++ b/Core/GDCore/Events/CodeGeneration/ExpressionCodeGenerator.cpp @@ -55,6 +55,7 @@ gd::String ExpressionCodeGenerator::GenerateExpressionCode( gd::ExpressionValidator validator(codeGenerator.GetPlatform(), codeGenerator.GetProjectScopedContainers(), rootType, + rootObjectName, extraInfo); node->Visit(validator); if (!validator.GetFatalErrors().empty()) { diff --git a/Core/GDCore/IDE/Events/EventsBehaviorRenamer.cpp b/Core/GDCore/IDE/Events/EventsBehaviorRenamer.cpp index 6e97c89ea7..a450aa71ac 100644 --- a/Core/GDCore/IDE/Events/EventsBehaviorRenamer.cpp +++ b/Core/GDCore/IDE/Events/EventsBehaviorRenamer.cpp @@ -15,7 +15,6 @@ #include "GDCore/Events/Parsers/ExpressionParser2NodeWorker.h" #include "GDCore/Extensions/Metadata/MetadataProvider.h" #include "GDCore/Extensions/Metadata/ParameterMetadataTools.h" -#include "GDCore/IDE/Events/ExpressionValidator.h" #include "GDCore/Project/Layout.h" #include "GDCore/Project/Project.h" #include "GDCore/String.h" diff --git a/Core/GDCore/IDE/Events/EventsContextAnalyzer.cpp b/Core/GDCore/IDE/Events/EventsContextAnalyzer.cpp index 58aac2059c..8c209dcbb1 100644 --- a/Core/GDCore/IDE/Events/EventsContextAnalyzer.cpp +++ b/Core/GDCore/IDE/Events/EventsContextAnalyzer.cpp @@ -15,7 +15,6 @@ #include "GDCore/Extensions/Metadata/InstructionMetadata.h" #include "GDCore/Extensions/Metadata/MetadataProvider.h" #include "GDCore/Extensions/Metadata/ParameterMetadataTools.h" -#include "GDCore/IDE/Events/ExpressionValidator.h" #include "GDCore/IDE/Events/ExpressionTypeFinder.h" #include "GDCore/Project/Layout.h" #include "GDCore/Project/Project.h" diff --git a/Core/GDCore/IDE/Events/EventsParameterReplacer.cpp b/Core/GDCore/IDE/Events/EventsParameterReplacer.cpp index 9a3e800d38..b6cab33443 100644 --- a/Core/GDCore/IDE/Events/EventsParameterReplacer.cpp +++ b/Core/GDCore/IDE/Events/EventsParameterReplacer.cpp @@ -18,7 +18,6 @@ #include "GDCore/Extensions/Metadata/MetadataProvider.h" #include "GDCore/Extensions/Metadata/ParameterMetadata.h" #include "GDCore/Extensions/Metadata/ParameterMetadataTools.h" -#include "GDCore/IDE/Events/ExpressionValidator.h" #include "GDCore/Project/Layout.h" #include "GDCore/Project/Project.h" #include "GDCore/Project/ProjectScopedContainers.h" diff --git a/Core/GDCore/IDE/Events/EventsPropertyReplacer.cpp b/Core/GDCore/IDE/Events/EventsPropertyReplacer.cpp index 7783f7d74a..ac5ce5ce7c 100644 --- a/Core/GDCore/IDE/Events/EventsPropertyReplacer.cpp +++ b/Core/GDCore/IDE/Events/EventsPropertyReplacer.cpp @@ -18,7 +18,6 @@ #include "GDCore/Extensions/Metadata/MetadataProvider.h" #include "GDCore/Extensions/Metadata/ParameterMetadata.h" #include "GDCore/Extensions/Metadata/ParameterMetadataTools.h" -#include "GDCore/IDE/Events/ExpressionValidator.h" #include "GDCore/Project/Layout.h" #include "GDCore/Project/Project.h" #include "GDCore/Project/ProjectScopedContainers.h" diff --git a/Core/GDCore/IDE/Events/EventsVariableInstructionTypeSwitcher.cpp b/Core/GDCore/IDE/Events/EventsVariableInstructionTypeSwitcher.cpp index 974c3f3cc0..73eb2fff79 100644 --- a/Core/GDCore/IDE/Events/EventsVariableInstructionTypeSwitcher.cpp +++ b/Core/GDCore/IDE/Events/EventsVariableInstructionTypeSwitcher.cpp @@ -18,7 +18,6 @@ #include "GDCore/Extensions/Metadata/MetadataProvider.h" #include "GDCore/Extensions/Metadata/ParameterMetadata.h" #include "GDCore/Extensions/Metadata/ParameterMetadataTools.h" -#include "GDCore/IDE/Events/ExpressionValidator.h" #include "GDCore/IDE/Events/ExpressionVariableOwnerFinder.h" #include "GDCore/IDE/Events/ExpressionVariableNameFinder.h" #include "GDCore/IDE/VariableInstructionSwitcher.h" diff --git a/Core/GDCore/IDE/Events/EventsVariableReplacer.cpp b/Core/GDCore/IDE/Events/EventsVariableReplacer.cpp index cc3dabb4bb..ab18332ffc 100644 --- a/Core/GDCore/IDE/Events/EventsVariableReplacer.cpp +++ b/Core/GDCore/IDE/Events/EventsVariableReplacer.cpp @@ -18,7 +18,6 @@ #include "GDCore/Extensions/Metadata/MetadataProvider.h" #include "GDCore/Extensions/Metadata/ParameterMetadata.h" #include "GDCore/Extensions/Metadata/ParameterMetadataTools.h" -#include "GDCore/IDE/Events/ExpressionValidator.h" #include "GDCore/IDE/Events/ExpressionVariableOwnerFinder.h" #include "GDCore/IDE/Events/ExpressionVariableNameFinder.h" #include "GDCore/IDE/VariableInstructionSwitcher.h" diff --git a/Core/GDCore/IDE/Events/ExpressionValidator.cpp b/Core/GDCore/IDE/Events/ExpressionValidator.cpp index 672431985d..8de5525381 100644 --- a/Core/GDCore/IDE/Events/ExpressionValidator.cpp +++ b/Core/GDCore/IDE/Events/ExpressionValidator.cpp @@ -392,6 +392,12 @@ ExpressionValidator::Type ExpressionValidator::ValidateFunction( return returnType; } + const gd::String parentRootObjectName = rootObjectName; + // We don't check objectvar parameters since they are only used by the legacy + // functions like: `Object.Variable(MyVariable)` which allow undeclared + // variables. + rootObjectName = emptyParameterExtraInfo; + // TODO: reverse the order of diagnostic? size_t writtenParametersFirstIndex = ExpressionParser2::WrittenParametersFirstIndex(function.objectName, @@ -452,6 +458,7 @@ ExpressionValidator::Type ExpressionValidator::ValidateFunction( } metadataIndex++; } + rootObjectName = parentRootObjectName; return returnType; } diff --git a/Core/GDCore/IDE/Events/ExpressionValidator.h b/Core/GDCore/IDE/Events/ExpressionValidator.h index 27ada25ad2..869ff537f4 100644 --- a/Core/GDCore/IDE/Events/ExpressionValidator.h +++ b/Core/GDCore/IDE/Events/ExpressionValidator.h @@ -40,10 +40,12 @@ class GD_CORE_API ExpressionValidator : public ExpressionParser2NodeWorker { ExpressionValidator(const gd::Platform &platform_, const gd::ProjectScopedContainers & projectScopedContainers_, const gd::String &rootType_, + const gd::String &rootObjectName_ = emptyParameterExtraInfo, const gd::String &extraInfo_ = emptyParameterExtraInfo) : platform(platform_), projectScopedContainers(projectScopedContainers_), parentType(StringToType(gd::ValueTypeMetadata::GetExpressionPrimitiveValueType(rootType_))), + rootObjectName(rootObjectName_), childType(Type::Unknown), forbidsUsageOfBracketsBecauseParentIsObject(false), currentParameterExtraInfo(&extraInfo_), @@ -593,6 +595,8 @@ private: std::vector> supplementalErrors; Type childType; ///< The type "discovered" down the tree and passed up. Type parentType; ///< The type "required" by the top of the tree. + /** The root object name of the expression or a function call. */ + gd::String rootObjectName; bool forbidsUsageOfBracketsBecauseParentIsObject; gd::String variableObjectName; gd::ExpressionParserLocation variableObjectNameLocation; diff --git a/Core/GDCore/IDE/Events/ExpressionsParameterMover.cpp b/Core/GDCore/IDE/Events/ExpressionsParameterMover.cpp index 7eb6e23c1c..bf2a6d848b 100644 --- a/Core/GDCore/IDE/Events/ExpressionsParameterMover.cpp +++ b/Core/GDCore/IDE/Events/ExpressionsParameterMover.cpp @@ -14,7 +14,6 @@ #include "GDCore/Events/Parsers/ExpressionParser2NodePrinter.h" #include "GDCore/Events/Parsers/ExpressionParser2NodeWorker.h" #include "GDCore/Extensions/Metadata/MetadataProvider.h" -#include "GDCore/IDE/Events/ExpressionValidator.h" #include "GDCore/Project/Layout.h" #include "GDCore/Project/Project.h" #include "GDCore/String.h" diff --git a/Core/GDCore/IDE/Events/ExpressionsRenamer.cpp b/Core/GDCore/IDE/Events/ExpressionsRenamer.cpp index b0382ad322..e973d25894 100644 --- a/Core/GDCore/IDE/Events/ExpressionsRenamer.cpp +++ b/Core/GDCore/IDE/Events/ExpressionsRenamer.cpp @@ -14,7 +14,6 @@ #include "GDCore/Events/Parsers/ExpressionParser2NodePrinter.h" #include "GDCore/Events/Parsers/ExpressionParser2NodeWorker.h" #include "GDCore/Extensions/Metadata/MetadataProvider.h" -#include "GDCore/IDE/Events/ExpressionValidator.h" #include "GDCore/Project/Layout.h" #include "GDCore/Project/Project.h" #include "GDCore/String.h" diff --git a/Core/GDCore/IDE/Events/ProjectElementRenamer.cpp b/Core/GDCore/IDE/Events/ProjectElementRenamer.cpp index a8fc2d4115..6374da7b17 100644 --- a/Core/GDCore/IDE/Events/ProjectElementRenamer.cpp +++ b/Core/GDCore/IDE/Events/ProjectElementRenamer.cpp @@ -15,7 +15,6 @@ #include "GDCore/Events/Parsers/ExpressionParser2NodeWorker.h" #include "GDCore/Extensions/Metadata/MetadataProvider.h" #include "GDCore/Extensions/Metadata/ParameterMetadataTools.h" -#include "GDCore/IDE/Events/ExpressionValidator.h" #include "GDCore/Project/Layout.h" #include "GDCore/Project/Project.h" #include "GDCore/String.h" diff --git a/Core/GDCore/IDE/InstructionValidator.cpp b/Core/GDCore/IDE/InstructionValidator.cpp index 5608df5af2..1f7c35446e 100644 --- a/Core/GDCore/IDE/InstructionValidator.cpp +++ b/Core/GDCore/IDE/InstructionValidator.cpp @@ -65,10 +65,23 @@ ParameterValidationResult InstructionValidator::ValidateParameter( if (gd::ParameterMetadata::IsExpression("number", parameterType) || gd::ParameterMetadata::IsExpression("string", parameterType) || gd::ParameterMetadata::IsExpression("variable", parameterType)) { + + // New object variable instructions require the variable to be + // declared while legacy ones don't. + // For legacy variable instruction, we pass an empty object name. + gd::String rootObjectName = ""; + if (parameterType == "objectvar" && + gd::VariableInstructionSwitcher::IsSwitchableVariableInstruction( + instruction.GetType())) { + const auto &objectsContainersList = + projectScopedContainers.GetObjectsContainersList(); + rootObjectName = instruction.GetParameter(0).GetPlainString(); + } auto &expressionNode = *instruction.GetParameter(parameterIndex).GetRootNode(); ExpressionValidator expressionValidator(platform, projectScopedContainers, parameterType, + rootObjectName, parameterMetadata.GetExtraInfo()); expressionNode.Visit(expressionValidator); @@ -78,27 +91,6 @@ ParameterValidationResult InstructionValidator::ValidateParameter( if (!expressionValidator.GetDeprecationWarnings().empty()) { result.hasDeprecationWarning = true; } - - // New object variable instructions require the variable to be - // declared while legacy ones don't. - // This is why it's done here instead of in the parser directly. - if (result.isValid && parameterType == "objectvar" && - gd::VariableInstructionSwitcher::IsSwitchableVariableInstruction( - instruction.GetType())) { - // Check at least the name of the root variable, it's the best we can - // do. - const auto &objectsContainersList = - projectScopedContainers.GetObjectsContainersList(); - const auto &objectName = instruction.GetParameter(0).GetPlainString(); - const auto &variableName = - instruction.GetParameter(parameterIndex).GetPlainString(); - if (objectsContainersList.HasObjectOrGroupWithVariableNamed( - objectName, - gd::InstructionValidator::GetRootVariableName(variableName)) == - gd::ObjectsContainersList::DoesNotExist) { - result.isValid = false; - } - } } else if (gd::ParameterMetadata::IsObject(parameterType)) { const auto &objectOrGroupName = instruction.GetParameter(parameterIndex).GetPlainString(); diff --git a/Core/tests/DummyPlatform.cpp b/Core/tests/DummyPlatform.cpp index 9e888804d4..56a0ee8e51 100644 --- a/Core/tests/DummyPlatform.cpp +++ b/Core/tests/DummyPlatform.cpp @@ -5,7 +5,6 @@ */ #include "GDCore/Extensions/Platform.h" #include "GDCore/Extensions/PlatformExtension.h" -#include "GDCore/IDE/Events/ExpressionValidator.h" #include "GDCore/Project/Behavior.h" #include "GDCore/Project/ObjectConfiguration.h" #include "GDCore/Extensions/Builtin/SpriteExtension/SpriteObject.h" diff --git a/Core/tests/ExpressionParser2NaugtyStrings.cpp b/Core/tests/ExpressionParser2NaugtyStrings.cpp index 3a44004e5e..5fe6ab2ced 100644 --- a/Core/tests/ExpressionParser2NaugtyStrings.cpp +++ b/Core/tests/ExpressionParser2NaugtyStrings.cpp @@ -8,7 +8,6 @@ #include "DummyPlatform.h" #include "GDCore/Extensions/Platform.h" #include "GDCore/Extensions/PlatformExtension.h" -#include "GDCore/IDE/Events/ExpressionValidator.h" #include "GDCore/Project/Layout.h" #include "GDCore/Project/Project.h" #include "catch.hpp" diff --git a/Core/tests/ExpressionParser2NodePrinter.cpp b/Core/tests/ExpressionParser2NodePrinter.cpp index 5638a7b387..7fe9d0a9a8 100644 --- a/Core/tests/ExpressionParser2NodePrinter.cpp +++ b/Core/tests/ExpressionParser2NodePrinter.cpp @@ -8,7 +8,6 @@ #include "GDCore/Events/Parsers/ExpressionParser2.h" #include "GDCore/Extensions/Platform.h" #include "GDCore/Extensions/PlatformExtension.h" -#include "GDCore/IDE/Events/ExpressionValidator.h" #include "GDCore/Project/Layout.h" #include "GDCore/Project/Project.h" #include "catch.hpp"