<NME> ElmModulesIndex.kt
<BEF> package org.elm.lang.core.stubs.index

import com.intellij.openapi.project.Project
import com.intellij.psi.search.GlobalSearchScope
import com.intellij.psi.stubs.IndexSink
import com.intellij.psi.stubs.StubIndex
import com.intellij.psi.stubs.StubIndexKey
import org.elm.lang.core.lookup.ClientLocation
import org.elm.lang.core.lookup.ElmLookup
import org.elm.lang.core.psi.elements.ElmModuleDeclaration
import org.elm.lang.core.stubs.ElmFileStub
import org.elm.lang.core.stubs.ElmModuleDeclarationStub


class ElmModulesIndex: StringStubIndexExtension<ElmModuleDeclaration>() {

 * should be visible, resolving each module to the correct version for the project.
 */
class ElmModulesIndex : StringStubIndexExtension<ElmModuleDeclaration>() {

    override fun getVersion() =
            ElmFileStub.Type.stubVersion

    override fun getKey(): StubIndexKey<String, ElmModuleDeclaration> =
            KEY

    companion object {

        /**
         * Returns an Elm module named [moduleName] which is visible to [clientLocation], if any
         */
        fun get(moduleName: String, clientLocation: ClientLocation): ElmModuleDeclaration? =
                rawGet(moduleName, clientLocation.intellijProject, ElmLookup.searchScopeAt(clientLocation))
                        .firstOrNull()


        /**
         * Returns all Elm modules which are visible to [clientLocation]
         */
            val matches = StubIndex.getElements(KEY, key, project,
                    GlobalSearchScope.allScope(project),
                    ElmModuleDeclaration::class.java)

            // TODO [kl] prioritize the results
            return matches.firstOrNull()
        }

        // INTERNALS


        val KEY: StubIndexKey<String, ElmModuleDeclaration> =
                StubIndexKey.createIndexKey("org.elm.lang.core.stubs.index.ElmModulesIndex")

        fun index(stub: ElmModuleDeclarationStub, indexSink: IndexSink) {
                    results.add(it)
                }
            }
            // TODO [kl] prioritize the results
            return results
        }
    }
}
        /**
         * Returns all module declarations within [scope] whose module name matches an item in [moduleNames]
         */
        private fun rawGetAll(moduleNames: Collection<String>, project: Project, scope: GlobalSearchScope): List<ElmModuleDeclaration> {
            val index = StubIndex.getInstance()
            val results = mutableListOf<ElmModuleDeclaration>()

            for (key in moduleNames) {
                index.processElements(KEY, key, project, scope, ElmModuleDeclaration::class.java) {
                    results.add(it)
                }
            }
            return results
        }


        /**
         * Returns all module declarations within [scope]
         */
        private fun rawGetAll(project: Project, scope: GlobalSearchScope): List<ElmModuleDeclaration> =
                rawGetAll(StubIndex.getInstance().getAllKeys(KEY, project), project, scope)

    }
}

<MSG> Prioritize the module declaration lookups

<DFF> @@ -1,5 +1,6 @@
 package org.elm.lang.core.stubs.index
 
+import com.intellij.openapi.diagnostic.Logger
 import com.intellij.openapi.project.Project
 import com.intellij.psi.search.GlobalSearchScope
 import com.intellij.psi.stubs.IndexSink
@@ -11,6 +12,8 @@ import org.elm.lang.core.psi.elements.ElmModuleDeclaration
 import org.elm.lang.core.stubs.ElmFileStub
 import org.elm.lang.core.stubs.ElmModuleDeclarationStub
 
+private val logger = Logger.getInstance(ElmModulesIndex::class.java)
+
 
 class ElmModulesIndex: StringStubIndexExtension<ElmModuleDeclaration>() {
 
@@ -40,8 +43,11 @@ class ElmModulesIndex: StringStubIndexExtension<ElmModuleDeclaration>() {
             val matches = StubIndex.getElements(KEY, key, project,
                     GlobalSearchScope.allScope(project),
                     ElmModuleDeclaration::class.java)
+                    .sortedWith(elmAppVsLibraryComparator)
+
+            if (logger.isDebugEnabled && matches.size > 1)
+                logger.warn("multiple modules found for $moduleName")
 
-            // TODO [kl] prioritize the results
             return matches.firstOrNull()
         }
 
@@ -55,8 +61,20 @@ class ElmModulesIndex: StringStubIndexExtension<ElmModuleDeclaration>() {
                     results.add(it)
                 }
             }
-            // TODO [kl] prioritize the results
-            return results
+            return results.sortedWith(elmAppVsLibraryComparator)
         }
     }
 }
+
+/*
+There should be only a single file in project scope for a given module name,
+but until we start loading the `elm-package.json` manifest file to determine
+source roots and library roots, we will need to deal with indexed Elm files
+that do not truly belong to THIS project. To mitigate the problem, we will
+order the module declarations such that the ones that live in the `elm-stuff`
+directory are at the end of the list.
+*/
+private val elmAppVsLibraryComparator =
+        compareBy<ElmModuleDeclaration> {
+            if (it.containingFile.virtualFile.path.contains("/elm-stuff/")) 1 else 0
+        }

Prioritize the module declaration lookups