Revert "[light classes] drop old light classes and backend: iteration #12"
This reverts commit 36d1eef6fe.
This commit is contained in:
+66
-46
@@ -8,21 +8,24 @@ package org.jetbrains.kotlin.cli.jvm.compiler
|
|||||||
import com.intellij.openapi.util.Key
|
import com.intellij.openapi.util.Key
|
||||||
import com.intellij.psi.search.GlobalSearchScope
|
import com.intellij.psi.search.GlobalSearchScope
|
||||||
import com.intellij.psi.util.CachedValue
|
import com.intellij.psi.util.CachedValue
|
||||||
import com.intellij.psi.util.CachedValueProvider
|
|
||||||
import com.intellij.psi.util.CachedValuesManager
|
import com.intellij.psi.util.CachedValuesManager
|
||||||
import org.jetbrains.kotlin.analyzer.KotlinModificationTrackerService
|
|
||||||
import org.jetbrains.kotlin.asJava.KotlinAsJavaSupport
|
import org.jetbrains.kotlin.asJava.KotlinAsJavaSupport
|
||||||
import org.jetbrains.kotlin.asJava.LightClassGenerationSupport
|
import org.jetbrains.kotlin.asJava.LightClassGenerationSupport
|
||||||
import org.jetbrains.kotlin.asJava.classes.getOutermostClassOrObject
|
import org.jetbrains.kotlin.asJava.classes.getOutermostClassOrObject
|
||||||
import org.jetbrains.kotlin.asJava.classes.shouldNotBeVisibleAsLightClass
|
import org.jetbrains.kotlin.asJava.classes.shouldNotBeVisibleAsLightClass
|
||||||
import org.jetbrains.kotlin.cli.jvm.compiler.builder.extraJvmDiagnosticsFromBackend
|
import org.jetbrains.kotlin.cli.jvm.compiler.builder.InvalidLightClassDataHolder
|
||||||
|
import org.jetbrains.kotlin.cli.jvm.compiler.builder.LightClassDataHolder
|
||||||
|
import org.jetbrains.kotlin.cli.jvm.compiler.builder.buildLightClass
|
||||||
import org.jetbrains.kotlin.fileClasses.JvmFileClassUtil
|
import org.jetbrains.kotlin.fileClasses.JvmFileClassUtil
|
||||||
import org.jetbrains.kotlin.psi.KtClassOrObject
|
import org.jetbrains.kotlin.psi.KtClassOrObject
|
||||||
import org.jetbrains.kotlin.psi.KtFile
|
import org.jetbrains.kotlin.psi.KtFile
|
||||||
import org.jetbrains.kotlin.resolve.diagnostics.Diagnostics
|
import org.jetbrains.kotlin.resolve.diagnostics.Diagnostics
|
||||||
import org.jetbrains.kotlin.utils.addToStdlib.cast
|
import org.jetbrains.kotlin.utils.addToStdlib.cast
|
||||||
|
|
||||||
private val JAVA_API_STUB = Key.create<CachedValue<Diagnostics>>("JAVA_API_STUB")
|
private val JAVA_API_STUB = Key.create<CachedValue<LightClassDataHolder.ForClass>>("JAVA_API_STUB")
|
||||||
|
private val JAVA_API_STUB_LOCK = Key.create<Any>("JAVA_API_STUB_LOCK")
|
||||||
|
|
||||||
|
private val javaApiStubInitIsRunning: ThreadLocal<Boolean> = ThreadLocal.withInitial { false }
|
||||||
|
|
||||||
object CliExtraDiagnosticsProvider {
|
object CliExtraDiagnosticsProvider {
|
||||||
fun forClassOrObject(kclass: KtClassOrObject): Diagnostics {
|
fun forClassOrObject(kclass: KtClassOrObject): Diagnostics {
|
||||||
@@ -30,65 +33,82 @@ object CliExtraDiagnosticsProvider {
|
|||||||
return Diagnostics.EMPTY
|
return Diagnostics.EMPTY
|
||||||
}
|
}
|
||||||
|
|
||||||
return getLightClassCachedValue(kclass).value
|
val lightClassDataHolder = getLightClassCachedValue(kclass).value
|
||||||
|
return if (lightClassDataHolder is InvalidLightClassDataHolder) {
|
||||||
|
Diagnostics.EMPTY
|
||||||
|
} else {
|
||||||
|
lightClassDataHolder.extraDiagnostics
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun forFacade(file: KtFile): Diagnostics = CachedValuesManager.getCachedValue(file) {
|
fun forFacade(file: KtFile, moduleScope: GlobalSearchScope): Diagnostics {
|
||||||
CachedValueProvider.Result.create(
|
|
||||||
calculateForFacade(file),
|
|
||||||
KotlinModificationTrackerService.getInstance(file.project).outOfBlockModificationTracker,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun calculateForFacade(file: KtFile): Diagnostics {
|
|
||||||
val project = file.project
|
val project = file.project
|
||||||
val facadeFqName = JvmFileClassUtil.getFileClassInfoNoResolve(file).facadeClassFqName
|
val facadeFqName = JvmFileClassUtil.getFileClassInfoNoResolve(file).facadeClassFqName
|
||||||
val facadeCollection = KotlinAsJavaSupport.getInstance(project)
|
val files = KotlinAsJavaSupport.getInstance(project)
|
||||||
.findFilesForFacade(facadeFqName, GlobalSearchScope.allScope(project))
|
.findFilesForFacade(facadeFqName, moduleScope)
|
||||||
.ifEmpty { return Diagnostics.EMPTY }
|
.ifEmpty { return Diagnostics.EMPTY }
|
||||||
|
|
||||||
val context = LightClassGenerationSupport.getInstance(project).cast<CliLightClassGenerationSupport>().context
|
return LightClassGenerationSupport.getInstance(project).cast<CliLightClassGenerationSupport>()
|
||||||
val (_, _, diagnostics) = extraJvmDiagnosticsFromBackend(
|
.createDataHolderForFacade { constructionContext ->
|
||||||
facadeFqName.parent(),
|
buildLightClass(facadeFqName.parent(), files, ClassFilterForFacade, constructionContext) generate@{ state, files ->
|
||||||
facadeCollection,
|
val representativeFile = files.first()
|
||||||
ClassFilterForFacade,
|
val fileClassInfo = JvmFileClassUtil.getFileClassInfoNoResolve(representativeFile)
|
||||||
context,
|
if (!fileClassInfo.withJvmMultifileClass) {
|
||||||
) generate@{ state, files ->
|
val codegen = state.factory.forPackage(representativeFile.packageFqName, files)
|
||||||
val representativeFile = files.first()
|
codegen.generate()
|
||||||
val fileClassInfo = JvmFileClassUtil.getFileClassInfoNoResolve(representativeFile)
|
state.factory.done()
|
||||||
if (!fileClassInfo.withJvmMultifileClass) {
|
return@generate
|
||||||
val codegen = state.factory.forPackage(representativeFile.packageFqName, files)
|
}
|
||||||
codegen.generate()
|
|
||||||
state.factory.done()
|
|
||||||
return@generate
|
|
||||||
}
|
|
||||||
|
|
||||||
val codegen = state.factory.forMultifileClass(facadeFqName, files)
|
val codegen = state.factory.forMultifileClass(facadeFqName, files)
|
||||||
codegen.generate()
|
codegen.generate()
|
||||||
state.factory.done()
|
state.factory.done()
|
||||||
}
|
}
|
||||||
|
}.extraDiagnostics
|
||||||
return diagnostics
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getLightClassCachedValue(classOrObject: KtClassOrObject): CachedValue<Diagnostics> {
|
private fun getLightClassCachedValue(classOrObject: KtClassOrObject): CachedValue<LightClassDataHolder.ForClass> {
|
||||||
val outerClassValue = getOutermostClassOrObject(classOrObject).getUserData(JAVA_API_STUB)
|
val outerClassValue = getOutermostClassOrObject(classOrObject).getUserData(JAVA_API_STUB)
|
||||||
outerClassValue?.let {
|
outerClassValue?.let {
|
||||||
// stub computed for outer class can be used for inner/nested
|
// stub computed for outer class can be used for inner/nested
|
||||||
return it
|
return it
|
||||||
}
|
}
|
||||||
|
// the idea behind this locking approach:
|
||||||
|
// Thread T1 starts to calculate value for A it acquires lock for A
|
||||||
|
//
|
||||||
|
// Assumption 1: Lets say A calculation requires another value e.g. B to be calculated
|
||||||
|
// Assumption 2: Thread T2 wants to calculate value for B
|
||||||
|
|
||||||
return computeLightClassCachedValue(classOrObject)
|
// to avoid dead-lock case we mark thread as doing calculation and acquire lock only once per thread
|
||||||
}
|
// as a trade-off to prevent dependent value could be calculated several time
|
||||||
|
// due to CAS (within putUserDataIfAbsent etc) the same instance of calculated value will be used
|
||||||
private fun computeLightClassCachedValue(classOrObject: KtClassOrObject): CachedValue<Diagnostics> {
|
val value: CachedValue<LightClassDataHolder.ForClass> = if (!javaApiStubInitIsRunning.get()) {
|
||||||
val value = classOrObject.getUserData(JAVA_API_STUB) ?: run {
|
classOrObject.getUserData(JAVA_API_STUB) ?: run {
|
||||||
val manager = CachedValuesManager.getManager(classOrObject.project)
|
val lock = classOrObject.putUserDataIfAbsent(JAVA_API_STUB_LOCK, Object())
|
||||||
val cachedValue = manager.createCachedValue(LightClassDataProviderForClassOrObject(classOrObject))
|
synchronized(lock) {
|
||||||
|
try {
|
||||||
classOrObject.putUserDataIfAbsent(JAVA_API_STUB, cachedValue)
|
javaApiStubInitIsRunning.set(true)
|
||||||
|
computeLightClassCachedValue(classOrObject)
|
||||||
|
} finally {
|
||||||
|
javaApiStubInitIsRunning.set(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
computeLightClassCachedValue(classOrObject)
|
||||||
}
|
}
|
||||||
|
|
||||||
return value
|
return value
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun computeLightClassCachedValue(classOrObject: KtClassOrObject): CachedValue<LightClassDataHolder.ForClass> {
|
||||||
|
val value = classOrObject.getUserData(JAVA_API_STUB) ?: run {
|
||||||
|
val manager = CachedValuesManager.getManager(classOrObject.project)
|
||||||
|
val cachedValue = manager.createCachedValue(
|
||||||
|
LightClassDataProviderForClassOrObject(classOrObject), false
|
||||||
|
)
|
||||||
|
classOrObject.putUserDataIfAbsent(JAVA_API_STUB, cachedValue)
|
||||||
|
}
|
||||||
|
return value
|
||||||
|
}
|
||||||
+27
-7
@@ -11,7 +11,7 @@ import org.jetbrains.kotlin.asJava.classes.KtUltraLightSupport
|
|||||||
import org.jetbrains.kotlin.asJava.classes.cleanFromAnonymousTypes
|
import org.jetbrains.kotlin.asJava.classes.cleanFromAnonymousTypes
|
||||||
import org.jetbrains.kotlin.asJava.classes.lazyPub
|
import org.jetbrains.kotlin.asJava.classes.lazyPub
|
||||||
import org.jetbrains.kotlin.asJava.classes.tryGetPredefinedName
|
import org.jetbrains.kotlin.asJava.classes.tryGetPredefinedName
|
||||||
import org.jetbrains.kotlin.cli.jvm.compiler.builder.LightClassConstructionContext
|
import org.jetbrains.kotlin.cli.jvm.compiler.builder.*
|
||||||
import org.jetbrains.kotlin.codegen.ClassBuilderMode
|
import org.jetbrains.kotlin.codegen.ClassBuilderMode
|
||||||
import org.jetbrains.kotlin.codegen.JvmCodegenUtil
|
import org.jetbrains.kotlin.codegen.JvmCodegenUtil
|
||||||
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper
|
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper
|
||||||
@@ -89,12 +89,30 @@ class CliLightClassGenerationSupport(
|
|||||||
return ultraLightSupport
|
return ultraLightSupport
|
||||||
}
|
}
|
||||||
|
|
||||||
internal val context: LightClassConstructionContext
|
fun createDataHolderForClass(classOrObject: KtClassOrObject, builder: LightClassBuilder): LightClassDataHolder.ForClass {
|
||||||
get() = LightClassConstructionContext(
|
//force resolve companion for light class generation
|
||||||
traceHolder.bindingContext,
|
traceHolder.bindingContext.get(BindingContext.CLASS, classOrObject)?.companionObjectDescriptor
|
||||||
traceHolder.module,
|
|
||||||
traceHolder.languageVersionSettings,
|
val (_, bindingContext, diagnostics) = builder(getContext())
|
||||||
traceHolder.jvmTarget,
|
|
||||||
|
bindingContext.get(BindingContext.CLASS, classOrObject) ?: return InvalidLightClassDataHolder
|
||||||
|
|
||||||
|
return LightClassDataHolderImpl(diagnostics)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun createDataHolderForFacade(builder: LightClassBuilder): LightClassDataHolder.ForFacade {
|
||||||
|
val (_, _, diagnostics) = builder(getContext())
|
||||||
|
return LightClassDataHolderImpl(diagnostics)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun createDataHolderForScript(builder: LightClassBuilder): LightClassDataHolder.ForScript {
|
||||||
|
val (_, _, diagnostics) = builder(getContext())
|
||||||
|
return LightClassDataHolderImpl(diagnostics)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getContext(): LightClassConstructionContext =
|
||||||
|
LightClassConstructionContext(
|
||||||
|
traceHolder.bindingContext, traceHolder.module, null /* TODO: traceHolder.languageVersionSettings? */, traceHolder.jvmTarget
|
||||||
)
|
)
|
||||||
|
|
||||||
override fun resolveToDescriptor(declaration: KtDeclaration): DeclarationDescriptor? {
|
override fun resolveToDescriptor(declaration: KtDeclaration): DeclarationDescriptor? {
|
||||||
@@ -107,3 +125,5 @@ class CliLightClassGenerationSupport(
|
|||||||
|
|
||||||
override fun analyzeWithContent(element: KtClassOrObject) = traceHolder.bindingContext
|
override fun analyzeWithContent(element: KtClassOrObject) = traceHolder.bindingContext
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typealias LightClassBuilder = (LightClassConstructionContext) -> LightClassBuilderResult
|
||||||
|
|||||||
@@ -12,45 +12,40 @@ import org.jetbrains.kotlin.analyzer.KotlinModificationTrackerService
|
|||||||
import org.jetbrains.kotlin.asJava.LightClassGenerationSupport
|
import org.jetbrains.kotlin.asJava.LightClassGenerationSupport
|
||||||
import org.jetbrains.kotlin.asJava.classes.getOutermostClassOrObject
|
import org.jetbrains.kotlin.asJava.classes.getOutermostClassOrObject
|
||||||
import org.jetbrains.kotlin.asJava.classes.safeIsLocal
|
import org.jetbrains.kotlin.asJava.classes.safeIsLocal
|
||||||
import org.jetbrains.kotlin.cli.jvm.compiler.builder.extraJvmDiagnosticsFromBackend
|
import org.jetbrains.kotlin.cli.jvm.compiler.builder.LightClassDataHolder
|
||||||
|
import org.jetbrains.kotlin.cli.jvm.compiler.builder.buildLightClass
|
||||||
import org.jetbrains.kotlin.codegen.MemberCodegen
|
import org.jetbrains.kotlin.codegen.MemberCodegen
|
||||||
import org.jetbrains.kotlin.codegen.state.GenerationState
|
import org.jetbrains.kotlin.codegen.state.GenerationState
|
||||||
import org.jetbrains.kotlin.fileClasses.JvmFileClassUtil
|
import org.jetbrains.kotlin.fileClasses.JvmFileClassUtil
|
||||||
import org.jetbrains.kotlin.psi.*
|
import org.jetbrains.kotlin.psi.*
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.isAncestor
|
import org.jetbrains.kotlin.psi.psiUtil.isAncestor
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext
|
|
||||||
import org.jetbrains.kotlin.resolve.diagnostics.Diagnostics
|
|
||||||
import org.jetbrains.kotlin.utils.addToStdlib.cast
|
import org.jetbrains.kotlin.utils.addToStdlib.cast
|
||||||
import org.jetbrains.org.objectweb.asm.Type
|
import org.jetbrains.org.objectweb.asm.Type
|
||||||
|
|
||||||
internal class LightClassDataProviderForClassOrObject(
|
internal class LightClassDataProviderForClassOrObject(
|
||||||
private val classOrObject: KtClassOrObject
|
private val classOrObject: KtClassOrObject
|
||||||
) : CachedValueProvider<Diagnostics> {
|
) : CachedValueProvider<LightClassDataHolder.ForClass> {
|
||||||
private fun computeLightClassData(): Diagnostics {
|
private fun computeLightClassData(): LightClassDataHolder.ForClass {
|
||||||
val file = classOrObject.containingKtFile
|
val file = classOrObject.containingKtFile
|
||||||
val packageFqName = file.packageFqName
|
val packageFqName = file.packageFqName
|
||||||
val cliSupport = LightClassGenerationSupport.getInstance(classOrObject.project).cast<CliLightClassGenerationSupport>()
|
return LightClassGenerationSupport.getInstance(classOrObject.project).cast<CliLightClassGenerationSupport>()
|
||||||
|
.createDataHolderForClass(classOrObject) { constructionContext ->
|
||||||
//force resolve companion for light class generation
|
buildLightClass(
|
||||||
cliSupport.traceHolder.bindingContext.get(BindingContext.CLASS, classOrObject)?.companionObjectDescriptor
|
packageFqName,
|
||||||
|
listOf(file),
|
||||||
val (_, bindingContext, diagnostics) = extraJvmDiagnosticsFromBackend(
|
ClassFilterForClassOrObject(classOrObject),
|
||||||
packageFqName,
|
constructionContext
|
||||||
listOf(file),
|
) { state, files ->
|
||||||
ClassFilterForClassOrObject(classOrObject),
|
val packageCodegen = state.factory.forPackage(packageFqName, files)
|
||||||
cliSupport.context,
|
val packagePartType = Type.getObjectType(JvmFileClassUtil.getFileClassInternalName(file))
|
||||||
) { state, files ->
|
val context = state.rootContext.intoPackagePart(packageCodegen.packageFragment, packagePartType, file)
|
||||||
val packageCodegen = state.factory.forPackage(packageFqName, files)
|
MemberCodegen.genClassOrObject(context, getOutermostClassOrObject(classOrObject), state, null)
|
||||||
val packagePartType = Type.getObjectType(JvmFileClassUtil.getFileClassInternalName(file))
|
state.factory.done()
|
||||||
val context = state.rootContext.intoPackagePart(packageCodegen.packageFragment, packagePartType, file)
|
}
|
||||||
MemberCodegen.genClassOrObject(context, getOutermostClassOrObject(classOrObject), state, null)
|
}
|
||||||
state.factory.done()
|
|
||||||
}
|
|
||||||
|
|
||||||
return diagnostics.takeIf { bindingContext.get(BindingContext.CLASS, classOrObject) != null } ?: Diagnostics.EMPTY
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun compute(): CachedValueProvider.Result<Diagnostics> {
|
override fun compute(): CachedValueProvider.Result<LightClassDataHolder.ForClass> {
|
||||||
val trackerService = KotlinModificationTrackerService.getInstance(classOrObject.project)
|
val trackerService = KotlinModificationTrackerService.getInstance(classOrObject.project)
|
||||||
return CachedValueProvider.Result.create(
|
return CachedValueProvider.Result.create(
|
||||||
computeLightClassData(),
|
computeLightClassData(),
|
||||||
|
|||||||
+19
-8
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.cli.jvm.compiler.builder
|
|||||||
import com.intellij.openapi.diagnostic.Logger
|
import com.intellij.openapi.diagnostic.Logger
|
||||||
import com.intellij.openapi.progress.ProcessCanceledException
|
import com.intellij.openapi.progress.ProcessCanceledException
|
||||||
import com.intellij.openapi.util.SystemInfo
|
import com.intellij.openapi.util.SystemInfo
|
||||||
|
import com.intellij.openapi.util.registry.Registry
|
||||||
import com.intellij.openapi.vfs.VirtualFile
|
import com.intellij.openapi.vfs.VirtualFile
|
||||||
import com.intellij.psi.impl.compiled.ClsFileImpl
|
import com.intellij.psi.impl.compiled.ClsFileImpl
|
||||||
import com.intellij.psi.impl.java.stubs.PsiJavaFileStub
|
import com.intellij.psi.impl.java.stubs.PsiJavaFileStub
|
||||||
@@ -22,18 +23,22 @@ import org.jetbrains.kotlin.psi.KtFile
|
|||||||
import org.jetbrains.kotlin.resolve.BindingContext
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
import org.jetbrains.kotlin.resolve.diagnostics.Diagnostics
|
import org.jetbrains.kotlin.resolve.diagnostics.Diagnostics
|
||||||
|
|
||||||
data class CodeGenerationResult(val stub: PsiJavaFileStub, val bindingContext: BindingContext, val diagnostics: Diagnostics)
|
data class LightClassBuilderResult(val stub: PsiJavaFileStub, val bindingContext: BindingContext, val diagnostics: Diagnostics)
|
||||||
|
|
||||||
fun extraJvmDiagnosticsFromBackend(
|
fun buildLightClass(
|
||||||
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
|
||||||
): CodeGenerationResult {
|
): LightClassBuilderResult {
|
||||||
val project = files.first().project
|
val project = files.first().project
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
if (Registry.`is`("kotlin.ultra.light.classes.error.on.old.backend", false)) {
|
||||||
|
error("Access to backend detected")
|
||||||
|
}
|
||||||
|
|
||||||
val classBuilderFactory = KotlinLightClassBuilderFactory(createJavaFileStub(packageFqName, files))
|
val classBuilderFactory = KotlinLightClassBuilderFactory(createJavaFileStub(packageFqName, files))
|
||||||
val state = GenerationState.Builder(
|
val state = GenerationState.Builder(
|
||||||
project,
|
project,
|
||||||
@@ -46,7 +51,8 @@ fun extraJvmDiagnosticsFromBackend(
|
|||||||
put(JVMConfigurationKeys.JVM_TARGET, context.jvmTarget)
|
put(JVMConfigurationKeys.JVM_TARGET, context.jvmTarget)
|
||||||
isReadOnly = true
|
isReadOnly = true
|
||||||
}
|
}
|
||||||
} ?: CompilerConfiguration.EMPTY,
|
} ?: CompilerConfiguration.EMPTY
|
||||||
|
|
||||||
).generateDeclaredClassFilter(generateClassFilter).wantsDiagnostics(false).build()
|
).generateDeclaredClassFilter(generateClassFilter).wantsDiagnostics(false).build()
|
||||||
state.beforeCompile()
|
state.beforeCompile()
|
||||||
state.oldBEInitTrace(files)
|
state.oldBEInitTrace(files)
|
||||||
@@ -54,7 +60,7 @@ fun extraJvmDiagnosticsFromBackend(
|
|||||||
generate(state, files)
|
generate(state, files)
|
||||||
|
|
||||||
val javaFileStub = classBuilderFactory.result()
|
val javaFileStub = classBuilderFactory.result()
|
||||||
return CodeGenerationResult(javaFileStub, context.bindingContext, state.collectedExtraJvmDiagnostics)
|
return LightClassBuilderResult(javaFileStub, context.bindingContext, state.collectedExtraJvmDiagnostics)
|
||||||
} catch (e: ProcessCanceledException) {
|
} catch (e: ProcessCanceledException) {
|
||||||
throw e
|
throw e
|
||||||
} catch (e: RuntimeException) {
|
} catch (e: RuntimeException) {
|
||||||
@@ -69,9 +75,14 @@ private fun createJavaFileStub(packageFqName: FqName, files: Collection<KtFile>)
|
|||||||
|
|
||||||
val fakeFile = object : ClsFileImpl(files.first().viewProvider) {
|
val fakeFile = object : ClsFileImpl(files.first().viewProvider) {
|
||||||
override fun getStub() = javaFileStub
|
override fun getStub() = javaFileStub
|
||||||
|
|
||||||
override fun getPackageName() = packageFqName.asString()
|
override fun getPackageName() = packageFqName.asString()
|
||||||
|
|
||||||
override fun isPhysical() = false
|
override fun isPhysical() = false
|
||||||
override fun getText(): String = files.singleOrNull()?.text ?: super.getText()
|
|
||||||
|
override fun getText(): String {
|
||||||
|
return files.singleOrNull()?.text ?: super.getText()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
javaFileStub.psi = fakeFile
|
javaFileStub.psi = fakeFile
|
||||||
@@ -87,4 +98,4 @@ private fun logErrorWithOSInfo(cause: Throwable?, fqName: FqName, virtualFile: V
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private val LOG = Logger.getInstance(CodeGenerationResult::class.java)
|
private val LOG = Logger.getInstance(LightClassBuilderResult::class.java)
|
||||||
+26
@@ -0,0 +1,26 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2022 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.cli.jvm.compiler.builder
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.resolve.diagnostics.Diagnostics
|
||||||
|
|
||||||
|
interface LightClassDataHolder {
|
||||||
|
val extraDiagnostics: Diagnostics
|
||||||
|
|
||||||
|
interface ForClass : LightClassDataHolder
|
||||||
|
interface ForFacade : LightClassDataHolder
|
||||||
|
interface ForScript : ForClass
|
||||||
|
}
|
||||||
|
|
||||||
|
object InvalidLightClassDataHolder : LightClassDataHolder.ForClass {
|
||||||
|
override val extraDiagnostics: Diagnostics get() = shouldNotBeCalled()
|
||||||
|
|
||||||
|
private fun shouldNotBeCalled(): Nothing = throw UnsupportedOperationException("Should not be called")
|
||||||
|
}
|
||||||
|
|
||||||
|
class LightClassDataHolderImpl(
|
||||||
|
override val extraDiagnostics: Diagnostics
|
||||||
|
) : LightClassDataHolder.ForClass, LightClassDataHolder.ForFacade, LightClassDataHolder.ForScript
|
||||||
@@ -6,6 +6,7 @@
|
|||||||
package org.jetbrains.kotlin.cli.jvm.compiler
|
package org.jetbrains.kotlin.cli.jvm.compiler
|
||||||
|
|
||||||
import com.intellij.psi.PsiElement
|
import com.intellij.psi.PsiElement
|
||||||
|
import com.intellij.psi.search.GlobalSearchScope
|
||||||
import org.jetbrains.kotlin.asJava.classes.getOutermostClassOrObject
|
import org.jetbrains.kotlin.asJava.classes.getOutermostClassOrObject
|
||||||
import org.jetbrains.kotlin.asJava.classes.safeIsScript
|
import org.jetbrains.kotlin.asJava.classes.safeIsScript
|
||||||
import org.jetbrains.kotlin.diagnostics.Diagnostic
|
import org.jetbrains.kotlin.diagnostics.Diagnostic
|
||||||
@@ -18,7 +19,7 @@ import org.jetbrains.kotlin.resolve.jvm.diagnostics.ErrorsJvm.*
|
|||||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOriginKind.*
|
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOriginKind.*
|
||||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||||
|
|
||||||
fun getJvmSignatureDiagnostics(element: PsiElement, otherDiagnostics: Diagnostics): Diagnostics? {
|
fun getJvmSignatureDiagnostics(element: PsiElement, otherDiagnostics: Diagnostics, moduleScope: GlobalSearchScope): Diagnostics? {
|
||||||
fun getDiagnosticsForClass(ktClassOrObject: KtClassOrObject): Diagnostics {
|
fun getDiagnosticsForClass(ktClassOrObject: KtClassOrObject): Diagnostics {
|
||||||
val outermostClass = getOutermostClassOrObject(ktClassOrObject)
|
val outermostClass = getOutermostClassOrObject(ktClassOrObject)
|
||||||
return CliExtraDiagnosticsProvider.forClassOrObject(outermostClass)
|
return CliExtraDiagnosticsProvider.forClassOrObject(outermostClass)
|
||||||
@@ -44,7 +45,7 @@ fun getJvmSignatureDiagnostics(element: PsiElement, otherDiagnostics: Diagnostic
|
|||||||
|
|
||||||
when (parent) {
|
when (parent) {
|
||||||
is KtFile -> {
|
is KtFile -> {
|
||||||
return CliExtraDiagnosticsProvider.forFacade(parent)
|
return CliExtraDiagnosticsProvider.forFacade(parent, moduleScope)
|
||||||
}
|
}
|
||||||
|
|
||||||
is KtClassBody -> {
|
is KtClassBody -> {
|
||||||
|
|||||||
+3
-1
@@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.test.frontend.classic.handlers
|
package org.jetbrains.kotlin.test.frontend.classic.handlers
|
||||||
|
|
||||||
|
import com.intellij.psi.search.GlobalSearchScope
|
||||||
import com.intellij.psi.util.PsiTreeUtil
|
import com.intellij.psi.util.PsiTreeUtil
|
||||||
import org.jetbrains.kotlin.checkers.diagnostics.SyntaxErrorDiagnostic
|
import org.jetbrains.kotlin.checkers.diagnostics.SyntaxErrorDiagnostic
|
||||||
import org.jetbrains.kotlin.checkers.utils.CheckerTestUtil
|
import org.jetbrains.kotlin.checkers.utils.CheckerTestUtil
|
||||||
@@ -76,6 +77,7 @@ class ClassicDiagnosticsHandler(testServices: TestServices) : ClassicFrontendAna
|
|||||||
if (testServices.moduleStructure.modules.any { !it.targetPlatform.isJvm() }) return emptySet()
|
if (testServices.moduleStructure.modules.any { !it.targetPlatform.isJvm() }) return emptySet()
|
||||||
if (REPORT_JVM_DIAGNOSTICS_ON_FRONTEND !in testServices.moduleStructure.allDirectives) return emptySet()
|
if (REPORT_JVM_DIAGNOSTICS_ON_FRONTEND !in testServices.moduleStructure.allDirectives) return emptySet()
|
||||||
val bindingContext = info.analysisResult.bindingContext
|
val bindingContext = info.analysisResult.bindingContext
|
||||||
|
val project = info.project
|
||||||
val jvmSignatureDiagnostics = HashSet<Diagnostic>()
|
val jvmSignatureDiagnostics = HashSet<Diagnostic>()
|
||||||
for (ktFile in info.ktFiles.values) {
|
for (ktFile in info.ktFiles.values) {
|
||||||
val declarations = PsiTreeUtil.findChildrenOfType(ktFile, KtDeclaration::class.java)
|
val declarations = PsiTreeUtil.findChildrenOfType(ktFile, KtDeclaration::class.java)
|
||||||
@@ -83,8 +85,8 @@ class ClassicDiagnosticsHandler(testServices: TestServices) : ClassicFrontendAna
|
|||||||
val diagnostics = getJvmSignatureDiagnostics(
|
val diagnostics = getJvmSignatureDiagnostics(
|
||||||
declaration,
|
declaration,
|
||||||
bindingContext.diagnostics,
|
bindingContext.diagnostics,
|
||||||
|
GlobalSearchScope.allScope(project)
|
||||||
) ?: continue
|
) ?: continue
|
||||||
|
|
||||||
jvmSignatureDiagnostics.addAll(diagnostics.forElement(declaration))
|
jvmSignatureDiagnostics.addAll(diagnostics.forElement(declaration))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import com.intellij.openapi.project.Project
|
|||||||
import com.intellij.openapi.util.Condition
|
import com.intellij.openapi.util.Condition
|
||||||
import com.intellij.openapi.util.Conditions
|
import com.intellij.openapi.util.Conditions
|
||||||
import com.intellij.openapi.util.TextRange
|
import com.intellij.openapi.util.TextRange
|
||||||
|
import com.intellij.psi.search.GlobalSearchScope
|
||||||
import com.intellij.psi.util.PsiTreeUtil
|
import com.intellij.psi.util.PsiTreeUtil
|
||||||
import com.intellij.util.containers.ContainerUtil
|
import com.intellij.util.containers.ContainerUtil
|
||||||
import org.jetbrains.kotlin.checkers.BaseDiagnosticsTest.TestFile
|
import org.jetbrains.kotlin.checkers.BaseDiagnosticsTest.TestFile
|
||||||
@@ -329,12 +330,10 @@ abstract class BaseDiagnosticsTest : KotlinMultiFileTestWithJava<TestModule, Tes
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
val message = "Unexpected ${diagnostic.description}${
|
val message = "Unexpected ${diagnostic.description}${PsiDiagnosticUtils.atLocation(
|
||||||
PsiDiagnosticUtils.atLocation(
|
ktFile,
|
||||||
ktFile,
|
TextRange(actualStart, actualEnd)
|
||||||
TextRange(actualStart, actualEnd)
|
)}"
|
||||||
)
|
|
||||||
}"
|
|
||||||
System.err.println(message)
|
System.err.println(message)
|
||||||
ok[0] = false
|
ok[0] = false
|
||||||
}
|
}
|
||||||
@@ -376,8 +375,8 @@ abstract class BaseDiagnosticsTest : KotlinMultiFileTestWithJava<TestModule, Tes
|
|||||||
val diagnostics = getJvmSignatureDiagnostics(
|
val diagnostics = getJvmSignatureDiagnostics(
|
||||||
declaration,
|
declaration,
|
||||||
bindingContext.diagnostics,
|
bindingContext.diagnostics,
|
||||||
|
GlobalSearchScope.allScope(project)
|
||||||
) ?: continue
|
) ?: continue
|
||||||
|
|
||||||
jvmSignatureDiagnostics.addAll(diagnostics.forElement(declaration).map { ActualDiagnostic(it, null, newInferenceEnabled) })
|
jvmSignatureDiagnostics.addAll(diagnostics.forElement(declaration).map { ActualDiagnostic(it, null, newInferenceEnabled) })
|
||||||
}
|
}
|
||||||
return jvmSignatureDiagnostics
|
return jvmSignatureDiagnostics
|
||||||
@@ -491,7 +490,6 @@ abstract class BaseDiagnosticsTest : KotlinMultiFileTestWithJava<TestModule, Tes
|
|||||||
}
|
}
|
||||||
condition = newCondition
|
condition = newCondition
|
||||||
}
|
}
|
||||||
|
|
||||||
"+" -> condition = Conditions.or(condition, newCondition)
|
"+" -> condition = Conditions.or(condition, newCondition)
|
||||||
"-" -> condition = Conditions.and(condition, Conditions.not(newCondition))
|
"-" -> condition = Conditions.and(condition, Conditions.not(newCondition))
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user