Convert to Kotlin KotlinLightClassForPackage: fixes for j2k converter

This commit is contained in:
Nikolay Krasko
2015-02-06 15:30:49 +03:00
parent a4e2c3b6fa
commit 8dd910bd36
4 changed files with 91 additions and 186 deletions
@@ -217,7 +217,7 @@ public class CliLightClassGenerationSupport extends LightClassGenerationSupport
if (PackagePartClassUtils.getPackageFilesWithCallables(filesInPackage).isEmpty()) return Collections.emptyList(); if (PackagePartClassUtils.getPackageFilesWithCallables(filesInPackage).isEmpty()) return Collections.emptyList();
//noinspection RedundantTypeArguments //noinspection RedundantTypeArguments
return UtilsPackage.<PsiClass>emptyOrSingletonList(KotlinLightClassForPackage.create(psiManager, packageFqName, scope, filesInPackage)); return UtilsPackage.<PsiClass>emptyOrSingletonList(KotlinLightClassForPackage.OBJECT$.create(psiManager, packageFqName, scope, filesInPackage));
} }
@NotNull @NotNull
@@ -24,9 +24,7 @@ import com.intellij.psi.*
import com.intellij.psi.impl.compiled.ClsFileImpl import com.intellij.psi.impl.compiled.ClsFileImpl
import com.intellij.psi.impl.light.LightEmptyImplementsList import com.intellij.psi.impl.light.LightEmptyImplementsList
import com.intellij.psi.impl.light.LightModifierList import com.intellij.psi.impl.light.LightModifierList
import com.intellij.psi.javadoc.PsiDocComment
import com.intellij.psi.search.GlobalSearchScope import com.intellij.psi.search.GlobalSearchScope
import com.intellij.psi.stubs.PsiClassHolderFileStub
import com.intellij.psi.util.CachedValue import com.intellij.psi.util.CachedValue
import com.intellij.psi.util.CachedValueProvider import com.intellij.psi.util.CachedValueProvider
import com.intellij.psi.util.CachedValuesManager import com.intellij.psi.util.CachedValuesManager
@@ -41,34 +39,17 @@ import org.jetbrains.kotlin.psi.JetFile
import javax.swing.* import javax.swing.*
public class KotlinLightClassForPackage private(manager: PsiManager, private val packageFqName: FqName, private val searchScope: GlobalSearchScope, files: Collection<JetFile>) : KotlinWrappingLightClass(manager), JetJavaMirrorMarker { public class KotlinLightClassForPackage private(
manager: PsiManager,
private val packageFqName: FqName,
private val searchScope: GlobalSearchScope,
files: Collection<JetFile>) : KotlinWrappingLightClass(manager), JetJavaMirrorMarker {
public class FileStubCache(private val project: Project) { public class FileStubCache(private val project: Project) {
private data class Key(val fqName: FqName, val searchScope: GlobalSearchScope)
private class Key private(private val fqName: FqName, private val searchScope: GlobalSearchScope) {
override fun equals(o: Any?): Boolean {
if (this == o) return true
if (o == null || javaClass != o.javaClass) return false
val key = o as Key
if (fqName != key.fqName) return false
if (searchScope != key.searchScope) return false
return true
}
override fun hashCode(): Int {
var result = fqName.hashCode()
result = 31 * result + searchScope.hashCode()
return result
}
}
private inner class CacheData { private inner class CacheData {
val cache = object : SLRUCache<Key, CachedValue<KotlinPackageLightClassData>>(20, 30) {
private val cache = object : SLRUCache<Key, CachedValue<KotlinPackageLightClassData>>(20, 30) {
override fun createValue(key: Key): CachedValue<KotlinPackageLightClassData> { override fun createValue(key: Key): CachedValue<KotlinPackageLightClassData> {
val stubProvider = KotlinJavaFileStubProvider.createForPackageClass(project, key.fqName, key.searchScope) val stubProvider = KotlinJavaFileStubProvider.createForPackageClass(project, key.fqName, key.searchScope)
return CachedValuesManager.getManager(project).createCachedValue<KotlinPackageLightClassData>(stubProvider, /*trackValue = */false) return CachedValuesManager.getManager(project).createCachedValue<KotlinPackageLightClassData>(stubProvider, /*trackValue = */false)
@@ -76,15 +57,9 @@ public class KotlinLightClassForPackage private(manager: PsiManager, private val
} }
} }
private val cachedValue: CachedValue<CacheData> private val cachedValue: CachedValue<CacheData> = CachedValuesManager.getManager(project).createCachedValue<CacheData>(
{ CachedValueProvider.Result.create<CacheData>(CacheData(), PsiModificationTracker.OUT_OF_CODE_BLOCK_MODIFICATION_COUNT) },
{ /*trackValue = */ false)
this.cachedValue = CachedValuesManager.getManager(project).createCachedValue<CacheData>(object : CachedValueProvider<CacheData> {
override fun compute(): CachedValueProvider.Result<CacheData>? {
return CachedValueProvider.Result.create<CacheData>(CacheData(), PsiModificationTracker.OUT_OF_CODE_BLOCK_MODIFICATION_COUNT)
}
}, /*trackValue = */ false)
}
public fun get(qualifiedName: FqName, searchScope: GlobalSearchScope): CachedValue<KotlinPackageLightClassData> { public fun get(qualifiedName: FqName, searchScope: GlobalSearchScope): CachedValue<KotlinPackageLightClassData> {
synchronized (cachedValue) { synchronized (cachedValue) {
@@ -93,172 +68,112 @@ public class KotlinLightClassForPackage private(manager: PsiManager, private val
} }
class object { class object {
public fun getInstance(project: Project): FileStubCache { public fun getInstance(project: Project): FileStubCache {
return ServiceManager.getService<FileStubCache>(project, javaClass<FileStubCache>()) return ServiceManager.getService<FileStubCache>(project, javaClass<FileStubCache>())
} }
} }
} }
private val packageClassFqName: FqName // derived from packageFqName {
public val files: Collection<JetFile> assert(!files.isEmpty()) { "No files for package " + packageFqName }
private val hashCode: Int }
private val lightClassDataCache: CachedValue<KotlinPackageLightClassData>
private val modifierList: PsiModifierList public val files: Collection<JetFile> =
private val implementsList: LightEmptyImplementsList Sets.newHashSet<JetFile>(files) // needed for hashCode
private val packageClassFqName: FqName =
PackageClassUtils.getPackageClassFqName(packageFqName)
private val hashCode: Int =
computeHashCode()
private val lightClassDataCache: CachedValue<KotlinPackageLightClassData> =
FileStubCache.getInstance(getProject()).get(packageFqName, searchScope)
private val modifierList: PsiModifierList =
LightModifierList(manager, JetLanguage.INSTANCE, PsiModifier.PUBLIC, PsiModifier.FINAL)
private val implementsList: LightEmptyImplementsList =
LightEmptyImplementsList(manager)
private val packageClsFile: ClsFileImpl private val packageClsFile: ClsFileImpl
{ {
this.modifierList = LightModifierList(manager, JetLanguage.INSTANCE, PsiModifier.PUBLIC, PsiModifier.FINAL)
this.implementsList = LightEmptyImplementsList(manager)
this.packageClassFqName = PackageClassUtils.getPackageClassFqName(packageFqName)
assert(!files.isEmpty()) { "No files for package " + packageFqName }
this.files = Sets.newHashSet<JetFile>(files) // needed for hashCode
this.hashCode = computeHashCode()
this.lightClassDataCache = FileStubCache.getInstance(getProject()).get(packageFqName, searchScope)
val virtualFile = KotlinJavaFileStubProvider.getRepresentativeVirtualFile(files) val virtualFile = KotlinJavaFileStubProvider.getRepresentativeVirtualFile(files)
packageClsFile = object : ClsFileImpl(ClassFileViewProvider(PsiManager.getInstance(getProject()), virtualFile)) { packageClsFile = object : ClsFileImpl(ClassFileViewProvider(PsiManager.getInstance(getProject()), virtualFile)) {
override fun getStub(): PsiClassHolderFileStub<PsiFile> { override fun getStub() = (getDelegate().getContainingFile() as ClsFileImpl).getStub()
return (getDelegate().getContainingFile() as ClsFileImpl).getStub() override fun getPackageName() = this@KotlinLightClassForPackage.packageFqName.asString()
}
override fun getPackageName(): String {
return this@KotlinLightClassForPackage.packageFqName.asString()
}
} }
packageClsFile.setPhysical(false) packageClsFile.setPhysical(false)
} }
override fun getOrigin(): JetClassOrObject? { override fun getOrigin(): JetClassOrObject? = null
return null
}
override fun getModifierList(): PsiModifierList? { override fun getFqName(): FqName = packageClassFqName
return modifierList
}
override fun hasModifierProperty(NonNls name: String): Boolean { override fun getModifierList() = modifierList
return modifierList.hasModifierProperty(name)
}
override fun isDeprecated(): Boolean { override fun hasModifierProperty(NonNls name: String) = modifierList.hasModifierProperty(name)
return false
}
override fun isInterface(): Boolean { override fun isDeprecated() = false
return false
}
override fun isAnnotationType(): Boolean { override fun isInterface() = false
return false
}
override fun isEnum(): Boolean { override fun isAnnotationType() = false
return false
}
override fun getContainingClass(): PsiClass? { override fun isEnum() = false
return null
}
override fun getContainingFile(): PsiFile { override fun getContainingClass() = null
return packageClsFile
}
override fun hasTypeParameters(): Boolean { override fun getContainingFile() = packageClsFile
return false
}
override fun getTypeParameters(): Array<PsiTypeParameter> { override fun hasTypeParameters() = false
return PsiTypeParameter.EMPTY_ARRAY
}
override fun getTypeParameterList(): PsiTypeParameterList? { override fun getTypeParameters() = PsiTypeParameter.EMPTY_ARRAY
return null
}
override fun getDocComment(): PsiDocComment? { override fun getTypeParameterList() = null
return null
}
override fun getImplementsList(): PsiReferenceList? { override fun getDocComment() = null
return implementsList
}
override fun getImplementsListTypes(): Array<PsiClassType> { override fun getImplementsList() = implementsList
return PsiClassType.EMPTY_ARRAY
}
override fun getExtendsList(): PsiReferenceList? { override fun getImplementsListTypes() = PsiClassType.EMPTY_ARRAY
// TODO: Find a way to return just Object
return super.getExtendsList()
}
override fun getExtendsListTypes(): Array<PsiClassType> { // TODO: Find a way to return just Object
// TODO see getExtendsList() override fun getExtendsList() = super<KotlinWrappingLightClass>.getExtendsList()
return super.getExtendsListTypes()
}
override fun getSuperClass(): PsiClass? { // TODO see getExtendsList()
// TODO see getExtendsList() override fun getExtendsListTypes() = super<KotlinWrappingLightClass>.getExtendsListTypes()
return super.getSuperClass()
}
override fun getSupers(): Array<PsiClass> { // TODO see getExtendsList()
// TODO see getExtendsList() override fun getSuperClass(): PsiClass? = super<KotlinWrappingLightClass>.getSuperClass()
return super.getSupers()
}
override fun getSuperTypes(): Array<PsiClassType> { // TODO see getExtendsList()
// TODO see getExtendsList() override fun getSupers(): Array<PsiClass> = super<KotlinWrappingLightClass>.getSupers()
return super.getSuperTypes()
}
override fun getInterfaces(): Array<PsiClass> { // TODO see getExtendsList()
return PsiClass.EMPTY_ARRAY override fun getSuperTypes() = super<KotlinWrappingLightClass>.getSuperTypes()
}
override fun getInnerClasses(): Array<PsiClass> { override fun getInterfaces() = PsiClass.EMPTY_ARRAY
return PsiClass.EMPTY_ARRAY
}
override fun getOwnInnerClasses(): List<PsiClass> { override fun getInnerClasses() = PsiClass.EMPTY_ARRAY
return listOf()
}
override fun getAllInnerClasses(): Array<PsiClass> { override fun getOwnInnerClasses(): List<PsiClass> = listOf()
return PsiClass.EMPTY_ARRAY
}
override fun getInitializers(): Array<PsiClassInitializer> { override fun getAllInnerClasses() = PsiClass.EMPTY_ARRAY
return PsiClassInitializer.EMPTY_ARRAY
}
override fun findInnerClassByName(NonNls name: String, checkBases: Boolean): PsiClass? { override fun getInitializers() = PsiClassInitializer.EMPTY_ARRAY
return null
}
override fun getFqName(): FqName { override fun findInnerClassByName(NonNls name: String, checkBases: Boolean) = null
return packageClassFqName
}
override fun getName(): String? { override fun getName() = packageClassFqName.shortName().asString()
return packageClassFqName.shortName().asString()
}
override fun getQualifiedName(): String? { override fun getQualifiedName() = packageClassFqName.asString()
return packageClassFqName.asString()
}
override fun isValid(): Boolean { override fun isValid() = files.all { it.isValid() }
return allValid(files)
}
override fun copy(): PsiElement { override fun copy() = KotlinLightClassForPackage(getManager(), packageFqName, searchScope, files)
return KotlinLightClassForPackage(getManager(), packageFqName, searchScope, files)
}
override fun getDelegate(): PsiClass { override fun getDelegate(): PsiClass {
val psiClass = LightClassUtil.findClass(packageClassFqName, lightClassDataCache.getValue().javaFileStub) val psiClass = LightClassUtil.findClass(packageClassFqName, lightClassDataCache.getValue().javaFileStub)
@@ -268,21 +183,15 @@ public class KotlinLightClassForPackage private(manager: PsiManager, private val
return psiClass return psiClass
} }
override fun getNavigationElement(): PsiElement { override fun getNavigationElement() = files.iterator().next()
return files.iterator().next()
}
override fun isEquivalentTo(another: PsiElement?): Boolean { override fun isEquivalentTo(another: PsiElement?): Boolean {
return another is PsiClass && Comparing.equal((another as PsiClass).getQualifiedName(), getQualifiedName()) return another is PsiClass && Comparing.equal(another.getQualifiedName(), getQualifiedName())
} }
override fun getElementIcon(flags: Int): Icon? { override fun getElementIcon(flags: Int): Icon? = throw UnsupportedOperationException("This should be done by JetIconProvider")
throw UnsupportedOperationException("This should be done byt JetIconProvider")
}
override fun hashCode(): Int { override fun hashCode() = hashCode
return hashCode
}
private fun computeHashCode(): Int { private fun computeHashCode(): Int {
var result = getManager().hashCode() var result = getManager().hashCode()
@@ -291,13 +200,13 @@ public class KotlinLightClassForPackage private(manager: PsiManager, private val
return result return result
} }
override fun equals(obj: Any?): Boolean { override fun equals(other: Any?): Boolean {
if (this == obj) return true if (other == null || javaClass != other.javaClass) {
if (obj == null || javaClass != obj.javaClass) {
return false return false
} }
val lightClass = obj as KotlinLightClassForPackage val lightClass = other as KotlinLightClassForPackage
if (this === other) return true
if (this.hashCode != lightClass.hashCode) return false if (this.hashCode != lightClass.hashCode) return false
if (getManager() != lightClass.getManager()) return false if (getManager() != lightClass.getManager()) return false
@@ -314,24 +223,20 @@ public class KotlinLightClassForPackage private(manager: PsiManager, private val
catch (e: Throwable) { catch (e: Throwable) {
return javaClass<KotlinLightClassForPackage>().getSimpleName() + ":" + e.toString() return javaClass<KotlinLightClassForPackage>().getSimpleName() + ":" + e.toString()
} }
} }
class object { class object {
public fun create(
public fun create(manager: PsiManager, qualifiedName: FqName, searchScope: GlobalSearchScope, files: Collection<JetFile> // this is redundant, but computing it multiple times is costly manager: PsiManager,
qualifiedName: FqName,
searchScope: GlobalSearchScope,
files: Collection<JetFile> // this is redundant, but computing it multiple times is costly
): KotlinLightClassForPackage? { ): KotlinLightClassForPackage? {
for (file in files) { if (files.any { LightClassUtil.belongsToKotlinBuiltIns(it) }) {
if (LightClassUtil.belongsToKotlinBuiltIns(file)) return null return null
} }
return KotlinLightClassForPackage(manager, qualifiedName, searchScope, files) return KotlinLightClassForPackage(manager, qualifiedName, searchScope, files)
} }
private fun allValid(files: Collection<JetFile>): Boolean {
for (file in files) {
if (!file.isValid()) return false
}
return true
}
} }
}//NOTE: this is only needed to compute plugin module info }
@@ -282,7 +282,7 @@ public class IDELightClassGenerationSupport extends LightClassGenerationSupport
IdeaModuleInfo moduleInfo = info.getModuleInfo(); IdeaModuleInfo moduleInfo = info.getModuleInfo();
if (moduleInfo instanceof ModuleSourceInfo) { if (moduleInfo instanceof ModuleSourceInfo) {
KotlinLightClassForPackage lightClass = KotlinLightClassForPackage lightClass =
KotlinLightClassForPackage.create(psiManager, packageFqName, moduleInfo.contentScope(), files); KotlinLightClassForPackage.OBJECT$.create(psiManager, packageFqName, moduleInfo.contentScope(), files);
if (lightClass == null) continue; if (lightClass == null) continue;
result.add(lightClass); result.add(lightClass);
@@ -113,7 +113,7 @@ private fun KotlinLightElement<*, *>.getModuleInfoForLightElement(): IdeaModuleI
} }
val element = getOrigin() ?: when (this) { val element = getOrigin() ?: when (this) {
is FakeLightClassForFileOfPackage -> this.getContainingFile()!! is FakeLightClassForFileOfPackage -> this.getContainingFile()!!
is KotlinLightClassForPackage -> this.getFiles().first() is KotlinLightClassForPackage -> this.files.first()
else -> throw IllegalStateException("Unknown light class without origin is referenced by IDE lazy resolve: $javaClass") else -> throw IllegalStateException("Unknown light class without origin is referenced by IDE lazy resolve: $javaClass")
} }
return element.getModuleInfo() return element.getModuleInfo()