plugin: run command. Lyng string "hello"*repeatCount operator. Plugin spell check is still not working properly
This commit is contained in:
1 parent
2d2a74656c
commit
6fa57c8197
17 files changed
+354
-784
No files matched your search
@@ -1881,6 +1881,7 @@ class Compiler(
|
||||
pendingDeclStart = null
|
||||
// so far only simplest enums:
|
||||
val names = mutableListOf<String>()
|
||||
val positions = mutableListOf<Pos>()
|
||||
// skip '{'
|
||||
cc.skipTokenOfType(Token.Type.LBRACE)
|
||||
|
||||
@@ -1889,6 +1890,7 @@ class Compiler(
|
||||
when (t.type) {
|
||||
Token.Type.ID -> {
|
||||
names += t.value
|
||||
positions += t.pos
|
||||
val t1 = cc.nextNonWhitespace()
|
||||
when (t1.type) {
|
||||
Token.Type.COMMA ->
|
||||
@@ -1912,7 +1914,8 @@ class Compiler(
|
||||
entries = names,
|
||||
doc = doc,
|
||||
nameStart = nameToken.pos,
|
||||
isExtern = isExtern
|
||||
isExtern = isExtern,
|
||||
entryPositions = positions
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
@@ -42,7 +42,7 @@ private val fallbackKeywordIds = setOf(
|
||||
"and", "or", "not",
|
||||
// declarations & modifiers
|
||||
"fun", "fn", "class", "interface", "enum", "val", "var", "import", "package",
|
||||
"abstract", "closed", "override",
|
||||
"abstract", "closed", "override", "public", "lazy", "dynamic",
|
||||
"private", "protected", "static", "open", "extern", "init", "get", "set", "by",
|
||||
// control flow and misc
|
||||
"if", "else", "when", "while", "do", "for", "try", "catch", "finally",
|
||||
|
||||
@@ -205,6 +205,7 @@ data class MiniEnumDecl(
|
||||
override val nameStart: Pos,
|
||||
override val isExtern: Boolean = false,
|
||||
override val isStatic: Boolean = false,
|
||||
val entryPositions: List<Pos> = emptyList()
|
||||
) : MiniDecl
|
||||
|
||||
data class MiniCtorField(
|
||||
|
||||
@@ -72,10 +72,11 @@ open class ObjException(
|
||||
val l = getStackTrace().list
|
||||
return buildString {
|
||||
append(message.value)
|
||||
for( t in l)
|
||||
for (t in l)
|
||||
append("\n\tat ${t.toString(scope)}")
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun defaultToString(scope: Scope): ObjString {
|
||||
val at = getStackTrace().list.firstOrNull()?.toString(scope)
|
||||
?: ObjString("(unknown)")
|
||||
@@ -100,21 +101,23 @@ open class ObjException(
|
||||
while (s != null) {
|
||||
val pos = s.pos
|
||||
if (pos != lastPos && !pos.currentLine.isEmpty()) {
|
||||
if (maybeCls != null) {
|
||||
result.list += maybeCls.callWithArgs(
|
||||
scope,
|
||||
pos.source.objSourceName,
|
||||
ObjInt(pos.line.toLong()),
|
||||
ObjInt(pos.column.toLong()),
|
||||
ObjString(pos.currentLine)
|
||||
)
|
||||
} else {
|
||||
// Fallback textual entry if StackTraceEntry class is not available in this scope
|
||||
result.list += ObjString("${pos.source.objSourceName}:${pos.line}:${pos.column}: ${pos.currentLine}")
|
||||
if( (lastPos == null || (lastPos.source != pos.source || lastPos.line != pos.line)) ) {
|
||||
if (maybeCls != null) {
|
||||
result.list += maybeCls.callWithArgs(
|
||||
scope,
|
||||
pos.source.objSourceName,
|
||||
ObjInt(pos.line.toLong()),
|
||||
ObjInt(pos.column.toLong()),
|
||||
ObjString(pos.currentLine)
|
||||
)
|
||||
} else {
|
||||
// Fallback textual entry if StackTraceEntry class is not available in this scope
|
||||
result.list += ObjString("?${pos.source.objSourceName}:${pos.line+1}:${pos.column+1}: ${pos.currentLine}")
|
||||
}
|
||||
lastPos = pos
|
||||
}
|
||||
}
|
||||
s = s.parent
|
||||
lastPos = pos
|
||||
}
|
||||
return result
|
||||
}
|
||||
@@ -339,8 +342,8 @@ fun Obj.isLyngException(): Boolean = isInstanceOf("Exception")
|
||||
/**
|
||||
* Get the exception message.
|
||||
*/
|
||||
suspend fun Obj.getLyngExceptionMessage(scope: Scope?=null): String {
|
||||
require( this.isLyngException() )
|
||||
suspend fun Obj.getLyngExceptionMessage(scope: Scope? = null): String {
|
||||
require(this.isLyngException())
|
||||
val s = scope ?: Script.newScope()
|
||||
return invokeInstanceMethod(s, "message").toString(s).value
|
||||
}
|
||||
@@ -356,18 +359,18 @@ suspend fun Obj.getLyngExceptionMessage(scope: Scope?=null): String {
|
||||
* The stack trace details each frame using indentation for clarity.
|
||||
* @throws IllegalArgumentException if the object is not a Lyng exception.
|
||||
*/
|
||||
suspend fun Obj.getLyngExceptionMessageWithStackTrace(scope: Scope?=null): String {
|
||||
require( this.isLyngException() )
|
||||
suspend fun Obj.getLyngExceptionMessageWithStackTrace(scope: Scope? = null,showDetails:Boolean=true): String {
|
||||
require(this.isLyngException())
|
||||
val s = scope ?: Script.newScope()
|
||||
val msg = getLyngExceptionMessage(s)
|
||||
val trace = getLyngExceptionStackTrace(s)
|
||||
var at = "unknown"
|
||||
val stack = if( !trace.list.isEmpty() ) {
|
||||
// var firstLine = true
|
||||
val stack = if (!trace.list.isEmpty()) {
|
||||
val first = trace.list[0]
|
||||
at = (first.readField(s, "at").value as ObjString).value
|
||||
"\n" + trace.list.map { " at " + it.toString(s).value }.joinToString("\n")
|
||||
}
|
||||
else ""
|
||||
} else ""
|
||||
return "$at: $msg$stack"
|
||||
}
|
||||
|
||||
@@ -392,7 +395,7 @@ suspend fun Obj.getLyngExceptionString(scope: Scope): String =
|
||||
/**
|
||||
* Rethrow this object as a Kotlin [ExecutionError] if it's an exception.
|
||||
*/
|
||||
suspend fun Obj.raiseAsExecutionError(scope: Scope?=null): Nothing {
|
||||
suspend fun Obj.raiseAsExecutionError(scope: Scope? = null): Nothing {
|
||||
if (this is ObjException) raise()
|
||||
val sc = scope ?: Script.newScope()
|
||||
val msg = getLyngExceptionMessage(sc)
|
||||
|
||||
@@ -79,6 +79,14 @@ data class ObjString(val value: String) : Obj() {
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun mul(scope: Scope, other: Obj): Obj {
|
||||
var times = other.toInt()
|
||||
if( times < 0 ) scope.raiseIllegalArgument("negative string repetitions")
|
||||
return ObjString( buildString {
|
||||
while( times-- > 0 ) append(value)
|
||||
})
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
return value.hashCode()
|
||||
}
|
||||
|
||||
@@ -168,6 +168,7 @@ class MiniAstTest {
|
||||
assertNotNull(ed.doc)
|
||||
assertTrue(ed.doc.raw.contains("Enum E docs"))
|
||||
assertEquals(listOf("A", "B", "C"), ed.entries)
|
||||
assertEquals(3, ed.entryPositions.size)
|
||||
assertEquals("E", ed.name)
|
||||
}
|
||||
|
||||
|
||||
@@ -4160,6 +4160,14 @@ class ScriptTest {
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testStringMul() = runTest {
|
||||
eval("""
|
||||
assertEquals("hellohello", "hello"*2)
|
||||
assertEquals("", "hello"*0)
|
||||
""".trimIndent())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testLogicalNot() = runTest {
|
||||
eval(
|
||||
@@ -4672,6 +4680,29 @@ class ScriptTest {
|
||||
// source name, in our case, is is "tc2":
|
||||
assertContains(x1.message!!, "tc2")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testFilterStackTrace() = runTest {
|
||||
var x = try {
|
||||
evalNamed( "tc1","""
|
||||
fun f2() = throw IllegalArgumentException("test3")
|
||||
fun f1() = f2()
|
||||
f1()
|
||||
""".trimIndent())
|
||||
fail("this should throw")
|
||||
}
|
||||
catch(x: ExecutionError) {
|
||||
x
|
||||
}
|
||||
assertEquals("""
|
||||
tc1:1:12: test3
|
||||
at tc1:1:12: fun f2() = throw IllegalArgumentException("test3")
|
||||
at tc1:2:12: fun f1() = f2()
|
||||
at tc1:3:1: f1()
|
||||
""".trimIndent(),x.errorObject.getLyngExceptionMessageWithStackTrace())
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
fun testLyngToKotlinExceptionHelpers() = runTest {
|
||||
var x = evalNamed( "tc1","""
|
||||
|
||||
Reference in new issue
Block a user