Add support for symbol inclusion via directive and refactor extern classes handling
This commit is contained in:
parent
d2a47d34a3
commit
a6492bb750
@ -36,6 +36,7 @@ object LyngAstManager {
|
|||||||
private val STAMP_KEY = Key.create<Long>("lyng.mini.cache.stamp")
|
private val STAMP_KEY = Key.create<Long>("lyng.mini.cache.stamp")
|
||||||
private val ANALYSIS_KEY = Key.create<LyngAnalysisResult>("lyng.analysis.cache")
|
private val ANALYSIS_KEY = Key.create<LyngAnalysisResult>("lyng.analysis.cache")
|
||||||
private val implicitBuiltinNames = setOf("void")
|
private val implicitBuiltinNames = setOf("void")
|
||||||
|
private val includeSymbolsDirective = Regex("""(?im)^\s*//\s*include\s+symbols\s*:\s*(.+?)\s*$""")
|
||||||
|
|
||||||
fun getMiniAst(file: PsiFile): MiniScript? = runReadAction {
|
fun getMiniAst(file: PsiFile): MiniScript? = runReadAction {
|
||||||
getAnalysis(file)?.mini
|
getAnalysis(file)?.mini
|
||||||
@ -44,8 +45,8 @@ object LyngAstManager {
|
|||||||
fun getCombinedStamp(file: PsiFile): Long = runReadAction {
|
fun getCombinedStamp(file: PsiFile): Long = runReadAction {
|
||||||
var combinedStamp = file.viewProvider.modificationStamp
|
var combinedStamp = file.viewProvider.modificationStamp
|
||||||
if (!file.name.endsWith(".lyng.d")) {
|
if (!file.name.endsWith(".lyng.d")) {
|
||||||
collectDeclarationFiles(file).forEach { df ->
|
collectDeclarationFiles(file).forEach { symbolsFile ->
|
||||||
combinedStamp += df.viewProvider.modificationStamp
|
combinedStamp += symbolsFile.viewProvider.modificationStamp
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
combinedStamp
|
combinedStamp
|
||||||
@ -66,6 +67,22 @@ object LyngAstManager {
|
|||||||
currentDir = currentDir.parentDirectory
|
currentDir = currentDir.parentDirectory
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val includeSpecs = includeSymbolsDirective.findAll(file.viewProvider.contents)
|
||||||
|
.flatMap { it.groupValues[1].split(',').asSequence() }
|
||||||
|
.map { it.trim() }
|
||||||
|
.filter { it.isNotEmpty() }
|
||||||
|
.toList()
|
||||||
|
val baseDir = file.virtualFile?.parent
|
||||||
|
if (baseDir != null) {
|
||||||
|
for (spec in includeSpecs) {
|
||||||
|
val included = baseDir.findFileByRelativePath(spec) ?: continue
|
||||||
|
if (included.path == file.virtualFile?.path) continue
|
||||||
|
if (seen.add(included.path)) {
|
||||||
|
psiManager.findFile(included)?.let { result.add(it) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (result.isNotEmpty()) return@runReadAction result
|
if (result.isNotEmpty()) return@runReadAction result
|
||||||
|
|
||||||
// Fallback for virtual/light files without a stable parent chain (e.g., tests)
|
// Fallback for virtual/light files without a stable parent chain (e.g., tests)
|
||||||
|
|||||||
@ -50,6 +50,18 @@ class LyngDefinitionFilesTest : BasePlatformTestCase() {
|
|||||||
myFixture.addFileToProject("api.lyng.d", defs)
|
myFixture.addFileToProject("api.lyng.d", defs)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun addPlainSymbolsFile() {
|
||||||
|
val defs = """
|
||||||
|
/** Symbols exposed via include directive */
|
||||||
|
class PlainDeclared(val name: String) {
|
||||||
|
fun hello(): String = "ok"
|
||||||
|
}
|
||||||
|
|
||||||
|
fun plainTopFun(x: Int): Int = x + 2
|
||||||
|
""".trimIndent()
|
||||||
|
myFixture.addFileToProject("plain_symbols.lyng", defs)
|
||||||
|
}
|
||||||
|
|
||||||
fun test_CompletionsIncludeDefinitions() {
|
fun test_CompletionsIncludeDefinitions() {
|
||||||
addDefinitionsFile()
|
addDefinitionsFile()
|
||||||
enableCompletion()
|
enableCompletion()
|
||||||
@ -136,4 +148,35 @@ class LyngDefinitionFilesTest : BasePlatformTestCase() {
|
|||||||
val messages = analysis?.diagnostics?.map { it.message } ?: emptyList()
|
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") })
|
assertTrue("Should not report unresolved name for void, got=$messages", messages.none { it.contains("unresolved name: void") })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun test_CompletionsIncludePlainLyngViaDirective() {
|
||||||
|
addPlainSymbolsFile()
|
||||||
|
enableCompletion()
|
||||||
|
val code = """
|
||||||
|
// include symbols: plain_symbols.lyng
|
||||||
|
val v = plainTop<caret>
|
||||||
|
""".trimIndent()
|
||||||
|
myFixture.configureByText("main.lyng", code)
|
||||||
|
val text = myFixture.editor.document.text
|
||||||
|
val caret = myFixture.caretOffset
|
||||||
|
val analysis = LyngAstManager.getAnalysis(myFixture.file)
|
||||||
|
val engine = runBlocking { CompletionEngineLight.completeSuspend(text, caret, analysis?.mini, analysis?.binding).map { it.name } }
|
||||||
|
assertTrue("Expected plainTopFun from included .lyng; got=$engine", engine.contains("plainTopFun"))
|
||||||
|
}
|
||||||
|
|
||||||
|
fun test_DiagnosticsIgnorePlainLyngSymbolsViaDirective() {
|
||||||
|
addPlainSymbolsFile()
|
||||||
|
val code = """
|
||||||
|
// include symbols: plain_symbols.lyng
|
||||||
|
val x = plainTopFun(1)
|
||||||
|
val y = PlainDeclared("x")
|
||||||
|
y.hello()
|
||||||
|
""".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 plainTopFun", messages.none { it.contains("unresolved name: plainTopFun") })
|
||||||
|
assertTrue("Should not report unresolved name for PlainDeclared", messages.none { it.contains("unresolved name: PlainDeclared") })
|
||||||
|
assertTrue("Should not report unresolved member for hello", messages.none { it.contains("unresolved member: hello") })
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -21,7 +21,7 @@ import org.jetbrains.kotlin.gradle.ExperimentalWasmDsl
|
|||||||
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
|
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
|
||||||
|
|
||||||
group = "net.sergeych"
|
group = "net.sergeych"
|
||||||
version = "1.5.0-SNAPSHOT"
|
version = "1.5.2-SNAPSHOT"
|
||||||
|
|
||||||
// Removed legacy buildscript classpath declarations; plugins are applied via the plugins DSL below
|
// Removed legacy buildscript classpath declarations; plugins are applied via the plugins DSL below
|
||||||
|
|
||||||
|
|||||||
@ -8,22 +8,22 @@ extern class IllegalArgumentException
|
|||||||
extern class NotImplementedException
|
extern class NotImplementedException
|
||||||
extern class Delegate
|
extern class Delegate
|
||||||
extern class Iterable<T> {
|
extern class Iterable<T> {
|
||||||
extern fun iterator(): Iterator<T>
|
fun iterator(): Iterator<T>
|
||||||
extern fun forEach(action: (T)->void): void
|
fun forEach(action: (T)->void): void
|
||||||
extern fun map<R>(transform: (T)->R): List<R>
|
fun map<R>(transform: (T)->R): List<R>
|
||||||
extern fun toList(): List<T>
|
fun toList(): List<T>
|
||||||
extern fun toImmutableList(): ImmutableList<T>
|
fun toImmutableList(): ImmutableList<T>
|
||||||
extern val toSet: Set<T>
|
val toSet: Set<T>
|
||||||
extern val toImmutableSet: ImmutableSet<T>
|
val toImmutableSet: ImmutableSet<T>
|
||||||
extern val toMap: Map<Object,Object>
|
val toMap: Map<Object,Object>
|
||||||
extern val toImmutableMap: ImmutableMap<Object,Object>
|
val toImmutableMap: ImmutableMap<Object,Object>
|
||||||
}
|
}
|
||||||
|
|
||||||
extern class Iterator<T> {
|
extern class Iterator<T> {
|
||||||
extern fun hasNext(): Bool
|
fun hasNext(): Bool
|
||||||
extern fun next(): T
|
fun next(): T
|
||||||
extern fun cancelIteration(): void
|
fun cancelIteration(): void
|
||||||
extern fun toList(): List<T>
|
fun toList(): List<T>
|
||||||
}
|
}
|
||||||
|
|
||||||
// Host-provided iterator wrapper for Kotlin collections.
|
// Host-provided iterator wrapper for Kotlin collections.
|
||||||
@ -33,47 +33,47 @@ class KotlinIterator<T> : Iterator<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
extern class Collection<T> : Iterable<T> {
|
extern class Collection<T> : Iterable<T> {
|
||||||
extern val size: Int
|
val size: Int
|
||||||
}
|
}
|
||||||
|
|
||||||
extern class Array<T> : Collection<T> {
|
extern class Array<T> : Collection<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
extern class ImmutableList<T> : Array<T> {
|
extern class ImmutableList<T> : Array<T> {
|
||||||
extern fun toMutable(): List<T>
|
fun toMutable(): List<T>
|
||||||
}
|
}
|
||||||
|
|
||||||
extern class List<T> : Array<T> {
|
extern class List<T> : Array<T> {
|
||||||
extern fun add(value: T, more...): void
|
fun add(value: T, more...): void
|
||||||
extern fun toImmutable(): ImmutableList<T>
|
fun toImmutable(): ImmutableList<T>
|
||||||
}
|
}
|
||||||
|
|
||||||
extern class RingBuffer<T> : Iterable<T> {
|
extern class RingBuffer<T> : Iterable<T> {
|
||||||
extern val size: Int
|
val size: Int
|
||||||
extern fun first(): T
|
fun first(): T
|
||||||
extern fun add(value: T): void
|
fun add(value: T): void
|
||||||
}
|
}
|
||||||
|
|
||||||
extern class Set<T> : Collection<T> {
|
extern class Set<T> : Collection<T> {
|
||||||
extern fun toImmutable(): ImmutableSet<T>
|
fun toImmutable(): ImmutableSet<T>
|
||||||
}
|
}
|
||||||
|
|
||||||
extern class ImmutableSet<T> : Collection<T> {
|
extern class ImmutableSet<T> : Collection<T> {
|
||||||
extern fun toMutable(): Set<T>
|
fun toMutable(): Set<T>
|
||||||
}
|
}
|
||||||
|
|
||||||
extern class Map<K,V> : Collection<MapEntry<K,V>> {
|
extern class Map<K,V> : Collection<MapEntry<K,V>> {
|
||||||
extern fun toImmutable(): ImmutableMap<K,V>
|
fun toImmutable(): ImmutableMap<K,V>
|
||||||
}
|
}
|
||||||
|
|
||||||
extern class ImmutableMap<K,V> : Collection<MapEntry<K,V>> {
|
extern class ImmutableMap<K,V> : Collection<MapEntry<K,V>> {
|
||||||
extern fun getOrNull(key: K): V?
|
fun getOrNull(key: K): V?
|
||||||
extern fun toMutable(): Map<K,V>
|
fun toMutable(): Map<K,V>
|
||||||
}
|
}
|
||||||
|
|
||||||
extern class MapEntry<K,V> : Array<Object> {
|
extern class MapEntry<K,V> : Array<Object> {
|
||||||
extern val key: K
|
val key: K
|
||||||
extern val value: V
|
val value: V
|
||||||
}
|
}
|
||||||
|
|
||||||
// Built-in math helpers (implemented in host runtime).
|
// Built-in math helpers (implemented in host runtime).
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user