<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.StringStubIndexExtension
import com.intellij.psi.stubs.StubIndex
import com.intellij.psi.stubs.StubIndexKey
import org.elm.lang.core.psi.elements.ElmModuleDeclaration
import org.elm.lang.core.stubs.ElmFileStub
import org.elm.lang.core.stubs.ElmModuleDeclarationStub
import org.elm.lang.core.stubs.ElmModuleDeclarationStub
import org.elm.workspace.ElmProject

/**
 * Find Elm modules within an Elm project.
 *
 * This API takes into account [ElmProject] structure to determine which modules
 * should be visible, resolving each module to the correct version for the project.
 */
class ElmModulesIndex : StringStubIndexExtension<ElmModuleDeclaration>() {

    override fun getVersion() =
            ElmFileStub.Type.stubVersion

        fun index(stub: ElmModuleDeclarationStub, indexSink: IndexSink) {
            val key = makeKey(stub.psi)
            if (key != null) {
                indexSink.occurrence(KEY, key)
            }
        }

        private fun makeKey(moduleDeclaration: ElmModuleDeclaration): String? {
            // TODO [kl] what about the Cmd and Sub module name hacks?
            return moduleDeclaration.name
        }

        fun get(moduleName: String, project: Project): ElmModuleDeclaration? {
            val matches = StubIndex.getElements(KEY, moduleName, project,
                    GlobalSearchScope.allScope(project),
                    ElmModuleDeclaration::class.java)

                rawGetAll(clientLocation.intellijProject, ElmLookup.searchScopeAt(clientLocation))


        /**
         * Returns all Elm modules whose names match an element in [moduleNames] and which are visible to [clientLocation]
         */
        fun getAll(moduleNames: Collection<String>, clientLocation: ClientLocation): List<ElmModuleDeclaration> =
                rawGetAll(moduleNames, clientLocation.intellijProject, ElmLookup.searchScopeAt(clientLocation))


        // INTERNALS


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

        fun index(stub: ElmModuleDeclarationStub, indexSink: IndexSink) {
            val key = makeKey(stub.psi)
            indexSink.occurrence(KEY, key)
        }

        private fun makeKey(moduleDeclaration: ElmModuleDeclaration) =
                makeKey(moduleDeclaration.name)

        private fun makeKey(moduleName: String) =
                moduleName


        /**
         * Returns all module declarations within [scope] with name [moduleName]
         */
        private fun rawGet(moduleName: String, project: Project, scope: GlobalSearchScope): List<ElmModuleDeclaration> {
            val key = makeKey(moduleName)
            return StubIndex.getElements(KEY, key, project, scope, ElmModuleDeclaration::class.java).toList()
        }


        /**
         * 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> Fix implicit Cmd and Sub aliases

<DFF> @@ -6,6 +6,7 @@ import com.intellij.psi.stubs.IndexSink
 import com.intellij.psi.stubs.StringStubIndexExtension
 import com.intellij.psi.stubs.StubIndex
 import com.intellij.psi.stubs.StubIndexKey
+import org.elm.lang.core.moduleLookupHack
 import org.elm.lang.core.psi.elements.ElmModuleDeclaration
 import org.elm.lang.core.stubs.ElmFileStub
 import org.elm.lang.core.stubs.ElmModuleDeclarationStub
@@ -25,18 +26,18 @@ class ElmModulesIndex: StringStubIndexExtension<ElmModuleDeclaration>() {
 
         fun index(stub: ElmModuleDeclarationStub, indexSink: IndexSink) {
             val key = makeKey(stub.psi)
-            if (key != null) {
-                indexSink.occurrence(KEY, key)
-            }
+            indexSink.occurrence(KEY, key)
         }
 
-        private fun makeKey(moduleDeclaration: ElmModuleDeclaration): String? {
-            // TODO [kl] what about the Cmd and Sub module name hacks?
-            return moduleDeclaration.name
-        }
+        private fun makeKey(moduleDeclaration: ElmModuleDeclaration) =
+                makeKey(moduleDeclaration.name)
+
+        private fun makeKey(moduleName: String) =
+                moduleLookupHack(moduleName)
 
         fun get(moduleName: String, project: Project): ElmModuleDeclaration? {
-            val matches = StubIndex.getElements(KEY, moduleName, project,
+            val key = makeKey(moduleName)
+            val matches = StubIndex.getElements(KEY, key, project,
                     GlobalSearchScope.allScope(project),
                     ElmModuleDeclaration::class.java)
 

Fix implicit Cmd and Sub aliases