blob: 1f659a703777f83bb6c2a6dce7823428317c1d60 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
|
// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.util.indexing
import com.intellij.ide.actions.cache.*
import com.intellij.lang.LangBundle
import com.intellij.openapi.diagnostic.logger
import com.intellij.openapi.progress.ProgressIndicator
import com.intellij.openapi.progress.util.ProgressIndicatorUtils
import com.intellij.openapi.project.DumbModeTask
import com.intellij.openapi.vfs.VirtualFile
import com.intellij.openapi.vfs.VirtualFileWithId
import com.intellij.psi.stubs.StubTreeBuilder
import com.intellij.psi.stubs.StubUpdatingIndex
import com.intellij.util.BooleanFunction
import com.intellij.util.indexing.diagnostic.ProjectIndexingHistoryImpl
import com.intellij.util.indexing.diagnostic.ScanningType
import com.intellij.util.indexing.roots.IndexableFilesIterator
import com.intellij.util.indexing.roots.ProjectIndexableFilesIteratorImpl
import org.jetbrains.annotations.ApiStatus
import org.jetbrains.annotations.Nls
import java.util.*
import java.util.concurrent.CompletableFuture
@ApiStatus.Internal
class RescanIndexesAction : RecoveryAction {
override val performanceRate: Int
get() = 9990
override val presentableName: @Nls(capitalization = Nls.Capitalization.Title) String
get() = LangBundle.message("rescan.indexes.recovery.action.name")
override val actionKey: String
get() = "rescan"
override fun performSync(recoveryScope: RecoveryScope): List<CacheInconsistencyProblem> {
val project = recoveryScope.project
val historyFuture = CompletableFuture<ProjectIndexingHistoryImpl>()
val stubAndIndexingStampInconsistencies = Collections.synchronizedList(arrayListOf<CacheInconsistencyProblem>())
var predefinedIndexableFilesIterators: List<IndexableFilesIterator>? = null
if (recoveryScope is FilesRecoveryScope) {
predefinedIndexableFilesIterators = recoveryScope.files.map { ProjectIndexableFilesIteratorImpl(it) }
}
object : UnindexedFilesUpdater(project, false, false,
predefinedIndexableFilesIterators, "Rescanning indexes recovery action",
if(predefinedIndexableFilesIterators == null) ScanningType.FULL_FORCED else ScanningType.PARTIAL_FORCED) {
private val stubIndex =
runCatching { (FileBasedIndex.getInstance() as FileBasedIndexImpl).getIndex(StubUpdatingIndex.INDEX_ID) }
.onFailure { logger<RescanIndexesAction>().error(it) }.getOrNull()
private inner class StubAndIndexStampInconsistency(private val path: String): CacheInconsistencyProblem {
override val message: String
get() = "`$path` should have already indexed stub but it's not present"
}
override fun getForceReindexingTrigger(): BooleanFunction<IndexedFile>? {
if (stubIndex != null) {
return BooleanFunction<IndexedFile> {
val fileId = (it.file as VirtualFileWithId).id
if (stubIndex.getIndexingStateForFile(fileId, it) == FileIndexingState.UP_TO_DATE &&
stubIndex.getIndexedFileData(fileId).isEmpty() &&
isAbleToBuildStub(it.file)) {
stubAndIndexingStampInconsistencies.add(StubAndIndexStampInconsistency(it.file.path))
return@BooleanFunction true
}
false
}
}
return null
}
private fun isAbleToBuildStub(file: VirtualFile): Boolean = runCatching {
StubTreeBuilder.buildStubTree(FileContentImpl.createByFile(file))
}.getOrNull() != null
override fun performScanningAndIndexing(indicator: ProgressIndicator): ProjectIndexingHistoryImpl {
try {
IndexingFlag.cleanupProcessedFlag()
val history = super.performScanningAndIndexing(indicator)
historyFuture.complete(history)
return history
}
catch (e: Exception) {
historyFuture.completeExceptionally(e)
throw e
}
}
override fun tryMergeWith(taskFromQueue: DumbModeTask): DumbModeTask? =
if (taskFromQueue is UnindexedFilesUpdater && project == taskFromQueue.myProject && taskFromQueue.javaClass == javaClass) this else null
}.queue(project)
try {
return ProgressIndicatorUtils.awaitWithCheckCanceled(historyFuture).extractConsistencyProblems() +
stubAndIndexingStampInconsistencies
}
catch (e: Exception) {
return listOf(ExceptionalCompletionProblem(e))
}
}
private fun ProjectIndexingHistoryImpl.extractConsistencyProblems(): List<CacheInconsistencyProblem> =
scanningStatistics.filter { it.numberOfFilesForIndexing != 0 }.map {
UnindexedFilesInconsistencyProblem(it.numberOfFilesForIndexing, it.providerName)
}
private class UnindexedFilesInconsistencyProblem(private val numberOfFilesForIndexing: Int, private val providerName: String) : CacheInconsistencyProblem {
override val message: String
get() = "Provider `$providerName` had $numberOfFilesForIndexing unindexed files"
}
}
|