plugin: autocomplete for enums and members, better support for local symbols; fixed bug in space normalization
This commit is contained in:
1 parent
22f6c149db
commit
fac58675d5
12 files changed
+581
-187
No files matched your search
@@ -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");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -131,4 +131,78 @@ class MiniAstTest {
|
||||
// Bases captured as plain names for now
|
||||
assertEquals(listOf("Base1", "Base2"), cd.bases)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun miniAst_captures_enum_entries_and_doc() = runTest {
|
||||
val code = """
|
||||
/** Enum E docs */
|
||||
enum E {
|
||||
A,
|
||||
B,
|
||||
C
|
||||
}
|
||||
"""
|
||||
val (_, sink) = compileWithMini(code)
|
||||
val mini = sink.build()
|
||||
assertNotNull(mini)
|
||||
val ed = mini!!.declarations.filterIsInstance<MiniEnumDecl>().firstOrNull { it.name == "E" }
|
||||
assertNotNull(ed)
|
||||
assertNotNull(ed.doc)
|
||||
assertTrue(ed.doc!!.raw.contains("Enum E docs"))
|
||||
assertEquals(listOf("A", "B", "C"), ed.entries)
|
||||
assertEquals("E", ed.name)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun enum_to_synthetic_class_members() = runTest {
|
||||
val code = """
|
||||
enum MyEnum { V1, V2 }
|
||||
"""
|
||||
val (_, sink) = compileWithMini(code)
|
||||
val mini = sink.build()
|
||||
assertNotNull(mini)
|
||||
|
||||
// I'll check via aggregateClasses by mocking the registry or just checking it includes Enum base.
|
||||
val stdlib = BuiltinDocRegistry.docsForModule("lyng.stdlib")
|
||||
val enumBase = stdlib.filterIsInstance<MiniClassDecl>().firstOrNull { it.name == "Enum" }
|
||||
assertNotNull(enumBase, "Enum base class should be in stdlib")
|
||||
assertTrue(enumBase.members.any { it.name == "name" })
|
||||
assertTrue(enumBase.members.any { it.name == "ordinal" })
|
||||
|
||||
// Check if aggregateClasses handles enums from local MiniScript
|
||||
val classes = DocLookupUtils.aggregateClasses(listOf("lyng.stdlib"), mini)
|
||||
val myEnum = classes["MyEnum"]
|
||||
assertNotNull(myEnum, "Local enum should be aggregated as a class")
|
||||
assertEquals(listOf("Enum"), myEnum.bases)
|
||||
assertTrue(myEnum.members.any { it.name == "entries" }, "Should have entries")
|
||||
assertTrue(myEnum.members.any { it.name == "valueOf" }, "Should have valueOf")
|
||||
assertTrue(myEnum.members.any { it.name == "V1" }, "Should have V1")
|
||||
assertTrue(myEnum.members.any { it.name == "V2" }, "Should have V2")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun complete_enum_members() = runTest {
|
||||
val code = """
|
||||
enum MyEnum { V1, V2 }
|
||||
val x = MyEnum.V1.<caret>
|
||||
"""
|
||||
val items = CompletionEngineLight.completeAtMarkerSuspend(code)
|
||||
val names = items.map { it.name }.toSet()
|
||||
assertTrue(names.contains("name"), "Should contain name from Enum base")
|
||||
assertTrue(names.contains("ordinal"), "Should contain ordinal from Enum base")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun complete_enum_class_members() = runTest {
|
||||
val code = """
|
||||
enum MyEnum { V1, V2 }
|
||||
val x = MyEnum.<caret>
|
||||
"""
|
||||
val items = CompletionEngineLight.completeAtMarkerSuspend(code)
|
||||
val names = items.map { it.name }.toSet()
|
||||
assertTrue(names.contains("entries"), "Should contain entries")
|
||||
assertTrue(names.contains("valueOf"), "Should contain valueOf")
|
||||
assertTrue(names.contains("V1"), "Should contain V1")
|
||||
assertTrue(names.contains("V2"), "Should contain V2")
|
||||
}
|
||||
}
|
||||
@@ -676,4 +676,58 @@ class LyngFormatterTest {
|
||||
// Idempotent
|
||||
assertEquals(expected, LyngFormatter.reindent(out, cfg))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun stringLiterals_areNotNormalized() {
|
||||
val src = """
|
||||
val s = "a=b"
|
||||
val s2 = "a + b"
|
||||
val s3 = "a - b"
|
||||
val s4 = "a,b"
|
||||
val s5 = "if(x){}"
|
||||
""".trimIndent()
|
||||
|
||||
val cfg = LyngFormatConfig(applySpacing = true)
|
||||
val formatted = LyngFormatter.format(src, cfg)
|
||||
|
||||
assertEquals(src, formatted, "String literals should not be changed by space normalization")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun mixedCodeAndStrings_normalization() {
|
||||
val src = "val x=1+\"a+b\"+2"
|
||||
val expected = "val x = 1 + \"a+b\" + 2"
|
||||
|
||||
val cfg = LyngFormatConfig(applySpacing = true)
|
||||
val formatted = LyngFormatter.format(src, cfg)
|
||||
|
||||
assertEquals(expected, formatted)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun reindent_ignoresBracesInStrings() {
|
||||
val src = """
|
||||
fun test() {
|
||||
val s = "{"
|
||||
val s2 = "}"
|
||||
}
|
||||
""".trimIndent()
|
||||
|
||||
val cfg = LyngFormatConfig(indentSize = 4)
|
||||
val formatted = LyngFormatter.reindent(src, cfg)
|
||||
|
||||
// If it fails, s2 will be indented differently
|
||||
assertEquals(src, formatted, "Braces in strings should not affect indentation")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun blockComments_spacing_robustness() {
|
||||
val src = "val x=1/*a=b*/+2"
|
||||
val expected = "val x = 1/*a=b*/ + 2"
|
||||
|
||||
val cfg = LyngFormatConfig(applySpacing = true)
|
||||
val formatted = LyngFormatter.format(src, cfg)
|
||||
|
||||
assertEquals(expected, formatted)
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user