Optimization: introduce FirIdeResolveStateService to cache FirResolveState
This commit is contained in:
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.idea.fir
|
||||
|
||||
import com.intellij.openapi.components.ServiceManager
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.util.ModificationTracker
|
||||
import org.jetbrains.kotlin.analyzer.KotlinModificationTrackerService
|
||||
import org.jetbrains.kotlin.analyzer.TrackableModuleInfo
|
||||
import org.jetbrains.kotlin.fir.java.FirProjectSessionProvider
|
||||
import org.jetbrains.kotlin.idea.caches.project.IdeaModuleInfo
|
||||
|
||||
interface FirIdeResolveStateService {
|
||||
companion object {
|
||||
fun getInstance(project: Project): FirIdeResolveStateService =
|
||||
ServiceManager.getService(project, FirIdeResolveStateService::class.java)!!
|
||||
}
|
||||
|
||||
val fallbackModificationTracker: ModificationTracker?
|
||||
|
||||
fun getResolveState(moduleInfo: IdeaModuleInfo): FirResolveState
|
||||
}
|
||||
|
||||
private class FirModuleData(val state: FirResolveState, val modificationTracker: ModificationTracker?) {
|
||||
val modificationCount: Long = modificationTracker?.modificationCount ?: Long.MIN_VALUE
|
||||
|
||||
fun isOutOfDate(): Boolean {
|
||||
val currentModCount = modificationTracker?.modificationCount
|
||||
return currentModCount != null && currentModCount > modificationCount
|
||||
}
|
||||
}
|
||||
|
||||
class FirIdeResolveStateServiceImpl(val project: Project) : FirIdeResolveStateService {
|
||||
private val stateCache = mutableMapOf<IdeaModuleInfo, FirModuleData>()
|
||||
|
||||
private fun createResolveState(): FirResolveState {
|
||||
val provider = FirProjectSessionProvider(project)
|
||||
return FirResolveStateImpl(provider)
|
||||
}
|
||||
|
||||
private fun createModuleData(moduleInfo: IdeaModuleInfo): FirModuleData {
|
||||
val state = createResolveState()
|
||||
val modificationTracker = (moduleInfo as? TrackableModuleInfo)?.createModificationTracker() ?: fallbackModificationTracker
|
||||
return FirModuleData(state, modificationTracker)
|
||||
}
|
||||
|
||||
// TODO: multi thread protection
|
||||
override fun getResolveState(moduleInfo: IdeaModuleInfo): FirResolveState {
|
||||
var moduleData = stateCache.getOrPut(moduleInfo) {
|
||||
createModuleData(moduleInfo)
|
||||
}
|
||||
if (moduleData.isOutOfDate()) {
|
||||
moduleData = createModuleData(moduleInfo)
|
||||
stateCache[moduleInfo] = moduleData
|
||||
}
|
||||
return moduleData.state
|
||||
}
|
||||
|
||||
override val fallbackModificationTracker: ModificationTracker? =
|
||||
KotlinModificationTrackerService.getInstance(project).outOfBlockModificationTracker
|
||||
}
|
||||
@@ -58,12 +58,5 @@ class FirResolveStateImpl(override val sessionProvider: FirSessionProvider) : Fi
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: caching
|
||||
object FirIdeResolveFactory {
|
||||
fun initiate(psi: KtElement): FirResolveState {
|
||||
val provider = FirProjectSessionProvider(psi.project)
|
||||
return FirResolveStateImpl(provider)
|
||||
}
|
||||
}
|
||||
|
||||
fun KtElement.firResolveState(): FirResolveState = FirIdeResolveFactory.initiate(this)
|
||||
fun KtElement.firResolveState(): FirResolveState =
|
||||
FirIdeResolveStateService.getInstance(project).getResolveState(getModuleInfo())
|
||||
@@ -274,6 +274,9 @@
|
||||
<projectService serviceInterface="org.jetbrains.kotlin.caches.resolve.KotlinCacheService"
|
||||
serviceImplementation="org.jetbrains.kotlin.idea.caches.resolve.KotlinCacheServiceImpl"/>
|
||||
|
||||
<projectService serviceInterface="org.jetbrains.kotlin.idea.fir.FirIdeResolveStateService"
|
||||
serviceImplementation="org.jetbrains.kotlin.idea.fir.FirIdeResolveStateServiceImpl"/>
|
||||
|
||||
<projectService serviceInterface="org.jetbrains.kotlin.load.kotlin.MetadataFinderFactory"
|
||||
serviceImplementation="org.jetbrains.kotlin.idea.vfilefinder.IDEVirtualFileFinderFactory"/>
|
||||
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.idea.fir
|
||||
|
||||
import org.jetbrains.kotlin.idea.AbstractResolveElementCacheTest
|
||||
|
||||
class FirResolveStateTest : AbstractResolveElementCacheTest() {
|
||||
fun testSimpleStateCaching() {
|
||||
doTest {
|
||||
val firstStatement = statements[0]
|
||||
val secondStatement = statements[1]
|
||||
assertSame(firstStatement.firResolveState(), secondStatement.firResolveState())
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user