Go to (show) implementations: skip light methods that are generated with DELEGATION or DELEGATION_TO_DEFAULT_IMPLS JvmDeclarationOriginKind
Add some unrelated tests for fake overrides
This commit is contained in:
+16
-9
@@ -27,19 +27,20 @@ import com.intellij.psi.impl.java.stubs.*;
|
||||
import com.intellij.psi.stubs.StubBase;
|
||||
import com.intellij.psi.stubs.StubElement;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.kotlin.psi.KtDeclaration;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
class ClsWrapperStubPsiFactory extends StubPsiFactory {
|
||||
public static final Key<PsiElement> ORIGIN_ELEMENT = Key.create("ORIGIN_ELEMENT");
|
||||
public static final Key<LightElementOrigin> ORIGIN = Key.create("ORIGIN");
|
||||
private final StubPsiFactory delegate = new ClsStubPsiFactory();
|
||||
|
||||
public static KtDeclaration getOriginalDeclaration(PsiMember member) {
|
||||
@Nullable
|
||||
public static LightMemberOrigin getMemberOrigin(@NotNull PsiMember member) {
|
||||
if (member instanceof ClsRepositoryPsiElement<?>) {
|
||||
StubElement stubElement = ((ClsRepositoryPsiElement<?>) member).getStub();
|
||||
if (stubElement instanceof UserDataHolder) {
|
||||
PsiElement original = ((UserDataHolder) stubElement).getUserData(ORIGIN_ELEMENT);
|
||||
if (original instanceof KtDeclaration) {
|
||||
return (KtDeclaration) original;
|
||||
LightElementOrigin origin = ((UserDataHolder) stubElement).getUserData(ORIGIN);
|
||||
if (origin instanceof LightMemberOrigin) {
|
||||
return (LightMemberOrigin) origin;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -48,8 +49,8 @@ class ClsWrapperStubPsiFactory extends StubPsiFactory {
|
||||
}
|
||||
|
||||
@Override
|
||||
public PsiClass createClass(PsiClassStub stub) {
|
||||
final PsiElement origin = ((StubBase) stub).getUserData(ORIGIN_ELEMENT);
|
||||
public PsiClass createClass(@NotNull PsiClassStub stub) {
|
||||
final PsiElement origin = getOriginalElement(stub);
|
||||
if (origin == null) return delegate.createClass(stub);
|
||||
|
||||
return new ClsClassImpl(stub) {
|
||||
@@ -61,6 +62,12 @@ class ClsWrapperStubPsiFactory extends StubPsiFactory {
|
||||
};
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static PsiElement getOriginalElement(@NotNull StubElement stub) {
|
||||
LightElementOrigin origin = ((StubBase) stub).getUserData(ORIGIN);
|
||||
return origin != null ? origin.getOriginalElement() : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PsiAnnotation createAnnotation(PsiAnnotationStub stub) {
|
||||
return delegate.createAnnotation(stub);
|
||||
@@ -78,7 +85,7 @@ class ClsWrapperStubPsiFactory extends StubPsiFactory {
|
||||
|
||||
@Override
|
||||
public PsiField createField(PsiFieldStub stub) {
|
||||
final PsiElement origin = ((StubBase) stub).getUserData(ORIGIN_ELEMENT);
|
||||
final PsiElement origin = getOriginalElement(stub);
|
||||
if (origin == null) return delegate.createField(stub);
|
||||
if (stub.isEnumConstant()) {
|
||||
return new ClsEnumConstantImpl(stub) {
|
||||
|
||||
@@ -25,14 +25,19 @@ import com.intellij.psi.util.*
|
||||
import com.intellij.util.IncorrectOperationException
|
||||
import org.jetbrains.kotlin.idea.KotlinLanguage
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOriginKind
|
||||
|
||||
public interface KtLightMethod : PsiMethod, KtLightElement<KtDeclaration, PsiMethod>
|
||||
public interface KtLightMethod : PsiMethod, KtLightElement<KtDeclaration, PsiMethod> {
|
||||
val isDelegated: Boolean
|
||||
}
|
||||
|
||||
sealed class KtLightMethodImpl(
|
||||
private val delegate: PsiMethod,
|
||||
private val origin: KtDeclaration?,
|
||||
private val lightMethodOrigin: LightMemberOrigin?,
|
||||
containingClass: KtLightClass
|
||||
): LightMethod(delegate.manager, delegate, containingClass), KtLightMethod {
|
||||
) : LightMethod(delegate.manager, delegate, containingClass), KtLightMethod {
|
||||
private val origin = lightMethodOrigin?.originalElement as? KtDeclaration
|
||||
|
||||
override fun getContainingClass(): KtLightClass = super.getContainingClass() as KtLightClass
|
||||
|
||||
private val paramsList: CachedValue<PsiParameterList> by lazy {
|
||||
@@ -70,7 +75,11 @@ sealed class KtLightMethodImpl(
|
||||
override fun getOrigin() = origin
|
||||
override fun getParent(): PsiElement? = containingClass
|
||||
override fun getText() = origin?.text ?: ""
|
||||
override fun getTextRange() = origin?.textRange ?: TextRange.EMPTY_RANGE
|
||||
override fun getTextRange() = origin?.textRange ?: TextRange.EMPTY_RANGE
|
||||
|
||||
override val isDelegated: Boolean
|
||||
get() = lightMethodOrigin?.originKind == JvmDeclarationOriginKind.DELEGATION
|
||||
|| lightMethodOrigin?.originKind == JvmDeclarationOriginKind.DELEGATION_TO_DEFAULT_IMPLS
|
||||
|
||||
override fun accept(visitor: PsiElementVisitor) {
|
||||
if (visitor is JavaElementVisitor) {
|
||||
@@ -114,7 +123,7 @@ sealed class KtLightMethodImpl(
|
||||
}
|
||||
|
||||
override fun copy(): PsiElement {
|
||||
return Factory.create(delegate, origin?.copy() as? KtDeclaration, containingClass)
|
||||
return Factory.create(delegate, lightMethodOrigin?.copy(), containingClass)
|
||||
}
|
||||
|
||||
override fun getUseScope() = origin?.useScope ?: super.getUseScope()
|
||||
@@ -143,14 +152,14 @@ sealed class KtLightMethodImpl(
|
||||
override fun hashCode(): Int = ((name.hashCode() * 31 + (origin?.hashCode() ?: 0)) * 31 + containingClass.hashCode()) * 31 + delegate.hashCode()
|
||||
|
||||
override fun toString(): String = "${this.javaClass.simpleName}:$name"
|
||||
|
||||
|
||||
private class KtLightMethodForDeclaration(
|
||||
delegate: PsiMethod, origin: KtDeclaration?, containingClass: KtLightClass
|
||||
delegate: PsiMethod, origin: LightMemberOrigin?, containingClass: KtLightClass
|
||||
) : KtLightMethodImpl(delegate, origin, containingClass)
|
||||
|
||||
private class KtLightAnnotationMethod(
|
||||
delegate: PsiAnnotationMethod,
|
||||
origin: KtDeclaration?,
|
||||
origin: LightMemberOrigin?,
|
||||
containingClass: KtLightClass
|
||||
) : KtLightMethodImpl(delegate, origin, containingClass), PsiAnnotationMethod {
|
||||
override fun getDefaultValue() = getDelegate().defaultValue
|
||||
@@ -159,7 +168,7 @@ sealed class KtLightMethodImpl(
|
||||
|
||||
companion object Factory {
|
||||
fun create(
|
||||
delegate: PsiMethod, origin: KtDeclaration?, containingClass: KtLightClass
|
||||
delegate: PsiMethod, origin: LightMemberOrigin?, containingClass: KtLightClass
|
||||
): KtLightMethodImpl {
|
||||
return when (delegate) {
|
||||
is PsiAnnotationMethod -> KtLightAnnotationMethod(delegate, origin, containingClass)
|
||||
|
||||
@@ -33,7 +33,10 @@ import kotlin.jvm.functions.Function1;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.idea.KotlinLanguage;
|
||||
import org.jetbrains.kotlin.psi.*;
|
||||
import org.jetbrains.kotlin.psi.KtClassOrObject;
|
||||
import org.jetbrains.kotlin.psi.KtDeclaration;
|
||||
import org.jetbrains.kotlin.psi.KtProperty;
|
||||
import org.jetbrains.kotlin.psi.KtPropertyAccessor;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@@ -119,8 +122,8 @@ public abstract class KtWrappingLightClass extends AbstractLightClass implements
|
||||
return ContainerUtil.map(getDelegate().getFields(), new Function<PsiField, PsiField>() {
|
||||
@Override
|
||||
public PsiField fun(PsiField field) {
|
||||
KtDeclaration declaration = ClsWrapperStubPsiFactory.getOriginalDeclaration(field);
|
||||
return KtLightFieldImpl.Factory.create(declaration, field, KtWrappingLightClass.this);
|
||||
LightMemberOrigin origin = ClsWrapperStubPsiFactory.getMemberOrigin(field);
|
||||
return KtLightFieldImpl.Factory.create(origin != null ? origin.getOriginalElement() : null, field, KtWrappingLightClass.this);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -131,12 +134,14 @@ public abstract class KtWrappingLightClass extends AbstractLightClass implements
|
||||
return ArraysKt.map(getDelegate().getMethods(), new Function1<PsiMethod, PsiMethod>() {
|
||||
@Override
|
||||
public PsiMethod invoke(PsiMethod method) {
|
||||
KtDeclaration declaration = ClsWrapperStubPsiFactory.getOriginalDeclaration(method);
|
||||
if (declaration instanceof KtPropertyAccessor) {
|
||||
declaration = PsiTreeUtil.getParentOfType(declaration, KtProperty.class);
|
||||
LightMemberOrigin origin = ClsWrapperStubPsiFactory.getMemberOrigin(method);
|
||||
KtDeclaration originalElement = origin != null ? origin.getOriginalElement() : null;
|
||||
if (originalElement instanceof KtPropertyAccessor) {
|
||||
//noinspection ConstantConditions
|
||||
origin = origin.copy(PsiTreeUtil.getParentOfType(originalElement, KtProperty.class), origin.getOriginKind());
|
||||
}
|
||||
|
||||
return KtLightMethodImpl.Factory.create(method, declaration, KtWrappingLightClass.this);
|
||||
return KtLightMethodImpl.Factory.create(method, origin, KtWrappingLightClass.this);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* 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.PsiElement
|
||||
import org.jetbrains.kotlin.psi.KtDeclaration
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOriginKind
|
||||
|
||||
|
||||
interface LightElementOrigin {
|
||||
val originalElement: PsiElement?
|
||||
val originKind: JvmDeclarationOriginKind?
|
||||
|
||||
object None : LightElementOrigin {
|
||||
override val originalElement: PsiElement?
|
||||
get() = null
|
||||
override val originKind: JvmDeclarationOriginKind?
|
||||
get() = null
|
||||
|
||||
override fun toString() = "NONE"
|
||||
}
|
||||
}
|
||||
|
||||
fun JvmDeclarationOrigin.toLightMemberOrigin(): LightElementOrigin {
|
||||
val originalElement = element
|
||||
return when (originalElement) {
|
||||
is KtDeclaration -> LightMemberOrigin(originalElement, originKind)
|
||||
else -> LightElementOrigin.None
|
||||
}
|
||||
}
|
||||
|
||||
data class LightMemberOrigin(override val originalElement: KtDeclaration, override val originKind: JvmDeclarationOriginKind) : LightElementOrigin
|
||||
|
||||
data class LightClassOrigin(override val originalElement: PsiElement?) : LightElementOrigin {
|
||||
override val originKind: JvmDeclarationOriginKind? get() = null
|
||||
}
|
||||
|
||||
fun PsiElement?.toLightClassOrigin(): LightElementOrigin {
|
||||
return if (this != null) LightClassOrigin(this) else LightElementOrigin.None
|
||||
}
|
||||
|
||||
fun LightMemberOrigin.copy() = LightMemberOrigin(originalElement.copy() as KtDeclaration, originKind)
|
||||
@@ -92,7 +92,7 @@ public class StubClassBuilder extends AbstractClassBuilder {
|
||||
parentStack.push(v.getResult());
|
||||
}
|
||||
|
||||
((StubBase) v.getResult()).putUserData(ClsWrapperStubPsiFactory.ORIGIN_ELEMENT, origin);
|
||||
((StubBase) v.getResult()).putUserData(ClsWrapperStubPsiFactory.ORIGIN, LightElementOriginKt.toLightClassOrigin(origin));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -109,7 +109,7 @@ public class StubClassBuilder extends AbstractClassBuilder {
|
||||
|
||||
if (internalVisitor != EMPTY_METHOD_VISITOR) {
|
||||
// If stub for method generated
|
||||
markLastChild(origin.getElement());
|
||||
markLastChild(origin);
|
||||
}
|
||||
|
||||
return internalVisitor;
|
||||
@@ -129,22 +129,24 @@ public class StubClassBuilder extends AbstractClassBuilder {
|
||||
|
||||
if (internalVisitor != EMPTY_FIELD_VISITOR) {
|
||||
// If stub for field generated
|
||||
markLastChild(origin.getElement());
|
||||
markLastChild(origin);
|
||||
}
|
||||
|
||||
return internalVisitor;
|
||||
}
|
||||
|
||||
private void markLastChild(@Nullable PsiElement origin) {
|
||||
private void markLastChild(@NotNull JvmDeclarationOrigin origin) {
|
||||
List children = v.getResult().getChildrenStubs();
|
||||
StubBase last = (StubBase) children.get(children.size() - 1);
|
||||
|
||||
PsiElement oldOrigin = last.getUserData(ClsWrapperStubPsiFactory.ORIGIN_ELEMENT);
|
||||
LightElementOrigin oldOrigin = last.getUserData(ClsWrapperStubPsiFactory.ORIGIN);
|
||||
if (oldOrigin != null) {
|
||||
throw new IllegalStateException("Rewriting origin element: " + oldOrigin.getText() + " for stub " + last.toString());
|
||||
PsiElement originalElement = oldOrigin.getOriginalElement();
|
||||
throw new IllegalStateException("Rewriting origin element: " +
|
||||
(originalElement != null ? originalElement.getText() : null) + " for stub " + last.toString());
|
||||
}
|
||||
|
||||
last.putUserData(ClsWrapperStubPsiFactory.ORIGIN_ELEMENT, origin);
|
||||
last.putUserData(ClsWrapperStubPsiFactory.ORIGIN, LightElementOriginKt.toLightMemberOrigin(origin));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
Reference in New Issue
Block a user