135 lines
4.1 KiB
Kotlin
135 lines
4.1 KiB
Kotlin
/*
|
|
* 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.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*
|
|
*/
|
|
|
|
/*
|
|
* Mini binding tests for highlighting/editor features
|
|
*/
|
|
package net.sergeych.lyng
|
|
|
|
import kotlinx.coroutines.test.runTest
|
|
import net.sergeych.lyng.binding.Binder
|
|
import net.sergeych.lyng.miniast.MiniAstBuilder
|
|
import kotlin.test.Ignore
|
|
import kotlin.test.Test
|
|
import kotlin.test.assertEquals
|
|
import kotlin.test.assertNotNull
|
|
import kotlin.test.assertTrue
|
|
|
|
@Ignore
|
|
class BindingTest {
|
|
|
|
private suspend fun bind(code: String): net.sergeych.lyng.binding.BindingSnapshot {
|
|
val src = code.trimIndent()
|
|
val sink = MiniAstBuilder()
|
|
Compiler.compileWithMini(src, sink)
|
|
val mini = sink.build()
|
|
assertNotNull(mini, "MiniScript should be built")
|
|
return Binder.bind(src, mini)
|
|
}
|
|
|
|
@Test
|
|
fun binds_params_and_locals() = runTest {
|
|
val snap = bind(
|
|
"""
|
|
fun f(a:Int){
|
|
val x = 1
|
|
a + x
|
|
}
|
|
"""
|
|
)
|
|
// Expect at least one Parameter symbol "a" and one Value symbol "x"
|
|
val aIds = snap.symbols.filter { it.name == "a" }.map { it.id }
|
|
val xIds = snap.symbols.filter { it.name == "x" }.map { it.id }
|
|
assertTrue(aIds.isNotEmpty())
|
|
assertTrue(xIds.isNotEmpty())
|
|
// Both should have at least one reference across any symbol with that name
|
|
val aRefs = snap.references.count { it.symbolId in aIds }
|
|
val xRefs = snap.references.count { it.symbolId in xIds }
|
|
assertEquals(1, aRefs)
|
|
assertEquals(1, xRefs)
|
|
}
|
|
|
|
@Test
|
|
fun binds_top_level_val_usage() = runTest {
|
|
val snap = bind(
|
|
"""
|
|
val x = 1
|
|
x + 1
|
|
"""
|
|
)
|
|
val xSym = snap.symbols.firstOrNull { it.name == "x" }
|
|
assertNotNull(xSym)
|
|
// One reference usage to top-level x
|
|
val refs = snap.references.filter { it.symbolId == xSym.id }
|
|
assertEquals(1, refs.size)
|
|
}
|
|
|
|
@Test
|
|
fun shadowing_scopes() = runTest {
|
|
val snap = bind(
|
|
"""
|
|
val x = 1
|
|
fun f(){
|
|
val x = 2
|
|
x
|
|
}
|
|
"""
|
|
)
|
|
val allX = snap.symbols.filter { it.name == "x" }
|
|
// Expect at least two x symbols (top-level and local)
|
|
assertEquals(true, allX.size >= 2)
|
|
// The single reference inside f body should bind to the inner x (containerId != null)
|
|
val localXs = allX.filter { it.containerId != null }
|
|
assertEquals(true, localXs.isNotEmpty())
|
|
val localX = localXs.maxBy { it.declStart }
|
|
val refsToLocal = snap.references.count { it.symbolId == localX.id }
|
|
assertEquals(1, refsToLocal)
|
|
}
|
|
|
|
@Test
|
|
fun class_fields_basic() = runTest {
|
|
val snap = bind(
|
|
"""
|
|
class C {
|
|
val foo = 1
|
|
fun bar(){ foo }
|
|
}
|
|
"""
|
|
)
|
|
val fooField = snap.symbols.firstOrNull { it.name == "foo" }
|
|
assertNotNull(fooField)
|
|
// Should have at least one reference (usage in bar)
|
|
val refs = snap.references.count { it.symbolId == fooField.id }
|
|
assertEquals(1, refs)
|
|
}
|
|
|
|
@Test
|
|
fun ctor_params_as_fields() = runTest {
|
|
val snap = bind(
|
|
"""
|
|
class C(val x:Int){
|
|
fun f(){ x }
|
|
}
|
|
"""
|
|
)
|
|
val xField = snap.symbols.firstOrNull { it.name == "x" }
|
|
assertNotNull(xField)
|
|
val refs = snap.references.count { it.symbolId == xField.id }
|
|
assertEquals(1, refs)
|
|
}
|
|
}
|