From f2ff752dd1e6480a5902c631e0a1929b1e2227cf Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Tue, 18 Aug 2015 20:06:38 +0200 Subject: [PATCH] KotlinLightClassForExplicitDeclaration: J2K --- .../CliLightClassGenerationSupport.java | 2 +- ...tlinLightClassForAnonymousDeclaration.java | 4 +- .../KotlinLightClassForExplicitDeclaration.kt | 721 ++++++++---------- .../IDELightClassGenerationSupport.java | 2 +- 4 files changed, 309 insertions(+), 420 deletions(-) diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/CliLightClassGenerationSupport.java b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/CliLightClassGenerationSupport.java index 0a4025a1668..7d533583aaa 100644 --- a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/CliLightClassGenerationSupport.java +++ b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/CliLightClassGenerationSupport.java @@ -189,7 +189,7 @@ public class CliLightClassGenerationSupport extends LightClassGenerationSupport @Nullable @Override public PsiClass getPsiClass(@NotNull JetClassOrObject classOrObject) { - return KotlinLightClassForExplicitDeclaration.create(psiManager, classOrObject); + return KotlinLightClassForExplicitDeclaration.Companion.create(psiManager, classOrObject); } @NotNull diff --git a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/KotlinLightClassForAnonymousDeclaration.java b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/KotlinLightClassForAnonymousDeclaration.java index 3c8126bd841..73c9f1d6dc4 100644 --- a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/KotlinLightClassForAnonymousDeclaration.java +++ b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/KotlinLightClassForAnonymousDeclaration.java @@ -44,7 +44,7 @@ class KotlinLightClassForAnonymousDeclaration extends KotlinLightClassForExplici @NotNull @Override public PsiJavaCodeReferenceElement getBaseClassReference() { - return JavaPsiFacade.getElementFactory(classOrObject.getProject()).createReferenceElementByType(getBaseClassType()); + return JavaPsiFacade.getElementFactory(getClassOrObject().getProject()).createReferenceElementByType(getBaseClassType()); } @NotNull @@ -85,7 +85,7 @@ class KotlinLightClassForAnonymousDeclaration extends KotlinLightClassForExplici } if (type == null) { - Project project = classOrObject.getProject(); + Project project = getClassOrObject().getProject(); type = PsiType.getJavaLangObject(PsiManager.getInstance(project), GlobalSearchScope.allScope(project)); } diff --git a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/KotlinLightClassForExplicitDeclaration.kt b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/KotlinLightClassForExplicitDeclaration.kt index b05fd81edae..0cee8a671a3 100644 --- a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/KotlinLightClassForExplicitDeclaration.kt +++ b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/KotlinLightClassForExplicitDeclaration.kt @@ -14,593 +14,482 @@ * limitations under the License. */ -package org.jetbrains.kotlin.asJava; +package org.jetbrains.kotlin.asJava -import com.google.common.collect.Lists; -import com.google.common.collect.Sets; -import com.intellij.openapi.util.Comparing; -import com.intellij.openapi.util.Key; -import com.intellij.openapi.util.NullableLazyValue; -import com.intellij.openapi.util.Pair; -import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.psi.*; -import com.intellij.psi.PsiPackage; -import com.intellij.psi.impl.compiled.ClsFileImpl; -import com.intellij.psi.impl.java.stubs.PsiJavaFileStub; -import com.intellij.psi.impl.light.LightClass; -import com.intellij.psi.impl.light.LightMethod; -import com.intellij.psi.scope.PsiScopeProcessor; -import com.intellij.psi.search.SearchScope; -import com.intellij.psi.stubs.PsiClassHolderFileStub; -import com.intellij.psi.util.CachedValue; -import com.intellij.psi.util.CachedValuesManager; -import com.intellij.psi.util.PsiTreeUtil; -import com.intellij.util.ArrayUtil; -import com.intellij.util.IncorrectOperationException; -import kotlin.KotlinPackage; -import kotlin.jvm.functions.Function1; -import org.jetbrains.annotations.NonNls; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.jetbrains.kotlin.builtins.KotlinBuiltIns; -import org.jetbrains.kotlin.codegen.binding.PsiCodegenPredictor; -import org.jetbrains.kotlin.descriptors.ClassDescriptor; -import org.jetbrains.kotlin.descriptors.ClassifierDescriptor; -import org.jetbrains.kotlin.idea.JetLanguage; -import org.jetbrains.kotlin.lexer.JetModifierKeywordToken; -import org.jetbrains.kotlin.name.FqName; -import org.jetbrains.kotlin.psi.*; -import org.jetbrains.kotlin.resolve.DescriptorUtils; -import org.jetbrains.kotlin.resolve.jvm.JvmClassName; -import org.jetbrains.kotlin.types.JetType; +import com.google.common.collect.Lists +import com.google.common.collect.Sets +import com.intellij.openapi.util.Comparing +import com.intellij.openapi.util.Key +import com.intellij.openapi.util.NullableLazyValue +import com.intellij.openapi.util.Pair +import com.intellij.psi.* +import com.intellij.psi.impl.compiled.ClsFileImpl +import com.intellij.psi.impl.java.stubs.PsiJavaFileStub +import com.intellij.psi.impl.light.LightClass +import com.intellij.psi.impl.light.LightMethod +import com.intellij.psi.scope.PsiScopeProcessor +import com.intellij.psi.search.SearchScope +import com.intellij.psi.stubs.PsiClassHolderFileStub +import com.intellij.psi.util.CachedValue +import com.intellij.psi.util.CachedValuesManager +import com.intellij.psi.util.PsiTreeUtil +import com.intellij.util.ArrayUtil +import com.intellij.util.IncorrectOperationException +import org.jetbrains.annotations.NonNls +import org.jetbrains.kotlin.builtins.KotlinBuiltIns +import org.jetbrains.kotlin.codegen.binding.PsiCodegenPredictor +import org.jetbrains.kotlin.descriptors.ClassDescriptor +import org.jetbrains.kotlin.idea.JetLanguage +import org.jetbrains.kotlin.lexer.JetTokens.* +import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.psi.* +import org.jetbrains.kotlin.resolve.DescriptorUtils +import org.jetbrains.kotlin.resolve.jvm.JvmClassName +import javax.swing.Icon -import javax.swing.*; -import java.util.Collection; -import java.util.List; +public open class KotlinLightClassForExplicitDeclaration( + manager: PsiManager, + private val classFqName: FqName // FqName of (possibly inner) class + , + protected val classOrObject: JetClassOrObject) : KotlinWrappingLightClass(manager), JetJavaMirrorMarker { + private var delegate: PsiClass? = null -import static org.jetbrains.kotlin.lexer.JetTokens.*; - -public class KotlinLightClassForExplicitDeclaration extends KotlinWrappingLightClass implements JetJavaMirrorMarker { - private final static Key> JAVA_API_STUB = Key.create("JAVA_API_STUB"); - - @Nullable - public static KotlinLightClassForExplicitDeclaration create(@NotNull PsiManager manager, @NotNull JetClassOrObject classOrObject) { - if (LightClassUtil.belongsToKotlinBuiltIns(classOrObject.getContainingJetFile())) { - return null; - } - - FqName fqName = predictFqName(classOrObject); - if (fqName == null) return null; - - if (classOrObject instanceof JetObjectDeclaration && ((JetObjectDeclaration) classOrObject).isObjectLiteral()) { - return new KotlinLightClassForAnonymousDeclaration(manager, fqName, classOrObject); - } - return new KotlinLightClassForExplicitDeclaration(manager, fqName, classOrObject); - } - - @Nullable - private static FqName predictFqName(@NotNull JetClassOrObject classOrObject) { - if (classOrObject.isLocal()) { - LightClassDataForKotlinClass data = getLightClassDataExactly(classOrObject); - return data == null ? null : data.getJvmQualifiedName(); - } - String internalName = PsiCodegenPredictor.getPredefinedJvmInternalName(classOrObject); - return internalName == null ? null : JvmClassName.byInternalName(internalName).getFqNameForClassNameWithoutDollars(); - } - - private final FqName classFqName; // FqName of (possibly inner) class - protected final JetClassOrObject classOrObject; - private PsiClass delegate; - - private final NullableLazyValue parent = new NullableLazyValue() { - @Nullable - @Override - protected PsiElement compute() { + private val parent = object : NullableLazyValue() { + override fun compute(): PsiElement? { if (classOrObject.isLocal()) { //noinspection unchecked - PsiElement declaration = JetPsiUtil.getTopmostParentOfTypes( + var declaration: PsiElement? = JetPsiUtil.getTopmostParentOfTypes( classOrObject, - JetNamedFunction.class, JetConstructor.class, JetProperty.class, JetClassInitializer.class, JetParameter.class - ); + javaClass(), javaClass>(), javaClass(), javaClass(), javaClass()) - if (declaration instanceof JetParameter) { - declaration = PsiTreeUtil.getParentOfType(declaration, JetNamedDeclaration.class); + if (declaration is JetParameter) { + declaration = PsiTreeUtil.getParentOfType(declaration, javaClass()) } - if (declaration instanceof JetFunction) { - JetFunction function = (JetFunction) declaration; - return getParentByPsiMethod(LightClassUtil.getLightClassMethod(function), function.getName(), false); + if (declaration is JetFunction) { + return getParentByPsiMethod(LightClassUtil.getLightClassMethod(declaration), declaration.name, false) } // Represent the property as a fake method with the same name - if (declaration instanceof JetProperty) { - JetProperty property = (JetProperty) declaration; - return getParentByPsiMethod(LightClassUtil.getLightClassPropertyMethods(property).getGetter(), property.getName(), true); + if (declaration is JetProperty) { + return getParentByPsiMethod(LightClassUtil.getLightClassPropertyMethods(declaration).getter, declaration.name, true) } - if (declaration instanceof JetClassInitializer) { - PsiElement parent = declaration.getParent(); - PsiElement grandparent = parent.getParent(); + if (declaration is JetClassInitializer) { + val parent = declaration.parent + val grandparent = parent.parent - if (parent instanceof JetClassBody && grandparent instanceof JetClassOrObject) { - return LightClassUtil.getPsiClass((JetClassOrObject) grandparent); + if (parent is JetClassBody && grandparent is JetClassOrObject) { + return LightClassUtil.getPsiClass(grandparent) } } - if (declaration instanceof JetClass) { - return LightClassUtil.getPsiClass((JetClass) declaration); + if (declaration is JetClass) { + return LightClassUtil.getPsiClass(declaration) } } - return classOrObject.getParent() == classOrObject.getContainingFile() ? getContainingFile() : getContainingClass(); + return if (classOrObject.parent === classOrObject.containingFile) containingFile else containingClass } - private PsiElement getParentByPsiMethod(PsiMethod method, final String name, boolean forceMethodWrapping) { - if (method == null || name == null) return null; + private fun getParentByPsiMethod(method: PsiMethod?, name: String?, forceMethodWrapping: Boolean): PsiElement? { + if (method == null || name == null) return null - PsiClass containingClass = method.getContainingClass(); - if (containingClass == null) return null; + var containingClass: com.intellij.psi.PsiClass? = method.containingClass ?: return null - final String currentFileName = classOrObject.getContainingFile().getName(); + val currentFileName = classOrObject.containingFile.name - boolean createWrapper = forceMethodWrapping; + var createWrapper = forceMethodWrapping // Use PsiClass wrapper instead of package light class to avoid names like "FooPackage" in Type Hierarchy and related views - if (containingClass instanceof KotlinLightClassForPackage) { - containingClass = new LightClass(containingClass, JetLanguage.INSTANCE) { - @Nullable - @Override - public String getName() { - return currentFileName; + if (containingClass is KotlinLightClassForPackage) { + containingClass = object : LightClass(containingClass as KotlinLightClassForPackage, JetLanguage.INSTANCE) { + override fun getName(): String? { + return currentFileName } - }; - createWrapper = true; + } + createWrapper = true } if (createWrapper) { - return new LightMethod(myManager, method, containingClass, JetLanguage.INSTANCE) { - @Override - public PsiElement getParent() { - return getContainingClass(); + return object : LightMethod(myManager, method, containingClass!!, JetLanguage.INSTANCE) { + override fun getParent(): PsiElement { + return getContainingClass()!! } - @NotNull - @Override - public String getName() { - return name; + override fun getName(): String { + return name } - }; + } } - return method; + return method } - }; + } - @Nullable - private PsiModifierList modifierList; + private var modifierList: PsiModifierList? = null - private final NullableLazyValue typeParameterList = new NullableLazyValue() { - @Nullable - @Override - protected PsiTypeParameterList compute() { - return LightClassUtil.buildLightTypeParameterList(KotlinLightClassForExplicitDeclaration.this, classOrObject); + private val typeParameterList = object : NullableLazyValue() { + override fun compute(): PsiTypeParameterList? { + return LightClassUtil.buildLightTypeParameterList(this@KotlinLightClassForExplicitDeclaration, classOrObject) } - }; - - KotlinLightClassForExplicitDeclaration( - @NotNull PsiManager manager, - @NotNull FqName name, - @NotNull JetClassOrObject classOrObject - ) { - super(manager); - this.classFqName = name; - this.classOrObject = classOrObject; } - @Override - @NotNull - public JetClassOrObject getOrigin() { - return classOrObject; + override fun getOrigin(): JetClassOrObject { + return classOrObject } - @NotNull - @Override - public FqName getFqName() { - return classFqName; + override fun getFqName(): FqName { + return classFqName } - @NotNull - @Override - public PsiElement copy() { - return new KotlinLightClassForExplicitDeclaration(getManager(), classFqName, (JetClassOrObject) classOrObject.copy()); + override fun copy(): PsiElement { + return KotlinLightClassForExplicitDeclaration(manager, classFqName, classOrObject.copy() as JetClassOrObject) } - @NotNull - @Override - public PsiClass getDelegate() { + override fun getDelegate(): PsiClass { if (delegate == null) { - PsiJavaFileStub javaFileStub = getJavaFileStub(); + val javaFileStub = getJavaFileStub() - PsiClass psiClass = LightClassUtil.findClass(classFqName, javaFileStub); + val psiClass = LightClassUtil.findClass(classFqName, javaFileStub) if (psiClass == null) { - JetClassOrObject outermostClassOrObject = getOutermostClassOrObject(classOrObject); - throw new IllegalStateException("Class was not found " + classFqName + "\n" + - "in " + outermostClassOrObject.getContainingFile().getText() + "\n" + - "stub: \n" + javaFileStub.getPsi().getText()); + val outermostClassOrObject = getOutermostClassOrObject(classOrObject) + throw IllegalStateException("Class was not found " + classFqName + "\n" + "in " + outermostClassOrObject.containingFile.text + "\n" + "stub: \n" + javaFileStub.psi.text) } - delegate = psiClass; + delegate = psiClass } - return delegate; + return delegate!! } - @NotNull - private PsiJavaFileStub getJavaFileStub() { - return getLightClassData().getJavaFileStub(); + private fun getJavaFileStub(): PsiJavaFileStub { + return getLightClassData().javaFileStub } - @Nullable - protected final ClassDescriptor getDescriptor() { - LightClassDataForKotlinClass data = getLightClassDataExactly(classOrObject); - return data != null ? data.getDescriptor() : null; + protected fun getDescriptor(): ClassDescriptor? { + val data = getLightClassDataExactly(classOrObject) + return data?.descriptor } - @NotNull - private OutermostKotlinClassLightClassData getLightClassData() { - return getLightClassData(classOrObject); + private fun getLightClassData(): OutermostKotlinClassLightClassData { + return getLightClassData(classOrObject) } - @NotNull - public static OutermostKotlinClassLightClassData getLightClassData(@NotNull JetClassOrObject classOrObject) { - JetClassOrObject outermostClassOrObject = getOutermostClassOrObject(classOrObject); - return CachedValuesManager.getManager(classOrObject.getProject()).getCachedValue( - outermostClassOrObject, - JAVA_API_STUB, - KotlinJavaFileStubProvider.createForDeclaredClass(outermostClassOrObject), - /*trackValue = */false - ); - } - - @Nullable - private static LightClassDataForKotlinClass getLightClassDataExactly(JetClassOrObject classOrObject) { - OutermostKotlinClassLightClassData data = getLightClassData(classOrObject); - return data.getClassOrObject().equals(classOrObject) ? data : data.getAllInnerClasses().get(classOrObject); - } - - @NotNull - private static JetClassOrObject getOutermostClassOrObject(@NotNull JetClassOrObject classOrObject) { - JetClassOrObject outermostClass = JetPsiUtil.getOutermostClassOrObject(classOrObject); - if (outermostClass == null) { - throw new IllegalStateException("Attempt to build a light class for a local class: " + classOrObject.getText()); - } - else { - return outermostClass; - } - } - - private final NullableLazyValue _containingFile = new NullableLazyValue() { - @Nullable - @Override - protected PsiFile compute() { - VirtualFile virtualFile = classOrObject.getContainingFile().getVirtualFile(); - assert virtualFile != null : "No virtual file for " + classOrObject.getText(); - return new ClsFileImpl(new ClassFileViewProvider(getManager(), virtualFile)) { - @NotNull - @Override - public String getPackageName() { - return classOrObject.getContainingJetFile().getPackageFqName().asString(); + private val _containingFile = object : NullableLazyValue() { + override fun compute(): PsiFile? { + val virtualFile = classOrObject.containingFile.virtualFile + assert(virtualFile != null) { "No virtual file for " + classOrObject.text } + return object : ClsFileImpl(ClassFileViewProvider(getManager(), virtualFile)) { + override fun getPackageName(): String { + return classOrObject.getContainingJetFile().packageFqName.asString() } - @NotNull - @Override - public PsiClassHolderFileStub getStub() { - return getJavaFileStub(); + override fun getStub(): PsiClassHolderFileStub { + return getJavaFileStub() } - @SuppressWarnings("Contract") - @Override - public boolean processDeclarations( - @NotNull PsiScopeProcessor processor, - @NotNull ResolveState state, - PsiElement lastParent, - @NotNull PsiElement place - ) { - if (!super.processDeclarations(processor, state, lastParent, place)) return false; + SuppressWarnings("Contract") + override fun processDeclarations( + processor: PsiScopeProcessor, + state: ResolveState, + lastParent: PsiElement?, + place: PsiElement): Boolean { + if (!super.processDeclarations(processor, state, lastParent, place)) return false // We have to explicitly process package declarations if current file belongs to default package // so that Java resolve can find classes located in that package - String packageName = getPackageName(); - if (!packageName.isEmpty()) return true; + val packageName = packageName + if (!packageName.isEmpty()) return true - PsiPackage aPackage = JavaPsiFacade.getInstance(myManager.getProject()).findPackage(packageName); - if (aPackage != null && !aPackage.processDeclarations(processor, state, null, place)) return false; + val aPackage = JavaPsiFacade.getInstance(myManager.project).findPackage(packageName) + if (aPackage != null && !aPackage.processDeclarations(processor, state, null, place)) return false - return true; + return true } - }; + } } - }; - - @Override - public PsiFile getContainingFile() { - return _containingFile.getValue(); } - @NotNull - @Override - public PsiElement getNavigationElement() { - return classOrObject; + override fun getContainingFile(): PsiFile? { + return _containingFile.value } - @Override - public boolean isEquivalentTo(PsiElement another) { - return another instanceof PsiClass && Comparing.equal(((PsiClass) another).getQualifiedName(), getQualifiedName()); + override fun getNavigationElement(): PsiElement { + return classOrObject } - @Override - public Icon getElementIcon(int flags) { - throw new UnsupportedOperationException("This should be done byt JetIconProvider"); + override fun isEquivalentTo(another: PsiElement?): Boolean { + return another is PsiClass && Comparing.equal(another.getQualifiedName(), qualifiedName) } - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - - KotlinLightClassForExplicitDeclaration aClass = (KotlinLightClassForExplicitDeclaration) o; - - if (!classFqName.equals(aClass.classFqName)) return false; - - return true; + override fun getElementIcon(flags: Int): Icon? { + throw UnsupportedOperationException("This should be done byt JetIconProvider") } - @Override - public int hashCode() { - return classFqName.hashCode(); + override fun equals(o: Any?): Boolean { + if (this === o) return true + if (o == null || javaClass != o.javaClass) return false + + val aClass = o as KotlinLightClassForExplicitDeclaration + + if (classFqName != aClass.classFqName) return false + + return true } - @Nullable - @Override - public PsiClass getContainingClass() { - if (classOrObject.getParent() == classOrObject.getContainingFile()) return null; - return super.getContainingClass(); + override fun hashCode(): Int { + return classFqName.hashCode() } - @Nullable - @Override - public PsiElement getParent() { - return parent.getValue(); + override fun getContainingClass(): PsiClass? { + if (classOrObject.parent === classOrObject.containingFile) return null + return super.getContainingClass() } - @Override - public PsiElement getContext() { - return getParent(); + override fun getParent(): PsiElement? { + return parent.value } - @Nullable - @Override - public PsiTypeParameterList getTypeParameterList() { - return typeParameterList.getValue(); + override fun getContext(): PsiElement? { + return getParent() } - @NotNull - @Override - public PsiTypeParameter[] getTypeParameters() { - PsiTypeParameterList typeParameterList = getTypeParameterList(); - return typeParameterList == null ? PsiTypeParameter.EMPTY_ARRAY : typeParameterList.getTypeParameters(); + override fun getTypeParameterList(): PsiTypeParameterList? { + return typeParameterList.value } - @Nullable - @Override - public String getName() { - return classFqName.shortName().asString(); + override fun getTypeParameters(): Array { + val typeParameterList = getTypeParameterList() + return if (typeParameterList == null) PsiTypeParameter.EMPTY_ARRAY else typeParameterList.typeParameters } - @Nullable - @Override - public String getQualifiedName() { - return classFqName.asString(); + override fun getName(): String? { + return classFqName.shortName().asString() } - @NotNull - @Override - public PsiModifierList getModifierList() { + override fun getQualifiedName(): String? { + return classFqName.asString() + } + + override fun getModifierList(): PsiModifierList { if (modifierList == null) { - modifierList = new KotlinLightModifierList(this.getManager(), computeModifiers()) { - @Override - public PsiAnnotationOwner getDelegate() { - return KotlinLightClassForExplicitDeclaration.this.getDelegate().getModifierList(); + modifierList = object : KotlinLightModifierList(this.manager, computeModifiers()) { + override fun getDelegate(): PsiModifierList { + return this@KotlinLightClassForExplicitDeclaration.getDelegate().modifierList!! } - }; + } } - return modifierList; + return modifierList!! } - @NotNull - private String[] computeModifiers() { - Collection psiModifiers = Sets.newHashSet(); + private fun computeModifiers(): Array { + val psiModifiers = Sets.newHashSet() // PUBLIC, PROTECTED, PRIVATE, ABSTRACT, FINAL //noinspection unchecked - List> jetTokenToPsiModifier = Lists.newArrayList( + val jetTokenToPsiModifier = Lists.newArrayList( Pair.create(PUBLIC_KEYWORD, PsiModifier.PUBLIC), Pair.create(INTERNAL_KEYWORD, PsiModifier.PUBLIC), Pair.create(PROTECTED_KEYWORD, PsiModifier.PROTECTED), - Pair.create(FINAL_KEYWORD, PsiModifier.FINAL)); + Pair.create(FINAL_KEYWORD, PsiModifier.FINAL)) - for (Pair tokenAndModifier : jetTokenToPsiModifier) { + for (tokenAndModifier in jetTokenToPsiModifier) { if (classOrObject.hasModifier(tokenAndModifier.first)) { - psiModifiers.add(tokenAndModifier.second); + psiModifiers.add(tokenAndModifier.second) } } if (classOrObject.hasModifier(PRIVATE_KEYWORD)) { // Top-level private class has PUBLIC visibility in Java // Nested private class has PRIVATE visibility - psiModifiers.add(classOrObject.isTopLevel() ? PsiModifier.PUBLIC : PsiModifier.PRIVATE); + psiModifiers.add(if (classOrObject.isTopLevel()) PsiModifier.PUBLIC else PsiModifier.PRIVATE) } if (!psiModifiers.contains(PsiModifier.PRIVATE) && !psiModifiers.contains(PsiModifier.PROTECTED)) { - psiModifiers.add(PsiModifier.PUBLIC); // For internal (default) visibility + psiModifiers.add(PsiModifier.PUBLIC) // For internal (default) visibility } // FINAL if (isAbstract(classOrObject)) { - psiModifiers.add(PsiModifier.ABSTRACT); + psiModifiers.add(PsiModifier.ABSTRACT) } - else if (!(classOrObject.hasModifier(OPEN_KEYWORD) || (classOrObject instanceof JetClass && ((JetClass) classOrObject).isEnum()))) { - psiModifiers.add(PsiModifier.FINAL); + else if (!(classOrObject.hasModifier(OPEN_KEYWORD) || (classOrObject is JetClass && classOrObject.isEnum()))) { + psiModifiers.add(PsiModifier.FINAL) } if (!classOrObject.isTopLevel() && !classOrObject.hasModifier(INNER_KEYWORD)) { - psiModifiers.add(PsiModifier.STATIC); + psiModifiers.add(PsiModifier.STATIC) } - return ArrayUtil.toStringArray(psiModifiers); + return ArrayUtil.toStringArray(psiModifiers) } - private boolean isAbstract(@NotNull JetClassOrObject object) { - return object.hasModifier(ABSTRACT_KEYWORD) || isInterface(); + private fun isAbstract(`object`: JetClassOrObject): Boolean { + return `object`.hasModifier(ABSTRACT_KEYWORD) || isInterface } - @Override - public boolean hasModifierProperty(@NonNls @NotNull String name) { - return getModifierList().hasModifierProperty(name); + override fun hasModifierProperty(NonNls name: String): Boolean { + return getModifierList().hasModifierProperty(name) } - @Override - public boolean isDeprecated() { - JetModifierList jetModifierList = classOrObject.getModifierList(); - if (jetModifierList == null) { - return false; + override fun isDeprecated(): Boolean { + val jetModifierList = classOrObject.modifierList ?: return false + + val deprecatedFqName = KotlinBuiltIns.FQ_NAMES.deprecated + val deprecatedName = deprecatedFqName.shortName().asString() + + for (annotationEntry in jetModifierList.annotationEntries) { + val typeReference = annotationEntry.typeReference ?: continue + + val typeElement = typeReference.typeElement + if (typeElement !is JetUserType) continue // If it's not a user type, it's definitely not a ref to deprecated + + val fqName = JetPsiUtil.toQualifiedName(typeElement) ?: continue + + if (deprecatedFqName == fqName) return true + if (deprecatedName == fqName.asString()) return true } - - FqName deprecatedFqName = KotlinBuiltIns.FQ_NAMES.deprecated; - String deprecatedName = deprecatedFqName.shortName().asString(); - - for (JetAnnotationEntry annotationEntry : jetModifierList.getAnnotationEntries()) { - JetTypeReference typeReference = annotationEntry.getTypeReference(); - if (typeReference == null) continue; - - JetTypeElement typeElement = typeReference.getTypeElement(); - if (!(typeElement instanceof JetUserType)) continue; // If it's not a user type, it's definitely not a ref to deprecated - - FqName fqName = JetPsiUtil.toQualifiedName((JetUserType) typeElement); - if (fqName == null) continue; - - if (deprecatedFqName.equals(fqName)) return true; - if (deprecatedName.equals(fqName.asString())) return true; - } - return false; + return false } - @Override - public boolean isInterface() { - if (!(classOrObject instanceof JetClass)) return false; - JetClass jetClass = (JetClass) classOrObject; - return jetClass.isInterface() || jetClass.isAnnotation(); + override fun isInterface(): Boolean { + if (classOrObject !is JetClass) return false + return classOrObject.isInterface() || classOrObject.isAnnotation() } - @Override - public boolean isAnnotationType() { - return classOrObject instanceof JetClass && ((JetClass) classOrObject).isAnnotation(); + override fun isAnnotationType(): Boolean { + return classOrObject is JetClass && classOrObject.isAnnotation() } - @Override - public boolean isEnum() { - return classOrObject instanceof JetClass && ((JetClass) classOrObject).isEnum(); + override fun isEnum(): Boolean { + return classOrObject is JetClass && classOrObject.isEnum() } - @Override - public boolean hasTypeParameters() { - return classOrObject instanceof JetClass && !((JetClass) classOrObject).getTypeParameters().isEmpty(); + override fun hasTypeParameters(): Boolean { + return classOrObject is JetClass && !classOrObject.typeParameters.isEmpty() } - @Override - public boolean isValid() { - return classOrObject.isValid(); + override fun isValid(): Boolean { + return classOrObject.isValid } - @Override - public boolean isInheritor(@NotNull PsiClass baseClass, boolean checkDeep) { + override fun isInheritor(baseClass: PsiClass, checkDeep: Boolean): Boolean { // Java inheritor check doesn't work when trait (interface in Java) subclasses Java class and for Kotlin local classes - if (baseClass instanceof KotlinLightClassForExplicitDeclaration || (isInterface() && !baseClass.isInterface())) { - String qualifiedName; - if (baseClass instanceof KotlinLightClassForExplicitDeclaration) { - ClassDescriptor baseDescriptor = ((KotlinLightClassForExplicitDeclaration) baseClass).getDescriptor(); - qualifiedName = baseDescriptor != null ? DescriptorUtils.getFqName(baseDescriptor).asString() : null; + if (baseClass is KotlinLightClassForExplicitDeclaration || (isInterface && !baseClass.isInterface)) { + val qualifiedName: String? + if (baseClass is KotlinLightClassForExplicitDeclaration) { + val baseDescriptor = baseClass.getDescriptor() + qualifiedName = if (baseDescriptor != null) DescriptorUtils.getFqName(baseDescriptor).asString() else null } else { - qualifiedName = baseClass.getQualifiedName(); + qualifiedName = baseClass.qualifiedName } - ClassDescriptor thisDescriptor = getDescriptor(); - return qualifiedName != null - && thisDescriptor != null - && checkSuperTypeByFQName(thisDescriptor, qualifiedName, checkDeep); + val thisDescriptor = getDescriptor() + return qualifiedName != null && thisDescriptor != null && checkSuperTypeByFQName(thisDescriptor, qualifiedName, checkDeep) } - return super.isInheritor(baseClass, checkDeep); + return super.isInheritor(baseClass, checkDeep) } - @Override - public PsiElement setName(@NonNls @NotNull String name) throws IncorrectOperationException { - getOrigin().setName(name); - return this; + throws(IncorrectOperationException::class) + override fun setName(NonNls name: String): PsiElement { + getOrigin().setName(name) + return this } - @Override - public String toString() { + override fun toString(): String { try { - return KotlinLightClass.class.getSimpleName() + ":" + getQualifiedName(); + return javaClass().simpleName + ":" + qualifiedName } - catch (Throwable e) { - return KotlinLightClass.class.getSimpleName() + ":" + e.toString(); + catch (e: Throwable) { + return javaClass().simpleName + ":" + e.toString() } + } - @NotNull - @Override - public List getOwnInnerClasses() { - return KotlinPackage.filterNotNull( - KotlinPackage.map( - getDelegate().getInnerClasses(), - new Function1() { - @Override - public PsiClass invoke(PsiClass aClass) { - JetClassOrObject declaration = (JetClassOrObject) ClsWrapperStubPsiFactory.getOriginalDeclaration(aClass); - return declaration != null ? create(myManager, declaration) : null; - } + override fun getOwnInnerClasses(): List { + return getDelegate().innerClasses + .map { + val declaration = ClsWrapperStubPsiFactory.getOriginalDeclaration(it) as JetClassOrObject? + if (declaration != null) create(myManager, declaration) else null + } + .filterNotNull() + } + + override fun getUseScope(): SearchScope { + return getOrigin().useScope + } + + companion object { + private val JAVA_API_STUB = Key.create>("JAVA_API_STUB") + + public fun create(manager: PsiManager, classOrObject: JetClassOrObject): KotlinLightClassForExplicitDeclaration? { + if (LightClassUtil.belongsToKotlinBuiltIns(classOrObject.getContainingJetFile())) { + return null + } + + val fqName = predictFqName(classOrObject) ?: return null + + if (classOrObject is JetObjectDeclaration && classOrObject.isObjectLiteral()) { + return KotlinLightClassForAnonymousDeclaration(manager, fqName, classOrObject) + } + return KotlinLightClassForExplicitDeclaration(manager, fqName, classOrObject) + } + + private fun predictFqName(classOrObject: JetClassOrObject): FqName? { + if (classOrObject.isLocal()) { + val data = getLightClassDataExactly(classOrObject) + return data?.jvmQualifiedName + } + val internalName = PsiCodegenPredictor.getPredefinedJvmInternalName(classOrObject) + return if (internalName == null) null else JvmClassName.byInternalName(internalName).fqNameForClassNameWithoutDollars + } + + public fun getLightClassData(classOrObject: JetClassOrObject): OutermostKotlinClassLightClassData { + val outermostClassOrObject = getOutermostClassOrObject(classOrObject) + return CachedValuesManager.getManager(classOrObject.project).getCachedValue( + outermostClassOrObject, + JAVA_API_STUB, + KotlinJavaFileStubProvider.createForDeclaredClass(outermostClassOrObject), + /*trackValue = */false) + } + + private fun getLightClassDataExactly(classOrObject: JetClassOrObject): LightClassDataForKotlinClass? { + val data = getLightClassData(classOrObject) + return if (data.classOrObject == classOrObject) data else data.allInnerClasses.get(classOrObject) + } + + private fun getOutermostClassOrObject(classOrObject: JetClassOrObject): JetClassOrObject { + val outermostClass = JetPsiUtil.getOutermostClassOrObject(classOrObject) + if (outermostClass == null) { + throw IllegalStateException("Attempt to build a light class for a local class: " + classOrObject.text) + } + else { + return outermostClass + } + } + + private fun checkSuperTypeByFQName(classDescriptor: ClassDescriptor, qualifiedName: String, deep: Boolean?): Boolean { + if (CommonClassNames.JAVA_LANG_OBJECT == qualifiedName) return true + + if (qualifiedName == DescriptorUtils.getFqName(classDescriptor).asString()) return true + + for (superType in classDescriptor.typeConstructor.supertypes) { + val superDescriptor = superType.constructor.declarationDescriptor + + if (superDescriptor is ClassDescriptor) { + if (qualifiedName == DescriptorUtils.getFqName(superDescriptor).asString()) return true + + if (deep!!) { + if (checkSuperTypeByFQName(superDescriptor, qualifiedName, true)) { + return true } - ) - ); - } - - @NotNull - @Override - public SearchScope getUseScope() { - return getOrigin().getUseScope(); - } - - private static boolean checkSuperTypeByFQName(@NotNull ClassDescriptor classDescriptor, @NotNull String qualifiedName, Boolean deep) { - if (CommonClassNames.JAVA_LANG_OBJECT.equals(qualifiedName)) return true; - - if (qualifiedName.equals(DescriptorUtils.getFqName(classDescriptor).asString())) return true; - - for (JetType superType : classDescriptor.getTypeConstructor().getSupertypes()) { - ClassifierDescriptor superDescriptor = superType.getConstructor().getDeclarationDescriptor(); - - if (superDescriptor instanceof ClassDescriptor) { - if (qualifiedName.equals(DescriptorUtils.getFqName(superDescriptor).asString())) return true; - - if (deep) { - if (checkSuperTypeByFQName((ClassDescriptor)superDescriptor, qualifiedName, true)) { - return true; } } } - } - return false; + return false + } } } diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/IDELightClassGenerationSupport.java b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/IDELightClassGenerationSupport.java index 3e3f4249fd4..7a96004b973 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/IDELightClassGenerationSupport.java +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/IDELightClassGenerationSupport.java @@ -219,7 +219,7 @@ public class IDELightClassGenerationSupport extends LightClassGenerationSupport } return JetSourceNavigationHelper.getOriginalClass(classOrObject); } - return KotlinLightClassForExplicitDeclaration.create(psiManager, classOrObject); + return KotlinLightClassForExplicitDeclaration.Companion.create(psiManager, classOrObject); } @Nullable