Convert to Kotlin KotlinLightClassForPackage: j2k converter

This commit is contained in:
Nikolay Krasko
2015-02-06 15:29:59 +03:00
parent 082ac7a05f
commit a4e2c3b6fa
@@ -14,439 +14,324 @@
* limitations under the License. * limitations under the License.
*/ */
package org.jetbrains.kotlin.asJava; package org.jetbrains.kotlin.asJava
import com.google.common.collect.Sets; import com.google.common.collect.Sets
import com.intellij.openapi.components.ServiceManager; import com.intellij.openapi.components.ServiceManager
import com.intellij.openapi.project.Project; import com.intellij.openapi.project.Project
import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.Comparing
import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.*
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.javadoc.PsiDocComment; import com.intellij.psi.search.GlobalSearchScope
import com.intellij.psi.search.GlobalSearchScope; import com.intellij.psi.stubs.PsiClassHolderFileStub
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; import com.intellij.psi.util.PsiModificationTracker
import com.intellij.psi.util.PsiModificationTracker; import com.intellij.util.containers.SLRUCache
import com.intellij.util.containers.SLRUCache; import org.jetbrains.annotations.NonNls
import org.jetbrains.annotations.NonNls; import org.jetbrains.kotlin.idea.JetLanguage
import org.jetbrains.annotations.NotNull; import org.jetbrains.kotlin.load.kotlin.PackageClassUtils
import org.jetbrains.annotations.Nullable; import org.jetbrains.kotlin.name.FqName
import org.jetbrains.annotations.ReadOnly; import org.jetbrains.kotlin.psi.JetClassOrObject
import org.jetbrains.kotlin.idea.JetLanguage; import org.jetbrains.kotlin.psi.JetFile
import org.jetbrains.kotlin.load.kotlin.PackageClassUtils;
import org.jetbrains.kotlin.name.FqName;
import org.jetbrains.kotlin.psi.JetClassOrObject;
import org.jetbrains.kotlin.psi.JetFile;
import javax.swing.*; import javax.swing.*
import java.util.Collection;
import java.util.Collections;
import java.util.List;
public class KotlinLightClassForPackage extends KotlinWrappingLightClass implements JetJavaMirrorMarker { public class KotlinLightClassForPackage private(manager: PsiManager, private val packageFqName: FqName, private val searchScope: GlobalSearchScope, files: Collection<JetFile>) : KotlinWrappingLightClass(manager), JetJavaMirrorMarker {
public static class FileStubCache { public class FileStubCache(private val project: Project) {
@NotNull private class Key private(private val fqName: FqName, private val searchScope: GlobalSearchScope) {
public static FileStubCache getInstance(@NotNull Project project) {
return ServiceManager.getService(project, FileStubCache.class);
}
private static final class Key { override fun equals(o: Any?): Boolean {
private final FqName fqName; if (this == o) return true
private final GlobalSearchScope searchScope; if (o == null || javaClass != o.javaClass) return false
private Key( val key = o as Key
@NotNull FqName fqName,
@NotNull GlobalSearchScope searchScope if (fqName != key.fqName) return false
) { if (searchScope != key.searchScope) return false
this.fqName = fqName;
this.searchScope = searchScope; return true
} }
@Override override fun hashCode(): Int {
public boolean equals(Object o) { var result = fqName.hashCode()
if (this == o) return true; result = 31 * result + searchScope.hashCode()
if (o == null || getClass() != o.getClass()) return false; return result
Key key = (Key) o;
if (!fqName.equals(key.fqName)) return false;
if (!searchScope.equals(key.searchScope)) return false;
return true;
}
@Override
public int hashCode() {
int result = fqName.hashCode();
result = 31 * result + searchScope.hashCode();
return result;
} }
} }
private final class CacheData { private inner class CacheData {
private final SLRUCache<Key, CachedValue<KotlinPackageLightClassData>> cache = new SLRUCache<Key, CachedValue<KotlinPackageLightClassData>>(20, 30) { private val cache = object : SLRUCache<Key, CachedValue<KotlinPackageLightClassData>>(20, 30) {
@NotNull override fun createValue(key: Key): CachedValue<KotlinPackageLightClassData> {
@Override val stubProvider = KotlinJavaFileStubProvider.createForPackageClass(project, key.fqName, key.searchScope)
public CachedValue<KotlinPackageLightClassData> createValue(Key key) { return CachedValuesManager.getManager(project).createCachedValue<KotlinPackageLightClassData>(stubProvider, /*trackValue = */false)
KotlinJavaFileStubProvider<KotlinPackageLightClassData> stubProvider =
KotlinJavaFileStubProvider.createForPackageClass(project, key.fqName, key.searchScope);
return CachedValuesManager.getManager(project).createCachedValue(stubProvider, /*trackValue = */false);
} }
}; }
} }
private final Project project; private val cachedValue: CachedValue<CacheData>
private final CachedValue<CacheData> cachedValue;
public FileStubCache(@NotNull Project project) { {
this.project = project; this.cachedValue = CachedValuesManager.getManager(project).createCachedValue<CacheData>(object : CachedValueProvider<CacheData> {
this.cachedValue = CachedValuesManager.getManager(project).createCachedValue( override fun compute(): CachedValueProvider.Result<CacheData>? {
new CachedValueProvider<CacheData>() { return CachedValueProvider.Result.create<CacheData>(CacheData(), PsiModificationTracker.OUT_OF_CODE_BLOCK_MODIFICATION_COUNT)
@Nullable }
@Override }, /*trackValue = */ false)
public Result<CacheData> compute() {
return Result.create(new CacheData(), PsiModificationTracker.OUT_OF_CODE_BLOCK_MODIFICATION_COUNT);
}
},
/*trackValue = */ false
);
} }
@NotNull public fun get(qualifiedName: FqName, searchScope: GlobalSearchScope): CachedValue<KotlinPackageLightClassData> {
public CachedValue<KotlinPackageLightClassData> get(
@NotNull FqName qualifiedName,
@NotNull GlobalSearchScope searchScope
) {
synchronized (cachedValue) { synchronized (cachedValue) {
return cachedValue.getValue().cache.get(new Key(qualifiedName, searchScope)); return cachedValue.getValue().cache.get(Key(qualifiedName, searchScope))
}
}
class object {
public fun getInstance(project: Project): FileStubCache {
return ServiceManager.getService<FileStubCache>(project, javaClass<FileStubCache>())
} }
} }
} }
private final FqName packageFqName; private val packageClassFqName: FqName // derived from packageFqName
private final FqName packageClassFqName; // derived from packageFqName public val files: Collection<JetFile>
private final GlobalSearchScope searchScope; private val hashCode: Int
private final Collection<JetFile> files; private val lightClassDataCache: CachedValue<KotlinPackageLightClassData>
private final int hashCode; private val modifierList: PsiModifierList
private final CachedValue<KotlinPackageLightClassData> lightClassDataCache; private val implementsList: LightEmptyImplementsList
private final PsiModifierList modifierList; private val packageClsFile: ClsFileImpl
private final LightEmptyImplementsList implementsList;
private final ClsFileImpl packageClsFile;
private KotlinLightClassForPackage( {
@NotNull PsiManager manager, this.modifierList = LightModifierList(manager, JetLanguage.INSTANCE, PsiModifier.PUBLIC, PsiModifier.FINAL)
@NotNull FqName packageFqName, this.implementsList = LightEmptyImplementsList(manager)
@NotNull GlobalSearchScope searchScope, this.packageClassFqName = PackageClassUtils.getPackageClassFqName(packageFqName)
@NotNull Collection<JetFile> files assert(!files.isEmpty()) { "No files for package " + packageFqName }
) { this.files = Sets.newHashSet<JetFile>(files) // needed for hashCode
super(manager); this.hashCode = computeHashCode()
this.modifierList = new LightModifierList(manager, JetLanguage.INSTANCE, PsiModifier.PUBLIC, PsiModifier.FINAL); this.lightClassDataCache = FileStubCache.getInstance(getProject()).get(packageFqName, searchScope)
this.implementsList = new LightEmptyImplementsList(manager);
this.packageFqName = packageFqName;
this.packageClassFqName = PackageClassUtils.getPackageClassFqName(packageFqName);
this.searchScope = searchScope;
assert !files.isEmpty() : "No files for package " + packageFqName;
this.files = Sets.newHashSet(files); // needed for hashCode
this.hashCode = computeHashCode();
this.lightClassDataCache = FileStubCache.getInstance(getProject()).get(packageFqName, searchScope);
VirtualFile virtualFile = KotlinJavaFileStubProvider.getRepresentativeVirtualFile(files); val virtualFile = KotlinJavaFileStubProvider.getRepresentativeVirtualFile(files)
packageClsFile = new ClsFileImpl(new ClassFileViewProvider(PsiManager.getInstance(getProject()), virtualFile)) { packageClsFile = object : ClsFileImpl(ClassFileViewProvider(PsiManager.getInstance(getProject()), virtualFile)) {
@NotNull override fun getStub(): PsiClassHolderFileStub<PsiFile> {
@Override return (getDelegate().getContainingFile() as ClsFileImpl).getStub()
public PsiClassHolderFileStub getStub() {
return ((ClsFileImpl) getDelegate().getContainingFile()).getStub();
} }
@NotNull override fun getPackageName(): String {
@Override return this@KotlinLightClassForPackage.packageFqName.asString()
public String getPackageName() {
return KotlinLightClassForPackage.this.packageFqName.asString();
} }
};
packageClsFile.setPhysical(false);
}
@Nullable
public static KotlinLightClassForPackage create(
@NotNull PsiManager manager,
@NotNull FqName qualifiedName,
@NotNull GlobalSearchScope searchScope,
@NotNull Collection<JetFile> files // this is redundant, but computing it multiple times is costly
) {
for (JetFile file : files) {
if (LightClassUtil.belongsToKotlinBuiltIns(file)) return null;
} }
return new KotlinLightClassForPackage(manager, qualifiedName, searchScope, files); packageClsFile.setPhysical(false)
} }
private static boolean allValid(Collection<JetFile> files) { override fun getOrigin(): JetClassOrObject? {
for (JetFile file : files) { return null
if (!file.isValid()) return false;
}
return true;
} }
@Nullable override fun getModifierList(): PsiModifierList? {
@Override return modifierList
public JetClassOrObject getOrigin() {
return null;
} }
@Nullable override fun hasModifierProperty(NonNls name: String): Boolean {
@Override return modifierList.hasModifierProperty(name)
public PsiModifierList getModifierList() {
return modifierList;
} }
@Override override fun isDeprecated(): Boolean {
public boolean hasModifierProperty(@NonNls @NotNull String name) { return false
return modifierList.hasModifierProperty(name);
} }
@Override override fun isInterface(): Boolean {
public boolean isDeprecated() { return false
return false;
} }
@Override override fun isAnnotationType(): Boolean {
public boolean isInterface() { return false
return false;
} }
@Override override fun isEnum(): Boolean {
public boolean isAnnotationType() { return false
return false;
} }
@Override override fun getContainingClass(): PsiClass? {
public boolean isEnum() { return null
return false;
} }
@Nullable override fun getContainingFile(): PsiFile {
@Override return packageClsFile
public PsiClass getContainingClass() {
return null;
} }
@Override override fun hasTypeParameters(): Boolean {
public PsiFile getContainingFile() { return false
return packageClsFile;
} }
@Override override fun getTypeParameters(): Array<PsiTypeParameter> {
public boolean hasTypeParameters() { return PsiTypeParameter.EMPTY_ARRAY
return false;
} }
@NotNull override fun getTypeParameterList(): PsiTypeParameterList? {
@Override return null
public PsiTypeParameter[] getTypeParameters() {
return PsiTypeParameter.EMPTY_ARRAY;
} }
@Nullable override fun getDocComment(): PsiDocComment? {
@Override return null
public PsiTypeParameterList getTypeParameterList() {
return null;
} }
@Nullable override fun getImplementsList(): PsiReferenceList? {
@Override return implementsList
public PsiDocComment getDocComment() {
return null;
} }
@Nullable override fun getImplementsListTypes(): Array<PsiClassType> {
@Override return PsiClassType.EMPTY_ARRAY
public PsiReferenceList getImplementsList() {
return implementsList;
} }
@NotNull override fun getExtendsList(): PsiReferenceList? {
@Override
public PsiClassType[] getImplementsListTypes() {
return PsiClassType.EMPTY_ARRAY;
}
@Nullable
@Override
public PsiReferenceList getExtendsList() {
// TODO: Find a way to return just Object // TODO: Find a way to return just Object
return super.getExtendsList(); return super.getExtendsList()
} }
@NotNull override fun getExtendsListTypes(): Array<PsiClassType> {
@Override
public PsiClassType[] getExtendsListTypes() {
// TODO see getExtendsList() // TODO see getExtendsList()
return super.getExtendsListTypes(); return super.getExtendsListTypes()
} }
@Nullable override fun getSuperClass(): PsiClass? {
@Override
public PsiClass getSuperClass() {
// TODO see getExtendsList() // TODO see getExtendsList()
return super.getSuperClass(); return super.getSuperClass()
} }
@NotNull override fun getSupers(): Array<PsiClass> {
@Override
public PsiClass[] getSupers() {
// TODO see getExtendsList() // TODO see getExtendsList()
return super.getSupers(); return super.getSupers()
} }
@NotNull override fun getSuperTypes(): Array<PsiClassType> {
@Override
public PsiClassType[] getSuperTypes() {
// TODO see getExtendsList() // TODO see getExtendsList()
return super.getSuperTypes(); return super.getSuperTypes()
} }
@Override override fun getInterfaces(): Array<PsiClass> {
public PsiClass[] getInterfaces() { return PsiClass.EMPTY_ARRAY
return PsiClass.EMPTY_ARRAY;
} }
@NotNull override fun getInnerClasses(): Array<PsiClass> {
@Override return PsiClass.EMPTY_ARRAY
public PsiClass[] getInnerClasses() {
return PsiClass.EMPTY_ARRAY;
} }
@NotNull override fun getOwnInnerClasses(): List<PsiClass> {
@Override return listOf()
public List<PsiClass> getOwnInnerClasses() {
return Collections.emptyList();
} }
@NotNull override fun getAllInnerClasses(): Array<PsiClass> {
@Override return PsiClass.EMPTY_ARRAY
public PsiClass[] getAllInnerClasses() {
return PsiClass.EMPTY_ARRAY;
} }
@NotNull override fun getInitializers(): Array<PsiClassInitializer> {
@Override return PsiClassInitializer.EMPTY_ARRAY
public PsiClassInitializer[] getInitializers() {
return PsiClassInitializer.EMPTY_ARRAY;
} }
@Nullable override fun findInnerClassByName(NonNls name: String, checkBases: Boolean): PsiClass? {
@Override return null
public PsiClass findInnerClassByName(@NonNls String name, boolean checkBases) {
return null;
} }
@NotNull override fun getFqName(): FqName {
@Override return packageClassFqName
public FqName getFqName() {
return packageClassFqName;
} }
@Nullable override fun getName(): String? {
@Override return packageClassFqName.shortName().asString()
public String getName() {
return packageClassFqName.shortName().asString();
} }
@Nullable override fun getQualifiedName(): String? {
@Override return packageClassFqName.asString()
public String getQualifiedName() {
return packageClassFqName.asString();
} }
@Override override fun isValid(): Boolean {
public boolean isValid() { return allValid(files)
return allValid(files);
} }
@NotNull override fun copy(): PsiElement {
@Override return KotlinLightClassForPackage(getManager(), packageFqName, searchScope, files)
public PsiElement copy() {
return new KotlinLightClassForPackage(getManager(), packageFqName, searchScope, files);
} }
@NotNull override fun getDelegate(): PsiClass {
@Override val psiClass = LightClassUtil.findClass(packageClassFqName, lightClassDataCache.getValue().javaFileStub)
public PsiClass getDelegate() {
PsiClass psiClass = LightClassUtil.findClass(packageClassFqName, lightClassDataCache.getValue().getJavaFileStub());
if (psiClass == null) { if (psiClass == null) {
throw new IllegalStateException("Package class was not found " + packageFqName); throw IllegalStateException("Package class was not found " + packageFqName)
} }
return psiClass; return psiClass
} }
@NotNull override fun getNavigationElement(): PsiElement {
@Override return files.iterator().next()
public PsiElement getNavigationElement() {
return files.iterator().next();
} }
@Override override fun isEquivalentTo(another: PsiElement?): Boolean {
public boolean isEquivalentTo(PsiElement another) { return another is PsiClass && Comparing.equal((another as PsiClass).getQualifiedName(), getQualifiedName())
return another instanceof PsiClass && Comparing.equal(((PsiClass) another).getQualifiedName(), getQualifiedName());
} }
@Override override fun getElementIcon(flags: Int): Icon? {
public Icon getElementIcon(int flags) { throw UnsupportedOperationException("This should be done byt JetIconProvider")
throw new UnsupportedOperationException("This should be done byt JetIconProvider");
} }
@Override override fun hashCode(): Int {
public int hashCode() { return hashCode
return hashCode;
} }
private int computeHashCode() { private fun computeHashCode(): Int {
int result = getManager().hashCode(); var result = getManager().hashCode()
result = 31 * result + files.hashCode(); result = 31 * result + files.hashCode()
result = 31 * result + packageFqName.hashCode(); result = 31 * result + packageFqName.hashCode()
return result; return result
} }
@Override override fun equals(obj: Any?): Boolean {
public boolean equals(Object obj) { if (this == obj) return true
if (this == obj) return true; if (obj == null || javaClass != obj.javaClass) {
if (obj == null || getClass() != obj.getClass()) { return false
return false;
} }
KotlinLightClassForPackage lightClass = (KotlinLightClassForPackage) obj; val lightClass = obj as KotlinLightClassForPackage
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
if (!files.equals(lightClass.files)) return false; if (files != lightClass.files) return false
if (!packageFqName.equals(lightClass.packageFqName)) return false; if (packageFqName != lightClass.packageFqName) return false
return true; return true
} }
@Override override fun toString(): String {
public String toString() {
try { try {
return KotlinLightClassForPackage.class.getSimpleName() + ":" + getQualifiedName(); return javaClass<KotlinLightClassForPackage>().getSimpleName() + ":" + getQualifiedName()
} }
catch (Throwable e) { catch (e: Throwable) {
return KotlinLightClassForPackage.class.getSimpleName() + ":" + e.toString(); return javaClass<KotlinLightClassForPackage>().getSimpleName() + ":" + e.toString()
} }
} }
//NOTE: this is only needed to compute plugin module info class object {
@NotNull
@ReadOnly public fun create(manager: PsiManager, qualifiedName: FqName, searchScope: GlobalSearchScope, files: Collection<JetFile> // this is redundant, but computing it multiple times is costly
public final Collection<JetFile> getFiles() { ): KotlinLightClassForPackage? {
return files; for (file in files) {
if (LightClassUtil.belongsToKotlinBuiltIns(file)) return null
}
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