From 1456449a1bc0b5b82df5bfd7e433a0beec62310b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20S=C5=82abek?= Date: Thu, 31 Oct 2024 11:32:20 +0100 Subject: [PATCH] validate indexer expression on Unknown and on non-map non-list TypedClass (#7117) --- .../touk/nussknacker/engine/spel/Typer.scala | 4 +- .../engine/spel/SpelExpressionSpec.scala | 38 +++++++++++++------ 2 files changed, 29 insertions(+), 13 deletions(-) diff --git a/scenario-compiler/src/main/scala/pl/touk/nussknacker/engine/spel/Typer.scala b/scenario-compiler/src/main/scala/pl/touk/nussknacker/engine/spel/Typer.scala index 8fcaf1e6436..9f4c36ae0f8 100644 --- a/scenario-compiler/src/main/scala/pl/touk/nussknacker/engine/spel/Typer.scala +++ b/scenario-compiler/src/main/scala/pl/touk/nussknacker/engine/spel/Typer.scala @@ -229,9 +229,9 @@ private[spel] class Typer( invalidNodeResult(IllegalIndexingOperation) case TypedObjectWithValue(underlying, _) => typeIndexer(e, underlying) case Unknown => - validNodeResult(Unknown) + withTypedChildren(_ => valid(Unknown)) case _: TypedClass => - val w = validNodeResult(Unknown) + val w = withTypedChildren(_ => valid(Unknown)) if (dynamicPropertyAccessAllowed) w else w.tell(List(DynamicPropertyAccessError)) } } diff --git a/scenario-compiler/src/test/scala/pl/touk/nussknacker/engine/spel/SpelExpressionSpec.scala b/scenario-compiler/src/test/scala/pl/touk/nussknacker/engine/spel/SpelExpressionSpec.scala index dfcc4135d30..02679098923 100644 --- a/scenario-compiler/src/test/scala/pl/touk/nussknacker/engine/spel/SpelExpressionSpec.scala +++ b/scenario-compiler/src/test/scala/pl/touk/nussknacker/engine/spel/SpelExpressionSpec.scala @@ -105,15 +105,15 @@ class SpelExpressionSpec extends AnyFunSuite with Matchers with ValidatedValuesD private val ctx = Context("abc").withVariables( Map( - "obj" -> testValue, - "strVal" -> "", - "mapValue" -> Map("foo" -> "bar").asJava, - "array" -> Array("a", "b"), - "intArray" -> Array(1, 2, 3), - "nestedArray" -> Array(Array(1, 2), Array(3, 4)), - "arrayOfUnknown" -> Array("unknown".asInstanceOf[Any]), - "unknownString" -> ContainerOfUnknown("unknown"), - "setVal" -> Set("a").asJava, + "obj" -> testValue, + "strVal" -> "", + "mapValue" -> Map("foo" -> "bar").asJava, + "array" -> Array("a", "b"), + "intArray" -> Array(1, 2, 3), + "nestedArray" -> Array(Array(1, 2), Array(3, 4)), + "arrayOfUnknown" -> Array("unknown".asInstanceOf[Any]), + "unknownString" -> ContainerOfUnknown("unknown"), + "setVal" -> Set("a").asJava, "containerWithUnknownObject" -> ContainerOfUnknown(SampleValue(1)), "containerWithUnknownObjectWithStaticMethods" -> ContainerOfUnknown(new JavaClassWithStaticParameterlessMethod()), "containerWithUnknownClassWithStaticMethods" -> ContainerOfUnknown( @@ -1398,13 +1398,13 @@ class SpelExpressionSpec extends AnyFunSuite with Matchers with ValidatedValuesD } } - test("should not validate array constructor") { + test("should not allow array constructor") { List("new String[]", "new String[ ]", "new String[0]", "new String[#invalidRef]", "new String[invalidSyntax]").map( illegalExpr => parse[Any](illegalExpr, ctx).invalidValue shouldBe NonEmptyList.one(ArrayConstructorError) ) } - test("indexing on maps and lists should validate nodes inside indexer") { + test("indexing on maps and lists should validate expression inside indexer") { List("#processHelper.stringOnStringMap[#invalidRef]", "{1,2,3}[#invalidRef]").map(expr => parse[Any](expr, ctxWithGlobal).invalidValue shouldBe NonEmptyList.one( UnresolvedReferenceError("invalidRef") @@ -1412,6 +1412,22 @@ class SpelExpressionSpec extends AnyFunSuite with Matchers with ValidatedValuesD ) } + test("indexing on unknown should validate expression inside indexer") { + parse[Any]("#unknownString.value[#invalidRef]", ctx).invalidValue shouldBe NonEmptyList.one( + UnresolvedReferenceError("invalidRef") + ) + } + + test("indexing on class should validate expression inside indexer") { + parse[Any]( + "T(java.time.LocalDate)[#invalidRef]", + ctx, + dynamicPropertyAccessAllowed = true + ).invalidValue shouldBe NonEmptyList.one( + UnresolvedReferenceError("invalidRef") + ) + } + test("should return correct type in array projection") { evaluate[Any]("#array.![#this]") shouldBe Array("a", "b") }