Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions Core/GDCore/IDE/Events/ExpressionValidator.h
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,14 @@ class GD_CORE_API ExpressionValidator : public ExpressionParser2NodeWorker {
RaiseTypeError(
_("You entered a number, but a text was expected (in quotes)."),
node.location);
} else if (parentType == Type::Variable ||
parentType == Type::ObjectVariable ||
parentType == Type::LegacyVariable) {
RaiseTypeError(
_("The variable name looks like you're building an expression or a "
"formula. You can only use this for structure or arrays, for "
"example: Score[3]."),
node.location);
} else if (parentType != Type::Number &&
parentType != Type::NumberOrString) {
RaiseTypeError(_("You entered a number, but this type was expected:") +
Expand All @@ -204,6 +212,14 @@ class GD_CORE_API ExpressionValidator : public ExpressionParser2NodeWorker {
if (parentType == Type::Number) {
RaiseTypeError(_("You entered a text, but a number was expected."),
node.location);
} else if (parentType == Type::Variable ||
parentType == Type::ObjectVariable ||
parentType == Type::LegacyVariable) {
RaiseTypeError(
_("The variable name looks like you're building an expression or a "
"formula. You can only use this for structure or arrays, for "
"example: Score[\"Player1\"]."),
node.location);
} else if (parentType != Type::String &&
parentType != Type::NumberOrString) {
RaiseTypeError(_("You entered a text, but this type was expected:") +
Expand Down
52 changes: 31 additions & 21 deletions Core/GDCore/IDE/InstructionValidator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,27 +66,8 @@ ParameterValidationResult InstructionValidator::ValidateParameter(
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") {
const auto &objectsContainersList =
projectScopedContainers.GetObjectsContainersList();
rootObjectName = instruction.GetParameter(0).GetPlainString();

if (!gd::VariableInstructionSwitcher::IsSwitchableVariableInstruction(
instruction.GetType())) {
// Extensions still rely on legacy object variables instructions.
auto objectSourceType =
projectScopedContainers.GetObjectsContainersList()
.GetObjectsContainerSourceType(rootObjectName);
// Only child-object variable declarations are checked.
if (objectSourceType != gd::ObjectsContainer::SourceType::Object) {
rootObjectName = "";
}
}
}
gd::String rootObjectName = InstructionValidator::GetObjectNameForParameter(
projectScopedContainers, instruction, parameterType);
auto &expressionNode =
*instruction.GetParameter(parameterIndex).GetRootNode();
ExpressionValidator expressionValidator(platform, projectScopedContainers,
Expand Down Expand Up @@ -123,6 +104,35 @@ ParameterValidationResult InstructionValidator::ValidateParameter(
return result;
}

gd::String InstructionValidator::GetObjectNameForParameter(
const gd::ProjectScopedContainers projectScopedContainers,
const gd::Instruction &instruction, const gd::String &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") {
return "";
}
if (instruction.GetParametersCount() == 0) {
return "";
}
rootObjectName = instruction.GetParameter(0).GetPlainString();

if (!gd::VariableInstructionSwitcher::IsSwitchableVariableInstruction(
instruction.GetType())) {
// Extensions still rely on legacy object variables instructions.
auto objectSourceType =
projectScopedContainers.GetObjectsContainersList()
.GetObjectsContainerSourceType(rootObjectName);
// Only child-object variable declarations are checked.
if (objectSourceType != gd::ObjectsContainer::SourceType::Object) {
return "";
}
}
return rootObjectName;
}

bool InstructionValidator::IsParameterValid(
const gd::Platform &platform,
const gd::ProjectScopedContainers projectScopedContainers,
Expand Down
4 changes: 4 additions & 0 deletions Core/GDCore/IDE/InstructionValidator.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,10 @@ class GD_CORE_API InstructionValidator {

static gd::String GetRootVariableName(const gd::String &name);

static gd::String GetObjectNameForParameter(
const gd::ProjectScopedContainers projectScopedContainers,
const gd::Instruction &instruction, const gd::String &parameterType);

private:
static bool
HasRequiredBehaviors(const gd::Instruction &instruction,
Expand Down
8 changes: 6 additions & 2 deletions Core/tests/ExpressionParser2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4033,7 +4033,9 @@ TEST_CASE("ExpressionParser2", "[common][events]") {
node->Visit(validator);
RequireFatalErrorsCount(validator, 1);
REQUIRE(validator.GetFatalErrors()[0]->GetMessage() ==
"You entered a number, but this type was expected: variable");
"The variable name looks like you're building an expression or a "
"formula. You can only use this for structure or arrays, for "
"example: Score[3].");
}
SECTION("string instead") {
auto node = parser.ParseExpression("\"text\"");
Expand All @@ -4043,7 +4045,9 @@ TEST_CASE("ExpressionParser2", "[common][events]") {
node->Visit(validator);
RequireFatalErrorsCount(validator, 1);
REQUIRE(validator.GetFatalErrors()[0]->GetMessage() ==
"You entered a text, but this type was expected: variable");
"The variable name looks like you're building an expression or a "
"formula. You can only use this for structure or arrays, for "
"example: Score[\"Player1\"].");
}

SECTION("Object variable with unary operator") {
Expand Down
4 changes: 4 additions & 0 deletions GDevelop.js/Bindings/Bindings.idl
Original file line number Diff line number Diff line change
Expand Up @@ -3128,6 +3128,10 @@ interface InstructionValidator {
[Const, Ref] Instruction instruction,
[Const, Ref] InstructionMetadata metadata,
long parameterIndex);
[Const, Value] DOMString STATIC_GetObjectNameForParameter(
[Const, Ref] ProjectScopedContainers projectScopedContainers,
[Const, Ref] Instruction instruction,
[Const] DOMString parameterType);
};

interface ObjectTools {
Expand Down
1 change: 1 addition & 0 deletions GDevelop.js/Bindings/Wrapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -746,6 +746,7 @@ typedef std::vector<gd::PropertyDescriptorChoice> VectorPropertyDescriptorChoice
#define STATIC_FillBehaviorParameters FillBehaviorParameters
#define STATIC_ValidateParameter ValidateParameter
#define STATIC_IsParameterValid IsParameterValid
#define STATIC_GetObjectNameForParameter GetObjectNameForParameter
#define STATIC_FixInvalidRequiredBehaviorProperties \
FixInvalidRequiredBehaviorProperties
#define STATIC_RemoveLayerInScene RemoveLayerInScene
Expand Down
1 change: 1 addition & 0 deletions GDevelop.js/types.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2252,6 +2252,7 @@ export class ParameterValidationResult extends EmscriptenObject {
export class InstructionValidator extends EmscriptenObject {
static validateParameter(platform: Platform, projectScopedContainers: ProjectScopedContainers, instruction: Instruction, metadata: InstructionMetadata, parameterIndex: number): ParameterValidationResult;
static isParameterValid(platform: Platform, projectScopedContainers: ProjectScopedContainers, instruction: Instruction, metadata: InstructionMetadata, parameterIndex: number): boolean;
static getObjectNameForParameter(projectScopedContainers: ProjectScopedContainers, instruction: Instruction, parameterType: string): string;
}

export class ObjectTools extends EmscriptenObject {
Expand Down
1 change: 1 addition & 0 deletions GDevelop.js/types/gdinstructionvalidator.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
declare class gdInstructionValidator {
static validateParameter(platform: gdPlatform, projectScopedContainers: gdProjectScopedContainers, instruction: gdInstruction, metadata: gdInstructionMetadata, parameterIndex: number): gdParameterValidationResult;
static isParameterValid(platform: gdPlatform, projectScopedContainers: gdProjectScopedContainers, instruction: gdInstruction, metadata: gdInstructionMetadata, parameterIndex: number): boolean;
static getObjectNameForParameter(projectScopedContainers: gdProjectScopedContainers, instruction: gdInstruction, parameterType: string): string;
delete(): void;
ptr: number;
};
Original file line number Diff line number Diff line change
Expand Up @@ -103,10 +103,8 @@ export default (React.forwardRef<ParameterFieldProps, ParameterFieldInterface>(
return (
<React.Fragment>
<VariableField
forceDeclaration
project={project}
instruction={instruction}
isObjectVariable={false}
variablesContainers={variablesContainers}
enumerateVariables={enumerateGlobalAndSceneVariables}
parameterMetadata={props.parameterMetadata}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,10 +102,8 @@ export default (React.forwardRef<ParameterFieldProps, ParameterFieldInterface>(
return (
<React.Fragment>
<VariableField
forceDeclaration
project={project}
instruction={instruction}
isObjectVariable={false}
variablesContainers={variablesContainers}
enumerateVariables={enumerateGlobalAndSceneVariables}
parameterMetadata={props.parameterMetadata}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,10 +99,8 @@ export default (React.forwardRef<ParameterFieldProps, ParameterFieldInterface>(
return (
<React.Fragment>
<VariableField
forceDeclaration
project={project}
instruction={instruction}
isObjectVariable={false}
variablesContainers={variablesContainers}
enumerateVariables={enumerateGlobalAndSceneVariables}
parameterMetadata={props.parameterMetadata}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -129,13 +129,14 @@ type Props = {|

const MAX_ERRORS_COUNT = 10;

const extractErrors = (
export const extractErrors = (
platform: gdPlatform,
project: gdProject,
projectScopedContainersAccessor: ProjectScopedContainersAccessor,
expressionType: string,
parameterMetadata: ?gdParameterMetadata,
expressionNode: gdExpressionNode,
objectName: string,
showDeprecatedInstructionWarning:
| 'no'
| 'icon'
Expand All @@ -149,7 +150,7 @@ const extractErrors = (
gd.JsPlatform.get(),
projectScopedContainersAccessor.get(),
expressionType,
'',
objectName,
parameterMetadata ? parameterMetadata.getExtraInfo() : ''
);
expressionNode.visit(expressionValidator);
Expand Down Expand Up @@ -496,6 +497,7 @@ export default class ExpressionField extends React.Component<Props, State> {
expressionType,
parameterMetadata,
expressionNode,
'',
showDeprecatedInstructionWarning
);
const extraErrorText = onExtractAdditionalErrors
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,6 @@ export default (React.forwardRef<ParameterFieldProps, ParameterFieldInterface>(
return (
<React.Fragment>
<VariableField
isObjectVariable={false}
variablesContainers={variablesContainers}
enumerateVariables={enumerateGlobaleVariables}
parameterMetadata={props.parameterMetadata}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -179,15 +179,8 @@ export default (React.forwardRef<ParameterFieldProps, ParameterFieldInterface>(
return (
<React.Fragment>
<VariableField
forceDeclaration={
instruction &&
gd.VariableInstructionSwitcher.isSwitchableVariableInstruction(
instruction.getType()
)
}
project={project}
instruction={instruction}
isObjectVariable={true}
variablesContainers={variablesContainers}
enumerateVariables={enumerateObjectVariables}
parameterMetadata={props.parameterMetadata}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,6 @@ export default (React.forwardRef<ParameterFieldProps, ParameterFieldInterface>(
return (
<React.Fragment>
<VariableField
isObjectVariable={false}
variablesContainers={variablesContainers}
enumerateVariables={enumerateSceneVariables}
parameterMetadata={props.parameterMetadata}
Expand Down
Loading
Loading