<NME> StdlibInstallHelper.kt
<BEF> package org.elm.workspace

import com.intellij.openapi.project.Project
import com.intellij.openapi.util.io.FileUtil
import com.intellij.openapi.vfs.LocalFileSystem
import org.elm.fileTree
import org.elm.openapiext.pathAsPath
import org.intellij.lang.annotations.Language
import java.nio.file.Files

/*
Some of the Elm tests depend on having certain Elm packages installed in the global location.
Some of the Elm tests depend on having certain Elm packages installed in the global location.
And since Elm has pretty poor facilities for installing packages, we have to resort to tricks
like asking it to compile a dummy application.
 */

interface ElmStdlibVariant {

    /**
     * A description of the packages that we want to be installed
     */
    val jsonManifest: String

    /**
     * Install Elm 0.19 stdlib in the default location ($HOME/.elm)
     */
    fun ensureElmStdlibInstalled(project: Project, toolchain: ElmToolchain)
}

object EmptyElmStdlibVariant : ElmStdlibVariant {
    override fun ensureElmStdlibInstalled(project: Project, toolchain: ElmToolchain) {
        val elm = toolchain.elmCompilerPath?.let { ElmCLI(it) }
                ?: error("Must have a path to the Elm compiler to install Elm stdlib")

        val tmpDir = LocalFileSystem.getInstance()
                .refreshAndFindFileByIoFile(FileUtil.createTempDirectory("elm-stdlib-variant", null, true))
                ?: error("Could not create temp dir for Elm stdlib installation")

        fileTree {
            project("elm.json", jsonManifest)
            file("Main.elm", elmHeadlessWorkerCode)
        }.create(project, tmpDir)

        val manifestPath = tmpDir.pathAsPath.resolve("elm.json")

//        println("-----------------------------")
//        println("Installing Deps for $this")
        val output = elm.installDeps(project, manifestPath)
//        println("STDOUT: ${output.stdout}")
//        println("\n")
//        println("STDERR: ${output.stderr}")
//        println("-----------------------------")

        return ElmProject.parse(Files.newInputStream(manifestPath), manifestPath, toolchain)
    }
}

    override val jsonManifest: String
        @Language("JSON")
        get() = """
            {
                "type": "application",
                "source-directories": [
                    "."
                ],
                "elm-version": "0.19.1",
                "dependencies": {
                    "direct": {
                        "elm/core": "1.0.0",
                        "elm/json": "1.0.0"
                    },
                    "indirect": {}
                },
                "test-dependencies": {
                    "direct": {},
                    "indirect": {}
                }
            }
            """.trimIndent()

    override fun ensureElmStdlibInstalled(project: Project, toolchain: ElmToolchain) {
        val elmCLI = toolchain.elmCLI
                ?: error("Must have a path to the Elm compiler to install Elm stdlib")

        val compilerVersion = elmCLI.queryVersion(project).orNull()
                ?: error("Could not query the Elm compiler version")
        require(compilerVersion != Version(0, 18, 0))

        // Create the dummy Elm project on-disk (real file system) and invoke the Elm compiler on it.
        val onDiskTmpDir = LocalFileSystem.getInstance()
                .refreshAndFindFileByIoFile(FileUtil.createTempDirectory("elm-stdlib-variant", null, true))
                ?: error("Could not create on-disk temp dir for Elm stdlib installation")

        fileTree {
            project(ELM_JSON, jsonManifest)
            elm("Main.elm")
        }.create(project, onDiskTmpDir)

        val entryPoint: Triple<Path, String?, Int> = Triple(
            Paths.get("Main.elm"),
            null,
            0 // mainEntryPoint.textOffset
        )
        elmCLI.make(project, onDiskTmpDir.pathAsPath, null, listOf(entryPoint))
    }
}

<MSG> Setup an ElmProject when running tests; plug the "null ElmProject" hole (#129)


<DFF> @@ -5,8 +5,9 @@ import com.intellij.openapi.util.io.FileUtil
 import com.intellij.openapi.vfs.LocalFileSystem
 import org.elm.fileTree
 import org.elm.openapiext.pathAsPath
+import org.elm.workspace.ElmToolchain.Companion.ELM_JSON
 import org.intellij.lang.annotations.Language
-import java.nio.file.Files
+import java.nio.file.Paths
 
 /*
 Some of the Elm tests depend on having certain Elm packages installed in the global location.
@@ -33,26 +34,32 @@ interface ElmStdlibVariant {
         val elm = toolchain.elmCompilerPath?.let { ElmCLI(it) }
                 ?: error("Must have a path to the Elm compiler to install Elm stdlib")
 
-        val tmpDir = LocalFileSystem.getInstance()
+        // Create the dummy Elm project on-disk (real file system) and invoke the Elm compiler on it.
+        val onDiskTmpDir = LocalFileSystem.getInstance()
                 .refreshAndFindFileByIoFile(FileUtil.createTempDirectory("elm-stdlib-variant", null, true))
-                ?: error("Could not create temp dir for Elm stdlib installation")
+                ?: error("Could not create on-disk temp dir for Elm stdlib installation")
 
         fileTree {
-            project("elm.json", jsonManifest)
+            project(ELM_JSON, jsonManifest)
             file("Main.elm", elmHeadlessWorkerCode)
-        }.create(project, tmpDir)
-
-        val manifestPath = tmpDir.pathAsPath.resolve("elm.json")
+        }.create(project, onDiskTmpDir)
 
 //        println("-----------------------------")
 //        println("Installing Deps for $this")
-        val output = elm.installDeps(project, manifestPath)
+        val output = elm.installDeps(project, onDiskTmpDir.pathAsPath.resolve("elm.json"))
 //        println("STDOUT: ${output.stdout}")
 //        println("\n")
 //        println("STDERR: ${output.stderr}")
 //        println("-----------------------------")
 
-        return ElmProject.parse(Files.newInputStream(manifestPath), manifestPath, toolchain)
+        // Now return an `ElmProject` with a manifest path suitable for IntelliJ's "light"
+        // integration tests which put everything at `/src` using the in-memory VFS.
+        val inMemManifestPath = Paths.get("/src/$ELM_JSON")
+        val elmProj = ElmProject.parse(jsonManifest.byteInputStream(), inMemManifestPath, toolchain)
+        require(Paths.get(".") in elmProj.sourceDirectories) {
+            "Since the elm.json file is stored in `/src` (in-memory VFS), `source-directories` must contain \".\""
+        }
+        return elmProj
     }
 }
 

Setup an ElmProject when running tests; plug the "null ElmProject" hole (#129)