LightClassDataProvider: refactor, extract class filters to separate classes

This commit is contained in:
Pavel V. Talanov
2017-03-13 16:36:04 +03:00
parent 48cae0e480
commit ba185d7616
3 changed files with 55 additions and 76 deletions
@@ -69,7 +69,7 @@ class GenerationState @JvmOverloads constructor(
abstract class GenerateClassFilter {
abstract fun shouldAnnotateClass(processingClassOrObject: KtClassOrObject): Boolean
abstract fun shouldGenerateClass(processingClassOrObject: KtClassOrObject): Boolean
abstract fun shouldGeneratePackagePart(jetFile: KtFile): Boolean
abstract fun shouldGeneratePackagePart(ktFile: KtFile): Boolean
abstract fun shouldGenerateScript(script: KtScript): Boolean
open fun shouldGenerateClassMembers(processingClassOrObject: KtClassOrObject) = shouldGenerateClass(processingClassOrObject)
@@ -81,7 +81,7 @@ class GenerationState @JvmOverloads constructor(
override fun shouldGenerateScript(script: KtScript): Boolean = true
override fun shouldGeneratePackagePart(jetFile: KtFile): Boolean = true
override fun shouldGeneratePackagePart(ktFile: KtFile): Boolean = true
}
}
}
@@ -63,61 +63,10 @@ class LightClassDataProviderForClassOrObject(private val classOrObject: KtClassO
override fun computeLightClassData(): LightClassDataHolder {
val file = classOrObject.containingKtFile
val packageFqName = file.packageFqName
val generateClassFilter = object : GenerationState.GenerateClassFilter() {
override fun shouldGeneratePackagePart(jetFile: KtFile): Boolean {
return true
}
override fun shouldAnnotateClass(processingClassOrObject: KtClassOrObject): Boolean {
return shouldGenerateClass(processingClassOrObject)
}
override fun shouldGenerateClassMembers(processingClassOrObject: KtClassOrObject): Boolean {
if (classOrObject === processingClassOrObject) return true
// process all children
if (classOrObject.isAncestor(processingClassOrObject, true)) {
return true
}
// Local classes should be process by CodegenAnnotatingVisitor to
// decide what class they should be placed in.
//
// Example:
// class A
// fun foo() {
// trait Z: A {}
// fun bar() {
// class <caret>O2: Z {}
// }
// }
// TODO: current method will process local classes in irrelevant declarations, it should be fixed.
// We generate all enclosing classes
if (classOrObject.isLocal && processingClassOrObject.isLocal) {
val commonParent = PsiTreeUtil.findCommonParent(classOrObject, processingClassOrObject)
return commonParent != null && commonParent !is PsiFile
}
return false
}
override fun shouldGenerateClass(processingClassOrObject: KtClassOrObject): Boolean {
// generate outer classes but not their members
return shouldGenerateClassMembers(processingClassOrObject) || processingClassOrObject.isAncestor(classOrObject, true)
}
override fun shouldGenerateScript(script: KtScript): Boolean {
return PsiTreeUtil.isAncestor(script, classOrObject, false)
}
}
return LightClassGenerationSupport.getInstance(classOrObject.project).createLightClassDataHolderForClassOrObject(classOrObject) {
constructionContext ->
buildLightClass(classOrObject.project, packageFqName, listOf(file), generateClassFilter, constructionContext) {
buildLightClass(classOrObject.project, packageFqName, listOf(file), ClassFilterForClassOrObject(classOrObject), constructionContext) {
state, files ->
val packageCodegen = state.factory.forPackage(packageFqName, files)
val packagePartType = state.fileClassesProvider.getFileClassType(file)
@@ -143,29 +92,9 @@ sealed class LightClassDataProviderForFileFacade constructor(
get() = files.isEmpty()
override fun computeLightClassData(): LightClassDataHolder {
val generateClassFilter = object : GenerationState.GenerateClassFilter() {
override fun shouldAnnotateClass(processingClassOrObject: KtClassOrObject): Boolean {
return shouldGenerateClass(processingClassOrObject)
}
override fun shouldGenerateClass(processingClassOrObject: KtClassOrObject): Boolean {
return KtPsiUtil.isLocal(processingClassOrObject)
}
override fun shouldGeneratePackagePart(jetFile: KtFile): Boolean {
return true
}
override fun shouldGenerateScript(script: KtScript): Boolean {
return false
}
}
val packageFqName = facadeFqName.parent()
return LightClassGenerationSupport.getInstance(project).createLightClassDataHolderForFacade(files) {
constructionContext ->
buildLightClass(project, packageFqName, files, generateClassFilter, constructionContext) generate@ {
buildLightClass(project, facadeFqName.parent(), files, ClassFilterForFacade, constructionContext) generate@ {
state, files ->
if (!files.isEmpty()) {
val representativeFile = files.iterator().next()
@@ -214,3 +143,53 @@ sealed class LightClassDataProviderForFileFacade constructor(
interface StubComputationTracker {
fun onStubComputed(javaFileStub: PsiJavaFileStub, context: LightClassConstructionContext)
}
private class ClassFilterForClassOrObject(private val classOrObject: KtClassOrObject) : GenerationState.GenerateClassFilter() {
override fun shouldGeneratePackagePart(ktFile: KtFile) = true
override fun shouldAnnotateClass(processingClassOrObject: KtClassOrObject) = shouldGenerateClass(processingClassOrObject)
override fun shouldGenerateClassMembers(processingClassOrObject: KtClassOrObject): Boolean {
if (classOrObject === processingClassOrObject) return true
// process all children
if (classOrObject.isAncestor(processingClassOrObject, true)) {
return true
}
// Local classes should be process by CodegenAnnotatingVisitor to
// decide what class they should be placed in.
//
// Example:
// class A
// fun foo() {
// trait Z: A {}
// fun bar() {
// class <caret>O2: Z {}
// }
// }
// TODO: current method will process local classes in irrelevant declarations, it should be fixed.
// We generate all enclosing classes
if (classOrObject.isLocal && processingClassOrObject.isLocal) {
val commonParent = PsiTreeUtil.findCommonParent(classOrObject, processingClassOrObject)
return commonParent != null && commonParent !is PsiFile
}
return false
}
override fun shouldGenerateClass(processingClassOrObject: KtClassOrObject)
// generate outer classes but not their members
= shouldGenerateClassMembers(processingClassOrObject) || processingClassOrObject.isAncestor(classOrObject, true)
override fun shouldGenerateScript(script: KtScript) = PsiTreeUtil.isAncestor(script, classOrObject, false)
}
object ClassFilterForFacade : GenerationState.GenerateClassFilter() {
override fun shouldAnnotateClass(processingClassOrObject: KtClassOrObject) = shouldGenerateClass(processingClassOrObject)
override fun shouldGenerateClass(processingClassOrObject: KtClassOrObject) = KtPsiUtil.isLocal(processingClassOrObject)
override fun shouldGeneratePackagePart(ktFile: KtFile) = true
override fun shouldGenerateScript(script: KtScript) = false
}
@@ -384,7 +384,7 @@ class KotlinEvaluator(val codeFragment: KtCodeFragment, val sourcePosition: Sour
val (bindingContext, moduleDescriptor, files) = fileForDebugger.checkForErrors(true, codeFragment.getContextContainingFile())
val generateClassFilter = object : GenerationState.GenerateClassFilter() {
override fun shouldGeneratePackagePart(jetFile: KtFile) = jetFile == fileForDebugger
override fun shouldGeneratePackagePart(ktFile: KtFile) = ktFile == fileForDebugger
override fun shouldAnnotateClass(processingClassOrObject: KtClassOrObject) = true
override fun shouldGenerateClass(processingClassOrObject: KtClassOrObject) = processingClassOrObject.containingKtFile == fileForDebugger
override fun shouldGenerateScript(script: KtScript) = false