From 8a0045b3b01d48da7c0f9cc2de2bc30989a7b71e Mon Sep 17 00:00:00 2001 From: D8H Date: Fri, 13 Dec 2024 19:57:14 +0100 Subject: [PATCH] Rename events-function parameters in events (#7215) --- .../Extensions/Metadata/ValueTypeMetadata.h | 12 +- .../IDE/Events/EventsParameterReplacer.cpp | 243 +++++++++++++++ .../IDE/Events/EventsParameterReplacer.h | 52 ++++ .../IDE/Events/EventsPropertyReplacer.h | 1 + Core/GDCore/IDE/Events/EventsRefactorer.cpp | 272 ++++++---------- Core/GDCore/IDE/Events/EventsRefactorer.h | 39 +-- Core/GDCore/IDE/WholeProjectRefactorer.cpp | 72 ++++- Core/GDCore/IDE/WholeProjectRefactorer.h | 22 ++ Core/tests/DummyPlatform.cpp | 4 +- Core/tests/WholeProjectRefactorer.cpp | 290 +++++++++++++++++- GDevelop.js/Bindings/Bindings.idl | 16 +- GDevelop.js/Bindings/Wrapper.cpp | 1 + GDevelop.js/types.d.ts | 5 +- GDevelop.js/types/gdeventsrefactorer.js | 2 +- GDevelop.js/types/gdwholeprojectrefactorer.js | 3 +- .../EventsFunctionParametersEditor.js | 72 +++-- .../index.js | 10 + .../EventsFunctionsExtensionEditor/index.js | 23 ++ .../EventsFunctionExtractorDialog.js | 3 + ...entsFunctionConfigurationEditor.stories.js | 12 + 20 files changed, 898 insertions(+), 256 deletions(-) create mode 100644 Core/GDCore/IDE/Events/EventsParameterReplacer.cpp create mode 100644 Core/GDCore/IDE/Events/EventsParameterReplacer.h diff --git a/Core/GDCore/Extensions/Metadata/ValueTypeMetadata.h b/Core/GDCore/Extensions/Metadata/ValueTypeMetadata.h index ccc37cd693d1..a39e082fd817 100644 --- a/Core/GDCore/Extensions/Metadata/ValueTypeMetadata.h +++ b/Core/GDCore/Extensions/Metadata/ValueTypeMetadata.h @@ -135,7 +135,17 @@ class GD_CORE_API ValueTypeMetadata { * and ExpressionAutocompletion) and in the EventsCodeGenerator. */ bool IsVariable() const { - return gd::ValueTypeMetadata::GetPrimitiveValueType(name) == "variable"; + return gd::ValueTypeMetadata::IsVariable(name); + } + + /** + * \brief Return true if the type of the parameter is a variable. + * \note If you had a new type of parameter, also add it in the IDE ( + * see EventsFunctionParametersEditor, ParameterRenderingService + * and ExpressionAutocompletion) and in the EventsCodeGenerator. + */ + static bool IsVariable(const gd::String &type) { + return gd::ValueTypeMetadata::GetPrimitiveValueType(type) == "variable"; } /** diff --git a/Core/GDCore/IDE/Events/EventsParameterReplacer.cpp b/Core/GDCore/IDE/Events/EventsParameterReplacer.cpp new file mode 100644 index 000000000000..ae31c5a6548b --- /dev/null +++ b/Core/GDCore/IDE/Events/EventsParameterReplacer.cpp @@ -0,0 +1,243 @@ +/* + * GDevelop Core + * Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights + * reserved. This project is released under the MIT License. + */ +#include "GDCore/IDE/Events/EventsParameterReplacer.h" + +#include +#include +#include +#include +#include + +#include "GDCore/Events/Event.h" +#include "GDCore/Events/EventsList.h" +#include "GDCore/Events/Parsers/ExpressionParser2NodePrinter.h" +#include "GDCore/Events/Parsers/ExpressionParser2NodeWorker.h" +#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" +#include "GDCore/Project/PropertiesContainer.h" +#include "GDCore/String.h" +#include "GDCore/Tools/Log.h" + +namespace gd { + +/** + * \brief Go through the nodes and rename parameters. + * + * \see gd::ExpressionParser2 + */ +class GD_CORE_API ExpressionParameterReplacer + : public ExpressionParser2NodeWorker { + public: + ExpressionParameterReplacer( + const gd::Platform& platform_, + const gd::ProjectScopedContainers& projectScopedContainers_, + bool isParentTypeAVariable_, + const std::unordered_map& oldToNewPropertyNames_) + : hasDoneRenaming(false), + platform(platform_), + projectScopedContainers(projectScopedContainers_), + isParentTypeAVariable(isParentTypeAVariable_), + oldToNewPropertyNames(oldToNewPropertyNames_){}; + virtual ~ExpressionParameterReplacer(){}; + + bool HasDoneRenaming() const { return hasDoneRenaming; } + + protected: + void OnVisitSubExpressionNode(SubExpressionNode& node) override { + node.expression->Visit(*this); + } + void OnVisitOperatorNode(OperatorNode& node) override { + node.leftHandSide->Visit(*this); + node.rightHandSide->Visit(*this); + } + void OnVisitUnaryOperatorNode(UnaryOperatorNode& node) override { + node.factor->Visit(*this); + } + void OnVisitNumberNode(NumberNode& node) override {} + void OnVisitTextNode(TextNode& node) override {} + void OnVisitVariableNode(VariableNode& node) override { + if (isParentTypeAVariable) { + // Do nothing, it's a variable. + if (node.child) node.child->Visit(*this); + return; + } + + // The node represents a variable or an object name on which a variable + // will be accessed, or a property with a child. + + projectScopedContainers.MatchIdentifierWithName( + // The property name is changed after the refactor operation. + node.name, + [&]() { + // Do nothing, it's an object variable. + if (node.child) node.child->Visit(*this); + }, [&]() { + // Do nothing, it's a variable. + if (node.child) node.child->Visit(*this); + }, [&]() { + // Do nothing, it's a property. + if (node.child) node.child->Visit(*this); + }, [&]() { + // This is a parameter + RenameParameter(node.name); + if (node.child) node.child->Visit(*this); + }, [&]() { + // Do nothing, it's something else. + if (node.child) node.child->Visit(*this); + }); + } + void OnVisitVariableAccessorNode(VariableAccessorNode& node) override { + if (node.child) node.child->Visit(*this); + } + void OnVisitVariableBracketAccessorNode( + VariableBracketAccessorNode& node) override { + bool isGrandParentTypeAVariable = isParentTypeAVariable; + isParentTypeAVariable = false; + node.expression->Visit(*this); + isParentTypeAVariable = isGrandParentTypeAVariable; + if (node.child) node.child->Visit(*this); + } + void OnVisitIdentifierNode(IdentifierNode& node) override { + if (isParentTypeAVariable) { + // Do nothing, it's a variable. + return; + } + projectScopedContainers.MatchIdentifierWithName( + // The property name is changed after the refactor operation + node.identifierName, + [&]() { + // Do nothing, it's an object variable. + }, [&]() { + // Do nothing, it's a variable. + }, [&]() { + // Do nothing, it's a property. + }, [&]() { + // This is a parameter. + RenameParameter(node.identifierName); + }, [&]() { + // Do nothing, it's something else. + }); + } + void OnVisitObjectFunctionNameNode(ObjectFunctionNameNode& node) override {} + void OnVisitFunctionCallNode(FunctionCallNode &node) override { + bool isGrandParentTypeAVariable = isParentTypeAVariable; + for (auto ¶meter : node.parameters) { + const auto ¶meterMetadata = + gd::MetadataProvider::GetFunctionCallParameterMetadata( + platform, projectScopedContainers.GetObjectsContainersList(), + node, *parameter); + if (!parameterMetadata) { + continue; + } + const auto ¶meterTypeMetadata = + parameterMetadata->GetValueTypeMetadata(); + if (gd::EventsParameterReplacer::CanContainParameter( + parameterTypeMetadata)) { + isParentTypeAVariable = parameterTypeMetadata.IsVariable(); + parameter->Visit(*this); + } + } + isParentTypeAVariable = isGrandParentTypeAVariable; + } + void OnVisitEmptyNode(EmptyNode& node) override {} + + private: + bool hasDoneRenaming; + + bool RenameParameter( + gd::String& name) { + if (oldToNewPropertyNames.count(name) >= 1) { + name = oldToNewPropertyNames.find(name)->second; + hasDoneRenaming = true; + return true; + } + + return false; // Nothing was changed or done. + } + + // Scope: + const gd::Platform& platform; + const gd::ProjectScopedContainers& projectScopedContainers; + + // Renaming to do + const std::unordered_map& oldToNewPropertyNames; + + gd::String objectNameToUseForVariableAccessor; + bool isParentTypeAVariable; +}; + +bool EventsParameterReplacer::DoVisitInstruction(gd::Instruction& instruction, + bool isCondition) { + const auto& metadata = isCondition + ? gd::MetadataProvider::GetConditionMetadata( + platform, instruction.GetType()) + : gd::MetadataProvider::GetActionMetadata( + platform, instruction.GetType()); + + gd::ParameterMetadataTools::IterateOverParametersWithIndex( + instruction.GetParameters(), + metadata.GetParameters(), + [&](const gd::ParameterMetadata& parameterMetadata, + const gd::Expression& parameterValue, + size_t parameterIndex, + const gd::String& lastObjectName) { + if (!gd::EventsParameterReplacer::CanContainParameter( + parameterMetadata.GetValueTypeMetadata())) { + return; + } + auto node = parameterValue.GetRootNode(); + if (node) { + ExpressionParameterReplacer renamer( + platform, GetProjectScopedContainers(), + parameterMetadata.GetValueTypeMetadata().IsVariable(), + oldToNewPropertyNames); + node->Visit(renamer); + + if (renamer.HasDoneRenaming()) { + instruction.SetParameter( + parameterIndex, ExpressionParser2NodePrinter::PrintNode(*node)); + } + } + }); + + return false; +} + +bool EventsParameterReplacer::DoVisitEventExpression( + gd::Expression& expression, const gd::ParameterMetadata& metadata) { + if (!gd::EventsParameterReplacer::CanContainParameter( + metadata.GetValueTypeMetadata())) { + return false; + } + auto node = expression.GetRootNode(); + if (node) { + ExpressionParameterReplacer renamer( + platform, GetProjectScopedContainers(), + metadata.GetValueTypeMetadata().IsVariable(), oldToNewPropertyNames); + node->Visit(renamer); + + if (renamer.HasDoneRenaming()) { + expression = ExpressionParser2NodePrinter::PrintNode(*node); + } + } + + return false; +} + +bool EventsParameterReplacer::CanContainParameter( + const gd::ValueTypeMetadata &valueTypeMetadata) { + return valueTypeMetadata.IsVariable() || valueTypeMetadata.IsNumber() || + valueTypeMetadata.IsString(); +} + +EventsParameterReplacer::~EventsParameterReplacer() {} + +} // namespace gd diff --git a/Core/GDCore/IDE/Events/EventsParameterReplacer.h b/Core/GDCore/IDE/Events/EventsParameterReplacer.h new file mode 100644 index 000000000000..3e233f617438 --- /dev/null +++ b/Core/GDCore/IDE/Events/EventsParameterReplacer.h @@ -0,0 +1,52 @@ +/* + * GDevelop Core + * Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights + * reserved. This project is released under the MIT License. + */ +#pragma once + +#include +#include +#include +#include +#include + +#include "GDCore/IDE/Events/ArbitraryEventsWorker.h" +#include "GDCore/String.h" +namespace gd { +class BaseEvent; +class PropertiesContainer; +class EventsList; +class Platform; +} // namespace gd + +namespace gd { +/** + * \brief Replace in expressions and in parameters of actions or conditions, + * references to the name of a parameter by another. + * + * \ingroup IDE + */ +class GD_CORE_API EventsParameterReplacer + : public ArbitraryEventsWorkerWithContext { + public: + EventsParameterReplacer( + const gd::Platform &platform_, + const std::unordered_map &oldToNewPropertyNames_) + : platform(platform_), + oldToNewPropertyNames(oldToNewPropertyNames_){}; + virtual ~EventsParameterReplacer(); + + static bool CanContainParameter(const gd::ValueTypeMetadata &valueTypeMetadata); + + private: + bool DoVisitInstruction(gd::Instruction &instruction, + bool isCondition) override; + bool DoVisitEventExpression(gd::Expression &expression, + const gd::ParameterMetadata &metadata) override; + + const gd::Platform &platform; + const std::unordered_map &oldToNewPropertyNames; +}; + +} // namespace gd diff --git a/Core/GDCore/IDE/Events/EventsPropertyReplacer.h b/Core/GDCore/IDE/Events/EventsPropertyReplacer.h index 4a362b93bd10..5c850230a8a7 100644 --- a/Core/GDCore/IDE/Events/EventsPropertyReplacer.h +++ b/Core/GDCore/IDE/Events/EventsPropertyReplacer.h @@ -4,6 +4,7 @@ * reserved. This project is released under the MIT License. */ #pragma once + #include #include #include diff --git a/Core/GDCore/IDE/Events/EventsRefactorer.cpp b/Core/GDCore/IDE/Events/EventsRefactorer.cpp index 1b676888520e..058d2fa4c3e4 100644 --- a/Core/GDCore/IDE/Events/EventsRefactorer.cpp +++ b/Core/GDCore/IDE/Events/EventsRefactorer.cpp @@ -22,6 +22,7 @@ #include "GDCore/Project/EventsBasedObject.h" #include "GDCore/Project/ProjectScopedContainers.h" #include "GDCore/IDE/Events/ExpressionTypeFinder.h" +#include "GDCore/IDE/Events/ArbitraryEventsWorker.h" using namespace std; @@ -51,17 +52,17 @@ class GD_CORE_API ExpressionObjectRenamer : public ExpressionParser2NodeWorker { static bool Rename(const gd::Platform &platform, const gd::ProjectScopedContainers &projectScopedContainers, - const gd::String &rootType, - gd::ExpressionNode& node, - const gd::String& objectName, - const gd::String& objectNewName) { - if (gd::ExpressionValidator::HasNoErrors(platform, projectScopedContainers, rootType, node)) { - ExpressionObjectRenamer renamer(platform, projectScopedContainers, rootType, objectName, objectNewName); + const gd::String &rootType, gd::ExpressionNode &node, + const gd::String &objectName, + const gd::String &objectNewName) { + if (gd::ExpressionValidator::HasNoErrors(platform, projectScopedContainers, + rootType, node)) { + ExpressionObjectRenamer renamer(platform, projectScopedContainers, + rootType, objectName, objectNewName); node.Visit(renamer); return renamer.HasDoneRenaming(); } - return false; } @@ -83,7 +84,7 @@ class GD_CORE_API ExpressionObjectRenamer : public ExpressionParser2NodeWorker { void OnVisitVariableNode(VariableNode& node) override { auto type = gd::ExpressionTypeFinder::GetType(platform, projectScopedContainers, rootType, node); - if (gd::ValueTypeMetadata::IsTypeLegacyPreScopedVariable(type)) { + if (gd::ValueTypeMetadata::IsVariable(type)) { // Nothing to do (this can't reference an object) } else { if (node.name == objectName) { @@ -119,7 +120,7 @@ class GD_CORE_API ExpressionObjectRenamer : public ExpressionParser2NodeWorker { node.identifierName == objectName) { hasDoneRenaming = true; node.identifierName = objectNewName; - } else if (gd::ValueTypeMetadata::IsTypeLegacyPreScopedVariable(type)) { + } else if (gd::ValueTypeMetadata::IsVariable(type)) { // Nothing to do (this can't reference an object) } else { if (node.identifierName == objectName) { @@ -295,183 +296,114 @@ class GD_CORE_API ExpressionObjectFinder : public ExpressionParser2NodeWorker { const gd::String rootType; }; -bool EventsRefactorer::RenameObjectInActions(const gd::Platform& platform, - const gd::ProjectScopedContainers& projectScopedContainers, - gd::InstructionsList& actions, - gd::String oldName, - gd::String newName) { - bool somethingModified = false; - - for (std::size_t aId = 0; aId < actions.size(); ++aId) { - const gd::InstructionMetadata& instrInfos = - MetadataProvider::GetActionMetadata(platform, actions[aId].GetType()); - for (std::size_t pNb = 0; pNb < instrInfos.parameters.GetParametersCount(); ++pNb) { - // Replace object's name in parameters - if (gd::ParameterMetadata::IsObject(instrInfos.parameters.GetParameter(pNb).GetType()) && - actions[aId].GetParameter(pNb).GetPlainString() == oldName) - actions[aId].SetParameter(pNb, gd::Expression(newName)); - // Replace object's name in expressions - else if (ParameterMetadata::IsExpression( - "number", instrInfos.parameters.GetParameter(pNb).GetType())) { - auto node = actions[aId].GetParameter(pNb).GetRootNode(); - - if (ExpressionObjectRenamer::Rename(platform, projectScopedContainers, "number", *node, oldName, newName)) { - actions[aId].SetParameter( - pNb, ExpressionParser2NodePrinter::PrintNode(*node)); - } - } - // Replace object's name in text expressions - else if (ParameterMetadata::IsExpression( - "string", instrInfos.parameters.GetParameter(pNb).GetType())) { - auto node = actions[aId].GetParameter(pNb).GetRootNode(); - - if (ExpressionObjectRenamer::Rename(platform, projectScopedContainers, "string", *node, oldName, newName)) { - actions[aId].SetParameter( - pNb, ExpressionParser2NodePrinter::PrintNode(*node)); - } - } - } +/** + * \brief Replace in expressions and in parameters of actions or conditions, + * references to the name of an object by another. + * + * \ingroup IDE + */ +class GD_CORE_API EventsObjectReplacer + : public ArbitraryEventsWorkerWithContext { +public: + EventsObjectReplacer(const gd::Platform &platform_, + const gd::ObjectsContainer &targetedObjectsContainer_, + const gd::String &oldObjectName_, + const gd::String &newObjectName_) + : platform(platform_), + targetedObjectsContainer(targetedObjectsContainer_), + oldObjectName(oldObjectName_), newObjectName(newObjectName_){}; + + virtual ~EventsObjectReplacer() {} + +private: + bool DoVisitInstruction(gd::Instruction &instruction, + bool isCondition) override { + if (&targetedObjectsContainer != + GetProjectScopedContainers() + .GetObjectsContainersList() + .GetObjectsContainerFromObjectName(oldObjectName)) { + return false; + } + const auto &metadata = isCondition + ? gd::MetadataProvider::GetConditionMetadata( + platform, instruction.GetType()) + : gd::MetadataProvider::GetActionMetadata( + platform, instruction.GetType()); + + gd::ParameterMetadataTools::IterateOverParametersWithIndex( + instruction.GetParameters(), metadata.GetParameters(), + [&](const gd::ParameterMetadata ¶meterMetadata, + const gd::Expression ¶meterValue, size_t parameterIndex, + const gd::String &lastObjectName) { + if (!gd::EventsObjectReplacer::CanContainObject( + parameterMetadata.GetValueTypeMetadata())) { + return; + } + auto node = parameterValue.GetRootNode(); + if (node) { + ExpressionObjectRenamer renamer( + platform, GetProjectScopedContainers(), + parameterMetadata.GetValueTypeMetadata().GetName(), + oldObjectName, newObjectName); + node->Visit(renamer); + + if (renamer.HasDoneRenaming()) { + instruction.SetParameter( + parameterIndex, + ExpressionParser2NodePrinter::PrintNode(*node)); + } + } + }); - if (!actions[aId].GetSubInstructions().empty()) - somethingModified = - RenameObjectInActions(platform, - projectScopedContainers, - actions[aId].GetSubInstructions(), - oldName, - newName) || - somethingModified; + return false; } - return somethingModified; -} - -bool EventsRefactorer::RenameObjectInConditions( - const gd::Platform& platform, - const gd::ProjectScopedContainers& projectScopedContainers, - gd::InstructionsList& conditions, - gd::String oldName, - gd::String newName) { - bool somethingModified = false; - - for (std::size_t cId = 0; cId < conditions.size(); ++cId) { - const gd::InstructionMetadata& instrInfos = - MetadataProvider::GetConditionMetadata(platform, - conditions[cId].GetType()); - for (std::size_t pNb = 0; pNb < instrInfos.parameters.GetParametersCount(); ++pNb) { - // Replace object's name in parameters - if (gd::ParameterMetadata::IsObject(instrInfos.parameters.GetParameter(pNb).GetType()) && - conditions[cId].GetParameter(pNb).GetPlainString() == oldName) - conditions[cId].SetParameter(pNb, gd::Expression(newName)); - // Replace object's name in expressions - else if (ParameterMetadata::IsExpression( - "number", instrInfos.parameters.GetParameter(pNb).GetType())) { - auto node = conditions[cId].GetParameter(pNb).GetRootNode(); - - if (ExpressionObjectRenamer::Rename(platform, projectScopedContainers, "number", *node, oldName, newName)) { - conditions[cId].SetParameter( - pNb, ExpressionParser2NodePrinter::PrintNode(*node)); - } - } - // Replace object's name in text expressions - else if (ParameterMetadata::IsExpression( - "string", instrInfos.parameters.GetParameter(pNb).GetType())) { - auto node = conditions[cId].GetParameter(pNb).GetRootNode(); - - if (ExpressionObjectRenamer::Rename(platform, projectScopedContainers, "string", *node, oldName, newName)) { - conditions[cId].SetParameter( - pNb, ExpressionParser2NodePrinter::PrintNode(*node)); - } - } + bool DoVisitEventExpression(gd::Expression &expression, + const gd::ParameterMetadata &metadata) override { + if (&targetedObjectsContainer != + GetProjectScopedContainers() + .GetObjectsContainersList() + .GetObjectsContainerFromObjectName(oldObjectName)) { + return false; + } + if (!gd::EventsObjectReplacer::CanContainObject( + metadata.GetValueTypeMetadata())) { + return false; } - - if (!conditions[cId].GetSubInstructions().empty()) - somethingModified = - RenameObjectInConditions(platform, - projectScopedContainers, - conditions[cId].GetSubInstructions(), - oldName, - newName) || - somethingModified; - } - - return somethingModified; -} - -bool EventsRefactorer::RenameObjectInEventParameters( - const gd::Platform& platform, - const gd::ProjectScopedContainers& projectScopedContainers, - gd::Expression& expression, - gd::ParameterMetadata parameterMetadata, - gd::String oldName, - gd::String newName) { - bool somethingModified = false; - - if (gd::ParameterMetadata::IsObject(parameterMetadata.GetType()) && - expression.GetPlainString() == oldName) - expression = gd::Expression(newName); - // Replace object's name in expressions - else if (ParameterMetadata::IsExpression("number", - parameterMetadata.GetType())) { auto node = expression.GetRootNode(); - - if (ExpressionObjectRenamer::Rename(platform, projectScopedContainers, "number", *node, oldName, newName)) { - expression = ExpressionParser2NodePrinter::PrintNode(*node); + if (node) { + ExpressionObjectRenamer renamer(platform, GetProjectScopedContainers(), + metadata.GetValueTypeMetadata().GetName(), + oldObjectName, newObjectName); + node->Visit(renamer); + + if (renamer.HasDoneRenaming()) { + expression = ExpressionParser2NodePrinter::PrintNode(*node); + } } + + return false; } - // Replace object's name in text expressions - else if (ParameterMetadata::IsExpression("string", - parameterMetadata.GetType())) { - auto node = expression.GetRootNode(); - if (ExpressionObjectRenamer::Rename(platform, projectScopedContainers, "string", *node, oldName, newName)) { - expression = ExpressionParser2NodePrinter::PrintNode(*node); - } + bool CanContainObject(const gd::ValueTypeMetadata &valueTypeMetadata) { + return valueTypeMetadata.IsObject() || valueTypeMetadata.IsVariable() || + valueTypeMetadata.IsNumber() || valueTypeMetadata.IsString(); } - return somethingModified; -} + const gd::Platform &platform; + const gd::ObjectsContainer &targetedObjectsContainer; + const gd::String &oldObjectName; + const gd::String &newObjectName; +}; void EventsRefactorer::RenameObjectInEvents(const gd::Platform& platform, const gd::ProjectScopedContainers& projectScopedContainers, gd::EventsList& events, + const gd::ObjectsContainer &targetedObjectsContainer, gd::String oldName, gd::String newName) { - for (std::size_t i = 0; i < events.size(); ++i) { - vector conditionsVectors = - events[i].GetAllConditionsVectors(); - for (std::size_t j = 0; j < conditionsVectors.size(); ++j) { - bool somethingModified = RenameObjectInConditions( - platform, projectScopedContainers, *conditionsVectors[j], oldName, newName); - } - - vector actionsVectors = - events[i].GetAllActionsVectors(); - for (std::size_t j = 0; j < actionsVectors.size(); ++j) { - bool somethingModified = RenameObjectInActions( - platform, projectScopedContainers, *actionsVectors[j], oldName, newName); - } - - vector> - expressionsWithMetadata = events[i].GetAllExpressionsWithMetadata(); - for (std::size_t j = 0; j < expressionsWithMetadata.size(); ++j) { - gd::Expression* expression = expressionsWithMetadata[j].first; - gd::ParameterMetadata parameterMetadata = - expressionsWithMetadata[j].second; - bool somethingModified = RenameObjectInEventParameters(platform, - projectScopedContainers, - *expression, - parameterMetadata, - oldName, - newName); - } - - if (events[i].CanHaveSubEvents()) - RenameObjectInEvents(platform, - projectScopedContainers, - events[i].GetSubEvents(), - oldName, - newName); - } + gd::EventsObjectReplacer eventsParameterReplacer(platform, targetedObjectsContainer, oldName, newName); + eventsParameterReplacer.Launch(events, projectScopedContainers); } bool EventsRefactorer::RemoveObjectInActions(const gd::Platform& platform, diff --git a/Core/GDCore/IDE/Events/EventsRefactorer.h b/Core/GDCore/IDE/Events/EventsRefactorer.h index 099c0a6457d4..73a49504c7a6 100644 --- a/Core/GDCore/IDE/Events/EventsRefactorer.h +++ b/Core/GDCore/IDE/Events/EventsRefactorer.h @@ -83,6 +83,7 @@ class GD_CORE_API EventsRefactorer { static void RenameObjectInEvents(const gd::Platform& platform, const gd::ProjectScopedContainers& projectScopedContainers, gd::EventsList& events, + const gd::ObjectsContainer &targetedObjectsContainer, gd::String oldName, gd::String newName); @@ -121,44 +122,6 @@ class GD_CORE_API EventsRefactorer { virtual ~EventsRefactorer(){}; private: - /** - * Replace all occurrences of an object name by another name in an action - * ( include : objects in parameters and in math/text expressions ). - * - * \return true if something was modified. - */ - static bool RenameObjectInActions(const gd::Platform& platform, - const gd::ProjectScopedContainers& projectScopedContainers, - gd::InstructionsList& instructions, - gd::String oldName, - gd::String newName); - - /** - * Replace all occurrences of an object name by another name in a condition - * ( include : objects in parameters and in math/text expressions ). - * - * \return true if something was modified. - */ - static bool RenameObjectInConditions(const gd::Platform& platform, - const gd::ProjectScopedContainers& projectScopedContainers, - gd::InstructionsList& instructions, - gd::String oldName, - gd::String newName); - /** - * Replace all occurrences of an object name by another name in an expression - * with the specified metadata - * ( include : objects or objects in math/text expressions ). - * - * \return true if something was modified. - */ - static bool RenameObjectInEventParameters( - const gd::Platform& platform, - const gd::ProjectScopedContainers& projectScopedContainers, - gd::Expression& expression, - gd::ParameterMetadata parameterMetadata, - gd::String oldName, - gd::String newName); - /** * Remove all conditions of the list using an object * diff --git a/Core/GDCore/IDE/WholeProjectRefactorer.cpp b/Core/GDCore/IDE/WholeProjectRefactorer.cpp index 1a8088439769..7180dbf95611 100644 --- a/Core/GDCore/IDE/WholeProjectRefactorer.cpp +++ b/Core/GDCore/IDE/WholeProjectRefactorer.cpp @@ -19,6 +19,7 @@ #include "GDCore/IDE/Events/BehaviorTypeRenamer.h" #include "GDCore/IDE/Events/CustomObjectTypeRenamer.h" #include "GDCore/IDE/Events/EventsBehaviorRenamer.h" +#include "GDCore/IDE/Events/EventsParameterReplacer.h" #include "GDCore/IDE/Events/EventsPropertyReplacer.h" #include "GDCore/IDE/Events/EventsRefactorer.h" #include "GDCore/IDE/Events/EventsVariableInstructionTypeSwitcher.h" @@ -816,6 +817,51 @@ void WholeProjectRefactorer::RenameObjectEventsFunction( } } +void WholeProjectRefactorer::RenameParameter( + gd::Project &project, gd::ProjectScopedContainers &projectScopedContainers, + gd::EventsFunction &eventsFunction, + const gd::ObjectsContainer ¶meterObjectsContainer, + const gd::String &oldParameterName, const gd::String &newParameterName) { + auto ¶meters = eventsFunction.GetParameters(); + if (!parameters.HasParameterNamed(oldParameterName)) + return; + auto ¶meter = parameters.GetParameter(oldParameterName); + if (parameter.GetValueTypeMetadata().IsObject()) { + gd::WholeProjectRefactorer::ObjectOrGroupRenamedInEventsFunction( + project, projectScopedContainers, eventsFunction, + parameterObjectsContainer, oldParameterName, newParameterName, false); + } else if (parameter.GetValueTypeMetadata().IsBehavior()) { + size_t behaviorParameterIndex = parameters.GetParameterPosition(parameter); + size_t objectParameterIndex = + gd::ParameterMetadataTools::GetObjectParameterIndexFor( + parameters, behaviorParameterIndex); + if (objectParameterIndex == gd::String::npos) { + return; + } + const gd::String &objectName = + parameters.GetParameter(objectParameterIndex).GetName(); + gd::EventsBehaviorRenamer behaviorRenamer(project.GetCurrentPlatform(), + objectName, oldParameterName, + newParameterName); + behaviorRenamer.Launch(eventsFunction.GetEvents(), projectScopedContainers); + } else { + // Rename parameter names directly used as an identifier. + std::unordered_map oldToNewParameterNames = { + {oldParameterName, newParameterName}}; + gd::EventsParameterReplacer eventsParameterReplacer( + project.GetCurrentPlatform(), oldToNewParameterNames); + eventsParameterReplacer.Launch(eventsFunction.GetEvents(), + projectScopedContainers); + + // Rename parameter names in legacy expressions and instructions + gd::ProjectElementRenamer projectElementRenamer( + project.GetCurrentPlatform(), "functionParameterName", oldParameterName, + newParameterName); + projectElementRenamer.Launch(eventsFunction.GetEvents(), + projectScopedContainers); + } +} + void WholeProjectRefactorer::MoveEventsFunctionParameter( gd::Project &project, const gd::EventsFunctionsExtension &eventsFunctionsExtension, @@ -1705,6 +1751,15 @@ void WholeProjectRefactorer::BehaviorsAddedToObjectInScene( void WholeProjectRefactorer::ObjectOrGroupRenamedInScene( gd::Project &project, gd::Layout &layout, const gd::String &oldName, const gd::String &newName, bool isObjectGroup) { + gd::WholeProjectRefactorer::ObjectOrGroupRenamedInScene( + project, layout, layout.GetObjects(), oldName, newName, isObjectGroup); +} + +void WholeProjectRefactorer::ObjectOrGroupRenamedInScene( + gd::Project &project, gd::Layout &layout, + const gd::ObjectsContainer &targetedObjectsContainer, + const gd::String &oldName, const gd::String &newName, bool isObjectGroup) { + if (oldName == newName || newName.empty() || oldName.empty()) return; @@ -1714,7 +1769,7 @@ void WholeProjectRefactorer::ObjectOrGroupRenamedInScene( // Rename object in the current layout gd::EventsRefactorer::RenameObjectInEvents( project.GetCurrentPlatform(), projectScopedContainers, layout.GetEvents(), - oldName, newName); + layout.GetObjects(), oldName, newName); // Object groups can't have instances or be in other groups if (!isObjectGroup) { @@ -1731,7 +1786,7 @@ void WholeProjectRefactorer::ObjectOrGroupRenamedInScene( auto &externalEvents = project.GetExternalEvents(externalEventsName); gd::EventsRefactorer::RenameObjectInEvents( project.GetCurrentPlatform(), projectScopedContainers, - externalEvents.GetEvents(), oldName, newName); + externalEvents.GetEvents(), layout.GetObjects(), oldName, newName); } // Rename object in external layouts @@ -1977,8 +2032,8 @@ void WholeProjectRefactorer::ObjectOrGroupRenamedInEventsBasedObject( eventsBasedObject.GetEventsFunctions().GetInternalVector()) { auto *function = functionUniquePtr.get(); WholeProjectRefactorer::ObjectOrGroupRenamedInEventsFunction( - project, projectScopedContainers, *function, oldName, newName, - isObjectGroup); + project, projectScopedContainers, *function, + eventsBasedObject.GetObjects(), oldName, newName, isObjectGroup); } // Object groups can't have instances or be in other groups @@ -1995,11 +2050,12 @@ void WholeProjectRefactorer::ObjectOrGroupRenamedInEventsBasedObject( void WholeProjectRefactorer::ObjectOrGroupRenamedInEventsFunction( gd::Project &project, const gd::ProjectScopedContainers &projectScopedContainers, - gd::EventsFunction &eventsFunction, const gd::String &oldName, - const gd::String &newName, bool isObjectGroup) { + gd::EventsFunction &eventsFunction, + const gd::ObjectsContainer &targetedObjectsContainer, + const gd::String &oldName, const gd::String &newName, bool isObjectGroup) { gd::EventsRefactorer::RenameObjectInEvents( project.GetCurrentPlatform(), projectScopedContainers, - eventsFunction.GetEvents(), oldName, newName); + eventsFunction.GetEvents(), targetedObjectsContainer, oldName, newName); // Object groups can't be in other groups if (!isObjectGroup) { @@ -2025,7 +2081,7 @@ void WholeProjectRefactorer::GlobalObjectOrGroupRenamed( if (layout.GetObjects().HasObjectNamed(oldName)) continue; - ObjectOrGroupRenamedInScene(project, layout, oldName, newName, + ObjectOrGroupRenamedInScene(project, layout, project.GetObjects(), oldName, newName, isObjectGroup); } } diff --git a/Core/GDCore/IDE/WholeProjectRefactorer.h b/Core/GDCore/IDE/WholeProjectRefactorer.h index 0cc21b020c93..cdf8f0f61a76 100644 --- a/Core/GDCore/IDE/WholeProjectRefactorer.h +++ b/Core/GDCore/IDE/WholeProjectRefactorer.h @@ -176,6 +176,21 @@ class GD_CORE_API WholeProjectRefactorer { const gd::String& oldFunctionName, const gd::String& newFunctionName); + /** + * \brief Refactor the function **before** a parameter is renamed. + * + * \warning Do the renaming of the specified parameter after calling this. + * This is because the function is expected to have its old name for the + * refactoring. + */ + static void + RenameParameter(gd::Project &project, + gd::ProjectScopedContainers &projectScopedContainers, + gd::EventsFunction &eventsFunction, + const gd::ObjectsContainer ¶meterObjectsContainer, + const gd::String &oldParameterName, + const gd::String &newParameterName); + /** * \brief Refactor the project **before** an events function parameter * is moved. @@ -529,6 +544,7 @@ class GD_CORE_API WholeProjectRefactorer { gd::Project& project, const gd::ProjectScopedContainers &projectScopedContainers, gd::EventsFunction& eventsFunction, + const gd::ObjectsContainer &targetedObjectsContainer, const gd::String& oldName, const gd::String& newName, bool isObjectGroup); @@ -649,6 +665,12 @@ class GD_CORE_API WholeProjectRefactorer { virtual ~WholeProjectRefactorer(){}; private: + static void ObjectOrGroupRenamedInScene(gd::Project &project, + gd::Layout &scene, + const gd::ObjectsContainer &targetedObjectsContainer, + const gd::String &oldName, + const gd::String &newName, + bool isObjectGroup); static std::vector GetAssociatedExternalLayouts( gd::Project& project, gd::Layout& layout); static std::vector diff --git a/Core/tests/DummyPlatform.cpp b/Core/tests/DummyPlatform.cpp index f11d34801a05..54f5651e5257 100644 --- a/Core/tests/DummyPlatform.cpp +++ b/Core/tests/DummyPlatform.cpp @@ -340,8 +340,8 @@ void SetupProjectWithDummyPlatform(gd::Project& project, "", "", "") - .AddParameter("object", _("Object 1 parameter")) - .AddParameter("object", _("Object 2 parameter")) + .AddParameter("object", "Object 1 parameter") + .AddParameter("object", "Object 2 parameter") .SetFunctionName("doSomethingWithObjects"); extension diff --git a/Core/tests/WholeProjectRefactorer.cpp b/Core/tests/WholeProjectRefactorer.cpp index 3811b32c269b..8678d78b4b62 100644 --- a/Core/tests/WholeProjectRefactorer.cpp +++ b/Core/tests/WholeProjectRefactorer.cpp @@ -91,6 +91,37 @@ CreateInstructionWithNumberParameter(gd::Project &project, return event.GetActions().Insert(instruction); } +const gd::Instruction & +CreateInstructionWithObjectParameter(gd::Project &project, + gd::EventsList &events, + const gd::String &objectName) { + gd::StandardEvent &event = dynamic_cast( + events.InsertNewEvent(project, "BuiltinCommonInstructions::Standard")); + + gd::Instruction instruction; + instruction.SetType("MyExtension::DoSomethingWithObjects"); + instruction.SetParametersCount(2); + instruction.SetParameter(0, objectName); + instruction.SetParameter(1, ""); + return event.GetActions().Insert(instruction); +} + +const gd::Instruction & +CreateInstructionWithBehaviorParameter(gd::Project &project, + gd::EventsList &events, + const gd::String &objectName, + const gd::String &behaviorName) { + gd::StandardEvent &event = dynamic_cast( + events.InsertNewEvent(project, "BuiltinCommonInstructions::Standard")); + + gd::Instruction instruction; + instruction.SetType("MyExtension::BehaviorDoSomething"); + instruction.SetParametersCount(2); + instruction.SetParameter(0, objectName); + instruction.SetParameter(1, behaviorName); + return event.GetActions().Insert(instruction); +} + const gd::Instruction & CreateInstructionWithVariableParameter(gd::Project &project, gd::EventsList &events, @@ -1461,7 +1492,7 @@ TEST_CASE("WholeProjectRefactorer", "[common]") { auto &layout = project.GetLayout("Scene"); - // Trigger the refactoring after the renaming of an object + // Trigger the refactoring before the renaming of an object gd::WholeProjectRefactorer::ObjectOrGroupRenamedInScene( project, layout, "ObjectWithMyBehavior", "RenamedObjectWithMyBehavior", @@ -1489,7 +1520,7 @@ TEST_CASE("WholeProjectRefactorer", "[common]") { auto &layout = project.GetLayout("Scene"); - // Trigger the refactoring after the renaming of a group + // Trigger the refactoring before the renaming of a group gd::WholeProjectRefactorer::ObjectOrGroupRenamedInScene( project, layout, "GroupWithMyBehavior", "RenamedGroupWithMyBehavior", /* isObjectGroup=*/true); @@ -1568,10 +1599,10 @@ TEST_CASE("WholeProjectRefactorer", "[common]") { project, eventsExtension, eventsFunction, parametersObjectsContainer); - // Trigger the refactoring after the renaming of an object + // Trigger the refactoring before the renaming of an object gd::WholeProjectRefactorer::ObjectOrGroupRenamedInEventsFunction( project, projectScopedContainers, eventsFunction, - "Object1", "RenamedObject1", + parametersObjectsContainer, "Object1", "RenamedObject1", /* isObjectGroup=*/false); REQUIRE(objectGroup.Find("Object1") == false); @@ -1603,10 +1634,11 @@ TEST_CASE("WholeProjectRefactorer", "[common]") { objectWithMyBehavior.GetVariables().InsertNew("MyVariable"); objectWithMyBehavior.GetVariables().InsertNew("MyStructureVariable").CastTo(gd::Variable::Structure); - // Trigger the refactoring after the renaming of an object + // Trigger the refactoring before the renaming of an object gd::WholeProjectRefactorer::ObjectOrGroupRenamedInEventsFunction( project, projectScopedContainers, eventsFunction, - "ObjectWithMyBehavior", "RenamedObjectWithMyBehavior", + parametersObjectsContainer, "ObjectWithMyBehavior", + "RenamedObjectWithMyBehavior", /* isObjectGroup=*/false); // Check object name has been renamed in action parameters. @@ -1722,7 +1754,7 @@ TEST_CASE("WholeProjectRefactorer", "[common]") { project, eventsExtension, eventsBasedObject, parametersObjectsContainer); - // Trigger the refactoring after the renaming of an object + // Trigger the refactoring before the renaming of an object gd::WholeProjectRefactorer::ObjectOrGroupRenamedInEventsBasedObject( project, projectScopedContainers, eventsBasedObject, "ObjectWithMyBehavior", "RenamedObjectWithMyBehavior", @@ -2241,7 +2273,7 @@ TEST_CASE("WholeProjectRefactorer", "[common]") { .GetObjectType() == "MyRenamedExtension::MyEventsBasedObject"); } - SECTION("(Free) events action renamed") { + SECTION("(Free function) events action renamed") { gd::Project project; gd::Platform platform; SetupProjectWithDummyPlatform(project, platform); @@ -2259,7 +2291,7 @@ TEST_CASE("WholeProjectRefactorer", "[common]") { } } - SECTION("(Free) events expression renamed") { + SECTION("(Free function) events expression renamed") { gd::Project project; gd::Platform platform; SetupProjectWithDummyPlatform(project, platform); @@ -2277,7 +2309,7 @@ TEST_CASE("WholeProjectRefactorer", "[common]") { } } - SECTION("(Free) events expression and condition renamed") { + SECTION("(Free function) events expression and condition renamed") { gd::Project project; gd::Platform platform; SetupProjectWithDummyPlatform(project, platform); @@ -2306,7 +2338,239 @@ TEST_CASE("WholeProjectRefactorer", "[common]") { } } - SECTION("(Free) events action parameter moved") { + SECTION("(Free function) number parameter renamed (in expressions)") { + gd::Project project; + gd::Platform platform; + SetupProjectWithDummyPlatform(project, platform); + auto &eventsExtension = SetupProjectWithEventsFunctionExtension(project); + + auto &eventsFunction = + eventsExtension.InsertNewEventsFunction("MyFreeEventsFunction", 0); + eventsFunction.GetParameters() + .AddNewParameter("MyParameter") + .GetValueTypeMetadata() + .SetName("number"); + auto &instruction = CreateInstructionWithNumberParameter( + project, eventsFunction.GetEvents(), "MyParameter"); + auto &instruction2 = CreateInstructionWithNumberParameter( + project, eventsFunction.GetEvents(), + "MyExtension::GetVariableAsNumber(MyVariable.MyChild[MyParameter])"); + + gd::ObjectsContainer parametersObjectsContainer( + gd::ObjectsContainer::SourceType::Function); + auto projectScopedContainers = gd::ProjectScopedContainers:: + MakeNewProjectScopedContainersForFreeEventsFunction( + project, eventsExtension, eventsFunction, + parametersObjectsContainer); + gd::WholeProjectRefactorer::RenameParameter( + project, projectScopedContainers, eventsFunction, + parametersObjectsContainer, "MyParameter", "MyRenamedParameter"); + + REQUIRE(instruction.GetParameter(0).GetPlainString() == + "MyRenamedParameter"); + REQUIRE(instruction2.GetParameter(0).GetPlainString() == + "MyExtension::GetVariableAsNumber(MyVariable.MyChild[MyRenamedParameter])"); + } + + SECTION("(Free function) number parameter not renamed (in variable parameter)") { + gd::Project project; + gd::Platform platform; + SetupProjectWithDummyPlatform(project, platform); + auto &eventsExtension = SetupProjectWithEventsFunctionExtension(project); + + auto &eventsFunction = + eventsExtension.InsertNewEventsFunction("MyFreeEventsFunction", 0); + eventsFunction.GetParameters() + .AddNewParameter("MyParameter") + .GetValueTypeMetadata() + .SetName("number"); + // Parameters can't actually be used in "variable" parameters. + auto &instruction = CreateInstructionWithVariableParameter( + project, eventsFunction.GetEvents(), "MyParameter"); + auto &instruction2 = CreateInstructionWithNumberParameter( + project, eventsFunction.GetEvents(), + "MyExtension::GetVariableAsNumber(MyParameter)"); + + gd::ObjectsContainer parametersObjectsContainer( + gd::ObjectsContainer::SourceType::Function); + auto projectScopedContainers = gd::ProjectScopedContainers:: + MakeNewProjectScopedContainersForFreeEventsFunction( + project, eventsExtension, eventsFunction, + parametersObjectsContainer); + gd::WholeProjectRefactorer::RenameParameter( + project, projectScopedContainers, eventsFunction, + parametersObjectsContainer, "MyParameter", "MyRenamedParameter"); + + // "variable" parameters are left untouched. + REQUIRE(instruction.GetParameter(0).GetPlainString() == + "MyParameter"); + REQUIRE(instruction2.GetParameter(0).GetPlainString() == + "MyExtension::GetVariableAsNumber(MyParameter)"); + } + + SECTION("(Free function) object parameter renamed (in expressions)") { + gd::Project project; + gd::Platform platform; + SetupProjectWithDummyPlatform(project, platform); + auto &eventsExtension = SetupProjectWithEventsFunctionExtension(project); + + auto &eventsFunction = + eventsExtension.InsertNewEventsFunction("MyFreeEventsFunction", 0); + eventsFunction.GetParameters() + .AddNewParameter("MyObject") + .GetValueTypeMetadata() + .SetName("objectList") + .SetExtraInfo("MyExtension::Sprite"); + auto &instruction = CreateInstructionWithObjectParameter( + project, eventsFunction.GetEvents(), "MyObject"); + auto &instruction2 = CreateInstructionWithNumberParameter( + project, eventsFunction.GetEvents(), "MyObject.GetObjectStringWith1Param(0)"); + auto &instruction3 = CreateInstructionWithNumberParameter( + project, eventsFunction.GetEvents(), + "MyExtension::GetVariableAsNumber(MyVariable.MyChild[MyObject.GetObjectStringWith1Param(0)])"); + + gd::ObjectsContainer parametersObjectsContainer( + gd::ObjectsContainer::SourceType::Function); + auto projectScopedContainers = gd::ProjectScopedContainers:: + MakeNewProjectScopedContainersForFreeEventsFunction( + project, eventsExtension, eventsFunction, + parametersObjectsContainer); + gd::WholeProjectRefactorer::RenameParameter( + project, projectScopedContainers, eventsFunction, + parametersObjectsContainer, "MyObject", "MyRenamedObject"); + + REQUIRE(instruction.GetParameter(0).GetPlainString() == + "MyRenamedObject"); + REQUIRE(instruction2.GetParameter(0).GetPlainString() == + "MyRenamedObject.GetObjectStringWith1Param(0)"); + REQUIRE(instruction3.GetParameter(0).GetPlainString() == + "MyExtension::GetVariableAsNumber(MyVariable.MyChild[MyRenamedObject.GetObjectStringWith1Param(0)])"); + } + + SECTION("(Free function) object parameter not renamed (in variable parameter)") { + gd::Project project; + gd::Platform platform; + SetupProjectWithDummyPlatform(project, platform); + auto &eventsExtension = SetupProjectWithEventsFunctionExtension(project); + + auto &eventsFunction = + eventsExtension.InsertNewEventsFunction("MyFreeEventsFunction", 0); + eventsFunction.GetParameters() + .AddNewParameter("MyObject") + .GetValueTypeMetadata() + .SetName("objectList") + .SetExtraInfo("MyExtension::Sprite"); + // Parameters can't actually be used in "variable" parameters. + auto &instruction = CreateInstructionWithVariableParameter( + project, eventsFunction.GetEvents(), "MyObject"); + auto &instruction2 = CreateInstructionWithNumberParameter( + project, eventsFunction.GetEvents(), + "MyExtension::GetVariableAsNumber(MyObject)"); + + gd::ObjectsContainer parametersObjectsContainer( + gd::ObjectsContainer::SourceType::Function); + auto projectScopedContainers = gd::ProjectScopedContainers:: + MakeNewProjectScopedContainersForFreeEventsFunction( + project, eventsExtension, eventsFunction, + parametersObjectsContainer); + gd::WholeProjectRefactorer::RenameParameter( + project, projectScopedContainers, eventsFunction, + parametersObjectsContainer, "MyObject", "MyRenamedObject"); + + // "variable" parameters are left untouched. + REQUIRE(instruction.GetParameter(0).GetPlainString() == + "MyObject"); + REQUIRE(instruction2.GetParameter(0).GetPlainString() == + "MyExtension::GetVariableAsNumber(MyObject)"); + } + + SECTION("(Free function) behavior parameter renamed (in expressions)") { + gd::Project project; + gd::Platform platform; + SetupProjectWithDummyPlatform(project, platform); + auto &eventsExtension = SetupProjectWithEventsFunctionExtension(project); + + auto &eventsFunction = + eventsExtension.InsertNewEventsFunction("MyFreeEventsFunction", 0); + eventsFunction.GetParameters() + .AddNewParameter("MyObject") + .GetValueTypeMetadata() + .SetName("objectList") + .SetExtraInfo("MyExtension::Sprite"); + eventsFunction.GetParameters() + .AddNewParameter("MyBehavior") + .GetValueTypeMetadata() + .SetName("behavior") + .SetExtraInfo("MyExtension::MyBehavior"); + auto &instruction = CreateInstructionWithBehaviorParameter( + project, eventsFunction.GetEvents(), "MyObject", "MyBehavior"); + auto &instruction2 = CreateInstructionWithNumberParameter( + project, eventsFunction.GetEvents(), "MyObject.MyBehavior::GetBehaviorStringWith1Param(0)"); + auto &instruction3 = CreateInstructionWithNumberParameter( + project, eventsFunction.GetEvents(), + "MyExtension::GetVariableAsNumber(MyVariable.MyChild[MyObject.MyBehavior::GetBehaviorStringWith1Param(0)])"); + + gd::ObjectsContainer parametersObjectsContainer( + gd::ObjectsContainer::SourceType::Function); + auto projectScopedContainers = gd::ProjectScopedContainers:: + MakeNewProjectScopedContainersForFreeEventsFunction( + project, eventsExtension, eventsFunction, + parametersObjectsContainer); + gd::WholeProjectRefactorer::RenameParameter( + project, projectScopedContainers, eventsFunction, + parametersObjectsContainer, "MyBehavior", "MyRenamedBehavior"); + + REQUIRE(instruction.GetParameter(1).GetPlainString() == + "MyRenamedBehavior"); + REQUIRE(instruction2.GetParameter(0).GetPlainString() == + "MyObject.MyRenamedBehavior::GetBehaviorStringWith1Param(0)"); + REQUIRE(instruction3.GetParameter(0).GetPlainString() == + "MyExtension::GetVariableAsNumber(MyVariable.MyChild[MyObject.MyRenamedBehavior::GetBehaviorStringWith1Param(0)])"); + } + + SECTION("(Free function) behavior parameter not renamed (in variable parameter)") { + gd::Project project; + gd::Platform platform; + SetupProjectWithDummyPlatform(project, platform); + auto &eventsExtension = SetupProjectWithEventsFunctionExtension(project); + + auto &eventsFunction = + eventsExtension.InsertNewEventsFunction("MyFreeEventsFunction", 0); + eventsFunction.GetParameters() + .AddNewParameter("MyObject") + .GetValueTypeMetadata() + .SetName("objectList") + .SetExtraInfo("MyExtension::Sprite"); + eventsFunction.GetParameters() + .AddNewParameter("MyBehavior") + .GetValueTypeMetadata() + .SetName("behavior") + .SetExtraInfo("MyExtension::MyBehavior"); + // Parameters can't actually be used in "variable" parameters. + auto &instruction = CreateInstructionWithVariableParameter( + project, eventsFunction.GetEvents(), "MyBehavior"); + auto &instruction2 = CreateInstructionWithNumberParameter( + project, eventsFunction.GetEvents(), + "MyExtension::GetVariableAsNumber(MyBehavior)"); + + gd::ObjectsContainer parametersObjectsContainer( + gd::ObjectsContainer::SourceType::Function); + auto projectScopedContainers = gd::ProjectScopedContainers:: + MakeNewProjectScopedContainersForFreeEventsFunction( + project, eventsExtension, eventsFunction, + parametersObjectsContainer); + gd::WholeProjectRefactorer::RenameParameter( + project, projectScopedContainers, eventsFunction, + parametersObjectsContainer, "MyBehavior", "MyRenamedBehavior"); + + // "variable" parameters are left untouched. + REQUIRE(instruction.GetParameter(0).GetPlainString() == + "MyBehavior"); + REQUIRE(instruction2.GetParameter(0).GetPlainString() == + "MyExtension::GetVariableAsNumber(MyBehavior)"); + } + + SECTION("(Free function) events action parameter moved") { gd::Project project; gd::Platform platform; SetupProjectWithDummyPlatform(project, platform); @@ -2328,7 +2592,7 @@ TEST_CASE("WholeProjectRefactorer", "[common]") { } } - SECTION("(Free) events expression parameter moved") { + SECTION("(Free function) events expression parameter moved") { gd::Project project; gd::Platform platform; SetupProjectWithDummyPlatform(project, platform); @@ -2346,7 +2610,7 @@ TEST_CASE("WholeProjectRefactorer", "[common]") { } } - SECTION("(Free) events expression and condition parameter moved") { + SECTION("(Free function) events expression and condition parameter moved") { gd::Project project; gd::Platform platform; SetupProjectWithDummyPlatform(project, platform); diff --git a/GDevelop.js/Bindings/Bindings.idl b/GDevelop.js/Bindings/Bindings.idl index 278adb2abeeb..30095a72da3a 100644 --- a/GDevelop.js/Bindings/Bindings.idl +++ b/GDevelop.js/Bindings/Bindings.idl @@ -2437,7 +2437,13 @@ interface VectorEventsSearchResult { }; interface EventsRefactorer { - void STATIC_RenameObjectInEvents([Const, Ref] Platform platform, [Ref] ProjectScopedContainers projectScopedContainers, [Ref] EventsList events, [Const] DOMString oldName, [Const] DOMString newName); + void STATIC_RenameObjectInEvents( + [Const, Ref] Platform platform, + [Ref] ProjectScopedContainers projectScopedContainers, + [Ref] EventsList events, + [Const, Ref] ObjectsContainer targetedObjectsContainer, + [Const] DOMString oldName, + [Const] DOMString newName); [Value] VectorEventsSearchResult STATIC_ReplaceStringInEvents([Ref] ObjectsContainer project, [Ref] ObjectsContainer layout, [Ref] EventsList events, [Const] DOMString toReplace, [Const] DOMString newString, boolean matchCase, boolean inConditions, boolean inActions, boolean inEventStrings); [Value] VectorEventsSearchResult STATIC_SearchInEvents([Const, Ref] Platform platform, [Ref] EventsList events, [Const] DOMString search, boolean matchCase, boolean inConditions, boolean inActions, boolean inEventStrings, boolean inEventSentences); }; @@ -2517,6 +2523,13 @@ interface WholeProjectRefactorer { [Const, Ref] EventsBasedObject eventsBasedObject, [Const] DOMString oldName, [Const] DOMString newName); + void STATIC_RenameParameter( + [Ref] Project project, + [Ref] ProjectScopedContainers projectScopedContainers, + [Ref] EventsFunction eventsFunction, + [Const, Ref] ObjectsContainer parameterObjectsContainer, + [Const] DOMString oldName, + [Const] DOMString newName); void STATIC_MoveEventsFunctionParameter( [Ref] Project project, [Const, Ref] EventsFunctionsExtension eventsFunctionsExtension, @@ -2668,6 +2681,7 @@ interface WholeProjectRefactorer { [Ref] Project project, [Ref] ProjectScopedContainers projectScopedContainers, [Ref] EventsFunction eventsFunction, + [Const, Ref] ObjectsContainer parameterObjectsContainer, [Const] DOMString oldName, [Const] DOMString newName, boolean isObjectGroup); diff --git a/GDevelop.js/Bindings/Wrapper.cpp b/GDevelop.js/Bindings/Wrapper.cpp index 4641cbbc2333..24ecab1a1820 100644 --- a/GDevelop.js/Bindings/Wrapper.cpp +++ b/GDevelop.js/Bindings/Wrapper.cpp @@ -727,6 +727,7 @@ typedef ExtensionAndMetadata ExtensionAndExpressionMetadata; #define STATIC_RenameEventsFunction RenameEventsFunction #define STATIC_RenameBehaviorEventsFunction RenameBehaviorEventsFunction #define STATIC_RenameObjectEventsFunction RenameObjectEventsFunction +#define STATIC_RenameParameter RenameParameter #define STATIC_MoveEventsFunctionParameter MoveEventsFunctionParameter #define STATIC_MoveBehaviorEventsFunctionParameter \ MoveBehaviorEventsFunctionParameter diff --git a/GDevelop.js/types.d.ts b/GDevelop.js/types.d.ts index 2146cb0371bd..c52301dc1a10 100644 --- a/GDevelop.js/types.d.ts +++ b/GDevelop.js/types.d.ts @@ -1863,7 +1863,7 @@ export class VectorEventsSearchResult extends EmscriptenObject { } export class EventsRefactorer extends EmscriptenObject { - static renameObjectInEvents(platform: Platform, projectScopedContainers: ProjectScopedContainers, events: EventsList, oldName: string, newName: string): void; + static renameObjectInEvents(platform: Platform, projectScopedContainers: ProjectScopedContainers, events: EventsList, targetedObjectsContainer: ObjectsContainer, oldName: string, newName: string): void; static replaceStringInEvents(project: ObjectsContainer, layout: ObjectsContainer, events: EventsList, toReplace: string, newString: string, matchCase: boolean, inConditions: boolean, inActions: boolean, inEventStrings: boolean): VectorEventsSearchResult; static searchInEvents(platform: Platform, events: EventsList, search: string, matchCase: boolean, inConditions: boolean, inActions: boolean, inEventStrings: boolean, inEventSentences: boolean): VectorEventsSearchResult; } @@ -1905,6 +1905,7 @@ export class WholeProjectRefactorer extends EmscriptenObject { static renameEventsFunction(project: Project, eventsFunctionsExtension: EventsFunctionsExtension, oldName: string, newName: string): void; static renameBehaviorEventsFunction(project: Project, eventsFunctionsExtension: EventsFunctionsExtension, eventsBasedBehavior: EventsBasedBehavior, oldName: string, newName: string): void; static renameObjectEventsFunction(project: Project, eventsFunctionsExtension: EventsFunctionsExtension, eventsBasedObject: EventsBasedObject, oldName: string, newName: string): void; + static renameParameter(project: Project, projectScopedContainers: ProjectScopedContainers, eventsFunction: EventsFunction, parameterObjectsContainer: ObjectsContainer, oldName: string, newName: string): void; static moveEventsFunctionParameter(project: Project, eventsFunctionsExtension: EventsFunctionsExtension, functionName: string, oldIndex: number, newIndex: number): void; static moveBehaviorEventsFunctionParameter(project: Project, eventsFunctionsExtension: EventsFunctionsExtension, eventsBasedBehavior: EventsBasedBehavior, functionName: string, oldIndex: number, newIndex: number): void; static moveObjectEventsFunctionParameter(project: Project, eventsFunctionsExtension: EventsFunctionsExtension, eventsBasedObject: EventsBasedObject, functionName: string, oldIndex: number, newIndex: number): void; @@ -1931,7 +1932,7 @@ export class WholeProjectRefactorer extends EmscriptenObject { static objectOrGroupRenamedInScene(project: Project, scene: Layout, oldName: string, newName: string, isObjectGroup: boolean): void; static objectRemovedInScene(project: Project, scene: Layout, objectName: string): void; static behaviorsAddedToObjectInScene(project: Project, scene: Layout, objectName: string): void; - static objectOrGroupRenamedInEventsFunction(project: Project, projectScopedContainers: ProjectScopedContainers, eventsFunction: EventsFunction, oldName: string, newName: string, isObjectGroup: boolean): void; + static objectOrGroupRenamedInEventsFunction(project: Project, projectScopedContainers: ProjectScopedContainers, eventsFunction: EventsFunction, parameterObjectsContainer: ObjectsContainer, oldName: string, newName: string, isObjectGroup: boolean): void; static objectRemovedInEventsFunction(project: Project, eventsFunction: EventsFunction, objectName: string): void; static objectOrGroupRenamedInEventsBasedObject(project: Project, projectScopedContainers: ProjectScopedContainers, eventsBasedObject: EventsBasedObject, oldName: string, newName: string, isObjectGroup: boolean): void; static objectRemovedInEventsBasedObject(project: Project, eventsBasedObject: EventsBasedObject, objectName: string): void; diff --git a/GDevelop.js/types/gdeventsrefactorer.js b/GDevelop.js/types/gdeventsrefactorer.js index f187aa8e09ff..3c17c6045f46 100644 --- a/GDevelop.js/types/gdeventsrefactorer.js +++ b/GDevelop.js/types/gdeventsrefactorer.js @@ -1,6 +1,6 @@ // Automatically generated by GDevelop.js/scripts/generate-types.js declare class gdEventsRefactorer { - static renameObjectInEvents(platform: gdPlatform, projectScopedContainers: gdProjectScopedContainers, events: gdEventsList, oldName: string, newName: string): void; + static renameObjectInEvents(platform: gdPlatform, projectScopedContainers: gdProjectScopedContainers, events: gdEventsList, targetedObjectsContainer: gdObjectsContainer, oldName: string, newName: string): void; static replaceStringInEvents(project: gdObjectsContainer, layout: gdObjectsContainer, events: gdEventsList, toReplace: string, newString: string, matchCase: boolean, inConditions: boolean, inActions: boolean, inEventStrings: boolean): gdVectorEventsSearchResult; static searchInEvents(platform: gdPlatform, events: gdEventsList, search: string, matchCase: boolean, inConditions: boolean, inActions: boolean, inEventStrings: boolean, inEventSentences: boolean): gdVectorEventsSearchResult; delete(): void; diff --git a/GDevelop.js/types/gdwholeprojectrefactorer.js b/GDevelop.js/types/gdwholeprojectrefactorer.js index 5830ed55a40a..bb71b68309a3 100644 --- a/GDevelop.js/types/gdwholeprojectrefactorer.js +++ b/GDevelop.js/types/gdwholeprojectrefactorer.js @@ -9,6 +9,7 @@ declare class gdWholeProjectRefactorer { static renameEventsFunction(project: gdProject, eventsFunctionsExtension: gdEventsFunctionsExtension, oldName: string, newName: string): void; static renameBehaviorEventsFunction(project: gdProject, eventsFunctionsExtension: gdEventsFunctionsExtension, eventsBasedBehavior: gdEventsBasedBehavior, oldName: string, newName: string): void; static renameObjectEventsFunction(project: gdProject, eventsFunctionsExtension: gdEventsFunctionsExtension, eventsBasedObject: gdEventsBasedObject, oldName: string, newName: string): void; + static renameParameter(project: gdProject, projectScopedContainers: gdProjectScopedContainers, eventsFunction: gdEventsFunction, parameterObjectsContainer: gdObjectsContainer, oldName: string, newName: string): void; static moveEventsFunctionParameter(project: gdProject, eventsFunctionsExtension: gdEventsFunctionsExtension, functionName: string, oldIndex: number, newIndex: number): void; static moveBehaviorEventsFunctionParameter(project: gdProject, eventsFunctionsExtension: gdEventsFunctionsExtension, eventsBasedBehavior: gdEventsBasedBehavior, functionName: string, oldIndex: number, newIndex: number): void; static moveObjectEventsFunctionParameter(project: gdProject, eventsFunctionsExtension: gdEventsFunctionsExtension, eventsBasedObject: gdEventsBasedObject, functionName: string, oldIndex: number, newIndex: number): void; @@ -35,7 +36,7 @@ declare class gdWholeProjectRefactorer { static objectOrGroupRenamedInScene(project: gdProject, scene: gdLayout, oldName: string, newName: string, isObjectGroup: boolean): void; static objectRemovedInScene(project: gdProject, scene: gdLayout, objectName: string): void; static behaviorsAddedToObjectInScene(project: gdProject, scene: gdLayout, objectName: string): void; - static objectOrGroupRenamedInEventsFunction(project: gdProject, projectScopedContainers: gdProjectScopedContainers, eventsFunction: gdEventsFunction, oldName: string, newName: string, isObjectGroup: boolean): void; + static objectOrGroupRenamedInEventsFunction(project: gdProject, projectScopedContainers: gdProjectScopedContainers, eventsFunction: gdEventsFunction, parameterObjectsContainer: gdObjectsContainer, oldName: string, newName: string, isObjectGroup: boolean): void; static objectRemovedInEventsFunction(project: gdProject, eventsFunction: gdEventsFunction, objectName: string): void; static objectOrGroupRenamedInEventsBasedObject(project: gdProject, projectScopedContainers: gdProjectScopedContainers, eventsBasedObject: gdEventsBasedObject, oldName: string, newName: string, isObjectGroup: boolean): void; static objectRemovedInEventsBasedObject(project: gdProject, eventsBasedObject: gdEventsBasedObject, objectName: string): void; diff --git a/newIDE/app/src/EventsFunctionsExtensionEditor/EventsFunctionConfigurationEditor/EventsFunctionParametersEditor.js b/newIDE/app/src/EventsFunctionsExtensionEditor/EventsFunctionConfigurationEditor/EventsFunctionParametersEditor.js index eaa864a874d0..d7109b32e261 100644 --- a/newIDE/app/src/EventsFunctionsExtensionEditor/EventsFunctionConfigurationEditor/EventsFunctionParametersEditor.js +++ b/newIDE/app/src/EventsFunctionsExtensionEditor/EventsFunctionConfigurationEditor/EventsFunctionParametersEditor.js @@ -124,6 +124,11 @@ type Props = {| newIndex: number, done: (boolean) => void ) => void, + onFunctionParameterWillBeRenamed: ( + eventsFunction: gdEventsFunction, + oldName: string, + newName: string + ) => void, |}; export const EventsFunctionParametersEditor = ({ @@ -140,6 +145,7 @@ export const EventsFunctionParametersEditor = ({ onMoveFreeEventsParameter, onMoveBehaviorEventsParameter, onMoveObjectEventsParameter, + onFunctionParameterWillBeRenamed, }: Props) => { const scrollView = React.useRef(null); const [ @@ -193,18 +199,57 @@ export const EventsFunctionParametersEditor = ({ [eventsFunction, firstParameterIndex, freezeParameters] ); + const renameParameter = React.useCallback( + (parameter: gdParameterMetadata, newName: string) => { + if (newName === parameter.getName()) { + return; + } + const projectScopedContainers = projectScopedContainersAccessor.get(); + const validatedNewName = getValidatedParameterName( + eventsFunction.getParameters(), + projectScopedContainers, + newName + ); + onFunctionParameterWillBeRenamed( + eventsFunction, + parameter.getName(), + validatedNewName + ); + parameter.setName(validatedNewName); + forceUpdate(); + onParametersUpdated(); + }, + [ + eventsFunction, + forceUpdate, + onFunctionParameterWillBeRenamed, + onParametersUpdated, + projectScopedContainersAccessor, + ] + ); + const addParameterAt = React.useCallback( (index: number) => { const parameters = eventsFunction.getParameters(); - const newName = newNameGenerator('Parameter', name => - parameters.hasParameterNamed(name) + const projectScopedContainers = projectScopedContainersAccessor.get(); + const validatedNewName = getValidatedParameterName( + eventsFunction.getParameters(), + projectScopedContainers, + 'Parameter' ); - parameters.insertNewParameter(newName, index).setType('objectList'); + parameters + .insertNewParameter(validatedNewName, index) + .setType('objectList'); forceUpdate(); onParametersUpdated(); - setJustAddedParameterName(newName); + setJustAddedParameterName(validatedNewName); }, - [eventsFunction, forceUpdate, onParametersUpdated] + [ + eventsFunction, + forceUpdate, + onParametersUpdated, + projectScopedContainersAccessor, + ] ); const addParameter = React.useCallback( @@ -643,20 +688,9 @@ export const EventsFunctionParametersEditor = ({ margin="none" translatableHintText={t`Enter the parameter name (mandatory)`} value={parameter.getName()} - onChange={newName => { - if (newName === parameter.getName()) { - return; - } - const projectScopedContainers = projectScopedContainersAccessor.get(); - const validatedNewName = getValidatedParameterName( - parameters, - projectScopedContainers, - newName - ); - parameter.setName(validatedNewName); - forceUpdate(); - onParametersUpdated(); - }} + onChange={newName => + renameParameter(parameter, newName) + } disabled={isParameterDisabled(i)} fullWidth /> diff --git a/newIDE/app/src/EventsFunctionsExtensionEditor/EventsFunctionConfigurationEditor/index.js b/newIDE/app/src/EventsFunctionsExtensionEditor/EventsFunctionConfigurationEditor/index.js index 700bc25fb55b..b65fe5a226a9 100644 --- a/newIDE/app/src/EventsFunctionsExtensionEditor/EventsFunctionConfigurationEditor/index.js +++ b/newIDE/app/src/EventsFunctionsExtensionEditor/EventsFunctionConfigurationEditor/index.js @@ -52,6 +52,11 @@ type Props = {| newIndex: number, done: (boolean) => void ) => void, + onFunctionParameterWillBeRenamed: ( + eventsFunction: gdEventsFunction, + oldName: string, + newName: string + ) => void, unsavedChanges?: ?UnsavedChanges, getFunctionGroupNames?: () => string[], |}; @@ -102,6 +107,7 @@ export default class EventsFunctionConfigurationEditor extends React.Component< project, projectScopedContainersAccessor, eventsFunction, + objectsContainer, } = this.props; // newName is supposed to have been already validated @@ -112,6 +118,8 @@ export default class EventsFunctionConfigurationEditor extends React.Component< project, projectScopedContainersAccessor.get(), eventsFunction, + // This is the ObjectsContainer generated from parameters + objectsContainer, group.getName(), newName, /* isObjectGroup=*/ true @@ -147,6 +155,7 @@ export default class EventsFunctionConfigurationEditor extends React.Component< getFunctionGroupNames, eventsFunctionsContainer, eventsFunctionsExtension, + onFunctionParameterWillBeRenamed, } = this.props; const hasLegacyFunctionObjectGroups = @@ -212,6 +221,7 @@ export default class EventsFunctionConfigurationEditor extends React.Component< onMoveFreeEventsParameter={onMoveFreeEventsParameter} onMoveBehaviorEventsParameter={onMoveBehaviorEventsParameter} onMoveObjectEventsParameter={onMoveObjectEventsParameter} + onFunctionParameterWillBeRenamed={onFunctionParameterWillBeRenamed} key={eventsFunction ? eventsFunction.ptr : null} /> ) : null} diff --git a/newIDE/app/src/EventsFunctionsExtensionEditor/index.js b/newIDE/app/src/EventsFunctionsExtensionEditor/index.js index 1c1effdaa48e..a36776e7ad0e 100644 --- a/newIDE/app/src/EventsFunctionsExtensionEditor/index.js +++ b/newIDE/app/src/EventsFunctionsExtensionEditor/index.js @@ -1050,6 +1050,26 @@ export default class EventsFunctionsExtensionEditor extends React.Component< ); }; + _onFunctionParameterWillBeRenamed = ( + eventsFunction: gdEventsFunction, + oldName: string, + newName: string + ) => { + if (!this._projectScopedContainersAccessor) { + return; + } + const projectScopedContainers = this._projectScopedContainersAccessor.get(); + const { project } = this.props; + gd.WholeProjectRefactorer.renameParameter( + project, + projectScopedContainers, + eventsFunction, + this._objectsContainer, + oldName, + newName + ); + }; + _editOptions = (open: boolean = true) => { this.setState({ editOptionsDialogOpen: open, @@ -1339,6 +1359,9 @@ export default class EventsFunctionsExtensionEditor extends React.Component< onMoveObjectEventsParameter={this._makeMoveObjectEventsParameter( i18n )} + onFunctionParameterWillBeRenamed={ + this._onFunctionParameterWillBeRenamed + } unsavedChanges={this.props.unsavedChanges} getFunctionGroupNames={this._getFunctionGroupNames} /> diff --git a/newIDE/app/src/EventsSheet/EventsFunctionExtractor/EventsFunctionExtractorDialog.js b/newIDE/app/src/EventsSheet/EventsFunctionExtractor/EventsFunctionExtractorDialog.js index 228520192363..1a828f5e48db 100644 --- a/newIDE/app/src/EventsSheet/EventsFunctionExtractor/EventsFunctionExtractorDialog.js +++ b/newIDE/app/src/EventsSheet/EventsFunctionExtractor/EventsFunctionExtractorDialog.js @@ -326,6 +326,9 @@ export default class EventsFunctionExtractorDialog extends React.Component< // Force the dialog to adapt its size this.forceUpdate(); }} + onFunctionParameterWillBeRenamed={() => { + // Won't happen as the editor is freezed. + }} freezeParameters /> )} diff --git a/newIDE/app/src/stories/componentStories/EventsFunctionsExtensionEditor/EventsFunctionConfigurationEditor.stories.js b/newIDE/app/src/stories/componentStories/EventsFunctionsExtensionEditor/EventsFunctionConfigurationEditor.stories.js index f78fbb358754..e8b8a4f72bed 100644 --- a/newIDE/app/src/stories/componentStories/EventsFunctionsExtensionEditor/EventsFunctionConfigurationEditor.stories.js +++ b/newIDE/app/src/stories/componentStories/EventsFunctionsExtensionEditor/EventsFunctionConfigurationEditor.stories.js @@ -32,6 +32,9 @@ export const DefaultFreeFunction = () => ( eventsFunctionsContainer={testProject.testEventsFunctionsExtension} eventsFunctionsExtension={testProject.testEventsFunctionsExtension} onParametersOrGroupsUpdated={action('Parameters or groups were updated')} + onFunctionParameterWillBeRenamed={action( + 'onFunctionParameterWillBeRenamed' + )} /> ); @@ -52,6 +55,9 @@ export const DefaultBehaviorFunction = () => ( eventsFunctionsContainer={testProject.testEventsBasedBehavior.getEventsFunctions()} eventsFunctionsExtension={testProject.testEventsFunctionsExtension} onParametersOrGroupsUpdated={action('Parameters or groups were updated')} + onFunctionParameterWillBeRenamed={action( + 'onFunctionParameterWillBeRenamed' + )} /> ); @@ -72,6 +78,9 @@ export const DefaultBehaviorLifecycleFunction = () => ( eventsFunctionsContainer={testProject.testEventsBasedBehavior.getEventsFunctions()} eventsFunctionsExtension={testProject.testEventsFunctionsExtension} onParametersOrGroupsUpdated={action('Parameters or groups were updated')} + onFunctionParameterWillBeRenamed={action( + 'onFunctionParameterWillBeRenamed' + )} /> ); @@ -92,6 +101,9 @@ export const DefaultObjectFunction = () => ( eventsFunctionsContainer={testProject.testEventsBasedObject.getEventsFunctions()} eventsFunctionsExtension={testProject.testEventsFunctionsExtension} onParametersOrGroupsUpdated={action('Parameters or groups were updated')} + onFunctionParameterWillBeRenamed={action( + 'onFunctionParameterWillBeRenamed' + )} /> );