From 6043d463511e83cb1717d5265ca0f6e2d12e3d09 Mon Sep 17 00:00:00 2001 From: Mingun Date: Thu, 25 Nov 2021 23:11:37 +0500 Subject: [PATCH] Raise human-readable error in case of incorrect usage of `_on` or `_` special variables in expressions --- .../io/kaitai/struct/ClassTypeProvider.scala | 16 ++++++++++------ .../io/kaitai/struct/precompile/Exceptions.scala | 9 ++++++++- 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/shared/src/main/scala/io/kaitai/struct/ClassTypeProvider.scala b/shared/src/main/scala/io/kaitai/struct/ClassTypeProvider.scala index 650e6c046..58bc428c9 100644 --- a/shared/src/main/scala/io/kaitai/struct/ClassTypeProvider.scala +++ b/shared/src/main/scala/io/kaitai/struct/ClassTypeProvider.scala @@ -4,7 +4,7 @@ import io.kaitai.struct.datatype.DataType import io.kaitai.struct.datatype.DataType._ import io.kaitai.struct.exprlang.Ast import io.kaitai.struct.format._ -import io.kaitai.struct.precompile.{EnumNotFoundError, FieldNotFoundError, TypeNotFoundError, TypeUndecidedError} +import io.kaitai.struct.precompile.{EnumNotFoundError, ExpressionError, FieldNotFoundError, InvalidVarContextError, TypeNotFoundError, TypeUndecidedError} import io.kaitai.struct.translators.TypeProvider class ClassTypeProvider(classSpecs: ClassSpecs, var topClass: ClassSpec) extends TypeProvider { @@ -12,8 +12,6 @@ class ClassTypeProvider(classSpecs: ClassSpecs, var topClass: ClassSpec) extends var _currentIteratorType: Option[DataType] = None var _currentSwitchType: Option[DataType] = None - def currentIteratorType: DataType = _currentIteratorType.get - def currentSwitchType: DataType = _currentSwitchType.get override def determineType(attrName: String): DataType = { determineType(nowClass, attrName) @@ -25,14 +23,20 @@ class ClassTypeProvider(classSpecs: ClassSpecs, var topClass: ClassSpec) extends topClass.toDataType case Identifier.PARENT => if (inClass.parentClass == UnknownClassSpec) - throw new RuntimeException(s"Unable to derive ${Identifier.PARENT} type in ${inClass.name.mkString("::")}") + throw new ExpressionError(s"Unable to derive '${Identifier.PARENT}' type in '${inClass.nameAsStr}'") inClass.parentClass.toDataType case Identifier.IO => KaitaiStreamType case Identifier.ITERATOR => - currentIteratorType + _currentIteratorType match { + case Some(value) => value + case None => throw new InvalidVarContextError(attrName, "repeat-until") + } case Identifier.SWITCH_ON => - currentSwitchType + _currentSwitchType match { + case Some(value) => value + case None => throw new InvalidVarContextError(attrName, "cases.") + } case Identifier.INDEX => CalcIntType case Identifier.SIZEOF => diff --git a/shared/src/main/scala/io/kaitai/struct/precompile/Exceptions.scala b/shared/src/main/scala/io/kaitai/struct/precompile/Exceptions.scala index fe921f700..1c19109ce 100644 --- a/shared/src/main/scala/io/kaitai/struct/precompile/Exceptions.scala +++ b/shared/src/main/scala/io/kaitai/struct/precompile/Exceptions.scala @@ -7,7 +7,7 @@ import io.kaitai.struct.format.ClassSpec * Base class for all expression-related errors, not localized to a certain path * in source file. */ -sealed abstract class ExpressionError(msg: String) extends RuntimeException(msg) +sealed class ExpressionError(msg: String) extends RuntimeException(msg) class TypeMismatchError(msg: String) extends ExpressionError(msg) class TypeUndecidedError(msg: String) extends ExpressionError(msg) @@ -21,6 +21,13 @@ class EnumNotFoundError(val name: String, val curClass: ClassSpec) class MethodNotFoundError(val name: String, val dataType: DataType) extends NotFoundError(s"don't know how to call method '$name' of object type '$dataType'") +/** + * @param id Name of a special context variable that can be used in expressions (see [[Identifier]]) + * @param context Description of the context (name of property) in which variable can be used + */ +class InvalidVarContextError(val id: String, val context: String) + extends ExpressionError(s"Context variable '$id' is available only in the '$context' expressions") + /** * Internal compiler logic error: should never happen, but at least we want to * handle it gracefully if it's happening.