diff --git a/src/main/java/org/nixos/idea/imports/NixFilePathReferenceContributor.kt b/src/main/java/org/nixos/idea/imports/NixFilePathReferenceContributor.kt new file mode 100644 index 00000000..d1dbef12 --- /dev/null +++ b/src/main/java/org/nixos/idea/imports/NixFilePathReferenceContributor.kt @@ -0,0 +1,63 @@ +package org.nixos.idea.imports + +import com.intellij.codeInsight.lookup.LookupElement +import com.intellij.openapi.util.TextRange +import com.intellij.openapi.util.io.FileUtil +import com.intellij.openapi.vfs.LocalFileSystem +import com.intellij.openapi.vfs.VirtualFile +import com.intellij.openapi.vfs.VirtualFileSystem +import com.intellij.patterns.PlatformPatterns +import com.intellij.psi.PsiElement +import com.intellij.psi.PsiManager +import com.intellij.psi.PsiReference +import com.intellij.psi.PsiReferenceBase +import com.intellij.psi.PsiReferenceContributor +import com.intellij.psi.PsiReferenceProvider +import com.intellij.psi.PsiReferenceRegistrar +import com.intellij.util.ProcessingContext +import org.nixos.idea.psi.impl.NixExprStdPathMixin + +class NixFilePathReferenceContributor: PsiReferenceContributor() { + override fun registerReferenceProviders(registrar: PsiReferenceRegistrar) { + registrar.registerReferenceProvider( + PlatformPatterns.psiElement(NixExprStdPathMixin::class.java), + object : PsiReferenceProvider() { + override fun getReferencesByElement( + element: PsiElement, + context: ProcessingContext + ): Array { + val it = element as? NixExprStdPathMixin ?: return emptyArray() + return arrayOf(NixImportReferenceImpl(it)) + } + } + ) + } +} + +private class NixImportReferenceImpl(key: NixExprStdPathMixin) : PsiReferenceBase(key) { + override fun resolve(): PsiElement? { + val path = element.containingFile.parent?.virtualFile?.path ?: return null + val fs = LocalFileSystem.getInstance() + val file = resolvePath(fs, path, element.text) ?: return null + + val project = element.project + val psiFile = PsiManager.getInstance(project).findFile(file) + + return psiFile + } + + override fun getVariants(): Array = LookupElement.EMPTY_ARRAY + + override fun calculateDefaultRangeInElement(): TextRange = TextRange.from(0, element.textLength) +} + +private fun resolvePath(fs: VirtualFileSystem, cwd: String, target: String): VirtualFile? { + val resolved = FileUtil.join(cwd, target) + val resolvedFile = fs.findFileByPath(resolved) ?: return null + + if (resolvedFile.isDirectory) { + return resolvedFile.findChild("default.nix") + } + + return resolvedFile +} diff --git a/src/main/java/org/nixos/idea/psi/impl/NixExprStdPathMixin.kt b/src/main/java/org/nixos/idea/psi/impl/NixExprStdPathMixin.kt new file mode 100644 index 00000000..e52f1b84 --- /dev/null +++ b/src/main/java/org/nixos/idea/psi/impl/NixExprStdPathMixin.kt @@ -0,0 +1,10 @@ +package org.nixos.idea.psi.impl + +import com.intellij.lang.ASTNode +import com.intellij.psi.PsiReference +import com.intellij.psi.impl.source.resolve.reference.ReferenceProvidersRegistry + +open class NixExprStdPathMixin(node: ASTNode): NixExprPathImpl(node) { + override fun getReferences(): Array = + ReferenceProvidersRegistry.getReferencesFromProviders(this) +} \ No newline at end of file diff --git a/src/main/lang/Nix.bnf b/src/main/lang/Nix.bnf index 121d3302..29636c6f 100644 --- a/src/main/lang/Nix.bnf +++ b/src/main/lang/Nix.bnf @@ -191,7 +191,9 @@ expr_uri ::= URI ;{ extends("expr_lookup_path|expr_std_path")=expr_path } expr_path ::= expr_lookup_path | expr_std_path expr_lookup_path ::= SPATH -expr_std_path ::= PATH_SEGMENT (PATH_SEGMENT | antiquotation)* PATH_END +expr_std_path ::= PATH_SEGMENT (PATH_SEGMENT | antiquotation)* PATH_END { + mixin="org.nixos.idea.psi.impl.NixExprStdPathMixin" +} expr_parens ::= LPAREN expr recover_parens RPAREN { pin=1 } expr_attrs ::= [ REC | LET ] LCURLY recover_set (bind recover_set)* RCURLY { pin=2 } expr_list ::= LBRAC recover_list (expr_select recover_list)* RBRAC { pin=1 } diff --git a/src/main/resources/META-INF/plugin.xml b/src/main/resources/META-INF/plugin.xml index 0f24bfd2..ada14b49 100644 --- a/src/main/resources/META-INF/plugin.xml +++ b/src/main/resources/META-INF/plugin.xml @@ -38,6 +38,10 @@ + +