Require explicit extern members in extern class/object and update docs

This commit is contained in:
sergeych committed 2026-03-15 03:27:50 +03:00
1 parent e447c778ed
commit 979e6ea9b7
13 files changed
+105 -53

No files matched your search

@@ -7727,6 +7727,7 @@ class Compiler(
val annotation = lastAnnotation
val parentContext = codeContexts.last()
val parentClassCtx = parentContext as? CodeContext.ClassBody
// Is extension?
if (looksLikeExtensionReceiver()) {
@@ -7760,6 +7761,9 @@ class Compiler(
name = t.value
nameStartPos = t.pos
}
if (parentClassCtx?.isExtern == true && !isExtern) {
throw ScriptError(nameStartPos, "members of extern classes/objects must be marked extern")
}
val extensionWrapperName = extTypeName?.let { extensionCallableName(it, name) }
val classCtx = codeContexts.asReversed().firstOrNull { it is CodeContext.ClassBody } as? CodeContext.ClassBody
var memberMethodId = if (extTypeName == null) classCtx?.memberMethodIds?.get(name) else null
@@ -8782,6 +8786,10 @@ class Compiler(
name = nameToken.value
nameStartPos = nameToken.pos
}
val parentClassCtx = codeContexts.lastOrNull() as? CodeContext.ClassBody
if (parentClassCtx?.isExtern == true && !isExtern) {
throw ScriptError(nameStartPos, "members of extern classes/objects must be marked extern")
}
val receiverNormalization = normalizeReceiverTypeDecl(receiverTypeDecl, emptySet())
val implicitTypeParams = receiverNormalization.second
@@ -24,46 +24,46 @@ package lyng.observable
extern class ChangeRejectionException : Exception
extern class Subscription {
fun cancel(): Void
extern fun cancel(): Void
}
extern class Observable<Change> {
fun beforeChange(listener: (Change)->Void): Subscription
fun onChange(listener: (Change)->Void): Subscription
fun changes(): Flow<Change>
extern fun beforeChange(listener: (Change)->Void): Subscription
extern fun onChange(listener: (Change)->Void): Subscription
extern fun changes(): Flow<Change>
}
extern class ListChange<T>
extern class ListSet<T> : ListChange<T> {
val index: Int
val oldValue: Object
val newValue: Object
extern val index: Int
extern val oldValue: Object
extern val newValue: Object
}
extern class ListInsert<T> : ListChange<T> {
val index: Int
val values: List<T>
extern val index: Int
extern val values: List<T>
}
extern class ListRemove<T> : ListChange<T> {
val index: Int
val oldValue: Object
extern val index: Int
extern val oldValue: Object
}
extern class ListClear<T> : ListChange<T> {
val oldValues: List<T>
extern val oldValues: List<T>
}
extern class ListReorder<T> : ListChange<T> {
val oldValues: List<T>
val newValues: Object
extern val oldValues: List<T>
extern val newValues: Object
}
extern class ObservableList<T> : List<T> {
fun beforeChange(listener: (ListChange<T>)->Void): Subscription
fun onChange(listener: (ListChange<T>)->Void): Subscription
fun changes(): Flow<ListChange<T>>
extern fun beforeChange(listener: (ListChange<T>)->Void): Subscription
extern fun onChange(listener: (ListChange<T>)->Void): Subscription
extern fun changes(): Flow<ListChange<T>>
}
fun List<T>.observable(): ObservableList<T> {
+1 -2
View File
@@ -164,7 +164,7 @@ class BindingTest {
val ms = Script.newScope()
ms.eval("""
extern class A {
fun get1(): String
extern fun get1(): String
}
extern fun getA(): A
@@ -184,4 +184,3 @@ class BindingTest {
}
}
@@ -231,7 +231,7 @@ class BridgeBindingTest {
val ms = Script.newScope()
ms.eval("""
extern class A {
val field: Int
extern val field: Int
}
fun test(a: A) = a.field
+2 -2
View File
@@ -249,13 +249,13 @@ class MiniAstTest {
// Doc2
extern class C1 {
// Doc3
fun m1()
extern fun m1()
}
// Doc4
extern object O1 {
// Doc5
val v1: String
extern val v1: String
}
// Doc6
+16 -3
View File
@@ -3080,11 +3080,11 @@ class ScriptTest {
"""
extern fun hostFunction(a: Int, b: String): String
extern class HostClass(name: String) {
fun doSomething(): Int
val status: String
extern fun doSomething(): Int
extern val status: String
}
extern object HostObject {
fun getInstance(): HostClass
extern fun getInstance(): HostClass
}
extern enum HostEnum {
VALUE1, VALUE2
@@ -3097,6 +3097,19 @@ class ScriptTest {
)
}
@Test
fun testExternClassMembersMustBeExplicitlyExtern() = runTest {
assertFailsWith<ScriptError> {
eval(
"""
extern class HostClass {
fun doSomething(): Int
}
""".trimIndent()
)
}
}
@Test
fun testExternExtension() = runTest {
eval(
@@ -209,7 +209,7 @@ class CompletionEngineLightTest {
fun inferredTypeFromMemberCall() = runBlocking {
val code = """
extern class MyClass {
fun getList(): List<String>
extern fun getList(): List<String>
}
extern val c: MyClass
val x = c.getList()