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) data class LightClassBuilderResult(val stub: PsiJavaFileStub, val bindingContext: BindingContext, val diagnostics: Diagnostics)
fun buildLightClass( fun buildLightClass(
project: Project,
packageFqName: FqName, packageFqName: FqName,
files: Collection<KtFile>, files: Collection<KtFile>,
generateClassFilter: GenerationState.GenerateClassFilter, generateClassFilter: GenerationState.GenerateClassFilter,
context: LightClassConstructionContext, context: LightClassConstructionContext,
generate: (state: GenerationState, files: Collection<KtFile>) -> Unit generate: (state: GenerationState, files: Collection<KtFile>) -> Unit
): LightClassBuilderResult { ): LightClassBuilderResult {
val project = files.first().project
val javaFileStub = createJavaFileStub(project, packageFqName, files) val javaFileStub = createJavaFileStub(project, packageFqName, files)
val bindingContext: BindingContext val bindingContext: BindingContext
@@ -64,7 +63,7 @@ fun buildLightClass(
KotlinLightClassBuilderFactory(stubStack), KotlinLightClassBuilderFactory(stubStack),
context.module, context.module,
context.bindingContext, context.bindingContext,
files.toMutableList(), files.toList(),
CompilerConfiguration.EMPTY, CompilerConfiguration.EMPTY,
generateClassFilter, generateClassFilter,
wantsDiagnostics = false wantsDiagnostics = false
@@ -93,7 +92,7 @@ fun buildLightClass(
} }
private fun createJavaFileStub(project: Project, packageFqName: FqName, files: Collection<KtFile>): PsiJavaFileStub { 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 javaFileStub.psiFactory = ClsWrapperStubPsiFactory.INSTANCE
val manager = PsiManager.getInstance(project) 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.KtScript
import org.jetbrains.kotlin.psi.psiUtil.isAncestor import org.jetbrains.kotlin.psi.psiUtil.isAncestor
abstract class LightClassDataProvider<T : LightClassDataHolder>( class LightClassDataProviderForClassOrObject(private val classOrObject: KtClassOrObject) : CachedValueProvider<LightClassDataHolder> {
private val project: Project
) : CachedValueProvider<T> {
abstract val isLocal: Boolean
open val valueAbsent: Boolean = false private fun computeLightClassData(): LightClassDataHolder {
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 {
val file = classOrObject.containingKtFile val file = classOrObject.containingKtFile
val packageFqName = file.packageFqName val packageFqName = file.packageFqName
return LightClassGenerationSupport.getInstance(classOrObject.project).createLightClassDataHolderForClassOrObject(classOrObject) { return LightClassGenerationSupport.getInstance(classOrObject.project).createLightClassDataHolderForClassOrObject(classOrObject) {
constructionContext -> constructionContext ->
buildLightClass(classOrObject.project, packageFqName, listOf(file), ClassFilterForClassOrObject(classOrObject), constructionContext) { buildLightClass(packageFqName, listOf(file), ClassFilterForClassOrObject(classOrObject), constructionContext) {
state, files -> state, files ->
val packageCodegen = state.factory.forPackage(packageFqName, files) val packageCodegen = state.factory.forPackage(packageFqName, files)
val packagePartType = state.fileClassesProvider.getFileClassType(file) 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 { override fun toString(): String {
return this::class.java.name + " for " + classOrObject.name return this::class.java.name + " for " + classOrObject.name
} }
@@ -84,27 +68,21 @@ class LightClassDataProviderForClassOrObject(private val classOrObject: KtClassO
sealed class LightClassDataProviderForFileFacade constructor( sealed class LightClassDataProviderForFileFacade constructor(
protected val project: Project, protected val facadeFqName: FqName protected val project: Project, protected val facadeFqName: FqName
) : LightClassDataProvider<LightClassDataHolder>(project) { ) : CachedValueProvider<LightClassDataHolder> {
override val isLocal: Boolean get() = false abstract fun findFiles(): Collection<KtFile>
abstract val files: Collection<KtFile>
override val valueAbsent: Boolean private fun computeLightClassData(files: Collection<KtFile>): LightClassDataHolder {
get() = files.isEmpty()
override fun computeLightClassData(): LightClassDataHolder {
return LightClassGenerationSupport.getInstance(project).createLightClassDataHolderForFacade(files) { return LightClassGenerationSupport.getInstance(project).createLightClassDataHolderForFacade(files) {
constructionContext -> constructionContext ->
buildLightClass(project, facadeFqName.parent(), files, ClassFilterForFacade, constructionContext) generate@ { buildLightClass(facadeFqName.parent(), files, ClassFilterForFacade, constructionContext) generate@ {
state, files -> state, files ->
if (!files.isEmpty()) { val representativeFile = files.first()
val representativeFile = files.iterator().next() val fileClassInfo = NoResolveFileClassesProvider.getFileClassInfo(representativeFile)
val fileClassInfo = NoResolveFileClassesProvider.getFileClassInfo(representativeFile) if (!fileClassInfo.withJvmMultifileClass) {
if (!fileClassInfo.withJvmMultifileClass) { val codegen = state.factory.forPackage(representativeFile.packageFqName, files)
val codegen = state.factory.forPackage(representativeFile.packageFqName, files) codegen.generate(CompilationErrorHandler.THROW_EXCEPTION)
codegen.generate(CompilationErrorHandler.THROW_EXCEPTION) state.factory.asList()
state.factory.asList() return@generate
return@generate
}
} }
val codegen = state.factory.forMultifileClass(facadeFqName, files) 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 { override fun toString(): String {
return this::class.java.name + " for $facadeFqName" return this::class.java.name + " for $facadeFqName"
} }
@@ -124,8 +112,7 @@ sealed class LightClassDataProviderForFileFacade constructor(
facadeFqName: FqName, facadeFqName: FqName,
private val searchScope: GlobalSearchScope private val searchScope: GlobalSearchScope
) : LightClassDataProviderForFileFacade(project, facadeFqName) { ) : LightClassDataProviderForFileFacade(project, facadeFqName) {
override val files: Collection<KtFile> override fun findFiles() = LightClassGenerationSupport.getInstance(project).findFilesForFacade(facadeFqName, searchScope)
get() = LightClassGenerationSupport.getInstance(project).findFilesForFacade(facadeFqName, searchScope)
} }
// create delegate by single file // create delegate by single file
@@ -134,8 +121,7 @@ sealed class LightClassDataProviderForFileFacade constructor(
facadeFqName: FqName, facadeFqName: FqName,
private val file: KtFile private val file: KtFile
) : LightClassDataProviderForFileFacade(project, facadeFqName) { ) : LightClassDataProviderForFileFacade(project, facadeFqName) {
override val files: Collection<KtFile> override fun findFiles() = listOf(file)
get() = listOf(file)
} }
} }