Skip to content

Commit ebf16cf

Browse files
VladRassokhinSJrX
authored andcommitted
Resolves #231 - Speedup UnitDependencyOptionValue completion
It's not necessary to get all VirtualFiles with given extension since we only need file names. Also, it's faster to process all files and extensions at once.
1 parent 2ca0824 commit ebf16cf

File tree

1 file changed

+56
-11
lines changed

1 file changed

+56
-11
lines changed

src/main/kotlin/net/sjrx/intellij/plugins/systemdunitfiles/semanticdata/optionvalues/UnitDependencyOptionValue.kt

Lines changed: 56 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,20 @@ package net.sjrx.intellij.plugins.systemdunitfiles.semanticdata.optionvalues
22

33
import com.intellij.codeInspection.ProblemsHolder
44
import com.intellij.openapi.project.Project
5+
import com.intellij.openapi.util.ModificationTracker
56
import com.intellij.openapi.util.TextRange
67
import com.intellij.openapi.util.text.Strings
7-
import com.intellij.psi.search.FilenameIndex
8+
import com.intellij.openapi.vfs.newvfs.persistent.FSRecords
9+
import com.intellij.psi.search.FilenameIndex.processAllFileNames
10+
import com.intellij.psi.search.GlobalSearchScope
11+
import com.intellij.psi.util.CachedValueProvider
12+
import com.intellij.psi.util.CachedValuesManager
13+
import com.intellij.util.containers.CollectionFactory
814
import net.sjrx.intellij.plugins.systemdunitfiles.psi.UnitFilePropertyType
915
import net.sjrx.intellij.plugins.systemdunitfiles.semanticdata.SemanticDataRepository
1016
import net.sjrx.intellij.plugins.systemdunitfiles.semanticdata.Validator
11-
import java.io.BufferedReader
1217
import java.io.IOException
1318
import java.io.InputStream
14-
import java.io.InputStreamReader
1519
import java.util.*
1620

1721
/**
@@ -44,12 +48,8 @@ class UnitDependencyOptionValue : OptionValueInformation {
4448
}
4549

4650
override fun getAutoCompleteOptions(project: Project): Set<String> {
47-
val autoCompletionOptions: MutableSet<String> = HashSet(unitNames)
48-
for (unitTypes in validUnitTypes) {
49-
for (file in FilenameIndex.getAllFilesByExt(project, unitTypes)) {
50-
autoCompletionOptions.add(file.name)
51-
}
52-
}
51+
val autoCompletionOptions = CollectionFactory.createSmallMemoryFootprintSet(unitNames ?: emptySet())
52+
autoCompletionOptions.addAll(getAllProjectUnitFileNames(project))
5353
return autoCompletionOptions
5454
}
5555

@@ -82,8 +82,8 @@ class UnitDependencyOptionValue : OptionValueInformation {
8282
val unitType = word.substring(lastDot + 1)
8383
if (!validUnitTypes.contains(unitType)) {
8484
holder.registerProblem(
85-
property.valueNode.psi, range,
86-
"Unit type " + unitType + " is unsupported, valid types are: " + Strings.join(validUnitTypes, ", ")
85+
property.valueNode.psi, range,
86+
"Unit type " + unitType + " is unsupported, valid types are: " + Strings.join(validUnitTypes, ", ")
8787
)
8888
}
8989
} else {
@@ -97,6 +97,51 @@ class UnitDependencyOptionValue : OptionValueInformation {
9797
override val validatorName: String
9898
get() = VALIDATOR_NAME
9999

100+
/**
101+
* That's a simplified version of `com.intellij.psi.search.FilenameIndex.getAllFilesByExt()`
102+
* since we need only file names, but not whole VirtualFile's
103+
*/
104+
private fun getAllProjectUnitFileNames(project: Project): Set<String> {
105+
return CachedValuesManager.getManager(project).getCachedValue(project, CachedValueProvider {
106+
return@CachedValueProvider CachedValueProvider.Result<Set<String>>(
107+
getAllProjectUnitFileNamesImpl(project),
108+
getFilenameIndexModificationTracker(),
109+
)
110+
})
111+
}
112+
113+
/*
114+
* Simplified copy of com.intellij.openapi.fileEditor.impl.UniqueVFilePathBuilderImpl.getFilenameIndexModificationTracker
115+
* Assuming FileBasedIndexExtension.USE_VFS_FOR_FILENAME_INDEX == true (it was set so at least since 2022.2)
116+
*/
117+
private fun getFilenameIndexModificationTracker(): ModificationTracker {
118+
return ModificationTracker {
119+
@Suppress("UnstableApiUsage")
120+
FSRecords.getNamesIndexModCount()
121+
}
122+
}
123+
124+
private fun getAllProjectUnitFileNamesImpl(project: Project): Set<String> {
125+
val names = CollectionFactory.createSmallMemoryFootprintSet<String>()
126+
val minNameLength = validUnitTypes.minOf { it.length } + 2 /* dot and at least on character in name */
127+
val maxExtLength = validUnitTypes.maxOf { it.length }
128+
129+
processAllFileNames({ name: String ->
130+
val length = name.length
131+
if (length >= minNameLength) {
132+
val dot = name.lastIndexOf('.')
133+
if (dot != -1 && (length - (dot + 1) <= maxExtLength)) {
134+
val ext = name.substring(dot + 1)
135+
if (ext in validUnitTypes || ext.lowercase() in validUnitTypes) {
136+
names.add(name)
137+
}
138+
}
139+
}
140+
true
141+
}, GlobalSearchScope.allScope(project), null)
142+
return names
143+
}
144+
100145
companion object {
101146
@Volatile
102147
private var unitNames: Set<String>? = null

0 commit comments

Comments
 (0)