Add support for symbol inclusion via directive and refactor extern classes handling
This commit is contained in:
1 parent
d2a47d34a3
commit
a6492bb750
4 files changed
+90
-30
No files matched your search
@@ -36,6 +36,7 @@ object LyngAstManager {
|
||||
private val STAMP_KEY = Key.create<Long>("lyng.mini.cache.stamp")
|
||||
private val ANALYSIS_KEY = Key.create<LyngAnalysisResult>("lyng.analysis.cache")
|
||||
private val implicitBuiltinNames = setOf("void")
|
||||
private val includeSymbolsDirective = Regex("""(?im)^\s*//\s*include\s+symbols\s*:\s*(.+?)\s*$""")
|
||||
|
||||
fun getMiniAst(file: PsiFile): MiniScript? = runReadAction {
|
||||
getAnalysis(file)?.mini
|
||||
@@ -44,8 +45,8 @@ object LyngAstManager {
|
||||
fun getCombinedStamp(file: PsiFile): Long = runReadAction {
|
||||
var combinedStamp = file.viewProvider.modificationStamp
|
||||
if (!file.name.endsWith(".lyng.d")) {
|
||||
collectDeclarationFiles(file).forEach { df ->
|
||||
combinedStamp += df.viewProvider.modificationStamp
|
||||
collectDeclarationFiles(file).forEach { symbolsFile ->
|
||||
combinedStamp += symbolsFile.viewProvider.modificationStamp
|
||||
}
|
||||
}
|
||||
combinedStamp
|
||||
@@ -66,6 +67,22 @@ object LyngAstManager {
|
||||
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
|
||||
|
||||
// Fallback for virtual/light files without a stable parent chain (e.g., tests)
|
||||
|
||||
+43
@@ -50,6 +50,18 @@ class LyngDefinitionFilesTest : BasePlatformTestCase() {
|
||||
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() {
|
||||
addDefinitionsFile()
|
||||
enableCompletion()
|
||||
@@ -136,4 +148,35 @@ class LyngDefinitionFilesTest : BasePlatformTestCase() {
|
||||
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") })
|
||||
}
|
||||
|
||||
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") })
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user