Phase 5a: add configurable Jai module roots
This commit is contained in:
173
src/test/kotlin/dev/hgh/jai/settings/JaiConfiguredRootTest.kt
Normal file
173
src/test/kotlin/dev/hgh/jai/settings/JaiConfiguredRootTest.kt
Normal file
@@ -0,0 +1,173 @@
|
||||
package dev.hgh.jai.settings
|
||||
|
||||
import com.intellij.openapi.vfs.LocalFileSystem
|
||||
import com.intellij.psi.PsiFile
|
||||
import com.intellij.psi.PsiManager
|
||||
import com.intellij.psi.PsiReferenceService
|
||||
import com.intellij.psi.search.searches.ReferencesSearch
|
||||
import com.intellij.psi.util.PsiTreeUtil
|
||||
import com.intellij.testFramework.fixtures.BasePlatformTestCase
|
||||
import dev.hgh.jai.psi.JaiDeclName
|
||||
import dev.hgh.jai.psi.JaiLiteralExpr
|
||||
import dev.hgh.jai.psi.JaiRefExpr
|
||||
import java.nio.file.Files
|
||||
import java.nio.file.Path
|
||||
|
||||
class JaiConfiguredRootTest : BasePlatformTestCase() {
|
||||
private var temporaryRoot: Path? = null
|
||||
|
||||
fun testConfiguredRootResolvesImportedModuleAndSymbol() {
|
||||
val module = configureRoot("Custom/module.jai" to "Helper :: () {}")
|
||||
val source =
|
||||
myFixture.addFileToProject(
|
||||
"consumer.jai",
|
||||
"""
|
||||
#import "Custom";
|
||||
main :: () { Helper(); }
|
||||
""".trimIndent(),
|
||||
)
|
||||
|
||||
val moduleLiteral = literalWithText(source, "\"Custom\"")
|
||||
assertEquals(
|
||||
module.path,
|
||||
onlyReference(moduleLiteral)
|
||||
.resolve()
|
||||
?.containingFile
|
||||
?.virtualFile
|
||||
?.path,
|
||||
)
|
||||
|
||||
val symbolReference =
|
||||
PsiTreeUtil
|
||||
.findChildrenOfType(source, JaiRefExpr::class.java)
|
||||
.single { it.text == "Helper" }
|
||||
assertEquals(
|
||||
module.path,
|
||||
onlyReference(symbolReference)
|
||||
.resolve()
|
||||
?.containingFile
|
||||
?.virtualFile
|
||||
?.path,
|
||||
)
|
||||
}
|
||||
|
||||
fun testConfiguredRootResolvesLoadFileFromConfiguredRoot() {
|
||||
val externalFile = configureRoot("external.jai" to "value :: 1;")
|
||||
val source = myFixture.addFileToProject("consumer.jai", "#load \"external.jai\";")
|
||||
|
||||
val literal = literalWithText(source, "\"external.jai\"")
|
||||
|
||||
assertEquals(
|
||||
externalFile.path,
|
||||
onlyReference(literal)
|
||||
.resolve()
|
||||
?.containingFile
|
||||
?.virtualFile
|
||||
?.path,
|
||||
)
|
||||
}
|
||||
|
||||
fun testConfiguredRootSuppliesImportAndLoadCompletion() {
|
||||
configureRoot(
|
||||
"Custom/module.jai" to "value :: 1;",
|
||||
"external.jai" to "value :: 1;",
|
||||
)
|
||||
|
||||
val configuredRoots = JaiProjectSettings.getInstance(project).configuredRoots()
|
||||
assertEquals("expected one configured VFS root", 1, configuredRoots.size)
|
||||
assertNotNull("expected the configured module directory", configuredRoots.single().findChild("Custom"))
|
||||
|
||||
myFixture.configureByText("import-consumer.jai", "#import \"Cus<caret>\";")
|
||||
myFixture.completeBasic()
|
||||
myFixture.checkResult("#import \"Custom\";")
|
||||
|
||||
myFixture.configureByText("load-consumer.jai", "#load \"ext<caret>\";")
|
||||
myFixture.completeBasic()
|
||||
myFixture.checkResult("#load \"external.jai\";")
|
||||
}
|
||||
|
||||
fun testReferencesSearchIncludesProjectUsagesForConfiguredExternalDeclaration() {
|
||||
val module = configureRoot("Custom/module.jai" to "Helper :: () {}")
|
||||
val source =
|
||||
myFixture.addFileToProject(
|
||||
"consumer.jai",
|
||||
"""
|
||||
#import "Custom";
|
||||
main :: () { Helper(); }
|
||||
""".trimIndent(),
|
||||
)
|
||||
JaiProjectSettings.getInstance(project).refreshProjectRoots()
|
||||
val externalFile =
|
||||
PsiManager
|
||||
.getInstance(project)
|
||||
.findFile(module)
|
||||
assertNotNull("expected PSI for configured external module", externalFile)
|
||||
val declaration =
|
||||
PsiTreeUtil
|
||||
.findChildrenOfType(externalFile!!, JaiDeclName::class.java)
|
||||
.single { it.text == "Helper" }
|
||||
assertTrue(
|
||||
"configured Jai files should be indexed as library sources",
|
||||
com.intellij.openapi.roots.ProjectFileIndex
|
||||
.getInstance(project)
|
||||
.isInLibrarySource(module),
|
||||
)
|
||||
|
||||
val usages = ReferencesSearch.search(declaration).findAll()
|
||||
|
||||
assertEquals(
|
||||
"expected the project usage; scope=${declaration.useScope}, usages=$usages",
|
||||
1,
|
||||
usages.size,
|
||||
)
|
||||
assertEquals("Helper", usages.single().element.text)
|
||||
assertEquals(
|
||||
source.virtualFile.path,
|
||||
usages
|
||||
.single()
|
||||
.element.containingFile.virtualFile.path,
|
||||
)
|
||||
}
|
||||
|
||||
private fun configureRoot(vararg files: Pair<String, String>): com.intellij.openapi.vfs.VirtualFile {
|
||||
val root = Files.createTempDirectory("jai-configured-root-").toAbsolutePath().normalize()
|
||||
temporaryRoot = root
|
||||
files.forEach { (relativePath, contents) ->
|
||||
val file = root.resolve(relativePath)
|
||||
Files.createDirectories(file.parent)
|
||||
Files.writeString(file, contents)
|
||||
}
|
||||
|
||||
val virtualRoot = LocalFileSystem.getInstance().refreshAndFindFileByNioFile(root)
|
||||
assertNotNull("expected the configured root to be visible to VFS", virtualRoot)
|
||||
JaiProjectSettings.getInstance(project).setRootPaths(listOf(root.toString()))
|
||||
return virtualRoot!!.findFileByRelativePath(files.first().first)!!
|
||||
}
|
||||
|
||||
private fun literalWithText(
|
||||
source: PsiFile,
|
||||
text: String,
|
||||
): JaiLiteralExpr {
|
||||
val literal =
|
||||
PsiTreeUtil
|
||||
.findChildrenOfType(source, JaiLiteralExpr::class.java)
|
||||
.firstOrNull { it.text == text }
|
||||
assertNotNull("expected string literal $text", literal)
|
||||
return literal!!
|
||||
}
|
||||
|
||||
private fun onlyReference(element: com.intellij.psi.PsiElement) =
|
||||
PsiReferenceService
|
||||
.getService()
|
||||
.getContributedReferences(element)
|
||||
.also { assertEquals("expected exactly one reference", 1, it.size) }
|
||||
.single()
|
||||
|
||||
override fun tearDown() {
|
||||
try {
|
||||
super.tearDown()
|
||||
} finally {
|
||||
temporaryRoot?.toFile()?.deleteRecursively()
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user