Skip to content

Commit

Permalink
Use Ast.EnumRef everywhere instead of Ast.typeId + Ast.identifier
Browse files Browse the repository at this point in the history
Because of new types type system enforses fixing kaitai-io/kaitai_struct#857
  • Loading branch information
Mingun committed Oct 4, 2024
1 parent 6ac1562 commit 7e22455
Show file tree
Hide file tree
Showing 15 changed files with 101 additions and 105 deletions.
99 changes: 50 additions & 49 deletions jvm/src/test/scala/io/kaitai/struct/ClassTypeProvider$Test.scala
Original file line number Diff line number Diff line change
Expand Up @@ -624,35 +624,36 @@ class ClassTypeProvider$Test extends AnyFunSpec {
val e_12 = child_12.enums.get("e").getOrElse(throw new NoSuchElementException("'e_12' not found"))
val e_2 = child_2.enums.get("e").getOrElse(throw new NoSuchElementException("'e_2' not found"))

val none = Ast.typeId(false, Seq())
val one = Ast.typeId(false, Seq("one"))
val one_two = Ast.typeId(false, Seq("one", "two"))
val unknown = Ast.typeId(false, Seq("unknown"))
val none = Ast.EnumRef(false, Seq(), "e")
val one_e = Ast.EnumRef(false, Seq("one"), "e")
val one_unk = Ast.EnumRef(false, Seq("one"), "unknown")
val one_two = Ast.EnumRef(false, Seq("one", "two"), "e")
val unknown = Ast.EnumRef(false, Seq("unknown"), "e")

describe("in 'root' context") {
val resolver = new ClassTypeProvider(specs, root)

it("resolves 'e'") {
resolver.resolveEnum(none, "e") should be(e_root)
resolver.resolveEnum(none) should be(e_root)
}

it("doesn't resolve 'one::e'") {
val thrown = the[TypeNotFoundError] thrownBy resolver.resolveEnum(one, "e")
val thrown = the[TypeNotFoundError] thrownBy resolver.resolveEnum(one_e)
thrown.getMessage should be("unable to find type 'one', searching from 'root'")
}

it("doesn't resolve 'one::two::e'") {
val thrown = the[TypeNotFoundError] thrownBy resolver.resolveEnum(one_two, "e")
val thrown = the[TypeNotFoundError] thrownBy resolver.resolveEnum(one_two)
thrown.getMessage should be("unable to find type 'one', searching from 'root'")
}

it("doesn't resolve 'one::unknown'") {
val thrown = the[TypeNotFoundError] thrownBy resolver.resolveEnum(one, "unknown")
val thrown = the[TypeNotFoundError] thrownBy resolver.resolveEnum(one_unk)
thrown.getMessage should be("unable to find type 'one', searching from 'root'")
}

it("doesn't resolve 'unknown::e'") {
val thrown = the[TypeNotFoundError] thrownBy resolver.resolveEnum(unknown, "e")
val thrown = the[TypeNotFoundError] thrownBy resolver.resolveEnum(unknown)
thrown.getMessage should be("unable to find type 'unknown', searching from 'root'")
}
}
Expand All @@ -662,25 +663,25 @@ class ClassTypeProvider$Test extends AnyFunSpec {
resolver.nowClass = child_1

it("resolves 'e'") {
resolver.resolveEnum(none, "e") should be(e_root)
resolver.resolveEnum(none) should be(e_root)
}

it("resolves 'one::e'") {
resolver.resolveEnum(one, "e") should be(e_11)
resolver.resolveEnum(one_e) should be(e_11)
}

it("doesn't resolve 'one::two::e'") {
val thrown = the[TypeNotFoundError] thrownBy resolver.resolveEnum(one_two, "e")
val thrown = the[TypeNotFoundError] thrownBy resolver.resolveEnum(one_two)
thrown.getMessage should be("unable to find type 'two' in 'root::child_1::one'")
}

it("doesn't resolve 'one::unknown'") {
val thrown = the[EnumNotFoundError] thrownBy resolver.resolveEnum(one, "unknown")
val thrown = the[EnumNotFoundError] thrownBy resolver.resolveEnum(one_unk)
thrown.getMessage should be("unable to find enum 'unknown' in 'root::child_1::one'")
}

it("doesn't resolve 'unknown::e'") {
val thrown = the[TypeNotFoundError] thrownBy resolver.resolveEnum(unknown, "e")
val thrown = the[TypeNotFoundError] thrownBy resolver.resolveEnum(unknown)
thrown.getMessage should be("unable to find type 'unknown', searching from 'root::child_1'")
}
}
Expand All @@ -690,26 +691,26 @@ class ClassTypeProvider$Test extends AnyFunSpec {
resolver.nowClass = child_2

it("resolves 'e'") {
resolver.resolveEnum(none, "e") should be(e_2)
resolver.resolveEnum(none) should be(e_2)
}

it("doesn't resolve 'one::e'") {
val thrown = the[EnumNotFoundError] thrownBy resolver.resolveEnum(one, "e")
val thrown = the[EnumNotFoundError] thrownBy resolver.resolveEnum(one_e)
thrown.getMessage should be("unable to find enum 'e' in 'root::child_2::one'")
}

it("doesn't resolve 'one::two::e'") {
val thrown = the[TypeNotFoundError] thrownBy resolver.resolveEnum(one_two, "e")
val thrown = the[TypeNotFoundError] thrownBy resolver.resolveEnum(one_two)
thrown.getMessage should be("unable to find type 'two' in 'root::child_2::one'")
}

it("doesn't resolve 'one::unknown'") {
val thrown = the[EnumNotFoundError] thrownBy resolver.resolveEnum(one, "unknown")
val thrown = the[EnumNotFoundError] thrownBy resolver.resolveEnum(one_unk)
thrown.getMessage should be("unable to find enum 'unknown' in 'root::child_2::one'")
}

it("doesn't resolve 'unknown::e'") {
val thrown = the[TypeNotFoundError] thrownBy resolver.resolveEnum(unknown, "e")
val thrown = the[TypeNotFoundError] thrownBy resolver.resolveEnum(unknown)
thrown.getMessage should be("unable to find type 'unknown', searching from 'root::child_2'")
}
}
Expand All @@ -719,25 +720,25 @@ class ClassTypeProvider$Test extends AnyFunSpec {
resolver.nowClass = child_11

it("resolves 'e'") {
resolver.resolveEnum(none, "e") should be(e_11)
resolver.resolveEnum(none) should be(e_11)
}

it("resolves 'one::e'") {
resolver.resolveEnum(one, "e") should be(e_11)
resolver.resolveEnum(one_e) should be(e_11)
}

it("doesn't resolve 'one::two::e'") {
val thrown = the[TypeNotFoundError] thrownBy resolver.resolveEnum(one_two, "e")
val thrown = the[TypeNotFoundError] thrownBy resolver.resolveEnum(one_two)
thrown.getMessage should be("unable to find type 'two' in 'root::child_1::one'")
}

it("doesn't resolve 'one::unknown'") {
val thrown = the[EnumNotFoundError] thrownBy resolver.resolveEnum(one, "unknown")
val thrown = the[EnumNotFoundError] thrownBy resolver.resolveEnum(one_unk)
thrown.getMessage should be("unable to find enum 'unknown' in 'root::child_1::one'")
}

it("doesn't resolve 'unknown::e'") {
val thrown = the[TypeNotFoundError] thrownBy resolver.resolveEnum(unknown, "e")
val thrown = the[TypeNotFoundError] thrownBy resolver.resolveEnum(unknown)
thrown.getMessage should be("unable to find type 'unknown', searching from 'root::child_1::one'")
}
}
Expand All @@ -747,26 +748,26 @@ class ClassTypeProvider$Test extends AnyFunSpec {
resolver.nowClass = child_12

it("resolves 'e'") {
resolver.resolveEnum(none, "e") should be(e_12)
resolver.resolveEnum(none) should be(e_12)
}

it("doesn't resolve 'one::e'") {
val thrown = the[EnumNotFoundError] thrownBy resolver.resolveEnum(one, "e")
val thrown = the[EnumNotFoundError] thrownBy resolver.resolveEnum(one_e)
thrown.getMessage should be("unable to find enum 'e' in 'root::child_1::two::one'")
}

it("doesn't resolve 'one::two::e'") {
val thrown = the[TypeNotFoundError] thrownBy resolver.resolveEnum(one_two, "e")
val thrown = the[TypeNotFoundError] thrownBy resolver.resolveEnum(one_two)
thrown.getMessage should be("unable to find type 'two' in 'root::child_1::two::one'")
}

it("doesn't resolve 'one::unknown'") {
val thrown = the[EnumNotFoundError] thrownBy resolver.resolveEnum(one, "unknown")
val thrown = the[EnumNotFoundError] thrownBy resolver.resolveEnum(one_unk)
thrown.getMessage should be("unable to find enum 'unknown' in 'root::child_1::two::one'")
}

it("doesn't resolve 'unknown::e'") {
val thrown = the[TypeNotFoundError] thrownBy resolver.resolveEnum(unknown, "e")
val thrown = the[TypeNotFoundError] thrownBy resolver.resolveEnum(unknown)
thrown.getMessage should be("unable to find type 'unknown', searching from 'root::child_1::two'")
}
}
Expand All @@ -776,26 +777,26 @@ class ClassTypeProvider$Test extends AnyFunSpec {
resolver.nowClass = child_21

it("resolves 'e'") {
resolver.resolveEnum(none, "e") should be(e_2)
resolver.resolveEnum(none) should be(e_2)
}

it("doesn't resolve 'one::e'") {
val thrown = the[EnumNotFoundError] thrownBy resolver.resolveEnum(one, "e")
val thrown = the[EnumNotFoundError] thrownBy resolver.resolveEnum(one_e)
thrown.getMessage should be("unable to find enum 'e' in 'root::child_2::one'")
}

it("doesn't resolve 'one::two::e'") {
val thrown = the[TypeNotFoundError] thrownBy resolver.resolveEnum(one_two, "e")
val thrown = the[TypeNotFoundError] thrownBy resolver.resolveEnum(one_two)
thrown.getMessage should be("unable to find type 'two' in 'root::child_2::one'")
}

it("doesn't resolve 'one::unknown'") {
val thrown = the[EnumNotFoundError] thrownBy resolver.resolveEnum(one, "unknown")
val thrown = the[EnumNotFoundError] thrownBy resolver.resolveEnum(one_unk)
thrown.getMessage should be("unable to find enum 'unknown' in 'root::child_2::one'")
}

it("doesn't resolve 'unknown::e'") {
val thrown = the[TypeNotFoundError] thrownBy resolver.resolveEnum(unknown, "e")
val thrown = the[TypeNotFoundError] thrownBy resolver.resolveEnum(unknown)
thrown.getMessage should be("unable to find type 'unknown', searching from 'root::child_2::one'")
}
}
Expand All @@ -805,26 +806,26 @@ class ClassTypeProvider$Test extends AnyFunSpec {
resolver.nowClass = child_22

it("resolves 'e'") {
resolver.resolveEnum(none, "e") should be(e_2)
resolver.resolveEnum(none) should be(e_2)
}

it("doesn't resolve 'one::e'") {
val thrown = the[EnumNotFoundError] thrownBy resolver.resolveEnum(one, "e")
val thrown = the[EnumNotFoundError] thrownBy resolver.resolveEnum(one_e)
thrown.getMessage should be("unable to find enum 'e' in 'root::child_2::one'")
}

it("doesn't resolve 'one::two::e'") {
val thrown = the[TypeNotFoundError] thrownBy resolver.resolveEnum(one_two, "e")
val thrown = the[TypeNotFoundError] thrownBy resolver.resolveEnum(one_two)
thrown.getMessage should be("unable to find type 'two' in 'root::child_2::one'")
}

it("doesn't resolve 'one::unknown'") {
val thrown = the[EnumNotFoundError] thrownBy resolver.resolveEnum(one, "unknown")
val thrown = the[EnumNotFoundError] thrownBy resolver.resolveEnum(one_unk)
thrown.getMessage should be("unable to find enum 'unknown' in 'root::child_2::one'")
}

it("doesn't resolve 'unknown::e'") {
val thrown = the[TypeNotFoundError] thrownBy resolver.resolveEnum(unknown, "e")
val thrown = the[TypeNotFoundError] thrownBy resolver.resolveEnum(unknown)
thrown.getMessage should be("unable to find type 'unknown', searching from 'root::child_2::two'")
}
}
Expand All @@ -834,26 +835,26 @@ class ClassTypeProvider$Test extends AnyFunSpec {
resolver.nowClass = child_121

it("resolves 'e'") {
resolver.resolveEnum(none, "e") should be(e_12)
resolver.resolveEnum(none) should be(e_12)
}

it("doesn't resolve 'one::e'") {
val thrown = the[EnumNotFoundError] thrownBy resolver.resolveEnum(one, "e")
val thrown = the[EnumNotFoundError] thrownBy resolver.resolveEnum(one_e)
thrown.getMessage should be("unable to find enum 'e' in 'root::child_1::two::one'")
}

it("doesn't resolve 'one::two::e'") {
val thrown = the[TypeNotFoundError] thrownBy resolver.resolveEnum(one_two, "e")
val thrown = the[TypeNotFoundError] thrownBy resolver.resolveEnum(one_two)
thrown.getMessage should be("unable to find type 'two' in 'root::child_1::two::one'")
}

it("doesn't resolve 'one::unknown'") {
val thrown = the[EnumNotFoundError] thrownBy resolver.resolveEnum(one, "unknown")
val thrown = the[EnumNotFoundError] thrownBy resolver.resolveEnum(one_unk)
thrown.getMessage should be("unable to find enum 'unknown' in 'root::child_1::two::one'")
}

it("doesn't resolve 'unknown::e'") {
val thrown = the[TypeNotFoundError] thrownBy resolver.resolveEnum(unknown, "e")
val thrown = the[TypeNotFoundError] thrownBy resolver.resolveEnum(unknown)
thrown.getMessage should be("unable to find type 'unknown', searching from 'root::child_1::two::one'")
}
}
Expand All @@ -863,26 +864,26 @@ class ClassTypeProvider$Test extends AnyFunSpec {
resolver.nowClass = child_122

it("resolves 'e'") {
resolver.resolveEnum(none, "e") should be(e_12)
resolver.resolveEnum(none) should be(e_12)
}

it("doesn't resolve 'one::e'") {
val thrown = the[EnumNotFoundError] thrownBy resolver.resolveEnum(one, "e")
val thrown = the[EnumNotFoundError] thrownBy resolver.resolveEnum(one_e)
thrown.getMessage should be("unable to find enum 'e' in 'root::child_1::two::one'")
}

it("doesn't resolve 'one::two::e'") {
val thrown = the[TypeNotFoundError] thrownBy resolver.resolveEnum(one_two, "e")
val thrown = the[TypeNotFoundError] thrownBy resolver.resolveEnum(one_two)
thrown.getMessage should be("unable to find type 'two' in 'root::child_1::two::one'")
}

it("doesn't resolve 'one::unknown'") {
val thrown = the[EnumNotFoundError] thrownBy resolver.resolveEnum(one, "unknown")
val thrown = the[EnumNotFoundError] thrownBy resolver.resolveEnum(one_unk)
thrown.getMessage should be("unable to find enum 'unknown' in 'root::child_1::two::one'")
}

it("doesn't resolve 'unknown::e'") {
val thrown = the[TypeNotFoundError] thrownBy resolver.resolveEnum(unknown, "e")
val thrown = the[TypeNotFoundError] thrownBy resolver.resolveEnum(unknown)
thrown.getMessage should be("unable to find type 'unknown', searching from 'root::child_1::two::two'")
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -133,35 +133,32 @@ class ExpressionsSpec extends AnyFunSpec {

// Enums
it("parses port::http") {
Expressions.parse("port::http") should be (EnumByLabel(identifier("port"), identifier("http")))
Expressions.parse("port::http") should be (EnumByLabel(EnumRef(false, Seq(), "port"), identifier("http")))
}

it("parses some_type::port::http") {
Expressions.parse("some_type::port::http") should be (
EnumByLabel(
identifier("port"),
EnumRef(false, Seq("some_type"), "port"),
identifier("http"),
typeId(absolute = false, Seq("some_type"))
)
)
}

it("parses parent_type::child_type::port::http") {
Expressions.parse("parent_type::child_type::port::http") should be (
EnumByLabel(
identifier("port"),
EnumRef(false, Seq("parent_type", "child_type"), "port"),
identifier("http"),
typeId(absolute = false, Seq("parent_type", "child_type"))
)
)
}

it("parses ::parent_type::child_type::port::http") {
Expressions.parse("::parent_type::child_type::port::http") should be (
EnumByLabel(
identifier("port"),
EnumRef(true, Seq("parent_type", "child_type"), "port"),
identifier("http"),
typeId(absolute = true, Seq("parent_type", "child_type"))
)
)
}
Expand All @@ -171,7 +168,7 @@ class ExpressionsSpec extends AnyFunSpec {
Compare(
BinOp(
Attribute(
EnumByLabel(identifier("port"),identifier("http")),
EnumByLabel(EnumRef(false, Seq(), "port"), identifier("http")),
identifier("to_i")
),
Add,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ object TestTypeProviders {
abstract class FakeTypeProvider extends TypeProvider {
val nowClass = ClassSpec.opaquePlaceholder(List("top_class"))

override def resolveEnum(inType: Ast.typeId, enumName: String) =
override def resolveEnum(ref: Ast.EnumRef) =
throw new NotImplementedError

override def resolveType(typeName: Ast.typeId): DataType = {
Expand Down
14 changes: 7 additions & 7 deletions shared/src/main/scala/io/kaitai/struct/ClassTypeProvider.scala
Original file line number Diff line number Diff line change
Expand Up @@ -90,18 +90,18 @@ class ClassTypeProvider(classSpecs: ClassSpecs, var topClass: ClassSpec) extends
throw new FieldNotFoundError(attrName, inClass)
}

override def resolveEnum(inType: Ast.typeId, enumName: String): EnumSpec = {
val inClass = if (inType.absolute) topClass else nowClass
override def resolveEnum(ref: Ast.EnumRef): EnumSpec = {
val inClass = if (ref.absolute) topClass else nowClass
// When concrete type is not defined, search enum definition in all enclosing types
if (inType.names.isEmpty) {
resolveEnumName(inClass, enumName)
if (ref.typePath.isEmpty) {
resolveEnumName(inClass, ref.name)
} else {
val ty = resolveTypePath(inClass, inType.names)
ty.enums.get(enumName) match {
val ty = resolveTypePath(inClass, ref.typePath)
ty.enums.get(ref.name) match {
case Some(spec) =>
spec
case None =>
throw new EnumNotFoundInTypeError(enumName, ty)
throw new EnumNotFoundInTypeError(ref.name, ty)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -347,8 +347,8 @@ class GraphvizClassCompiler(classSpecs: ClassSpecs, topClass: ClassSpec) extends
List()
case _: Ast.expr.EnumByLabel =>
List()
case Ast.expr.EnumById(_, id, _) =>
affectedVars(id)
case Ast.expr.EnumById(_, expr) =>
affectedVars(expr)
case Ast.expr.Attribute(value, attr) =>
if (attr.name == Identifier.SIZEOF) {
val vars = value match {
Expand Down
Loading

0 comments on commit 7e22455

Please sign in to comment.