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