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

This reverts commit 074dd1c19d.
This commit is contained in:
Dmitry Gridin
2022-06-28 17:57:30 +02:00
parent dd824aacb6
commit ce183a8eeb
5 changed files with 108 additions and 116 deletions
@@ -0,0 +1,37 @@
/*
* 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
import com.intellij.psi.search.GlobalSearchScope
import org.jetbrains.kotlin.asJava.KotlinExtraDiagnosticsProvider
import org.jetbrains.kotlin.asJava.builder.InvalidLightClassDataHolder
import org.jetbrains.kotlin.asJava.builder.LightClassDataProviderForFileFacade
import org.jetbrains.kotlin.asJava.classes.KtLightClassForSourceDeclaration
import org.jetbrains.kotlin.fileClasses.JvmFileClassUtil
import org.jetbrains.kotlin.psi.KtClassOrObject
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.resolve.diagnostics.Diagnostics
class CliExtraDiagnosticsProvider : KotlinExtraDiagnosticsProvider {
override fun forClassOrObject(kclass: KtClassOrObject): Diagnostics {
val lightClassDataHolder = KtLightClassForSourceDeclaration.getLightClassDataHolder(kclass)
if (lightClassDataHolder is InvalidLightClassDataHolder) {
return Diagnostics.EMPTY
}
return lightClassDataHolder.extraDiagnostics
}
override fun forFacade(file: KtFile, moduleScope: GlobalSearchScope): Diagnostics {
val project = file.project
val facadeFqName = JvmFileClassUtil.getFileClassInfoNoResolve(file).facadeClassFqName
return LightClassDataProviderForFileFacade(project, facadeFqName, moduleScope)
.compute()
?.value
?.extraDiagnostics
?: Diagnostics.EMPTY
}
}
@@ -1,17 +1,6 @@
/*
* Copyright 2010-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* 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
@@ -50,6 +39,7 @@ import com.intellij.util.io.URLUtil
import com.intellij.util.lang.UrlClassLoader
import org.jetbrains.annotations.TestOnly
import org.jetbrains.kotlin.asJava.KotlinAsJavaSupport
import org.jetbrains.kotlin.asJava.KotlinExtraDiagnosticsProvider
import org.jetbrains.kotlin.asJava.LightClassGenerationSupport
import org.jetbrains.kotlin.asJava.classes.FacadeCache
import org.jetbrains.kotlin.asJava.finder.JavaElementFinder
@@ -61,7 +51,6 @@ import org.jetbrains.kotlin.cli.common.config.kotlinSourceRoots
import org.jetbrains.kotlin.cli.common.extensions.ScriptEvaluationExtension
import org.jetbrains.kotlin.cli.common.extensions.ShellExtension
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.ERROR
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.STRONG_WARNING
import org.jetbrains.kotlin.cli.common.messages.MessageCollector
import org.jetbrains.kotlin.cli.jvm.compiler.jarfs.FastJarFileSystem
@@ -70,7 +59,6 @@ import org.jetbrains.kotlin.cli.jvm.index.*
import org.jetbrains.kotlin.cli.jvm.javac.JavacWrapperRegistrar
import org.jetbrains.kotlin.cli.jvm.modules.CliJavaModuleFinder
import org.jetbrains.kotlin.cli.jvm.modules.CliJavaModuleResolver
import org.jetbrains.kotlin.cli.jvm.modules.CoreJrtFileSystem
import org.jetbrains.kotlin.codegen.extensions.ClassBuilderInterceptorExtension
import org.jetbrains.kotlin.codegen.extensions.ClassFileFactoryFinalizerExtension
import org.jetbrains.kotlin.codegen.extensions.ExpressionCodegenExtension
@@ -732,6 +720,7 @@ class KotlinCoreEnvironment private constructor(
val traceHolder = CliTraceHolder()
val cliLightClassGenerationSupport = CliLightClassGenerationSupport(traceHolder, project)
val kotlinAsJavaSupport = CliKotlinAsJavaSupport(this, traceHolder)
registerService(KotlinExtraDiagnosticsProvider::class.java, CliExtraDiagnosticsProvider())
registerService(LightClassGenerationSupport::class.java, cliLightClassGenerationSupport)
registerService(CliLightClassGenerationSupport::class.java, cliLightClassGenerationSupport)
registerService(KotlinAsJavaSupport::class.java, kotlinAsJavaSupport)
@@ -0,0 +1,25 @@
/*
* 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.asJava;
import com.intellij.openapi.project.Project;
import com.intellij.psi.search.GlobalSearchScope;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.kotlin.psi.KtClassOrObject;
import org.jetbrains.kotlin.psi.KtFile;
import org.jetbrains.kotlin.resolve.diagnostics.Diagnostics;
public interface KotlinExtraDiagnosticsProvider {
@NotNull
Diagnostics forClassOrObject(@NotNull KtClassOrObject kclass);
@NotNull
Diagnostics forFacade(@NotNull KtFile file, @NotNull GlobalSearchScope moduleScope);
static @NotNull KotlinExtraDiagnosticsProvider getInstance(@NotNull Project project) {
return project.getService(KotlinExtraDiagnosticsProvider.class);
}
}
@@ -1,17 +1,6 @@
/*
* Copyright 2010-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* 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.asJava.builder
@@ -36,23 +25,27 @@ import org.jetbrains.kotlin.psi.psiUtil.isAncestor
import org.jetbrains.org.objectweb.asm.Type
class LightClassDataProviderForClassOrObject(
private val classOrObject: KtClassOrObject
private val classOrObject: KtClassOrObject
) : CachedValueProvider<LightClassDataHolder.ForClass> {
private fun computeLightClassData(): LightClassDataHolder.ForClass {
val file = classOrObject.containingKtFile
val packageFqName = file.packageFqName
return LightClassGenerationSupport.getInstance(classOrObject.project).createDataHolderForClass(classOrObject) {
constructionContext ->
buildLightClass(packageFqName, listOf(file), ClassFilterForClassOrObject(classOrObject), constructionContext) {
state, files ->
val packageCodegen = state.factory.forPackage(packageFqName, files)
val packagePartType = Type.getObjectType(JvmFileClassUtil.getFileClassInternalName(file))
val context = state.rootContext.intoPackagePart(packageCodegen.packageFragment, packagePartType, file)
MemberCodegen.genClassOrObject(context, getOutermostClassOrObject(classOrObject), state, null)
state.factory.done()
return LightClassGenerationSupport.getInstance(classOrObject.project)
.createDataHolderForClass(classOrObject) { constructionContext ->
buildLightClass(
packageFqName,
listOf(file),
ClassFilterForClassOrObject(classOrObject),
constructionContext
) { state, files ->
val packageCodegen = state.factory.forPackage(packageFqName, files)
val packagePartType = Type.getObjectType(JvmFileClassUtil.getFileClassInternalName(file))
val context = state.rootContext.intoPackagePart(packageCodegen.packageFragment, packagePartType, file)
MemberCodegen.genClassOrObject(context, getOutermostClassOrObject(classOrObject), state, null)
state.factory.done()
}
}
}
}
override fun compute(): CachedValueProvider.Result<LightClassDataHolder.ForClass>? {
@@ -68,16 +61,14 @@ class LightClassDataProviderForClassOrObject(
}
}
sealed class LightClassDataProviderForFileFacade constructor(
protected val project: Project, protected val facadeFqName: FqName
class LightClassDataProviderForFileFacade constructor(
private val project: Project, private val facadeFqName: FqName, private val searchScope: GlobalSearchScope
) : CachedValueProvider<LightClassDataHolder.ForFacade> {
abstract fun findFiles(): Collection<KtFile>
fun findFiles(): Collection<KtFile> = KotlinAsJavaSupport.getInstance(project).findFilesForFacade(facadeFqName, searchScope)
private fun computeLightClassData(files: Collection<KtFile>): LightClassDataHolder.ForFacade {
return LightClassGenerationSupport.getInstance(project).createDataHolderForFacade(files) {
constructionContext ->
buildLightClass(facadeFqName.parent(), files, ClassFilterForFacade, constructionContext) generate@ {
state, files ->
return LightClassGenerationSupport.getInstance(project).createDataHolderForFacade(files) { constructionContext ->
buildLightClass(facadeFqName.parent(), files, ClassFilterForFacade, constructionContext) generate@{ state, files ->
val representativeFile = files.first()
val fileClassInfo = JvmFileClassUtil.getFileClassInfoNoResolve(representativeFile)
if (!fileClassInfo.withJvmMultifileClass) {
@@ -99,46 +90,26 @@ sealed class LightClassDataProviderForFileFacade constructor(
if (files.isEmpty()) return null
return CachedValueProvider.Result.create(
computeLightClassData(files),
KotlinModificationTrackerService.getInstance(project).outOfBlockModificationTracker
computeLightClassData(files),
KotlinModificationTrackerService.getInstance(project).outOfBlockModificationTracker
)
}
override fun toString(): String {
return this::class.java.name + " for $facadeFqName"
}
// create delegate by relevant files in project source using LightClassGenerationSupport
class ByProjectSource(
project: Project,
facadeFqName: FqName,
private val searchScope: GlobalSearchScope
) : LightClassDataProviderForFileFacade(project, facadeFqName) {
override fun findFiles() = KotlinAsJavaSupport.getInstance(project).findFilesForFacade(facadeFqName, searchScope)
}
// create delegate by single file
class ByFile(
project: Project,
facadeFqName: FqName,
private val file: KtFile
) : LightClassDataProviderForFileFacade(project, facadeFqName) {
override fun findFiles() = listOf(file)
}
}
class LightClassDataProviderForScript(private val script: KtScript) : CachedValueProvider<LightClassDataHolder.ForScript> {
private fun computeLightClassData(): LightClassDataHolder.ForScript {
return LightClassGenerationSupport.getInstance(script.project).createDataHolderForScript(script) {
constructionContext ->
return LightClassGenerationSupport.getInstance(script.project).createDataHolderForScript(script) { constructionContext ->
buildLightClass(
script.fqName.parent(),
listOf(script.containingKtFile),
ClassFilterForScript(script),
constructionContext
) generate@ {
state, files ->
script.fqName.parent(),
listOf(script.containingKtFile),
ClassFilterForScript(script),
constructionContext
) generate@{ state, files ->
val scriptFile = files.first()
val codegen = state.factory.forPackage(scriptFile.packageFqName, files)
codegen.generate()
@@ -148,10 +119,10 @@ class LightClassDataProviderForScript(private val script: KtScript) : CachedValu
}
override fun compute(): CachedValueProvider.Result<LightClassDataHolder.ForScript>? =
CachedValueProvider.Result.create(
computeLightClassData(),
KotlinModificationTrackerService.getInstance(script.project).outOfBlockModificationTracker
)
CachedValueProvider.Result.create(
computeLightClassData(),
KotlinModificationTrackerService.getInstance(script.project).outOfBlockModificationTracker
)
override fun toString(): String = this::class.java.name + " for ${script.fqName}"
}
@@ -197,7 +168,7 @@ private class ClassFilterForClassOrObject(private val classOrObject: KtClassOrOb
}
override fun shouldGenerateClass(processingClassOrObject: KtClassOrObject)
// generate outer classes but not their members
// generate outer classes but not their members
= shouldGenerateClassMembers(processingClassOrObject) || processingClassOrObject.isAncestor(classOrObject, true)
override fun shouldGenerateScript(script: KtScript) = PsiTreeUtil.isAncestor(script, classOrObject, false)
@@ -214,10 +185,10 @@ object ClassFilterForFacade : GenerationState.GenerateClassFilter() {
private class ClassFilterForScript(val script: KtScript) : GenerationState.GenerateClassFilter() {
override fun shouldAnnotateClass(processingClassOrObject: KtClassOrObject): Boolean =
shouldGenerateClass(processingClassOrObject)
shouldGenerateClass(processingClassOrObject)
override fun shouldGenerateClass(processingClassOrObject: KtClassOrObject): Boolean =
processingClassOrObject.isAncestor(script, true)
processingClassOrObject.isAncestor(script, true)
override fun shouldGenerateClassMembers(processingClassOrObject: KtClassOrObject): Boolean = true
@@ -1,32 +1,17 @@
/*
* Copyright 2010-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* 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.asJava
import com.intellij.psi.PsiElement
import com.intellij.psi.search.GlobalSearchScope
import org.jetbrains.kotlin.asJava.builder.InvalidLightClassDataHolder
import org.jetbrains.kotlin.asJava.builder.LightClassDataProviderForFileFacade
import org.jetbrains.kotlin.asJava.classes.KtLightClassForSourceDeclaration
import org.jetbrains.kotlin.asJava.classes.getOutermostClassOrObject
import org.jetbrains.kotlin.asJava.classes.safeIsScript
import org.jetbrains.kotlin.diagnostics.Diagnostic
import org.jetbrains.kotlin.diagnostics.DiagnosticFactory
import org.jetbrains.kotlin.diagnostics.Errors.*
import org.jetbrains.kotlin.fileClasses.JvmFileClassUtil
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.resolve.diagnostics.Diagnostics
import org.jetbrains.kotlin.resolve.jvm.diagnostics.ConflictingJvmDeclarationsData
@@ -34,25 +19,9 @@ import org.jetbrains.kotlin.resolve.jvm.diagnostics.ErrorsJvm.*
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOriginKind.*
fun getJvmSignatureDiagnostics(element: PsiElement, otherDiagnostics: Diagnostics, moduleScope: GlobalSearchScope): Diagnostics? {
fun getDiagnosticsForFileFacade(file: KtFile): Diagnostics? {
val project = file.project
val facadeFqName = JvmFileClassUtil.getFileClassInfoNoResolve(file).facadeClassFqName
//TODO Maybe it is better to cache this item
return LightClassDataProviderForFileFacade.ByProjectSource(project, facadeFqName, moduleScope)
.compute()
?.value
?.extraDiagnostics
}
fun getDiagnosticsForClass(ktClassOrObject: KtClassOrObject): Diagnostics {
val outermostClass = getOutermostClassOrObject(ktClassOrObject)
val lightClassDataHolder = KtLightClassForSourceDeclaration.getLightClassDataHolder(outermostClass)
if (lightClassDataHolder is InvalidLightClassDataHolder) {
return Diagnostics.EMPTY
}
return lightClassDataHolder.extraDiagnostics
return KotlinExtraDiagnosticsProvider.getInstance(ktClassOrObject.project).forClassOrObject(outermostClass)
}
fun doGetDiagnostics(): Diagnostics? {
@@ -76,8 +45,9 @@ fun getJvmSignatureDiagnostics(element: PsiElement, otherDiagnostics: Diagnostic
when (parent) {
is KtFile -> {
return getDiagnosticsForFileFacade(parent)
return KotlinExtraDiagnosticsProvider.getInstance(parent.project).forFacade(parent, moduleScope)
}
is KtClassBody -> {
val parentsParent = parent.getParent()