Support DefaultImpls in light-classes and indices

#KT-4647 Fixed
This commit is contained in:
Denis Zharkov
2015-09-29 13:27:00 +03:00
parent 8b8fa40348
commit 22d58239e3
13 changed files with 192 additions and 7 deletions
@@ -31,6 +31,7 @@ import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.SLRUCache;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.load.java.JvmAbi;
import org.jetbrains.kotlin.load.kotlin.PackageClassUtils;
import org.jetbrains.kotlin.name.FqName;
import org.jetbrains.kotlin.name.NamePackage;
@@ -127,7 +128,10 @@ public class JavaElementFinder extends PsiElementFinder implements KotlinFinderM
}
// Finds explicitly declared classes and objects, not package classes
// Also DefaultImpls classes of interfaces
private void findClassesAndObjects(FqName qualifiedName, GlobalSearchScope scope, List<PsiClass> answer) {
findInterfaceDefaultImpls(qualifiedName, scope, answer);
Collection<JetClassOrObject> classOrObjectDeclarations =
lightClassGenerationSupport.findClassOrObjectDeclarations(qualifiedName, scope);
@@ -141,6 +145,22 @@ public class JavaElementFinder extends PsiElementFinder implements KotlinFinderM
}
}
private void findInterfaceDefaultImpls(FqName qualifiedName, GlobalSearchScope scope, List<PsiClass> answer) {
if (!qualifiedName.shortName().asString().equals(JvmAbi.DEFAULT_IMPLS_CLASS_NAME)) return;
for (JetClassOrObject classOrObject : lightClassGenerationSupport.findClassOrObjectDeclarations(qualifiedName.parent(), scope)) {
if (LightClassUtilsKt.getHasInterfaceDefaultImpls(classOrObject)) {
PsiClass interfaceClass = LightClassUtil.INSTANCE$.getPsiClass(classOrObject);
if (interfaceClass != null) {
PsiClass implsClass = interfaceClass.findInnerClassByName(JvmAbi.DEFAULT_IMPLS_CLASS_NAME, false);
if (implsClass != null) {
answer.add(implsClass);
}
}
}
}
}
@NotNull
@Override
public Set<String> getClassNames(@NotNull PsiPackage psiPackage, @NotNull GlobalSearchScope scope) {
@@ -50,7 +50,7 @@ import javax.swing.Icon
public open class KotlinLightClassForExplicitDeclaration(
manager: PsiManager,
private val classFqName: FqName, // FqName of (possibly inner) class
protected val classFqName: FqName, // FqName of (possibly inner) class
protected val classOrObject: JetClassOrObject)
: KotlinWrappingLightClass(manager), JetJavaMirrorMarker, StubBasedPsiElement<KotlinClassOrObjectStub<out JetClassOrObject>> {
private var delegate: PsiClass? = null
@@ -268,7 +268,7 @@ public open class KotlinLightClassForExplicitDeclaration(
override fun getModifierList(): PsiModifierList = _modifierList
private fun computeModifiers(): Array<String> {
protected open fun computeModifiers(): Array<String> {
val psiModifiers = hashSetOf<String>()
// PUBLIC, PROTECTED, PRIVATE, ABSTRACT, FINAL
@@ -377,7 +377,7 @@ public open class KotlinLightClassForExplicitDeclaration(
return getDelegate().innerClasses
.map {
val declaration = ClsWrapperStubPsiFactory.getOriginalDeclaration(it) as JetClassOrObject?
if (declaration != null) create(myManager, declaration) else null
if (declaration != null) create(myManager, declaration, it) else null
}
.filterNotNull()
}
@@ -397,7 +397,12 @@ public open class KotlinLightClassForExplicitDeclaration(
FINAL_KEYWORD to PsiModifier.FINAL)
public fun create(manager: PsiManager, classOrObject: JetClassOrObject): KotlinLightClassForExplicitDeclaration? {
@JvmOverloads
public fun create(
manager: PsiManager,
classOrObject: JetClassOrObject,
psiClass: PsiClass? = null
): KotlinLightClassForExplicitDeclaration? {
if (LightClassUtil.belongsToKotlinBuiltIns(classOrObject.getContainingJetFile())) {
return null
}
@@ -407,6 +412,14 @@ public open class KotlinLightClassForExplicitDeclaration(
if (classOrObject is JetObjectDeclaration && classOrObject.isObjectLiteral()) {
return KotlinLightClassForAnonymousDeclaration(manager, fqName, classOrObject)
}
if (classOrObject.hasInterfaceDefaultImpls) {
val implsFqName = fqName.defaultImplsChild()
if (implsFqName.asString() == psiClass?.qualifiedName) {
return KotlinLightClassForInterfaceDefaultImpls(manager, implsFqName, classOrObject)
}
}
return KotlinLightClassForExplicitDeclaration(manager, fqName, classOrObject)
}
@@ -0,0 +1,50 @@
/*
* Copyright 2010-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.asJava
import com.intellij.psi.*
import com.intellij.util.IncorrectOperationException
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.psi.JetClassOrObject
public open class KotlinLightClassForInterfaceDefaultImpls(
manager: PsiManager,
classFqName: FqName,
classOrObject: JetClassOrObject)
: KotlinLightClassForExplicitDeclaration(manager, classFqName, classOrObject){
override fun copy(): PsiElement {
return KotlinLightClassForInterfaceDefaultImpls(manager, classFqName, classOrObject.copy() as JetClassOrObject)
}
override fun getTypeParameterList(): PsiTypeParameterList? = null
override fun getTypeParameters(): Array<PsiTypeParameter> = emptyArray()
override fun computeModifiers(): Array<String> = arrayOf(PsiModifier.PUBLIC, PsiModifier.STATIC, PsiModifier.FINAL)
override fun isInterface(): Boolean = false
override fun isDeprecated(): Boolean = false
override fun isAnnotationType(): Boolean = false
override fun isEnum(): Boolean = false
override fun hasTypeParameters(): Boolean = false
override fun isInheritor(baseClass: PsiClass, checkDeep: Boolean): Boolean = false
@Throws(IncorrectOperationException::class)
override fun setName(name: String): PsiElement {
throw IncorrectOperationException("Impossible to rename DefaultImpls")
}
}
@@ -17,6 +17,9 @@
package org.jetbrains.kotlin.asJava
import com.intellij.psi.*
import org.jetbrains.kotlin.load.java.JvmAbi
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType
import org.jetbrains.kotlin.psi.psiUtil.isExtensionDeclaration
@@ -98,3 +101,10 @@ public val PsiElement.unwrapped: PsiElement?
public val PsiElement.namedUnwrappedElement: PsiNamedElement?
get() = unwrapped?.getNonStrictParentOfType<PsiNamedElement>()
val JetClassOrObject.hasInterfaceDefaultImpls: Boolean
get() = this is JetClass && isInterface()
private val DEFAULT_IMPLS_CLASS_NAME = Name.identifier(JvmAbi.DEFAULT_IMPLS_CLASS_NAME)
fun FqName.defaultImplsChild() = child(DEFAULT_IMPLS_CLASS_NAME)