|
| 1 | +package org.nixos.idea.imports |
| 2 | + |
| 3 | +import com.intellij.codeInsight.lookup.LookupElement |
| 4 | +import com.intellij.openapi.util.TextRange |
| 5 | +import com.intellij.openapi.util.io.FileUtil |
| 6 | +import com.intellij.openapi.vfs.LocalFileSystem |
| 7 | +import com.intellij.openapi.vfs.VirtualFile |
| 8 | +import com.intellij.openapi.vfs.VirtualFileSystem |
| 9 | +import com.intellij.patterns.PlatformPatterns |
| 10 | +import com.intellij.psi.PsiElement |
| 11 | +import com.intellij.psi.PsiManager |
| 12 | +import com.intellij.psi.PsiReference |
| 13 | +import com.intellij.psi.PsiReferenceBase |
| 14 | +import com.intellij.psi.PsiReferenceContributor |
| 15 | +import com.intellij.psi.PsiReferenceProvider |
| 16 | +import com.intellij.psi.PsiReferenceRegistrar |
| 17 | +import com.intellij.util.ProcessingContext |
| 18 | +import org.nixos.idea.psi.impl.NixExprStdPathMixin |
| 19 | + |
| 20 | +class NixFilePathReferenceContributor: PsiReferenceContributor() { |
| 21 | + override fun registerReferenceProviders(registrar: PsiReferenceRegistrar) { |
| 22 | + registrar.registerReferenceProvider( |
| 23 | + PlatformPatterns.psiElement(NixExprStdPathMixin::class.java), |
| 24 | + object : PsiReferenceProvider() { |
| 25 | + override fun getReferencesByElement( |
| 26 | + element: PsiElement, |
| 27 | + context: ProcessingContext |
| 28 | + ): Array<PsiReference> { |
| 29 | + val it = element as? NixExprStdPathMixin ?: return emptyArray() |
| 30 | + return arrayOf(NixImportReferenceImpl(it)) |
| 31 | + } |
| 32 | + } |
| 33 | + ) |
| 34 | + } |
| 35 | +} |
| 36 | + |
| 37 | +private class NixImportReferenceImpl(key: NixExprStdPathMixin) : PsiReferenceBase<NixExprStdPathMixin>(key) { |
| 38 | + override fun resolve(): PsiElement? { |
| 39 | + val path = element.containingFile.parent?.virtualFile?.path ?: return null |
| 40 | + val fs = LocalFileSystem.getInstance() |
| 41 | + val file = resolvePath(fs, path, element.text) ?: return null |
| 42 | + |
| 43 | + val project = element.project |
| 44 | + val psiFile = PsiManager.getInstance(project).findFile(file) |
| 45 | + |
| 46 | + return psiFile |
| 47 | + } |
| 48 | + |
| 49 | + override fun getVariants(): Array<out LookupElement> = LookupElement.EMPTY_ARRAY |
| 50 | + |
| 51 | + override fun calculateDefaultRangeInElement(): TextRange = TextRange.from(0, element.textLength) |
| 52 | +} |
| 53 | + |
| 54 | +private fun resolvePath(fs: VirtualFileSystem, cwd: String, target: String): VirtualFile? { |
| 55 | + val resolved = FileUtil.join(cwd, target) |
| 56 | + val resolvedFile = fs.findFileByPath(resolved) ?: return null |
| 57 | + |
| 58 | + if (resolvedFile.isDirectory) { |
| 59 | + return resolvedFile.findChild("default.nix") |
| 60 | + } |
| 61 | + |
| 62 | + return resolvedFile |
| 63 | +} |
0 commit comments