From e447c778ed9921b1004599347b834c5b2ce3153c Mon Sep 17 00:00:00 2001 From: sergeych Date: Sun, 15 Mar 2026 02:53:33 +0300 Subject: [PATCH] fixed few bugs in compiler and plugin --- .../idea/annotators/LyngExternalAnnotator.kt | 8 +- .../sergeych/lyng/idea/highlight/LyngLexer.kt | 2 +- .../sergeych/lyng/idea/util/LyngAstManager.kt | 15 +-- .../definitions/LyngDefinitionFilesTest.kt | 12 ++ .../kotlin/net/sergeych/lyng/Compiler.kt | 123 +++++++++++++++++- .../lyng/highlight/SimpleLyngHighlighter.kt | 2 +- .../sergeych/lyng/tools/LyngLanguageTools.kt | 10 +- lynglib/src/commonTest/kotlin/TypesTest.kt | 45 +++++-- .../lyng/tools/LyngLanguageToolsTest.kt | 49 ++++++- lynglib/stdlib/lyng/root.lyng | 22 ++-- 10 files changed, 243 insertions(+), 45 deletions(-) diff --git a/lyng-idea/src/main/kotlin/net/sergeych/lyng/idea/annotators/LyngExternalAnnotator.kt b/lyng-idea/src/main/kotlin/net/sergeych/lyng/idea/annotators/LyngExternalAnnotator.kt index c8288ae..d418cf7 100644 --- a/lyng-idea/src/main/kotlin/net/sergeych/lyng/idea/annotators/LyngExternalAnnotator.kt +++ b/lyng-idea/src/main/kotlin/net/sergeych/lyng/idea/annotators/LyngExternalAnnotator.kt @@ -88,9 +88,11 @@ class LyngExternalAnnotator : ExternalAnnotator imp.segments.forEach { seg -> - val start = analysis.source.offsetOf(seg.range.start) - val end = analysis.source.offsetOf(seg.range.end) - putRange(start, end, LyngHighlighterColors.NAMESPACE) + if (seg.range.start.source === analysis.source && seg.range.end.source === analysis.source) { + val start = analysis.source.offsetOf(seg.range.start) + val end = analysis.source.offsetOf(seg.range.end) + putRange(start, end, LyngHighlighterColors.NAMESPACE) + } } } diff --git a/lyng-idea/src/main/kotlin/net/sergeych/lyng/idea/highlight/LyngLexer.kt b/lyng-idea/src/main/kotlin/net/sergeych/lyng/idea/highlight/LyngLexer.kt index bd14f57..0c3082f 100644 --- a/lyng-idea/src/main/kotlin/net/sergeych/lyng/idea/highlight/LyngLexer.kt +++ b/lyng-idea/src/main/kotlin/net/sergeych/lyng/idea/highlight/LyngLexer.kt @@ -35,7 +35,7 @@ class LyngLexer : LexerBase() { "fun", "val", "var", "class", "interface", "type", "import", "as", "abstract", "closed", "override", "static", "extern", "open", "private", "protected", "if", "else", "for", "while", "return", "true", "false", "null", - "when", "in", "is", "break", "continue", "try", "catch", "finally", + "when", "in", "is", "break", "continue", "try", "catch", "finally", "void", "get", "set", "object", "enum", "init", "by", "step", "property", "constructor" ) diff --git a/lyng-idea/src/main/kotlin/net/sergeych/lyng/idea/util/LyngAstManager.kt b/lyng-idea/src/main/kotlin/net/sergeych/lyng/idea/util/LyngAstManager.kt index b001b9b..ae69df8 100644 --- a/lyng-idea/src/main/kotlin/net/sergeych/lyng/idea/util/LyngAstManager.kt +++ b/lyng-idea/src/main/kotlin/net/sergeych/lyng/idea/util/LyngAstManager.kt @@ -26,23 +26,16 @@ import com.intellij.psi.search.FilenameIndex import com.intellij.psi.search.GlobalSearchScope import kotlinx.coroutines.runBlocking import net.sergeych.lyng.binding.BindingSnapshot -import net.sergeych.lyng.miniast.BuiltinDocRegistry -import net.sergeych.lyng.miniast.DocLookupUtils -import net.sergeych.lyng.miniast.MiniEnumDecl -import net.sergeych.lyng.miniast.MiniRange -import net.sergeych.lyng.miniast.MiniScript -import net.sergeych.lyng.tools.IdeLenientImportProvider -import net.sergeych.lyng.tools.LyngAnalysisRequest -import net.sergeych.lyng.tools.LyngAnalysisResult -import net.sergeych.lyng.tools.LyngDiagnostic -import net.sergeych.lyng.tools.LyngLanguageTools import net.sergeych.lyng.idea.LyngFileType +import net.sergeych.lyng.miniast.* +import net.sergeych.lyng.tools.* object LyngAstManager { private val MINI_KEY = Key.create("lyng.mini.cache") private val BINDING_KEY = Key.create("lyng.binding.cache") private val STAMP_KEY = Key.create("lyng.mini.cache.stamp") private val ANALYSIS_KEY = Key.create("lyng.analysis.cache") + private val implicitBuiltinNames = setOf("void") fun getMiniAst(file: PsiFile): MiniScript? = runReadAction { getAnalysis(file)?.mini @@ -217,7 +210,7 @@ object LyngAstManager { val msg = diag.message if (msg.startsWith("unresolved name: ")) { val name = msg.removePrefix("unresolved name: ").trim() - name in declaredTopLevel || name in builtinTopLevel + name in declaredTopLevel || name in builtinTopLevel || name in implicitBuiltinNames } else if (msg.startsWith("unresolved member: ")) { val name = msg.removePrefix("unresolved member: ").trim() val range = diag.range diff --git a/lyng-idea/src/test/kotlin/net/sergeych/lyng/idea/definitions/LyngDefinitionFilesTest.kt b/lyng-idea/src/test/kotlin/net/sergeych/lyng/idea/definitions/LyngDefinitionFilesTest.kt index 168c0cf..5913396 100644 --- a/lyng-idea/src/test/kotlin/net/sergeych/lyng/idea/definitions/LyngDefinitionFilesTest.kt +++ b/lyng-idea/src/test/kotlin/net/sergeych/lyng/idea/definitions/LyngDefinitionFilesTest.kt @@ -124,4 +124,16 @@ class LyngDefinitionFilesTest : BasePlatformTestCase() { assertTrue("Should not report unresolved name for Declared", messages.none { it.contains("unresolved name: Declared") }) assertTrue("Should not report unresolved member for greet", messages.none { it.contains("unresolved member: greet") }) } + + fun test_DiagnosticsDoNotReportVoidAsUnresolvedName() { + val code = """ + fun f(): void { + return void + } + """.trimIndent() + myFixture.configureByText("main.lyng", code) + val analysis = LyngAstManager.getAnalysis(myFixture.file) + val messages = analysis?.diagnostics?.map { it.message } ?: emptyList() + assertTrue("Should not report unresolved name for void, got=$messages", messages.none { it.contains("unresolved name: void") }) + } } diff --git a/lynglib/src/commonMain/kotlin/net/sergeych/lyng/Compiler.kt b/lynglib/src/commonMain/kotlin/net/sergeych/lyng/Compiler.kt index a65975a..e85d1ab 100644 --- a/lynglib/src/commonMain/kotlin/net/sergeych/lyng/Compiler.kt +++ b/lynglib/src/commonMain/kotlin/net/sergeych/lyng/Compiler.kt @@ -176,6 +176,8 @@ class Compiler( private val lambdaCaptureEntriesByRef: MutableMap> = mutableMapOf() private val classFieldTypesByName: MutableMap> = mutableMapOf() + private val classMethodReturnTypeByName: MutableMap> = mutableMapOf() + private val classMethodReturnTypeDeclByName: MutableMap> = mutableMapOf() private val classScopeMembersByClassName: MutableMap> = mutableMapOf() private val classScopeCallableMembersByClassName: MutableMap> = mutableMapOf() private val encodedPayloadTypeByScopeId: MutableMap> = mutableMapOf() @@ -2614,7 +2616,34 @@ class Compiler( } Token.Type.NOT -> { - if (operand != null) throw ScriptError(t.pos, "unexpected operator not '!' ") + if (operand != null) { + val save = cc.savePos() + val next = cc.next() + if (next.type == Token.Type.NOT) { + val operandRef = operand + val receiverClass = resolveReceiverClassForMember(operandRef) + val inferredType = resolveReceiverTypeDecl(operandRef) + ?: receiverClass?.let { TypeDecl.Simple(it.className, false) } + if (inferredType == null) { + operand = operandRef + continue + } + if (inferredType == TypeDecl.TypeAny || inferredType == TypeDecl.TypeNullableAny) { + operand = operandRef + continue + } + val nonNullType = makeTypeDeclNonNullable(inferredType) + operand = CastRef( + operandRef, + TypeDeclRef(nonNullType, t.pos), + isNullable = false, + atPos = t.pos + ) + continue + } + cc.restorePos(save) + throw ScriptError(t.pos, "unexpected operator not '!' ") + } val op = parseTerm() ?: throw ScriptError(t.pos, "Expecting expression") operand = UnaryOpRef(UnaryOp.NOT, op) } @@ -3821,6 +3850,21 @@ class Compiler( } } + private fun makeTypeDeclNonNullable(type: TypeDecl): TypeDecl { + if (!type.isNullable) return type + return when (type) { + TypeDecl.TypeAny -> type + TypeDecl.TypeNullableAny -> TypeDecl.TypeAny + is TypeDecl.Function -> type.copy(nullable = false) + is TypeDecl.Ellipsis -> type.copy(nullable = false) + is TypeDecl.TypeVar -> type.copy(nullable = false) + is TypeDecl.Union -> type.copy(nullable = false) + is TypeDecl.Intersection -> type.copy(nullable = false) + is TypeDecl.Simple -> TypeDecl.Simple(type.name, false) + is TypeDecl.Generic -> TypeDecl.Generic(type.name, type.args, false) + } + } + private fun makeMiniTypeNullable(type: MiniTypeRef): MiniTypeRef { return when (type) { is MiniTypeName -> type.copy(nullable = true) @@ -4491,6 +4535,48 @@ class Compiler( is TypeDecl.Intersection -> "I:${type.options.joinToString("&") { typeDeclKey(it) }}" } + private fun classMethodReturnTypeDecl(targetClass: ObjClass?, name: String): TypeDecl? { + if (targetClass == null) return null + if (targetClass == ObjDynamic.type) return TypeDecl.TypeAny + val member = targetClass.getInstanceMemberOrNull(name, includeAbstract = true) + val declaringName = member?.declaringClass?.className + if (declaringName != null) { + classMethodReturnTypeDeclByName[declaringName]?.get(name)?.let { return it } + classMethodReturnTypeByName[declaringName]?.get(name)?.let { + return TypeDecl.Simple(it.className, false) + } + } + classMethodReturnTypeDeclByName[targetClass.className]?.get(name)?.let { return it } + classMethodReturnTypeByName[targetClass.className]?.get(name)?.let { + return TypeDecl.Simple(it.className, false) + } + member?.typeDecl?.let { declaredType -> + if (declaredType is TypeDecl.Function) return declaredType.returnType + return declaredType + } + return null + } + + private fun classMethodReturnClass(targetClass: ObjClass?, name: String): ObjClass? { + if (targetClass == null) return null + if (targetClass == ObjDynamic.type) return ObjDynamic.type + classMethodReturnTypeDecl(targetClass, name)?.let { declared -> + resolveTypeDeclObjClass(declared)?.let { return it } + if (declared is TypeDecl.TypeVar) return Obj.rootObjectType + } + val member = targetClass.getInstanceMemberOrNull(name, includeAbstract = true) + val declaringName = member?.declaringClass?.className + if (declaringName != null) { + classMethodReturnTypeByName[declaringName]?.get(name)?.let { return it } + } + classMethodReturnTypeByName[targetClass.className]?.get(name)?.let { return it } + val declaredType = member?.typeDecl + if (declaredType is TypeDecl.Function) { + resolveTypeDeclObjClass(declaredType.returnType)?.let { return it } + } + return null + } + private fun inferObjClassFromRef(ref: ObjRef): ObjClass? = when (ref) { is ConstRef -> ref.constValue as? ObjClass ?: ref.constValue.objClass is LocalVarRef -> nameObjClass[ref.name] ?: resolveClassByName(ref.name) @@ -4511,6 +4597,11 @@ class Compiler( is RangeRef -> ObjRange.type is ClassOperatorRef -> ObjClassType is CastRef -> resolveTypeRefClass(ref.castTypeRef()) + is IndexRef -> { + val targetClass = resolveReceiverClassForMember(ref.targetRef) + classMethodReturnClass(targetClass, "getAt") + ?: inferFieldReturnClass(targetClass, "getAt") + } else -> null } @@ -4547,6 +4638,12 @@ class Compiler( else -> TypeDecl.TypeVar("${typeDeclName(targetDecl)}.${ref.name}", false) } } + is IndexRef -> { + val targetDecl = resolveReceiverTypeDecl(ref.targetRef) + inferMethodCallReturnTypeDecl("getAt", targetDecl)?.let { return it } + val targetClass = resolveReceiverClassForMember(ref.targetRef) + classMethodReturnTypeDecl(targetClass, "getAt") + } is MethodCallRef -> methodReturnTypeDeclByRef[ref] is CallRef -> callReturnTypeDeclByRef[ref] is StatementRef -> (ref.statement as? ExpressionStatement)?.let { resolveReceiverTypeDecl(it.ref) } @@ -4616,6 +4713,12 @@ class Compiler( val targetClass = resolveReceiverClassForMember(ref.target) inferFieldReturnClass(targetClass, ref.name) } + is IndexRef -> { + val targetClass = resolveReceiverClassForMember(ref.targetRef) + classMethodReturnClass(targetClass, "getAt") + ?: inferFieldReturnClass(targetClass, "getAt") + ?: inferMethodCallReturnClass("getAt") + } else -> null } } @@ -5102,6 +5205,7 @@ class Compiler( } private fun resolveTypeRefClass(ref: ObjRef): ObjClass? = when (ref) { + is TypeDeclRef -> resolveTypeDeclObjClass(ref.decl()) is ConstRef -> ref.constValue as? ObjClass is LocalSlotRef -> resolveTypeDeclObjClass(TypeDecl.Simple(ref.name, false)) ?: nameObjClass[ref.name] is LocalVarRef -> resolveTypeDeclObjClass(TypeDecl.Simple(ref.name, false)) ?: nameObjClass[ref.name] @@ -7885,6 +7989,23 @@ class Compiler( val rawFnStatements = parsedFnStatements?.let { unwrapBytecodeDeep(it) } val inferredReturnClass = returnTypeDecl?.let { resolveTypeDeclObjClass(it) } ?: inferReturnClassFromStatement(rawFnStatements) + if (declKind == SymbolKind.MEMBER && extTypeName == null) { + val ownerClassName = (parentContext as? CodeContext.ClassBody)?.name + if (ownerClassName != null) { + val returnDecl = returnTypeDecl + ?: inferredReturnClass?.let { TypeDecl.Simple(it.className, false) } + if (returnDecl != null) { + classMethodReturnTypeDeclByName + .getOrPut(ownerClassName) { mutableMapOf() }[name] = returnDecl + resolveTypeDeclObjClass(returnDecl)?.let { returnClass -> + classMethodReturnTypeByName + .getOrPut(ownerClassName) { mutableMapOf() }[name] = returnClass + classFieldTypesByName + .getOrPut(ownerClassName) { mutableMapOf() }[name] = returnClass + } + } + } + } if (declKind != SymbolKind.MEMBER && inferredReturnClass != null) { callableReturnTypeByName[name] = inferredReturnClass val slotLoc = lookupSlotLocation(name, includeModule = true) diff --git a/lynglib/src/commonMain/kotlin/net/sergeych/lyng/highlight/SimpleLyngHighlighter.kt b/lynglib/src/commonMain/kotlin/net/sergeych/lyng/highlight/SimpleLyngHighlighter.kt index 956e187..893c186 100644 --- a/lynglib/src/commonMain/kotlin/net/sergeych/lyng/highlight/SimpleLyngHighlighter.kt +++ b/lynglib/src/commonMain/kotlin/net/sergeych/lyng/highlight/SimpleLyngHighlighter.kt @@ -46,7 +46,7 @@ private val fallbackKeywordIds = setOf( "private", "protected", "static", "open", "extern", "init", "get", "set", "by", "step", // control flow and misc "if", "else", "when", "while", "do", "for", "try", "catch", "finally", - "throw", "return", "break", "continue", "this", "null", "true", "false", "unset" + "throw", "return", "break", "continue", "this", "null", "true", "false", "unset", "void" ) /** Maps lexer token type (and sometimes value) to a [HighlightKind]. */ diff --git a/lynglib/src/commonMain/kotlin/net/sergeych/lyng/tools/LyngLanguageTools.kt b/lynglib/src/commonMain/kotlin/net/sergeych/lyng/tools/LyngLanguageTools.kt index 12d19ee..b054a5a 100644 --- a/lynglib/src/commonMain/kotlin/net/sergeych/lyng/tools/LyngLanguageTools.kt +++ b/lynglib/src/commonMain/kotlin/net/sergeych/lyng/tools/LyngLanguageTools.kt @@ -179,6 +179,7 @@ object LyngLanguageTools { val source = analysis.source val out = ArrayList(128) val covered = HashSet>() + fun isCurrentSource(pos: Pos): Boolean = pos.source === source fun addRange(start: Int, end: Int, kind: LyngSemanticKind) { if (start < 0 || end <= start || end > analysis.text.length) return @@ -187,6 +188,7 @@ object LyngLanguageTools { } fun addName(pos: Pos, name: String, kind: LyngSemanticKind) { + if (!isCurrentSource(pos)) return val s = source.offsetOf(pos) addRange(s, s + name.length, kind) } @@ -206,7 +208,9 @@ object LyngLanguageTools { addTypeSegments(t.returnType) } is MiniTypeVar -> { - addRange(source.offsetOf(t.range.start), source.offsetOf(t.range.end), LyngSemanticKind.TypeRef) + if (isCurrentSource(t.range.start) && isCurrentSource(t.range.end)) { + addRange(source.offsetOf(t.range.start), source.offsetOf(t.range.end), LyngSemanticKind.TypeRef) + } } is MiniTypeUnion -> { t.options.forEach { addTypeSegments(it) } @@ -262,7 +266,9 @@ object LyngLanguageTools { mini.imports.forEach { imp -> imp.segments.forEach { seg -> - addRange(source.offsetOf(seg.range.start), source.offsetOf(seg.range.end), LyngSemanticKind.TypeRef) + if (isCurrentSource(seg.range.start) && isCurrentSource(seg.range.end)) { + addRange(source.offsetOf(seg.range.start), source.offsetOf(seg.range.end), LyngSemanticKind.TypeRef) + } } } diff --git a/lynglib/src/commonTest/kotlin/TypesTest.kt b/lynglib/src/commonTest/kotlin/TypesTest.kt index 78bc2b6..a9e944b 100644 --- a/lynglib/src/commonTest/kotlin/TypesTest.kt +++ b/lynglib/src/commonTest/kotlin/TypesTest.kt @@ -565,19 +565,6 @@ class TypesTest { """.trimIndent()) } -// @Test -// fun testNullableGenericTypes() = runTest { -// eval(""" -// fun t(): String = -// when(T) { -// is Object -> "%s is Object"(T::class.name) -// else -> throw "It should not happen" -// } -// assert( Int is Object) -// assertEquals( t(), "Class is Object") -// """.trimIndent()) -// } - @Test fun testIndexer() = runTest { eval(""" class Greeter { @@ -596,6 +583,38 @@ class TypesTest { """.trimIndent()) } + + @Test fun testIndexer2() = runTest { + eval(""" + class Foo(bar) + + class Greeter { + override fun getAt(name): Foo = Foo("Hello, %s!"(name)) + } + assertEquals("Hello, Bob!",Greeter()["Bob"].bar) + val g = Greeter() + assertEquals("Hello, Bob!",g["Bob"].bar) + + // it should work with objects too: + object Polite { + override fun getAt(name): Foo? = Foo("How do you do, %s?"(name)) + } + + assertEquals("How do you do, Bob?",Polite["Bob"].bar) + assertEquals("How do you do, Bob?",Polite["Bob"]?.bar) + assertEquals("How do you do, Bob?",Polite["Bob"]!!.bar) + + class Greeter2 { + override fun getAt(name): Foo? = Foo("How do you do, %s?"(name)) + } + val g2 = Greeter2() + assertEquals("How do you do, Bob?",g2["Bob"]?.bar) + val g2v: Foo = g2["Bob"]!! + assertEquals("How do you do, Bob?",g2v.bar) + assertEquals("How do you do, Bob?",Greeter2()["Bob"].bar) + + """.trimIndent()) + } // @Test fun nonTrivialOperatorsTest() = runTest { // val s = Script.newScope() // s.eval(""" diff --git a/lynglib/src/commonTest/kotlin/net/sergeych/lyng/tools/LyngLanguageToolsTest.kt b/lynglib/src/commonTest/kotlin/net/sergeych/lyng/tools/LyngLanguageToolsTest.kt index c53cdb6..7f893b0 100644 --- a/lynglib/src/commonTest/kotlin/net/sergeych/lyng/tools/LyngLanguageToolsTest.kt +++ b/lynglib/src/commonTest/kotlin/net/sergeych/lyng/tools/LyngLanguageToolsTest.kt @@ -18,8 +18,9 @@ package net.sergeych.lyng.tools import kotlinx.coroutines.test.runTest -import net.sergeych.lyng.miniast.MiniClassDecl -import net.sergeych.lyng.miniast.MiniMemberTypeAliasDecl +import net.sergeych.lyng.Pos +import net.sergeych.lyng.Source +import net.sergeych.lyng.miniast.* import net.sergeych.lyng.stdlib_included.rootLyng import kotlin.test.Test import kotlin.test.assertEquals @@ -127,4 +128,48 @@ class LyngLanguageToolsTest { val dis = LyngLanguageTools.disassembleSymbol(code, "add") assertTrue(!dis.contains("not a compiled body"), "Disassembly should be produced, got: $dis") } + + @Test + fun languageTools_semanticHighlights_ignore_foreign_sources() { + val localSource = Source("local.lyng", "val x = 1") + val foreignSource = Source("defs.lyng.d", "val y = 2") + val localStart = Pos(localSource, 0, 0) + val foreignStart = Pos(foreignSource, 0, 0) + + val mini = MiniScript( + range = MiniRange(localStart, localStart), + declarations = mutableListOf( + MiniValDecl( + range = MiniRange(foreignStart, foreignStart), + name = "y", + mutable = false, + type = null, + initRange = null, + doc = null, + nameStart = foreignStart + ) + ), + imports = mutableListOf( + MiniImport( + range = MiniRange(foreignStart, foreignStart), + segments = listOf( + MiniImport.Segment("defs", MiniRange(foreignStart, foreignStart)) + ) + ) + ) + ) + val analysis = LyngAnalysisResult( + source = localSource, + text = localSource.text, + mini = mini, + binding = null, + resolution = null, + importedModules = emptyList(), + diagnostics = emptyList(), + lexicalHighlights = emptyList() + ) + + val spans = LyngLanguageTools.semanticHighlights(analysis) + assertTrue(spans.isEmpty(), "Semantic spans should ignore positions from foreign sources, got $spans") + } } diff --git a/lynglib/stdlib/lyng/root.lyng b/lynglib/stdlib/lyng/root.lyng index d973396..9c5ce87 100644 --- a/lynglib/stdlib/lyng/root.lyng +++ b/lynglib/stdlib/lyng/root.lyng @@ -1,6 +1,6 @@ package lyng.stdlib -extern fun flow(builder: FlowBuilder.()->Void): Flow +extern fun flow(builder: FlowBuilder.()->void): Flow /* Built-in exception type. */ extern class Exception @@ -9,7 +9,7 @@ extern class NotImplementedException extern class Delegate extern class Iterable { fun iterator(): Iterator - fun forEach(action: (T)->Void): Void + fun forEach(action: (T)->void): void fun map(transform: (T)->R): List fun toList(): List fun toImmutableList(): ImmutableList @@ -22,7 +22,7 @@ extern class Iterable { extern class Iterator { fun hasNext(): Bool fun next(): T - fun cancelIteration(): Void + fun cancelIteration(): void fun toList(): List } @@ -44,14 +44,14 @@ extern class ImmutableList : Array { } extern class List : Array { - fun add(value: T, more...): Void + fun add(value: T, more...): void fun toImmutable(): ImmutableList } extern class RingBuffer : Iterable { val size: Int fun first(): T - fun add(value: T): Void + fun add(value: T): void } extern class Set : Collection { @@ -337,17 +337,17 @@ override fun List.toString() { } /* Sort list in-place by key selector. */ -fun List.sortBy(predicate: (T)->R): Void { +fun List.sortBy(predicate: (T)->R): void { sortWith { a, b -> predicate(a) <=> predicate(b) } } /* Sort list in-place by natural order. */ -fun List.sort(): Void { +fun List.sort(): void { sortWith { a, b -> a <=> b } } /* Print this exception and its stack trace to standard output. */ -fun Exception.printStackTrace(): Void { +fun Exception.printStackTrace(): void { println(this) for( entry in stackTrace ) { println("\tat "+entry.toString()) @@ -357,7 +357,7 @@ fun Exception.printStackTrace(): Void { /* Compile this string into a regular expression. */ val String.re: Regex get() = Regex(this) -fun TODO(message: Object?=null): Void { +fun TODO(message: Object?=null): void { throw "not implemented" } @@ -376,12 +376,12 @@ enum DelegateAccess { Implementing this interface is optional as Lyng uses dynamic dispatch, but it is recommended for documentation and clarity. */ -interface Delegate { +interface Delegate { /* Called when a delegated 'val' or 'var' is read. */ fun getValue(thisRef: ThisRefType, name: String): T = TODO("delegate getter is not implemented") /* Called when a delegated 'var' is written. */ - fun setValue(thisRef: ThisRefType, name: String, newValue: T): Void = TODO("delegate setter is not implemented") + fun setValue(thisRef: ThisRefType, name: String, newValue: T): void = TODO("delegate setter is not implemented") /* Called when a delegated function is invoked. */ fun invoke(thisRef: ThisRefType, name: String, args...): Object = TODO("delegate invoke is not implemented")