Revert "[light classes] drop old light classes and backend: iteration #12"

This reverts commit 36d1eef6fe.
This commit is contained in:
Dmitry Gridin
2022-06-28 13:52:06 +02:00
parent 36d1eef6fe
commit 732a08f0df
8 changed files with 170 additions and 97 deletions
@@ -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
}
@@ -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(),
@@ -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)
@@ -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 -> {
@@ -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))
} }