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. * 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.
* 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.
*/ */
package org.jetbrains.kotlin.cli.jvm.compiler package org.jetbrains.kotlin.cli.jvm.compiler
@@ -50,6 +39,7 @@ import com.intellij.util.io.URLUtil
import com.intellij.util.lang.UrlClassLoader import com.intellij.util.lang.UrlClassLoader
import org.jetbrains.annotations.TestOnly import org.jetbrains.annotations.TestOnly
import org.jetbrains.kotlin.asJava.KotlinAsJavaSupport import org.jetbrains.kotlin.asJava.KotlinAsJavaSupport
import org.jetbrains.kotlin.asJava.KotlinExtraDiagnosticsProvider
import org.jetbrains.kotlin.asJava.LightClassGenerationSupport import org.jetbrains.kotlin.asJava.LightClassGenerationSupport
import org.jetbrains.kotlin.asJava.classes.FacadeCache import org.jetbrains.kotlin.asJava.classes.FacadeCache
import org.jetbrains.kotlin.asJava.finder.JavaElementFinder 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.ScriptEvaluationExtension
import org.jetbrains.kotlin.cli.common.extensions.ShellExtension import org.jetbrains.kotlin.cli.common.extensions.ShellExtension
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity 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.CompilerMessageSeverity.STRONG_WARNING
import org.jetbrains.kotlin.cli.common.messages.MessageCollector import org.jetbrains.kotlin.cli.common.messages.MessageCollector
import org.jetbrains.kotlin.cli.jvm.compiler.jarfs.FastJarFileSystem 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.javac.JavacWrapperRegistrar
import org.jetbrains.kotlin.cli.jvm.modules.CliJavaModuleFinder import org.jetbrains.kotlin.cli.jvm.modules.CliJavaModuleFinder
import org.jetbrains.kotlin.cli.jvm.modules.CliJavaModuleResolver 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.ClassBuilderInterceptorExtension
import org.jetbrains.kotlin.codegen.extensions.ClassFileFactoryFinalizerExtension import org.jetbrains.kotlin.codegen.extensions.ClassFileFactoryFinalizerExtension
import org.jetbrains.kotlin.codegen.extensions.ExpressionCodegenExtension import org.jetbrains.kotlin.codegen.extensions.ExpressionCodegenExtension
@@ -732,6 +720,7 @@ class KotlinCoreEnvironment private constructor(
val traceHolder = CliTraceHolder() val traceHolder = CliTraceHolder()
val cliLightClassGenerationSupport = CliLightClassGenerationSupport(traceHolder, project) val cliLightClassGenerationSupport = CliLightClassGenerationSupport(traceHolder, project)
val kotlinAsJavaSupport = CliKotlinAsJavaSupport(this, traceHolder) val kotlinAsJavaSupport = CliKotlinAsJavaSupport(this, traceHolder)
registerService(KotlinExtraDiagnosticsProvider::class.java, CliExtraDiagnosticsProvider())
registerService(LightClassGenerationSupport::class.java, cliLightClassGenerationSupport) registerService(LightClassGenerationSupport::class.java, cliLightClassGenerationSupport)
registerService(CliLightClassGenerationSupport::class.java, cliLightClassGenerationSupport) registerService(CliLightClassGenerationSupport::class.java, cliLightClassGenerationSupport)
registerService(KotlinAsJavaSupport::class.java, kotlinAsJavaSupport) 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. * 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.
* 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.
*/ */
package org.jetbrains.kotlin.asJava.builder package org.jetbrains.kotlin.asJava.builder
@@ -36,23 +25,27 @@ import org.jetbrains.kotlin.psi.psiUtil.isAncestor
import org.jetbrains.org.objectweb.asm.Type import org.jetbrains.org.objectweb.asm.Type
class LightClassDataProviderForClassOrObject( class LightClassDataProviderForClassOrObject(
private val classOrObject: KtClassOrObject private val classOrObject: KtClassOrObject
) : CachedValueProvider<LightClassDataHolder.ForClass> { ) : CachedValueProvider<LightClassDataHolder.ForClass> {
private fun computeLightClassData(): LightClassDataHolder.ForClass { private fun computeLightClassData(): LightClassDataHolder.ForClass {
val file = classOrObject.containingKtFile val file = classOrObject.containingKtFile
val packageFqName = file.packageFqName val packageFqName = file.packageFqName
return LightClassGenerationSupport.getInstance(classOrObject.project).createDataHolderForClass(classOrObject) { return LightClassGenerationSupport.getInstance(classOrObject.project)
constructionContext -> .createDataHolderForClass(classOrObject) { constructionContext ->
buildLightClass(packageFqName, listOf(file), ClassFilterForClassOrObject(classOrObject), constructionContext) { buildLightClass(
state, files -> packageFqName,
val packageCodegen = state.factory.forPackage(packageFqName, files) listOf(file),
val packagePartType = Type.getObjectType(JvmFileClassUtil.getFileClassInternalName(file)) ClassFilterForClassOrObject(classOrObject),
val context = state.rootContext.intoPackagePart(packageCodegen.packageFragment, packagePartType, file) constructionContext
MemberCodegen.genClassOrObject(context, getOutermostClassOrObject(classOrObject), state, null) ) { state, files ->
state.factory.done() 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>? { override fun compute(): CachedValueProvider.Result<LightClassDataHolder.ForClass>? {
@@ -68,16 +61,14 @@ class LightClassDataProviderForClassOrObject(
} }
} }
sealed class LightClassDataProviderForFileFacade constructor( class LightClassDataProviderForFileFacade constructor(
protected val project: Project, protected val facadeFqName: FqName private val project: Project, private val facadeFqName: FqName, private val searchScope: GlobalSearchScope
) : CachedValueProvider<LightClassDataHolder.ForFacade> { ) : 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 { private fun computeLightClassData(files: Collection<KtFile>): LightClassDataHolder.ForFacade {
return LightClassGenerationSupport.getInstance(project).createDataHolderForFacade(files) { return LightClassGenerationSupport.getInstance(project).createDataHolderForFacade(files) { constructionContext ->
constructionContext -> buildLightClass(facadeFqName.parent(), files, ClassFilterForFacade, constructionContext) generate@{ state, files ->
buildLightClass(facadeFqName.parent(), files, ClassFilterForFacade, constructionContext) generate@ {
state, files ->
val representativeFile = files.first() val representativeFile = files.first()
val fileClassInfo = JvmFileClassUtil.getFileClassInfoNoResolve(representativeFile) val fileClassInfo = JvmFileClassUtil.getFileClassInfoNoResolve(representativeFile)
if (!fileClassInfo.withJvmMultifileClass) { if (!fileClassInfo.withJvmMultifileClass) {
@@ -99,46 +90,26 @@ sealed class LightClassDataProviderForFileFacade constructor(
if (files.isEmpty()) return null if (files.isEmpty()) return null
return CachedValueProvider.Result.create( return CachedValueProvider.Result.create(
computeLightClassData(files), computeLightClassData(files),
KotlinModificationTrackerService.getInstance(project).outOfBlockModificationTracker KotlinModificationTrackerService.getInstance(project).outOfBlockModificationTracker
) )
} }
override fun toString(): String { override fun toString(): String {
return this::class.java.name + " for $facadeFqName" 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> { class LightClassDataProviderForScript(private val script: KtScript) : CachedValueProvider<LightClassDataHolder.ForScript> {
private fun computeLightClassData(): LightClassDataHolder.ForScript { private fun computeLightClassData(): LightClassDataHolder.ForScript {
return LightClassGenerationSupport.getInstance(script.project).createDataHolderForScript(script) { return LightClassGenerationSupport.getInstance(script.project).createDataHolderForScript(script) { constructionContext ->
constructionContext ->
buildLightClass( buildLightClass(
script.fqName.parent(), script.fqName.parent(),
listOf(script.containingKtFile), listOf(script.containingKtFile),
ClassFilterForScript(script), ClassFilterForScript(script),
constructionContext constructionContext
) generate@ { ) generate@{ state, files ->
state, files ->
val scriptFile = files.first() val scriptFile = files.first()
val codegen = state.factory.forPackage(scriptFile.packageFqName, files) val codegen = state.factory.forPackage(scriptFile.packageFqName, files)
codegen.generate() codegen.generate()
@@ -148,10 +119,10 @@ class LightClassDataProviderForScript(private val script: KtScript) : CachedValu
} }
override fun compute(): CachedValueProvider.Result<LightClassDataHolder.ForScript>? = override fun compute(): CachedValueProvider.Result<LightClassDataHolder.ForScript>? =
CachedValueProvider.Result.create( CachedValueProvider.Result.create(
computeLightClassData(), computeLightClassData(),
KotlinModificationTrackerService.getInstance(script.project).outOfBlockModificationTracker KotlinModificationTrackerService.getInstance(script.project).outOfBlockModificationTracker
) )
override fun toString(): String = this::class.java.name + " for ${script.fqName}" 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) 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) = shouldGenerateClassMembers(processingClassOrObject) || processingClassOrObject.isAncestor(classOrObject, true)
override fun shouldGenerateScript(script: KtScript) = PsiTreeUtil.isAncestor(script, classOrObject, false) 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() { private class ClassFilterForScript(val script: KtScript) : GenerationState.GenerateClassFilter() {
override fun shouldAnnotateClass(processingClassOrObject: KtClassOrObject): Boolean = override fun shouldAnnotateClass(processingClassOrObject: KtClassOrObject): Boolean =
shouldGenerateClass(processingClassOrObject) shouldGenerateClass(processingClassOrObject)
override fun shouldGenerateClass(processingClassOrObject: KtClassOrObject): Boolean = override fun shouldGenerateClass(processingClassOrObject: KtClassOrObject): Boolean =
processingClassOrObject.isAncestor(script, true) processingClassOrObject.isAncestor(script, true)
override fun shouldGenerateClassMembers(processingClassOrObject: KtClassOrObject): Boolean = true override fun shouldGenerateClassMembers(processingClassOrObject: KtClassOrObject): Boolean = true
@@ -1,32 +1,17 @@
/* /*
* Copyright 2010-2016 JetBrains s.r.o. * 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.
* 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.
*/ */
package org.jetbrains.kotlin.asJava package org.jetbrains.kotlin.asJava
import com.intellij.psi.PsiElement import com.intellij.psi.PsiElement
import com.intellij.psi.search.GlobalSearchScope 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.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
import org.jetbrains.kotlin.diagnostics.DiagnosticFactory import org.jetbrains.kotlin.diagnostics.DiagnosticFactory
import org.jetbrains.kotlin.diagnostics.Errors.* import org.jetbrains.kotlin.diagnostics.Errors.*
import org.jetbrains.kotlin.fileClasses.JvmFileClassUtil
import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.resolve.diagnostics.Diagnostics import org.jetbrains.kotlin.resolve.diagnostics.Diagnostics
import org.jetbrains.kotlin.resolve.jvm.diagnostics.ConflictingJvmDeclarationsData 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.* import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOriginKind.*
fun getJvmSignatureDiagnostics(element: PsiElement, otherDiagnostics: Diagnostics, moduleScope: GlobalSearchScope): Diagnostics? { 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 { fun getDiagnosticsForClass(ktClassOrObject: KtClassOrObject): Diagnostics {
val outermostClass = getOutermostClassOrObject(ktClassOrObject) val outermostClass = getOutermostClassOrObject(ktClassOrObject)
val lightClassDataHolder = KtLightClassForSourceDeclaration.getLightClassDataHolder(outermostClass) return KotlinExtraDiagnosticsProvider.getInstance(ktClassOrObject.project).forClassOrObject(outermostClass)
if (lightClassDataHolder is InvalidLightClassDataHolder) {
return Diagnostics.EMPTY
}
return lightClassDataHolder.extraDiagnostics
} }
fun doGetDiagnostics(): Diagnostics? { fun doGetDiagnostics(): Diagnostics? {
@@ -76,8 +45,9 @@ fun getJvmSignatureDiagnostics(element: PsiElement, otherDiagnostics: Diagnostic
when (parent) { when (parent) {
is KtFile -> { is KtFile -> {
return getDiagnosticsForFileFacade(parent) return KotlinExtraDiagnosticsProvider.getInstance(parent.project).forFacade(parent, moduleScope)
} }
is KtClassBody -> { is KtClassBody -> {
val parentsParent = parent.getParent() val parentsParent = parent.getParent()