Repository: 4ian/GDevelop
File: Core/GDCore/IDE/InstructionValidator.cpp (C++)

Code before:
  auto &parameterType = parameterMetadata.GetType() == "expression"
                            ? "number"
                            : parameterMetadata.GetType();
  bool shouldNotBeValidated = parameterType == "layer" && value.empty();
  if (shouldNotBeValidated) {
    return true;
  }
  if (gd::ParameterMetadata::IsExpression("number", parameterType) ||
      gd::ParameterMetadata::IsExpression("string", parameterType) ||
      gd::ParameterMetadata::IsExpression("variable", parameterType)) {
    auto &expressionNode =
        *instruction.GetParameter(parameterIndex).GetRootNode();
    ExpressionValidator expressionValidator(platform, projectScopedContainers,
                                            parameterType,
                                            parameterMetadata.GetExtraInfo());
    expressionNode.Visit(expressionValidator);
    if (!expressionValidator.GetAllErrors().empty()) {
      return false;
    }
    // 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 (parameterType == "objectvar" &&
        gd::VariableInstructionSwitcher::IsSwitchableVariableInstruction(
            instruction.GetType())) {
      // Check at least the name of the root variable, it"s the best we can
      // do.
      auto &objectsContainersList =
          projectScopedContainers.GetObjectsContainersList();
      auto &objectName = instruction.GetParameter(0).GetPlainString();
      auto &variableName =
          instruction.GetParameter(parameterIndex).GetPlainString();
      if (objectsContainersList.HasObjectOrGroupWithVariableNamed(
              objectName,
              gd::InstructionValidator::GetRootVariableName(variableName)) ==
          gd::ObjectsContainersList::DoesNotExist) {
        return false;
      }
    }
  } else if (gd::ParameterMetadata::IsObject(parameterType)) {
    auto &objectOrGroupName =
        instruction.GetParameter(parameterIndex).GetPlainString();
    auto &objectsContainersList =
        projectScopedContainers.GetObjectsContainersList();
    return objectsContainersList.HasObjectOrGroupNamed(objectOrGroupName) &&
           (parameterMetadata.GetExtraInfo().empty() ||
            objectsContainersList.GetTypeOfObject(objectOrGroupName) ==
                parameterMetadata.GetExtraInfo()) &&
           InstructionValidator::HasRequiredBehaviors(
               instruction, metadata, parameterIndex, objectsContainersList);
  } else if (gd::ParameterMetadata::IsExpression("resource", parameterType)) {

Review comment (suggestion):
```suggestion
      // Check at least the name of the root variable, it's the best we can
```

Code after:
  }
  const auto &parameterMetadata = metadata.GetParameter(parameterIndex);
  // TODO Remove the ternary when all parameter declarations use
  // "number" instead of "expression".
  const auto &parameterType = parameterMetadata.GetType() == "expression"
                                  ? "number"
                                  : parameterMetadata.GetType();
  bool shouldNotBeValidated = parameterType == "layer" && value.empty();
  if (shouldNotBeValidated) {
    return true;
  }
  if (gd::ParameterMetadata::IsExpression("number", parameterType) ||
      gd::ParameterMetadata::IsExpression("string", parameterType) ||
      gd::ParameterMetadata::IsExpression("variable", parameterType)) {
    auto &expressionNode =
        *instruction.GetParameter(parameterIndex).GetRootNode();
    ExpressionValidator expressionValidator(platform, projectScopedContainers,
                                            parameterType,
                                            parameterMetadata.GetExtraInfo());
    expressionNode.Visit(expressionValidator);
    if (!expressionValidator.GetAllErrors().empty()) {
      return false;
    }
    // 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 (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) {
        return false;
      }
    }
  } else if (gd::ParameterMetadata::IsObject(parameterType)) {
    const auto &objectOrGroupName =
        instruction.GetParameter(parameterIndex).GetPlainString();
    const auto &objectsContainersList =
        projectScopedContainers.GetObjectsContainersList();
    return objectsContainersList.HasObjectOrGroupNamed(objectOrGroupName) &&
           (parameterMetadata.GetExtraInfo().empty() ||
            objectsContainersList.GetTypeOfObject(objectOrGroupName) ==