Skip to content

Commit d8221f9

Browse files
committed
Improve AS script folder detection performance
AngelScript folders are now detected using a FilenameIndex search for uprojects and uplugins, followed by a check for Script folders, rather than a recursive tree walk for the entire project. - New ScriptFolderDetector to centralize folder detection logic - ScriptFilesPanel and AngelScriptContentRootProvider updated to use ScriptFolderDetector
1 parent f877f60 commit d8221f9

3 files changed

Lines changed: 63 additions & 68 deletions

File tree

src/rider/main/kotlin/com/scriptacus/riderunrealangelscript/project/AngelScriptContentRootProvider.kt

Lines changed: 1 addition & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ package com.scriptacus.riderunrealangelscript.project
33
import com.intellij.openapi.application.ApplicationManager
44
import com.intellij.openapi.diagnostic.Logger
55
import com.intellij.openapi.module.ModuleManager
6-
import com.intellij.openapi.progress.ProgressManager
76
import com.intellij.openapi.project.Project
87
import com.intellij.openapi.roots.ModuleRootManager
98
import com.intellij.openapi.roots.ModuleRootModificationUtil
@@ -77,46 +76,7 @@ class AngelScriptContentRootProvider : ProjectActivity {
7776
}
7877

7978
private fun detectScriptFolders(project: Project): List<VirtualFile> {
80-
val basePath = project.basePath
81-
if (basePath == null) {
82-
LOG.warn("Project has no base path, cannot detect Script folders")
83-
return emptyList()
84-
}
85-
86-
val baseDir = VirtualFileManager.getInstance().findFileByUrl("file://$basePath")
87-
if (baseDir == null) {
88-
LOG.warn("Cannot find base directory at: $basePath")
89-
return emptyList()
90-
}
91-
92-
val scriptFolders = mutableSetOf<VirtualFile>()
93-
94-
// Visit all files recursively using VFS API
95-
VfsUtil.visitChildrenRecursively(baseDir, object : VirtualFileVisitor<Unit>() {
96-
override fun visitFile(file: VirtualFile): Boolean {
97-
// Support cancellation of long-running operations
98-
ProgressManager.checkCanceled()
99-
100-
// Skip common non-source directories for performance
101-
if (file.isDirectory && file.name in SKIP_DIRS) {
102-
return false
103-
}
104-
105-
// Check for .uproject or .uplugin files
106-
if (!file.isDirectory && (file.extension == "uproject" || file.extension == "uplugin")) {
107-
val parentDir = file.parent
108-
if (parentDir != null) {
109-
val scriptFolder = parentDir.findChild("Script")
110-
if (scriptFolder != null && scriptFolder.isDirectory) {
111-
scriptFolders.add(scriptFolder)
112-
}
113-
}
114-
}
115-
return true
116-
}
117-
})
118-
119-
return scriptFolders.toList()
79+
return ScriptFolderDetector.detectScriptFolders(project)
12080
}
12181

12282
private fun findMainModule(project: Project) = ModuleManager.getInstance(project)
@@ -248,18 +208,4 @@ class AngelScriptContentRootProvider : ProjectActivity {
248208
)
249209
}
250210

251-
companion object {
252-
// Directories to skip during VFS traversal for performance
253-
private val SKIP_DIRS = setOf(
254-
".git",
255-
"node_modules",
256-
"Binaries",
257-
"Intermediate",
258-
"Saved",
259-
".idea",
260-
"DerivedDataCache",
261-
".vs",
262-
".vscode"
263-
)
264-
}
265211
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
package com.scriptacus.riderunrealangelscript.project
2+
3+
import com.intellij.openapi.project.Project
4+
import com.intellij.openapi.vfs.VirtualFile
5+
import com.intellij.psi.search.FilenameIndex
6+
import com.intellij.psi.search.GlobalSearchScope
7+
8+
/**
9+
* Shared utility for efficiently detecting AngelScript Script folders in a project.
10+
*
11+
* Uses FilenameIndex for O(1) lookup of .uproject and .uplugin files instead of
12+
* recursive VFS traversal which is O(n) where n = total files in project.
13+
*/
14+
object ScriptFolderDetector {
15+
/**
16+
* Finds all Script folders next to .uproject or .uplugin files.
17+
*
18+
* @param project The project to search
19+
* @return List of Script folder VirtualFiles
20+
*/
21+
fun detectScriptFolders(project: Project): List<VirtualFile> {
22+
val scriptFolders = mutableSetOf<VirtualFile>()
23+
val scope = GlobalSearchScope.projectScope(project)
24+
25+
// Find all .uproject files and check for Script folders
26+
val uprojectFiles = FilenameIndex.getAllFilesByExt(project, "uproject", scope)
27+
for (uprojectFile in uprojectFiles) {
28+
val scriptFolder = uprojectFile.parent?.findChild("Script")
29+
if (scriptFolder?.isDirectory == true) {
30+
scriptFolders.add(scriptFolder)
31+
}
32+
}
33+
34+
// Find all .uplugin files and check for Script folders
35+
val upluginFiles = FilenameIndex.getAllFilesByExt(project, "uplugin", scope)
36+
for (upluginFile in upluginFiles) {
37+
val scriptFolder = upluginFile.parent?.findChild("Script")
38+
if (scriptFolder?.isDirectory == true) {
39+
scriptFolders.add(scriptFolder)
40+
}
41+
}
42+
43+
return scriptFolders.toList()
44+
}
45+
}

src/rider/main/kotlin/com/scriptacus/riderunrealangelscript/toolwindow/ScriptFilesPanel.kt

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -359,22 +359,26 @@ class ScriptFilesPanel(private val project: Project) : JPanel(BorderLayout()) {
359359
val isBaseDirScriptFolder = (baseDir.name == "Script")
360360

361361
if (!isBaseDirScriptFolder) {
362-
// Normal case: search for .uproject/.uplugin files with Script folders
363-
VfsUtil.visitChildrenRecursively(baseDir, object : VirtualFileVisitor<Unit>() {
364-
override fun visitFile(file: VirtualFile): Boolean {
365-
if (!file.isDirectory && (file.extension == "uproject" || file.extension == "uplugin")) {
366-
val parentDir = file.parent
367-
if (parentDir != null) {
368-
val scriptFolder = parentDir.findChild("Script")
369-
if (scriptFolder != null && scriptFolder.isDirectory && containsAngelScriptFiles(scriptFolder)) {
370-
allProjectFiles.add(ProjectFileInfo(file, scriptFolder))
371-
scriptFolders.add(scriptFolder)
372-
}
362+
// Use ScriptFolderDetector for efficient lookup
363+
val detectedFolders = com.scriptacus.riderunrealangelscript.project.ScriptFolderDetector.detectScriptFolders(project)
364+
365+
// Build ProjectFileInfo list - need to find the .uproject/.uplugin file for each Script folder
366+
for (scriptFolder in detectedFolders) {
367+
// Only include if it contains .as files
368+
if (containsAngelScriptFiles(scriptFolder)) {
369+
val parent = scriptFolder.parent
370+
if (parent != null) {
371+
// Find the .uproject or .uplugin file in parent
372+
val projectFile = parent.children.firstOrNull {
373+
it.extension == "uproject" || it.extension == "uplugin"
374+
}
375+
if (projectFile != null) {
376+
allProjectFiles.add(ProjectFileInfo(projectFile, scriptFolder))
377+
scriptFolders.add(scriptFolder)
373378
}
374379
}
375-
return true
376380
}
377-
})
381+
}
378382
}
379383

380384
// Find the .uproject file(s)

0 commit comments

Comments
 (0)