Refactor LightClassDataProvider: drop LightClassDataProvider class

Move code to inheritors
Improve api to avoid getting empty file lists in random places
This commit is contained in:
Pavel V. Talanov
2017-03-14 16:01:15 +03:00
parent ab0d939626
commit c73e58516b
2 changed files with 37 additions and 52 deletions
@@ -40,14 +40,13 @@ import org.jetbrains.kotlin.resolve.diagnostics.Diagnostics
data class LightClassBuilderResult(val stub: PsiJavaFileStub, val bindingContext: BindingContext, val diagnostics: Diagnostics)
fun buildLightClass(
project: Project,
packageFqName: FqName,
files: Collection<KtFile>,
generateClassFilter: GenerationState.GenerateClassFilter,
context: LightClassConstructionContext,
generate: (state: GenerationState, files: Collection<KtFile>) -> Unit
): LightClassBuilderResult {
val project = files.first().project
val javaFileStub = createJavaFileStub(project, packageFqName, files)
val bindingContext: BindingContext
@@ -64,7 +63,7 @@ fun buildLightClass(
KotlinLightClassBuilderFactory(stubStack),
context.module,
context.bindingContext,
files.toMutableList(),
files.toList(),
CompilerConfiguration.EMPTY,
generateClassFilter,
wantsDiagnostics = false
@@ -93,7 +92,7 @@ fun buildLightClass(
}
private fun createJavaFileStub(project: Project, packageFqName: FqName, files: Collection<KtFile>): PsiJavaFileStub {
val javaFileStub = PsiJavaFileStubImpl(packageFqName.asString(), true)
val javaFileStub = PsiJavaFileStubImpl(packageFqName.asString(), /*compiled = */true)
javaFileStub.psiFactory = ClsWrapperStubPsiFactory.INSTANCE
val manager = PsiManager.getInstance(project)
@@ -124,4 +123,4 @@ private fun logErrorWithOSInfo(cause: Throwable?, fqName: FqName, virtualFile: V
)
}
private val LOG = Logger.getInstance(LightClassDataProvider::class.java)
private val LOG = Logger.getInstance(LightClassBuilderResult::class.java)
@@ -36,37 +36,14 @@ import org.jetbrains.kotlin.psi.KtPsiUtil
import org.jetbrains.kotlin.psi.KtScript
import org.jetbrains.kotlin.psi.psiUtil.isAncestor
abstract class LightClassDataProvider<T : LightClassDataHolder>(
private val project: Project
) : CachedValueProvider<T> {
abstract val isLocal: Boolean
class LightClassDataProviderForClassOrObject(private val classOrObject: KtClassOrObject) : CachedValueProvider<LightClassDataHolder> {
open val valueAbsent: Boolean = false
override fun compute(): CachedValueProvider.Result<T>? {
if (valueAbsent) return null
return CachedValueProvider.Result.create(
computeLightClassData(),
if (isLocal) PsiModificationTracker.MODIFICATION_COUNT else PsiModificationTracker.OUT_OF_CODE_BLOCK_MODIFICATION_COUNT
)
}
abstract fun computeLightClassData(): T
}
class LightClassDataProviderForClassOrObject(private val classOrObject: KtClassOrObject) :
LightClassDataProvider<LightClassDataHolder>(classOrObject.project) {
override val isLocal: Boolean get() = classOrObject.isLocal
override fun computeLightClassData(): LightClassDataHolder {
private fun computeLightClassData(): LightClassDataHolder {
val file = classOrObject.containingKtFile
val packageFqName = file.packageFqName
return LightClassGenerationSupport.getInstance(classOrObject.project).createLightClassDataHolderForClassOrObject(classOrObject) {
constructionContext ->
buildLightClass(classOrObject.project, packageFqName, listOf(file), ClassFilterForClassOrObject(classOrObject), constructionContext) {
buildLightClass(packageFqName, listOf(file), ClassFilterForClassOrObject(classOrObject), constructionContext) {
state, files ->
val packageCodegen = state.factory.forPackage(packageFqName, files)
val packagePartType = state.fileClassesProvider.getFileClassType(file)
@@ -77,6 +54,13 @@ class LightClassDataProviderForClassOrObject(private val classOrObject: KtClassO
}
}
override fun compute(): CachedValueProvider.Result<LightClassDataHolder>? {
return CachedValueProvider.Result.create(
computeLightClassData(),
if (classOrObject.isLocal()) PsiModificationTracker.MODIFICATION_COUNT else PsiModificationTracker.OUT_OF_CODE_BLOCK_MODIFICATION_COUNT
)
}
override fun toString(): String {
return this::class.java.name + " for " + classOrObject.name
}
@@ -84,27 +68,21 @@ class LightClassDataProviderForClassOrObject(private val classOrObject: KtClassO
sealed class LightClassDataProviderForFileFacade constructor(
protected val project: Project, protected val facadeFqName: FqName
) : LightClassDataProvider<LightClassDataHolder>(project) {
override val isLocal: Boolean get() = false
abstract val files: Collection<KtFile>
) : CachedValueProvider<LightClassDataHolder> {
abstract fun findFiles(): Collection<KtFile>
override val valueAbsent: Boolean
get() = files.isEmpty()
override fun computeLightClassData(): LightClassDataHolder {
private fun computeLightClassData(files: Collection<KtFile>): LightClassDataHolder {
return LightClassGenerationSupport.getInstance(project).createLightClassDataHolderForFacade(files) {
constructionContext ->
buildLightClass(project, facadeFqName.parent(), files, ClassFilterForFacade, constructionContext) generate@ {
buildLightClass(facadeFqName.parent(), files, ClassFilterForFacade, constructionContext) generate@ {
state, files ->
if (!files.isEmpty()) {
val representativeFile = files.iterator().next()
val fileClassInfo = NoResolveFileClassesProvider.getFileClassInfo(representativeFile)
if (!fileClassInfo.withJvmMultifileClass) {
val codegen = state.factory.forPackage(representativeFile.packageFqName, files)
codegen.generate(CompilationErrorHandler.THROW_EXCEPTION)
state.factory.asList()
return@generate
}
val representativeFile = files.first()
val fileClassInfo = NoResolveFileClassesProvider.getFileClassInfo(representativeFile)
if (!fileClassInfo.withJvmMultifileClass) {
val codegen = state.factory.forPackage(representativeFile.packageFqName, files)
codegen.generate(CompilationErrorHandler.THROW_EXCEPTION)
state.factory.asList()
return@generate
}
val codegen = state.factory.forMultifileClass(facadeFqName, files)
@@ -114,6 +92,16 @@ sealed class LightClassDataProviderForFileFacade constructor(
}
}
override fun compute(): CachedValueProvider.Result<LightClassDataHolder>? {
val files = findFiles()
if (files.isEmpty()) return null
return CachedValueProvider.Result.create(
computeLightClassData(files),
PsiModificationTracker.OUT_OF_CODE_BLOCK_MODIFICATION_COUNT
)
}
override fun toString(): String {
return this::class.java.name + " for $facadeFqName"
}
@@ -124,8 +112,7 @@ sealed class LightClassDataProviderForFileFacade constructor(
facadeFqName: FqName,
private val searchScope: GlobalSearchScope
) : LightClassDataProviderForFileFacade(project, facadeFqName) {
override val files: Collection<KtFile>
get() = LightClassGenerationSupport.getInstance(project).findFilesForFacade(facadeFqName, searchScope)
override fun findFiles() = LightClassGenerationSupport.getInstance(project).findFilesForFacade(facadeFqName, searchScope)
}
// create delegate by single file
@@ -134,8 +121,7 @@ sealed class LightClassDataProviderForFileFacade constructor(
facadeFqName: FqName,
private val file: KtFile
) : LightClassDataProviderForFileFacade(project, facadeFqName) {
override val files: Collection<KtFile>
get() = listOf(file)
override fun findFiles() = listOf(file)
}
}