@@ -20,13 +20,16 @@ import java.util.concurrent.ConcurrentHashMap
2020 */
2121object LuaGutterCacheManager {
2222 private val gutterCache = ConcurrentHashMap <String , List <com.cppcxy.ide.lsp.GutterInfo >>()
23+ private val cacheTimestamps = ConcurrentHashMap <String , Long >()
2324
2425 fun clearCache (uri : String ) {
2526 gutterCache.remove(uri)
27+ cacheTimestamps.remove(uri)
2628 }
2729
2830 fun clearAllCache () {
2931 gutterCache.clear()
32+ cacheTimestamps.clear()
3033 }
3134
3235 fun getCache (uri : String ): List <com.cppcxy.ide.lsp.GutterInfo >? {
@@ -35,6 +38,16 @@ object LuaGutterCacheManager {
3538
3639 fun setCache (uri : String , infos : List <com.cppcxy.ide.lsp.GutterInfo >) {
3740 gutterCache[uri] = infos
41+ cacheTimestamps[uri] = System .currentTimeMillis()
42+ }
43+
44+ fun getCacheAge (uri : String ): Long {
45+ val timestamp = cacheTimestamps[uri] ? : return Long .MAX_VALUE
46+ return System .currentTimeMillis() - timestamp
47+ }
48+
49+ fun isCacheStale (uri : String , maxAgeMs : Long = 1000): Boolean {
50+ return getCacheAge(uri) > maxAgeMs
3851 }
3952}
4053
@@ -43,31 +56,57 @@ object LuaGutterCacheManager {
4356 */
4457class LuaDocumentListener (private val project : Project ) : DocumentListener {
4558 private val updateScheduler = mutableMapOf<Document , Long >()
59+ private val pendingUpdates = mutableMapOf<Document , Runnable >()
4660
4761 override fun documentChanged (event : DocumentEvent ) {
4862 val document = event.document
4963 val file = FileDocumentManager .getInstance().getFile(document) ? : return
5064
5165 if (file.extension != " lua" ) return
5266
53- // Clear cache immediately
67+ // Clear cache immediately for instant refresh
5468 LuaGutterCacheManager .clearCache(file.url)
5569
56- // Schedule restart of code analysis (debounced to avoid too frequent updates)
70+ // Cancel any pending update
71+ pendingUpdates[document]?.let {
72+ // The runnable will be replaced
73+ }
74+
75+ // Schedule restart of code analysis with shorter debounce (200ms)
5776 val now = System .currentTimeMillis()
5877 val lastUpdate = updateScheduler[document] ? : 0
5978
60- // Only update if 500ms has passed since last update
61- if (now - lastUpdate > 500 ) {
62- updateScheduler[document] = now
63-
79+ // Reduced debounce time to 200ms for better responsiveness
80+ val debounceTime = 200L
81+
82+ val updateRunnable = Runnable {
6483 ApplicationManager .getApplication().invokeLater {
6584 val psiFile = PsiManager .getInstance(project).findFile(file)
66- if (psiFile is LuaPsiFile ) {
85+ if (psiFile is LuaPsiFile && psiFile.isValid ) {
6786 DaemonCodeAnalyzer .getInstance(project).restart(psiFile)
6887 }
6988 }
7089 }
90+
91+ pendingUpdates[document] = updateRunnable
92+
93+ if (now - lastUpdate > debounceTime) {
94+ updateScheduler[document] = now
95+ // Execute immediately if enough time has passed
96+ updateRunnable.run ()
97+ pendingUpdates.remove(document)
98+ } else {
99+ // Schedule for later
100+ ApplicationManager .getApplication().executeOnPooledThread {
101+ Thread .sleep(debounceTime)
102+ val currentRunnable = pendingUpdates[document]
103+ if (currentRunnable == updateRunnable) {
104+ updateScheduler[document] = System .currentTimeMillis()
105+ currentRunnable.run ()
106+ pendingUpdates.remove(document)
107+ }
108+ }
109+ }
71110 }
72111}
73112
@@ -118,5 +157,29 @@ class LuaGutterCacheStartupActivity : ProjectActivity {
118157 FileEditorManagerListener .FILE_EDITOR_MANAGER ,
119158 LuaFileEditorListener (project)
120159 )
160+
161+ // Register bulk file listener to detect external changes
162+ connection.subscribe(
163+ com.intellij.openapi.vfs.VirtualFileManager .VFS_CHANGES ,
164+ object : com.intellij.openapi.vfs.newvfs.BulkFileListener {
165+ override fun after (events : List <com.intellij.openapi.vfs.newvfs.events.VFileEvent >) {
166+ for (event in events) {
167+ val file = event.file
168+ if (file != null && file.extension == " lua" ) {
169+ // Clear cache when file changes externally
170+ LuaGutterCacheManager .clearCache(file.url)
171+
172+ // Trigger update
173+ ApplicationManager .getApplication().invokeLater {
174+ val psiFile = PsiManager .getInstance(project).findFile(file)
175+ if (psiFile is LuaPsiFile && psiFile.isValid) {
176+ DaemonCodeAnalyzer .getInstance(project).restart(psiFile)
177+ }
178+ }
179+ }
180+ }
181+ }
182+ }
183+ )
121184 }
122185}
0 commit comments