AccessException -< IllegalAccessException; added TODO() and NotImplementedException

This commit is contained in:
Sergey Chernov 2026-01-05 11:14:05 +01:00
parent e0a59c8db6
commit 514ad96148
9 changed files with 107 additions and 42 deletions

View File

@ -93,8 +93,6 @@ If we want to evaluate the message lazily:
In this case, formatting will only occur if the condition is not met. In this case, formatting will only occur if the condition is not met.
### `check` ### `check`
check(condition, message="check failed") check(condition, message="check failed")
@ -107,3 +105,17 @@ With lazy message evaluation:
In this case, formatting will only occur if the condition is not met. In this case, formatting will only occur if the condition is not met.
### TODO
It is easy to mark some code and make it throw a special exception at cone with:
TODO()
or
TODO("some message")
It raises an `NotImplementedException` with the given message. You can catch it
as any other exception when necessary.
Many IDE and editors have built-in support for marking code with TODOs.

View File

@ -21,6 +21,7 @@ import kotlinx.coroutines.delay
import kotlinx.coroutines.yield import kotlinx.coroutines.yield
import net.sergeych.lyng.Script.Companion.defaultImportManager import net.sergeych.lyng.Script.Companion.defaultImportManager
import net.sergeych.lyng.miniast.addConstDoc import net.sergeych.lyng.miniast.addConstDoc
import net.sergeych.lyng.miniast.addFnDoc
import net.sergeych.lyng.miniast.addVoidFnDoc import net.sergeych.lyng.miniast.addVoidFnDoc
import net.sergeych.lyng.miniast.type import net.sergeych.lyng.miniast.type
import net.sergeych.lyng.obj.* import net.sergeych.lyng.obj.*
@ -204,18 +205,32 @@ class Script(
) )
) )
} }
addFn("assertThrows") { addFnDoc(
"assertThrows",
doc = """
Asserts that the provided code block throws an exception, with or without exception:
```lyng
assertThrows { /* ode */ }
assertThrows(IllegalArgumentException) { /* code */ }
```
If an expected exception class is provided,
it checks that the thrown exception is of that class. If no expected class is provided, any exception
will be accepted.
""".trimIndent()
) {
val code: Statement val code: Statement
val expectedClass: ObjClass? val expectedClass: ObjClass?
when(args.size) { when (args.size) {
1 -> { 1 -> {
code = requiredArg<Statement>(0) code = requiredArg<Statement>(0)
expectedClass = null expectedClass = null
} }
2 -> { 2 -> {
code = requiredArg<Statement>(1) code = requiredArg<Statement>(1)
expectedClass = requiredArg<ObjClass>(0) expectedClass = requiredArg<ObjClass>(0)
} }
else -> raiseIllegalArgument("Expected 1 or 2 arguments, got ${args.size}") else -> raiseIllegalArgument("Expected 1 or 2 arguments, got ${args.size}")
} }
val result = try { val result = try {
@ -226,10 +241,15 @@ class Script(
} catch (_: ScriptError) { } catch (_: ScriptError) {
ObjNull ObjNull
} }
if( result == null ) raiseError(ObjAssertionFailedException(this, "Expected exception but nothing was thrown")) if (result == null) raiseError(
ObjAssertionFailedException(
this,
"Expected exception but nothing was thrown"
)
)
expectedClass?.let { expectedClass?.let {
if( result !is ObjException) if (result !is ObjException)
raiseError("Expected $expectedClass, got $result") raiseError("Expected $expectedClass, got non-lyng exception $result")
if (result.exceptionClass != expectedClass) { if (result.exceptionClass != expectedClass) {
raiseError("Expected $expectedClass, got ${result.exceptionClass}") raiseError("Expected $expectedClass, got ${result.exceptionClass}")
} }
@ -255,7 +275,7 @@ class Script(
val condition = requiredArg<ObjBool>(0) val condition = requiredArg<ObjBool>(0)
if (!condition.value) { if (!condition.value) {
var message = args.list.getOrNull(1) var message = args.list.getOrNull(1)
if( message is Statement ) message = message.execute(this) if (message is Statement) message = message.execute(this)
raiseIllegalArgument(message?.toString() ?: "requirement not met") raiseIllegalArgument(message?.toString() ?: "requirement not met")
} }
ObjVoid ObjVoid
@ -264,7 +284,7 @@ class Script(
val condition = requiredArg<ObjBool>(0) val condition = requiredArg<ObjBool>(0)
if (!condition.value) { if (!condition.value) {
var message = args.list.getOrNull(1) var message = args.list.getOrNull(1)
if( message is Statement ) message = message.execute(this) if (message is Statement) message = message.execute(this)
raiseIllegalState(message?.toString() ?: "check failed") raiseIllegalState(message?.toString() ?: "check failed")
} }
ObjVoid ObjVoid

View File

@ -93,7 +93,7 @@ open class Obj {
val decl = rec.declaringClass ?: cls val decl = rec.declaringClass ?: cls
val caller = scope.currentClassCtx val caller = scope.currentClassCtx
if (!canAccessMember(rec.visibility, decl, caller)) if (!canAccessMember(rec.visibility, decl, caller))
scope.raiseError(ObjAccessException(scope, "can't invoke ${name}: not visible (declared in ${decl.className}, caller ${caller?.className ?: "?"})")) scope.raiseError(ObjIllegalAccessException(scope, "can't invoke ${name}: not visible (declared in ${decl.className}, caller ${caller?.className ?: "?"})"))
val saved = scope.currentClassCtx val saved = scope.currentClassCtx
scope.currentClassCtx = decl scope.currentClassCtx = decl
try { try {
@ -117,7 +117,7 @@ open class Obj {
val decl = rec.declaringClass ?: cls val decl = rec.declaringClass ?: cls
val caller = scope.currentClassCtx val caller = scope.currentClassCtx
if (!canAccessMember(rec.visibility, decl, caller)) if (!canAccessMember(rec.visibility, decl, caller))
scope.raiseError(ObjAccessException(scope, "can't invoke ${name}: not visible (declared in ${decl.className}, caller ${caller?.className ?: "?"})")) scope.raiseError(ObjIllegalAccessException(scope, "can't invoke ${name}: not visible (declared in ${decl.className}, caller ${caller?.className ?: "?"})"))
val saved = scope.currentClassCtx val saved = scope.currentClassCtx
scope.currentClassCtx = decl scope.currentClassCtx = decl
try { try {
@ -387,7 +387,7 @@ open class Obj {
val caller = scope.currentClassCtx val caller = scope.currentClassCtx
// Check visibility for non-property members here if they weren't checked before // Check visibility for non-property members here if they weren't checked before
if (!canAccessMember(obj.visibility, decl, caller)) if (!canAccessMember(obj.visibility, decl, caller))
scope.raiseError(ObjAccessException(scope, "can't access field ${name}: not visible (declared in ${decl?.className ?: "?"}, caller ${caller?.className ?: "?"})")) scope.raiseError(ObjIllegalAccessException(scope, "can't access field ${name}: not visible (declared in ${decl?.className ?: "?"}, caller ${caller?.className ?: "?"})"))
return obj return obj
} }
@ -424,7 +424,7 @@ open class Obj {
val decl = field.declaringClass val decl = field.declaringClass
val caller = scope.currentClassCtx val caller = scope.currentClassCtx
if (!canAccessMember(field.effectiveWriteVisibility, decl, caller)) if (!canAccessMember(field.effectiveWriteVisibility, decl, caller))
scope.raiseError(ObjAccessException(scope, "can't assign field ${name}: not visible (declared in ${decl?.className ?: "?"}, caller ${caller?.className ?: "?"})")) scope.raiseError(ObjIllegalAccessException(scope, "can't assign field ${name}: not visible (declared in ${decl?.className ?: "?"}, caller ${caller?.className ?: "?"})"))
if (field.value is ObjProperty) { if (field.value is ObjProperty) {
(field.value as ObjProperty).callSetter(scope, this, newValue, decl) (field.value as ObjProperty).callSetter(scope, this, newValue, decl)
} else if (field.isMutable) field.value = newValue else scope.raiseError("can't assign to read-only field: $name") } else if (field.isMutable) field.value = newValue else scope.raiseError("can't assign to read-only field: $name")

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2025 Sergey S. Chernov real.sergeych@gmail.com * Copyright 2026 Sergey S. Chernov real.sergeych@gmail.com
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -191,11 +191,12 @@ open class ObjException(
"IllegalAssignmentException", "IllegalAssignmentException",
"SymbolNotDefinedException", "SymbolNotDefinedException",
"IterationEndException", "IterationEndException",
"AccessException", "IllegalAccessException",
"UnknownException", "UnknownException",
"NotFoundException", "NotFoundException",
"IllegalOperationException", "IllegalOperationException",
"UnsetException", "UnsetException",
"NotImplementedException",
"SyntaxError" "SyntaxError"
)) { )) {
scope.addConst(name, getOrCreateExceptionClass(name)) scope.addConst(name, getOrCreateExceptionClass(name))
@ -236,8 +237,8 @@ class ObjSymbolNotDefinedException(scope: Scope, message: String = "symbol is no
class ObjIterationFinishedException(scope: Scope) : class ObjIterationFinishedException(scope: Scope) :
ObjException("IterationEndException", scope, "iteration finished") ObjException("IterationEndException", scope, "iteration finished")
class ObjAccessException(scope: Scope, message: String = "access not allowed error") : class ObjIllegalAccessException(scope: Scope, message: String = "access not allowed error") :
ObjException("AccessException", scope, message) ObjException("IllegalAccessException", scope, message)
class ObjUnknownException(scope: Scope, message: String = "access not allowed error") : class ObjUnknownException(scope: Scope, message: String = "access not allowed error") :
ObjException("UnknownException", scope, message) ObjException("UnknownException", scope, message)
@ -250,3 +251,6 @@ class ObjNotFoundException(scope: Scope, message: String = "not found") :
class ObjUnsetException(scope: Scope, message: String = "property is unset (not initialized)") : class ObjUnsetException(scope: Scope, message: String = "property is unset (not initialized)") :
ObjException("UnsetException", scope, message) ObjException("UnsetException", scope, message)
class ObjNotImplementedException(scope: Scope, message: String = "not implemented") :
ObjException("NotImplementedException", scope, message)

View File

@ -40,7 +40,7 @@ class ObjInstance(override val objClass: ObjClass) : Obj() {
val caller = scope.currentClassCtx val caller = scope.currentClassCtx
if (!canAccessMember(rec.visibility, decl, caller)) if (!canAccessMember(rec.visibility, decl, caller))
scope.raiseError( scope.raiseError(
ObjAccessException( ObjIllegalAccessException(
scope, scope,
"can't access field $name (declared in ${decl?.className ?: "?"})" "can't access field $name (declared in ${decl?.className ?: "?"})"
) )
@ -81,7 +81,7 @@ class ObjInstance(override val objClass: ObjClass) : Obj() {
val caller = scope.currentClassCtx val caller = scope.currentClassCtx
if (!canAccessMember(rec.visibility, declaring, caller)) if (!canAccessMember(rec.visibility, declaring, caller))
scope.raiseError( scope.raiseError(
ObjAccessException( ObjIllegalAccessException(
scope, scope,
"can't access field $name (declared in ${declaring?.className ?: "?"})" "can't access field $name (declared in ${declaring?.className ?: "?"})"
) )
@ -104,7 +104,7 @@ class ObjInstance(override val objClass: ObjClass) : Obj() {
if (scope.thisObj !== this || scope.currentClassCtx == null) { if (scope.thisObj !== this || scope.currentClassCtx == null) {
val caller = scope.currentClassCtx val caller = scope.currentClassCtx
if (!canAccessMember(f.effectiveWriteVisibility, decl, caller)) if (!canAccessMember(f.effectiveWriteVisibility, decl, caller))
ObjAccessException( ObjIllegalAccessException(
scope, scope,
"can't assign to field $name (declared in ${decl?.className ?: "?"})" "can't assign to field $name (declared in ${decl?.className ?: "?"})"
).raise() ).raise()
@ -139,7 +139,7 @@ class ObjInstance(override val objClass: ObjClass) : Obj() {
if (scope.thisObj !== this || scope.currentClassCtx == null) { if (scope.thisObj !== this || scope.currentClassCtx == null) {
val caller = scope.currentClassCtx val caller = scope.currentClassCtx
if (!canAccessMember(rec.effectiveWriteVisibility, declaring, caller)) if (!canAccessMember(rec.effectiveWriteVisibility, declaring, caller))
ObjAccessException( ObjIllegalAccessException(
scope, scope,
"can't assign to field $name (declared in ${declaring?.className ?: "?"})" "can't assign to field $name (declared in ${declaring?.className ?: "?"})"
).raise() ).raise()
@ -168,7 +168,7 @@ class ObjInstance(override val objClass: ObjClass) : Obj() {
val caller = scope.currentClassCtx ?: if (scope.thisObj === this) objClass else null val caller = scope.currentClassCtx ?: if (scope.thisObj === this) objClass else null
if (!canAccessMember(rec.visibility, decl, caller)) if (!canAccessMember(rec.visibility, decl, caller))
scope.raiseError( scope.raiseError(
ObjAccessException( ObjIllegalAccessException(
scope, scope,
"can't invoke method $name (declared in ${decl?.className ?: "?"})" "can't invoke method $name (declared in ${decl?.className ?: "?"})"
) )
@ -189,7 +189,7 @@ class ObjInstance(override val objClass: ObjClass) : Obj() {
val caller = scope.currentClassCtx ?: if (scope.thisObj === this) objClass else null val caller = scope.currentClassCtx ?: if (scope.thisObj === this) objClass else null
if (!canAccessMember(rec.visibility, decl, caller)) if (!canAccessMember(rec.visibility, decl, caller))
scope.raiseError( scope.raiseError(
ObjAccessException( ObjIllegalAccessException(
scope, scope,
"can't invoke method $name (declared in ${decl?.className ?: "?"})" "can't invoke method $name (declared in ${decl?.className ?: "?"})"
) )
@ -319,7 +319,7 @@ class ObjQualifiedView(val instance: ObjInstance, private val startClass: ObjCla
val decl = rec.declaringClass ?: startClass val decl = rec.declaringClass ?: startClass
val caller = scope.currentClassCtx val caller = scope.currentClassCtx
if (!canAccessMember(rec.visibility, decl, caller)) if (!canAccessMember(rec.visibility, decl, caller))
scope.raiseError(ObjAccessException(scope, "can't access field $name (declared in ${decl.className})")) scope.raiseError(ObjIllegalAccessException(scope, "can't access field $name (declared in ${decl.className})"))
return rec return rec
} }
// Then try instance locals (unmangled) only if startClass is the dynamic class itself // Then try instance locals (unmangled) only if startClass is the dynamic class itself
@ -329,7 +329,7 @@ class ObjQualifiedView(val instance: ObjInstance, private val startClass: ObjCla
val caller = scope.currentClassCtx val caller = scope.currentClassCtx
if (!canAccessMember(rec.visibility, decl, caller)) if (!canAccessMember(rec.visibility, decl, caller))
scope.raiseError( scope.raiseError(
ObjAccessException( ObjIllegalAccessException(
scope, scope,
"can't access field $name (declared in ${decl?.className ?: "?"})" "can't access field $name (declared in ${decl?.className ?: "?"})"
) )
@ -342,7 +342,7 @@ class ObjQualifiedView(val instance: ObjInstance, private val startClass: ObjCla
val decl = r.declaringClass ?: startClass val decl = r.declaringClass ?: startClass
val caller = scope.currentClassCtx val caller = scope.currentClassCtx
if (!canAccessMember(r.visibility, decl, caller)) if (!canAccessMember(r.visibility, decl, caller))
scope.raiseError(ObjAccessException(scope, "can't access field $name (declared in ${decl.className})")) scope.raiseError(ObjIllegalAccessException(scope, "can't access field $name (declared in ${decl.className})"))
return when (val value = r.value) { return when (val value = r.value) {
is net.sergeych.lyng.Statement -> ObjRecord( is net.sergeych.lyng.Statement -> ObjRecord(
value.execute( value.execute(
@ -364,7 +364,7 @@ class ObjQualifiedView(val instance: ObjInstance, private val startClass: ObjCla
val decl = f.declaringClass ?: startClass val decl = f.declaringClass ?: startClass
val caller = scope.currentClassCtx val caller = scope.currentClassCtx
if (!canAccessMember(f.effectiveWriteVisibility, decl, caller)) if (!canAccessMember(f.effectiveWriteVisibility, decl, caller))
ObjAccessException( ObjIllegalAccessException(
scope, scope,
"can't assign to field $name (declared in ${decl.className})" "can't assign to field $name (declared in ${decl.className})"
).raise() ).raise()
@ -378,7 +378,7 @@ class ObjQualifiedView(val instance: ObjInstance, private val startClass: ObjCla
val decl = f.declaringClass ?: instance.objClass.findDeclaringClassOf(name) val decl = f.declaringClass ?: instance.objClass.findDeclaringClassOf(name)
val caller = scope.currentClassCtx val caller = scope.currentClassCtx
if (!canAccessMember(f.effectiveWriteVisibility, decl, caller)) if (!canAccessMember(f.effectiveWriteVisibility, decl, caller))
ObjAccessException( ObjIllegalAccessException(
scope, scope,
"can't assign to field $name (declared in ${decl?.className ?: "?"})" "can't assign to field $name (declared in ${decl?.className ?: "?"})"
).raise() ).raise()
@ -391,7 +391,7 @@ class ObjQualifiedView(val instance: ObjInstance, private val startClass: ObjCla
val decl = r.declaringClass ?: startClass val decl = r.declaringClass ?: startClass
val caller = scope.currentClassCtx val caller = scope.currentClassCtx
if (!canAccessMember(r.effectiveWriteVisibility, decl, caller)) if (!canAccessMember(r.effectiveWriteVisibility, decl, caller))
ObjAccessException(scope, "can't assign to field $name (declared in ${decl.className})").raise() ObjIllegalAccessException(scope, "can't assign to field $name (declared in ${decl.className})").raise()
if (!r.isMutable) scope.raiseError("can't assign to read-only field: $name") if (!r.isMutable) scope.raiseError("can't assign to read-only field: $name")
if (r.value.assign(scope, newValue) == null) r.value = newValue if (r.value.assign(scope, newValue) == null) r.value = newValue
} }
@ -407,7 +407,7 @@ class ObjQualifiedView(val instance: ObjInstance, private val startClass: ObjCla
val decl = rec.declaringClass ?: startClass val decl = rec.declaringClass ?: startClass
val caller = scope.currentClassCtx val caller = scope.currentClassCtx
if (!canAccessMember(rec.visibility, decl, caller)) if (!canAccessMember(rec.visibility, decl, caller))
scope.raiseError(ObjAccessException(scope, "can't invoke method $name (declared in ${decl.className})")) scope.raiseError(ObjIllegalAccessException(scope, "can't invoke method $name (declared in ${decl.className})"))
val saved = instance.instanceScope.currentClassCtx val saved = instance.instanceScope.currentClassCtx
instance.instanceScope.currentClassCtx = decl instance.instanceScope.currentClassCtx = decl
try { try {
@ -423,7 +423,7 @@ class ObjQualifiedView(val instance: ObjInstance, private val startClass: ObjCla
val caller = scope.currentClassCtx val caller = scope.currentClassCtx
if (!canAccessMember(rec.visibility, decl, caller)) if (!canAccessMember(rec.visibility, decl, caller))
scope.raiseError( scope.raiseError(
ObjAccessException( ObjIllegalAccessException(
scope, scope,
"can't invoke method $name (declared in ${decl?.className ?: "?"})" "can't invoke method $name (declared in ${decl?.className ?: "?"})"
) )

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2025 Sergey S. Chernov real.sergeych@gmail.com * Copyright 2026 Sergey S. Chernov real.sergeych@gmail.com
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -595,7 +595,7 @@ class FieldRef(
val scope0 = (obj as ObjClass).classScope!! val scope0 = (obj as ObjClass).classScope!!
val r0 = scope0.getSlotRecord(capturedIdx) val r0 = scope0.getSlotRecord(capturedIdx)
if (!r0.visibility.isPublic) if (!r0.visibility.isPublic)
sc.raiseError(ObjAccessException(sc, "can't access non-public field $name")) sc.raiseError(ObjIllegalAccessException(sc, "can't access non-public field $name"))
r0 r0
} }
} else { } else {
@ -631,7 +631,7 @@ class FieldRef(
// visibility/mutability checks // visibility/mutability checks
if (!rec.isMutable) scope.raiseError(ObjIllegalAssignmentException(scope, "can't reassign val $name")) if (!rec.isMutable) scope.raiseError(ObjIllegalAssignmentException(scope, "can't reassign val $name"))
if (!rec.visibility.isPublic) if (!rec.visibility.isPublic)
scope.raiseError(ObjAccessException(scope, "can't access non-public field $name")) scope.raiseError(ObjIllegalAccessException(scope, "can't access non-public field $name"))
if (rec.value.assign(scope, newValue) == null) rec.value = newValue if (rec.value.assign(scope, newValue) == null) rec.value = newValue
return return
} }
@ -1195,7 +1195,7 @@ class MethodCallRef(
mKey1 = key; mVer1 = ver; mInvoker1 = { obj, sc, a -> mKey1 = key; mVer1 = ver; mInvoker1 = { obj, sc, a ->
val inst = obj as ObjInstance val inst = obj as ObjInstance
if (!visibility.isPublic && !canAccessMember(visibility, hierarchyMember.declaringClass ?: inst.objClass, sc.currentClassCtx)) if (!visibility.isPublic && !canAccessMember(visibility, hierarchyMember.declaringClass ?: inst.objClass, sc.currentClassCtx))
sc.raiseError(ObjAccessException(sc, "can't invoke non-public method $name")) sc.raiseError(ObjIllegalAccessException(sc, "can't invoke non-public method $name"))
callable.invoke(inst.instanceScope, inst, a) callable.invoke(inst.instanceScope, inst, a)
} }
} else { } else {
@ -1467,7 +1467,7 @@ class BoundLocalVarRef(
scope.pos = atPos scope.pos = atPos
val rec = scope.getSlotRecord(slot) val rec = scope.getSlotRecord(slot)
if (rec.declaringClass != null && !canAccessMember(rec.visibility, rec.declaringClass, scope.currentClassCtx)) if (rec.declaringClass != null && !canAccessMember(rec.visibility, rec.declaringClass, scope.currentClassCtx))
scope.raiseError(ObjAccessException(scope, "private field access")) scope.raiseError(ObjIllegalAccessException(scope, "private field access"))
return rec return rec
} }
@ -1475,7 +1475,7 @@ class BoundLocalVarRef(
scope.pos = atPos scope.pos = atPos
val rec = scope.getSlotRecord(slot) val rec = scope.getSlotRecord(slot)
if (rec.declaringClass != null && !canAccessMember(rec.visibility, rec.declaringClass, scope.currentClassCtx)) if (rec.declaringClass != null && !canAccessMember(rec.visibility, rec.declaringClass, scope.currentClassCtx))
scope.raiseError(ObjAccessException(scope, "private field access")) scope.raiseError(ObjIllegalAccessException(scope, "private field access"))
return rec.value return rec.value
} }
@ -1483,7 +1483,7 @@ class BoundLocalVarRef(
scope.pos = atPos scope.pos = atPos
val rec = scope.getSlotRecord(slot) val rec = scope.getSlotRecord(slot)
if (rec.declaringClass != null && !canAccessMember(rec.visibility, rec.declaringClass, scope.currentClassCtx)) if (rec.declaringClass != null && !canAccessMember(rec.visibility, rec.declaringClass, scope.currentClassCtx))
scope.raiseError(ObjAccessException(scope, "private field access")) scope.raiseError(ObjIllegalAccessException(scope, "private field access"))
if (!rec.isMutable) scope.raiseError("Cannot assign to immutable value") if (!rec.isMutable) scope.raiseError("Cannot assign to immutable value")
rec.value = newValue rec.value = newValue
} }

View File

@ -488,7 +488,7 @@ class OOTest {
fun setValue(newValue) { y = newValue } fun setValue(newValue) { y = newValue }
} }
assertEquals(100, A().y) assertEquals(100, A().y)
assertThrows(AccessException) { A().y = 200 } assertThrows(IllegalAccessException) { A().y = 200 }
val a = A() val a = A()
a.setValue(200) a.setValue(200)
assertEquals(200, a.y) assertEquals(200, a.y)
@ -502,7 +502,7 @@ class OOTest {
} }
val c = C(10) val c = C(10)
assertEquals(10, c.y) assertEquals(10, c.y)
assertThrows(AccessException) { c.y = 20 } assertThrows(IllegalAccessException) { c.y = 20 }
c.setBValue(30) c.setBValue(30)
assertEquals(30, c.y) assertEquals(30, c.y)
@ -515,7 +515,7 @@ class OOTest {
} }
val d = D() val d = D()
assertEquals(0, d.y) assertEquals(0, d.y)
assertThrows(AccessException) { d.y = 10 } assertThrows(IllegalAccessException) { d.y = 10 }
d.setY(20) d.setY(20)
assertEquals(20, d.y) assertEquals(20, d.y)
""" """

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2025 Sergey S. Chernov real.sergeych@gmail.com * Copyright 2026 Sergey S. Chernov real.sergeych@gmail.com
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -4532,4 +4532,32 @@ class ScriptTest {
""".trimIndent()) """.trimIndent())
} }
// @Test
// fun testUserClassExceptions() = runTest {
// eval("""
// val x = try { throw IllegalAccessException("test1") } catch { it }
// assertEquals("test1", x.message)
// assert( x is IllegalAccessException)
// assertThrows(IllegalAccessException) { throw IllegalAccessException("test2") }
//
// class X : Exception("test3")
// val y = try { throw X() } catch { it }
// println(y)
// assertEquals("test3", y.message)
// assert( y is X)
//
// """.trimIndent())
// }
@Test
fun testTodo() = runTest {
eval("""
assertThrows(NotImplementedException) {
TODO()
}
val x = try { TODO("check me") } catch { it }
assertEquals("check me", x.message)
""".trimIndent())
}
} }

View File

@ -276,3 +276,4 @@ fun Exception.printStackTrace() {
/* Compile this string into a regular expression. */ /* Compile this string into a regular expression. */
val String.re get() = Regex(this) val String.re get() = Regex(this)
fun TODO(message=null) = throw NotImplementedException(message ?: "not implemented")