diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/CliLightClassGenerationSupport.kt b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/CliLightClassGenerationSupport.kt index 2084545628a..8be567f5d78 100644 --- a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/CliLightClassGenerationSupport.kt +++ b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/CliLightClassGenerationSupport.kt @@ -14,285 +14,237 @@ * limitations under the License. */ -package org.jetbrains.kotlin.cli.jvm.compiler; +package org.jetbrains.kotlin.cli.jvm.compiler -import com.google.common.base.Predicate; -import com.google.common.collect.Collections2; -import com.intellij.openapi.project.Project; -import com.intellij.psi.PsiClass; -import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiManager; -import com.intellij.psi.search.GlobalSearchScope; -import com.intellij.psi.search.PsiSearchScopeUtil; -import com.intellij.util.Function; -import com.intellij.util.SmartList; -import com.intellij.util.containers.ContainerUtil; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.jetbrains.annotations.TestOnly; -import org.jetbrains.kotlin.asJava.KotlinLightClassForExplicitDeclaration; -import org.jetbrains.kotlin.asJava.KotlinLightClassForFacade; -import org.jetbrains.kotlin.asJava.LightClassConstructionContext; -import org.jetbrains.kotlin.asJava.LightClassGenerationSupport; -import org.jetbrains.kotlin.descriptors.ClassDescriptor; -import org.jetbrains.kotlin.descriptors.DeclarationDescriptor; -import org.jetbrains.kotlin.descriptors.ModuleDescriptor; -import org.jetbrains.kotlin.descriptors.PackageViewDescriptor; -import org.jetbrains.kotlin.load.kotlin.PackagePartClassUtils; -import org.jetbrains.kotlin.name.FqName; -import org.jetbrains.kotlin.psi.*; -import org.jetbrains.kotlin.resolve.*; -import org.jetbrains.kotlin.resolve.lazy.KotlinCodeAnalyzer; -import org.jetbrains.kotlin.resolve.lazy.ResolveSessionUtils; -import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter; -import org.jetbrains.kotlin.resolve.scopes.JetScope; -import org.jetbrains.kotlin.util.slicedMap.ReadOnlySlice; -import org.jetbrains.kotlin.util.slicedMap.WritableSlice; -import org.jetbrains.kotlin.utils.UtilsPackage; - -import java.util.Collection; -import java.util.Collections; -import java.util.List; +import com.google.common.base.Predicate +import com.google.common.collect.Collections2 +import com.intellij.openapi.project.Project +import com.intellij.psi.PsiClass +import com.intellij.psi.PsiElement +import com.intellij.psi.PsiManager +import com.intellij.psi.search.GlobalSearchScope +import com.intellij.psi.search.PsiSearchScopeUtil +import com.intellij.util.Function +import com.intellij.util.SmartList +import com.intellij.util.containers.ContainerUtil +import org.jetbrains.annotations.TestOnly +import org.jetbrains.kotlin.asJava.KotlinLightClassForExplicitDeclaration +import org.jetbrains.kotlin.asJava.KotlinLightClassForFacade +import org.jetbrains.kotlin.asJava.LightClassConstructionContext +import org.jetbrains.kotlin.asJava.LightClassGenerationSupport +import org.jetbrains.kotlin.descriptors.ClassDescriptor +import org.jetbrains.kotlin.descriptors.DeclarationDescriptor +import org.jetbrains.kotlin.descriptors.ModuleDescriptor +import org.jetbrains.kotlin.descriptors.PackageViewDescriptor +import org.jetbrains.kotlin.load.kotlin.PackagePartClassUtils +import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.psi.* +import org.jetbrains.kotlin.resolve.* +import org.jetbrains.kotlin.resolve.lazy.KotlinCodeAnalyzer +import org.jetbrains.kotlin.resolve.lazy.ResolveSessionUtils +import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter +import org.jetbrains.kotlin.resolve.scopes.JetScope +import org.jetbrains.kotlin.util.slicedMap.ReadOnlySlice +import org.jetbrains.kotlin.util.slicedMap.WritableSlice +import org.jetbrains.kotlin.utils.* +import java.util.Collections /** * This class solves the problem of interdependency between analyzing Kotlin code and generating JetLightClasses - * + * Consider the following example: - * + * KClass.kt refers to JClass.java and vice versa - * + * To analyze KClass.kt we need to load descriptors from JClass.java, and to do that we need a JetLightClass instance for KClass, * which can only be constructed when the structure of KClass is known. - * + * To mitigate this, CliLightClassGenerationSupport hold a trace that is shared between the analyzer and JetLightClasses */ -public class CliLightClassGenerationSupport extends LightClassGenerationSupport implements CodeAnalyzerInitializer { - private final PsiManager psiManager; - private BindingContext bindingContext = null; - private ModuleDescriptor module = null; +public class CliLightClassGenerationSupport(project: Project) : LightClassGenerationSupport(), CodeAnalyzerInitializer { + private val psiManager: PsiManager + private var bindingContext: BindingContext? = null + private var module: ModuleDescriptor? = null - public CliLightClassGenerationSupport(@NotNull Project project) { - this.psiManager = PsiManager.getInstance(project); + init { + this.psiManager = PsiManager.getInstance(project) } - @Override - public void initialize(@NotNull BindingTrace trace, @NotNull ModuleDescriptor module, @Nullable KotlinCodeAnalyzer analyzer) { - this.bindingContext = trace.getBindingContext(); - this.module = module; + override fun initialize(trace: BindingTrace, module: ModuleDescriptor, analyzer: KotlinCodeAnalyzer?) { + this.bindingContext = trace.bindingContext + this.module = module - if (!(trace instanceof CliBindingTrace)) { - throw new IllegalArgumentException("Shared trace is expected to be subclass of " + CliBindingTrace.class.getSimpleName() + " class"); + if (trace !is CliBindingTrace) { + throw IllegalArgumentException("Shared trace is expected to be subclass of " + javaClass().simpleName + " class") } - ((CliBindingTrace) trace).setKotlinCodeAnalyzer(analyzer); + trace.setKotlinCodeAnalyzer(analyzer) } - @NotNull - private BindingContext getBindingContext() { - assert bindingContext != null : "Call initialize() first"; - return bindingContext; + private fun getBindingContext(): BindingContext { + assert(bindingContext != null, "Call initialize() first") + return bindingContext } - @NotNull - private ModuleDescriptor getModule() { - assert module != null : "Call initialize() first"; - return module; + private fun getModule(): ModuleDescriptor { + assert(module != null, "Call initialize() first") + return module } - @NotNull - @Override - public LightClassConstructionContext getContextForPackage(@NotNull Collection files) { - return getContext(); + override fun getContextForPackage(files: Collection): LightClassConstructionContext { + return getContext() } - @NotNull - @Override - public LightClassConstructionContext getContextForClassOrObject(@NotNull JetClassOrObject classOrObject) { - return getContext(); + override fun getContextForClassOrObject(classOrObject: JetClassOrObject): LightClassConstructionContext { + return getContext() } - @NotNull - private LightClassConstructionContext getContext() { - return new LightClassConstructionContext(bindingContext, getModule()); + private fun getContext(): LightClassConstructionContext { + return LightClassConstructionContext(bindingContext, getModule()) } - @NotNull - @Override - public Collection findClassOrObjectDeclarations(@NotNull FqName fqName, @NotNull final GlobalSearchScope searchScope) { - Collection classDescriptors = ResolveSessionUtils.getClassDescriptorsByFqName(getModule(), fqName); + override fun findClassOrObjectDeclarations(fqName: FqName, searchScope: GlobalSearchScope): Collection { + val classDescriptors = ResolveSessionUtils.getClassDescriptorsByFqName(getModule(), fqName) - return ContainerUtil.mapNotNull(classDescriptors, new Function() { - @Override - public JetClassOrObject fun(ClassDescriptor descriptor) { - PsiElement element = DescriptorToSourceUtils.getSourceFromDescriptor(descriptor); - if (element instanceof JetClassOrObject && PsiSearchScopeUtil.isInScope(searchScope, element)) { - return (JetClassOrObject) element; + return ContainerUtil.mapNotNull(classDescriptors, object : Function { + override fun `fun`(descriptor: ClassDescriptor): JetClassOrObject? { + val element = DescriptorToSourceUtils.getSourceFromDescriptor(descriptor) + if (element is JetClassOrObject && PsiSearchScopeUtil.isInScope(searchScope, element)) { + return element } - return null; + return null } - }); + }) } - @NotNull - @Override - public Collection findFilesForPackage(@NotNull FqName fqName, @NotNull final GlobalSearchScope searchScope) { - Collection files = getBindingContext().get(BindingContext.PACKAGE_TO_FILES, fqName); + override fun findFilesForPackage(fqName: FqName, searchScope: GlobalSearchScope): Collection { + val files = getBindingContext().get(BindingContext.PACKAGE_TO_FILES, fqName) if (files != null) { - return Collections2.filter(files, new Predicate() { - @Override - public boolean apply(JetFile input) { - return PsiSearchScopeUtil.isInScope(searchScope, input); + return Collections2.filter(files, object : Predicate { + override fun apply(input: JetFile?): Boolean { + return PsiSearchScopeUtil.isInScope(searchScope, input) } - }); + }) } - return Collections.emptyList(); + return emptyList() } - @NotNull - @Override - public Collection findClassOrObjectDeclarationsInPackage( - @NotNull FqName packageFqName, @NotNull GlobalSearchScope searchScope - ) { - Collection files = findFilesForPackage(packageFqName, searchScope); - List result = new SmartList(); - for (JetFile file : files) { - for (JetDeclaration declaration : file.getDeclarations()) { - if (declaration instanceof JetClassOrObject) { - result.add((JetClassOrObject) declaration); + override fun findClassOrObjectDeclarationsInPackage( + packageFqName: FqName, searchScope: GlobalSearchScope): Collection { + val files = findFilesForPackage(packageFqName, searchScope) + val result = SmartList() + for (file in files) { + for (declaration in file.declarations) { + if (declaration is JetClassOrObject) { + result.add(declaration) } } } - return result; + return result } - @Override - public boolean packageExists(@NotNull FqName fqName, @NotNull GlobalSearchScope scope) { - return !getModule().getPackage(fqName).isEmpty(); + override fun packageExists(fqName: FqName, scope: GlobalSearchScope): Boolean { + return !getModule().getPackage(fqName).isEmpty() } - @NotNull - @Override - public Collection getSubPackages(@NotNull FqName fqn, @NotNull GlobalSearchScope scope) { - PackageViewDescriptor packageView = getModule().getPackage(fqn); - Collection members = packageView.getMemberScope().getDescriptors(DescriptorKindFilter.PACKAGES, JetScope.ALL_NAME_FILTER); - return ContainerUtil.mapNotNull(members, new Function() { - @Override - public FqName fun(DeclarationDescriptor member) { - if (member instanceof PackageViewDescriptor) { - return ((PackageViewDescriptor) member).getFqName(); + override fun getSubPackages(fqn: FqName, scope: GlobalSearchScope): Collection { + val packageView = getModule().getPackage(fqn) + val members = packageView.memberScope.getDescriptors(DescriptorKindFilter.PACKAGES, JetScope.ALL_NAME_FILTER) + return ContainerUtil.mapNotNull(members, object : Function { + override fun `fun`(member: DeclarationDescriptor): FqName? { + if (member is PackageViewDescriptor) { + return member.fqName } - return null; + return null } - }); + }) } - @Nullable - @Override - public PsiClass getPsiClass(@NotNull JetClassOrObject classOrObject) { - return KotlinLightClassForExplicitDeclaration.Companion.create(psiManager, classOrObject); + override fun getPsiClass(classOrObject: JetClassOrObject): PsiClass? { + return KotlinLightClassForExplicitDeclaration.create(psiManager, classOrObject) } - @NotNull - @Override - public Collection getPackageClasses(@NotNull FqName packageFqName, @NotNull GlobalSearchScope scope) { - Collection filesInPackage = findFilesForPackage(packageFqName, scope); + override fun getPackageClasses(packageFqName: FqName, scope: GlobalSearchScope): Collection { + val filesInPackage = findFilesForPackage(packageFqName, scope) - List filesWithCallables = PackagePartClassUtils.getFilesWithCallables(filesInPackage); - if (filesWithCallables.isEmpty()) return Collections.emptyList(); + val filesWithCallables = PackagePartClassUtils.getFilesWithCallables(filesInPackage) + if (filesWithCallables.isEmpty()) return emptyList() //noinspection RedundantTypeArguments - return UtilsPackage.emptyOrSingletonList( - KotlinLightClassForFacade.Factory.createForPackageFacade(psiManager, packageFqName, scope, filesWithCallables)); + return emptyOrSingletonList( + KotlinLightClassForFacade.createForPackageFacade(psiManager, packageFqName, scope, filesWithCallables)) } - @Nullable - @Override - public ClassDescriptor resolveClassToDescriptor(@NotNull JetClassOrObject classOrObject) { - return bindingContext.get(BindingContext.CLASS, classOrObject); + override fun resolveClassToDescriptor(classOrObject: JetClassOrObject): ClassDescriptor? { + return bindingContext!!.get(BindingContext.CLASS, classOrObject) } - @NotNull - @Override - public Collection getFacadeClasses(@NotNull FqName facadeFqName, @NotNull GlobalSearchScope scope) { - Collection filesForFacade = findFilesForFacade(facadeFqName, scope); - if (filesForFacade.isEmpty()) return Collections.emptyList(); + override fun getFacadeClasses(facadeFqName: FqName, scope: GlobalSearchScope): Collection { + val filesForFacade = findFilesForFacade(facadeFqName, scope) + if (filesForFacade.isEmpty()) return emptyList() //noinspection RedundantTypeArguments - return UtilsPackage.emptyOrSingletonList( - KotlinLightClassForFacade.Factory.createForFacade(psiManager, facadeFqName, scope, filesForFacade)); + return emptyOrSingletonList( + KotlinLightClassForFacade.createForFacade(psiManager, facadeFqName, scope, filesForFacade)) } - @NotNull - @Override - public Collection findFilesForFacade(@NotNull FqName facadeFqName, @NotNull GlobalSearchScope scope) { + override fun findFilesForFacade(facadeFqName: FqName, scope: GlobalSearchScope): Collection { // TODO We need a way to plug some platform-dependent stuff into LazyTopDownAnalyzer. // It already performs some ad hoc stuff for packages->files mapping, anyway. - Collection filesInPackage = findFilesForPackage(facadeFqName.parent(), scope); - return PackagePartClassUtils.getFilesForPart(facadeFqName, filesInPackage); + val filesInPackage = findFilesForPackage(facadeFqName.parent(), scope) + return PackagePartClassUtils.getFilesForPart(facadeFqName, filesInPackage) } - @NotNull - @Override - public LightClassConstructionContext getContextForFacade(@NotNull Collection files) { - return getContext(); + override fun getContextForFacade(files: Collection): LightClassConstructionContext { + return getContext() } - @NotNull - @Override - public BindingTraceContext createTrace() { - return new NoScopeRecordCliBindingTrace(); + override fun createTrace(): BindingTraceContext { + return NoScopeRecordCliBindingTrace() } - public static class NoScopeRecordCliBindingTrace extends CliBindingTrace { - @Override - public void record(WritableSlice slice, K key, V value) { - if (slice == BindingContext.RESOLUTION_SCOPE || slice == BindingContext.TYPE_RESOLUTION_SCOPE - || slice == BindingContext.LEXICAL_SCOPE) { + public class NoScopeRecordCliBindingTrace : CliBindingTrace() { + override fun record(slice: WritableSlice, key: K, value: V) { + if (slice === BindingContext.RESOLUTION_SCOPE || slice === BindingContext.TYPE_RESOLUTION_SCOPE || slice === BindingContext.LEXICAL_SCOPE) { // In the compiler there's no need to keep scopes - return; + return } - super.record(slice, key, value); + super.record(slice, key, value) } - @Override - public String toString() { - return NoScopeRecordCliBindingTrace.class.getName(); + override fun toString(): String { + return javaClass().name } } - public static class CliBindingTrace extends BindingTraceContext { - private KotlinCodeAnalyzer kotlinCodeAnalyzer; + public open class CliBindingTrace + TestOnly + constructor() : BindingTraceContext() { + private var kotlinCodeAnalyzer: KotlinCodeAnalyzer? = null - @TestOnly - public CliBindingTrace() { + override fun toString(): String { + return javaClass().name } - @Override - public String toString() { - return CliBindingTrace.class.getName(); + public fun setKotlinCodeAnalyzer(kotlinCodeAnalyzer: KotlinCodeAnalyzer) { + this.kotlinCodeAnalyzer = kotlinCodeAnalyzer } - public void setKotlinCodeAnalyzer(KotlinCodeAnalyzer kotlinCodeAnalyzer) { - this.kotlinCodeAnalyzer = kotlinCodeAnalyzer; - } - - @Override - public V get(ReadOnlySlice slice, K key) { - V value = super.get(slice, key); + override fun get(slice: ReadOnlySlice, key: K): V? { + val value = super.get(slice, key) if (value == null) { - if (BindingContext.FUNCTION == slice || BindingContext.VARIABLE == slice) { - if (key instanceof JetDeclaration) { - JetDeclaration jetDeclaration = (JetDeclaration) key; - if (!JetPsiUtil.isLocal(jetDeclaration)) { - kotlinCodeAnalyzer.resolveToDescriptor(jetDeclaration); - return super.get(slice, key); + if (BindingContext.FUNCTION === slice || BindingContext.VARIABLE === slice) { + if (key is JetDeclaration) { + if (!JetPsiUtil.isLocal(key)) { + kotlinCodeAnalyzer!!.resolveToDescriptor(key) + return super.get(slice, key) } } } } - return value; + return value } } }