Repository: intellij-rust/intellij-rust (language: rust)

Issue:
Failed to expand the macro: internal error: expansion file not found, but cache has valid expansion
## Environment

* **IntelliJ Rust plugin version:** 0.4.198.5419-232-nightly
* **Rust toolchain version:** 1.70.0-nightly (900c35403 2023-03-08) aarch64-apple-darwin
* **IDE name and version:** CLion 2023.2 EAP (CL-232.8296.18)
* **Operating system:** macOS 13.4.1
* **Macro expansion:** enabled
* **Additional experimental features:** org.rust.macros.proc.attr, org.rust.cargo.features.settings.gutter, org.rust.cargo.emulate.terminal, org.rust.ide.intentions.macros.function-like, org.rust.mir.borrow-check, org.rust.macros.proc, org.rust.ssr

## Problem description
Some macros don't want to expand?

I've already set the timeout in the registry to 20 seconds, the macro previously expanded with 10 seconds.

I don't see any logs about macro expansion

## Steps to reproduce
Try expanding this macro: https://github.com/swc-project/swc/blob/ed9a4ae5bc73b54641fc3f60843eb96c8cff6145/crates/swc_ecma_visit/src/lib.rs#L537

I'm working on https://github.com/vercel/turbo trying to implement the `Visit` trait the macro generates, but it doesn't seem to expand so intellij-rust doesn't give me any code completion and says I need to import it



Discussion / hints:
Hi!
I'm not dure what exactly caused the macro expansion error, but there is a chance that invalidating caches can help you.
Could you please press `Ctrl + Shift + A`, then type "Invalidate Caches ...", then check "Clear file system cache and Local History" checkbox and press "Invalidate and Restart" button?
@vlad20012 tried invalidating multiple times and even manually deleted the rust cache files in the IDE directory

never with "Clear file system cache" though, just tried it and it doesn't seem to change anything
Okaay, let's try another option: `Ctrl`+`Shift`+`A` -> "Registry..." -> find `org.rust.macros.proc.timeout`, increase the value from `5000` to `10000`, then restart CLion
@vlad20012 I've already set that to `20000` as mentioned in my original post 🙈 
@ForsakenHarmony Ooook, `Help | Edit Custom Properties` -> add `idea.max.intellisense.filesize=10000`, restart the IDE 🙏🙏🙏
@vlad20012 yes that does seem to fix it

would be good to check for timeout and the filesize (if that's possible) and improve the error message

Fix patch:
diff --git a/src/main/kotlin/org/rust/cargo/toolchain/impl/CargoMetadata.kt b/src/main/kotlin/org/rust/cargo/toolchain/impl/CargoMetadata.kt
index 93012008cff..ddfcbd44ba5 100644
--- a/src/main/kotlin/org/rust/cargo/toolchain/impl/CargoMetadata.kt
+++ b/src/main/kotlin/org/rust/cargo/toolchain/impl/CargoMetadata.kt
@@ -9,8 +9,6 @@ import com.fasterxml.jackson.annotation.JsonProperty
 import com.intellij.openapi.diagnostic.Logger
 import com.intellij.openapi.diagnostic.logger
 import com.intellij.openapi.vfs.*
-import com.intellij.openapi.vfs.newvfs.RefreshQueue
-import com.intellij.psi.SingleRootFileViewProvider
 import com.intellij.util.PathUtil
 import com.intellij.util.text.SemVer
 import org.rust.cargo.CfgOptions
@@ -20,7 +18,6 @@ import org.rust.cargo.project.workspace.CargoWorkspace.LibKind
 import org.rust.openapiext.RsPathManager
 import org.rust.openapiext.findFileByMaybeRelativePath
 import org.rust.stdext.HashCode
-import org.rust.stdext.mapNotNullToSet
 import org.rust.stdext.mapToSet
 import java.io.IOException
 import java.nio.file.Files
@@ -341,8 +338,6 @@ object CargoMetadata {
             pkg.clean(fs, pkg.id in members, enabledFeatures, pkgBuildMessages)
         }
 
-        adjustFileSizeLimitForFilesInOutDirs(packages)
-
         return CargoWorkspaceData(
             packages,
             project.resolve.nodes.associate { node ->
@@ -362,41 +357,6 @@ object CargoMetadata {
         )
     }
 
-    /**
-     * Rust buildscripts (`build.rs`) often generate files that are larger than the default IntelliJ size limit.
-     * The default filesize limit is specified by [com.intellij.openapi.util.io.FileUtilRt.DEFAULT_INTELLISENSE_LIMIT]
-     * or "idea.max.intellisense.filesize" system property.
-     * Here we ensure that the file size limit is not less than [ADJUSTED_FILE_SIZE_LIMIT_FOR_OUTPUT_FILES] for
-     * cargo generated files.
-     */
-    private fun adjustFileSizeLimitForFilesInOutDirs(packages: List<CargoWorkspaceData.Package>) {
-        if (PersistentFSConstants.getMaxIntellisenseFileSize() >= ADJUSTED_FILE_SIZE_LIMIT_FOR_OUTPUT_FILES) return
-
-        val outDirs = packages
-            .mapNotNull { it.outDirUrl }
-            .mapNotNullToSet { VirtualFileManager.getInstance().refreshAndFindFileByUrl(it) }
-
-        if (outDirs.isEmpty()) return
-
-        RefreshQueue.getInstance().refresh(false, true, null, outDirs)
-
-        for (outDir in outDirs) {
-            VfsUtilCore.visitChildrenRecursively(outDir,
-                object : VirtualFileVisitor<ArrayList<VirtualFile>>() {
-                    override fun visitFile(outFile: VirtualFile): Boolean {
-                        if (!outFile.isDirectory && outFile.length <= ADJUSTED_FILE_SIZE_LIMIT_FOR_OUTPUT_FILES) {
-                            SingleRootFileViewProvider.doNotCheckFileSizeLimit(outFile)
-                        }
-                        return true
-                    }
-                })
-        }
-    }
-
-    // Experimentally verified that 8Mb works with the default IDEA -Xmx768M. Larger values may
-    // lead to OOM, please verify before adjusting
-    private const val ADJUSTED_FILE_SIZE_LIMIT_FOR_OUTPUT_FILES: Int = 8 * 1024 * 1024
-
     private fun Package.clean(
         fs: LocalFileSystem,
         isWorkspaceMember: Boolean,
diff --git a/src/main/kotlin/org/rust/lang/core/psi/RsFileViewProviderFactory.kt b/src/main/kotlin/org/rust/lang/core/psi/RsFileViewProviderFactory.kt
new file mode 100644
index 00000000000..2fc9f41a5a6
--- /dev/null
+++ b/src/main/kotlin/org/rust/lang/core/psi/RsFileViewProviderFactory.kt
@@ -0,0 +1,41 @@
+/*
+ * Use of this source code is governed by the MIT license that can be
+ * found in the LICENSE file.
+ */
+
+package org.rust.lang.core.psi
+
+import com.intellij.lang.Language
+import com.intellij.openapi.vfs.VirtualFile
+import com.intellij.psi.FileViewProvider
+import com.intellij.psi.FileViewProviderFactory
+import com.intellij.psi.PsiManager
+import com.intellij.psi.SingleRootFileViewProvider
+
+/**
+ * Hacky adjust the file limit for Rust file.
+ * Coupled with [org.rust.lang.core.resolve.indexes.RsAliasIndex.getFileTypesWithSizeLimitNotApplicable].
+ *
+ * @see SingleRootFileViewProvider.isTooLargeForIntelligence
+ */
+class RsFileViewProviderFactory : FileViewProviderFactory {
+    override fun createFileViewProvider(
+        file: VirtualFile,
+        language: Language,
+        manager: PsiManager,
+        eventSystemEnabled: Boolean
+    ): FileViewProvider {
+        val shouldAdjustFileLimit = SingleRootFileViewProvider.isTooLargeForIntelligence(file)
+            && file.length <= RUST_FILE_SIZE_LIMIT_FOR_INTELLISENSE
+
+        if (shouldAdjustFileLimit) {
+            SingleRootFileViewProvider.doNotCheckFileSizeLimit(file)
+        }
+
+        return SingleRootFileViewProvider(manager, file, eventSystemEnabled)
+    }
+}
+
+// Experimentally verified that 8Mb works with the default IDEA -Xmx768M. Larger values may
+// lead to OOM, please verify before adjusting
+private const val RUST_FILE_SIZE_LIMIT_FOR_INTELLISENSE: Int = 8 * 1024 * 1024
diff --git a/src/main/kotlin/org/rust/lang/core/resolve/indexes/RsAliasIndex.kt b/src/main/kotlin/org/rust/lang/core/resolve/indexes/RsAliasIndex.kt
index 1f2ba8d287b..6a1af6562f9 100644
--- a/src/main/kotlin/org/rust/lang/core/resolve/indexes/RsAliasIndex.kt
+++ b/src/main/kotlin/org/rust/lang/core/resolve/indexes/RsAliasIndex.kt
@@ -5,6 +5,7 @@
 
 package org.rust.lang.core.resolve.indexes
 
+import com.intellij.openapi.fileTypes.FileType
 import com.intellij.openapi.project.Project
 import com.intellij.psi.stubs.StubTree
 import com.intellij.psi.stubs.StubTreeBuilder
@@ -76,6 +77,14 @@ class RsAliasIndex : FileBasedIndexExtension<TyFingerprint, List<String>>() {
 
     override fun dependsOnFileContent(): Boolean = true
 
+    /**
+     * Hacky adjust the file limit for Rust file.
+     * Coupled with [org.rust.lang.core.psi.RsFileViewProviderFactory]
+     */
+    override fun getFileTypesWithSizeLimitNotApplicable(): Collection<FileType> {
+        return listOf(RsFileType)
+    }
+
     companion object {
         fun findPotentialAliases(
             project: Project,
diff --git a/src/main/resources/META-INF/rust-core.xml b/src/main/resources/META-INF/rust-core.xml
index a917003b612..496d84bce66 100644
--- a/src/main/resources/META-INF/rust-core.xml
+++ b/src/main/resources/META-INF/rust-core.xml
@@ -43,6 +43,7 @@
 
         <!-- PSI managing -->
 
+        <lang.fileViewProviderFactory language="Rust" implementationClass="org.rust.lang.core.psi.RsFileViewProviderFactory"/>
         <projectService serviceInterface="org.rust.lang.core.psi.RsPsiManager"
                         serviceImplementation="org.rust.lang.core.psi.RsPsiManagerImpl"/>
 


Test patch: