Generate light type parameters for Kotlin light methods

This commit is contained in:
Alexey Sedunov
2014-01-22 15:13:29 +04:00
parent 598a3214d2
commit 5b2858ef26
5 changed files with 66 additions and 28 deletions
@@ -22,4 +22,5 @@ import org.jetbrains.jet.lang.psi.JetDeclaration;
/** Java method created for Kotlin declaration to make it resolvable in Java */ /** Java method created for Kotlin declaration to make it resolvable in Java */
public interface KotlinLightMethod extends PsiMethod { public interface KotlinLightMethod extends PsiMethod {
JetDeclaration getOrigin(); JetDeclaration getOrigin();
PsiMethod getDelegate();
} }
@@ -32,7 +32,6 @@ import com.intellij.psi.impl.java.stubs.PsiJavaFileStub;
import com.intellij.psi.impl.light.LightClass; import com.intellij.psi.impl.light.LightClass;
import com.intellij.psi.impl.light.LightMethod; import com.intellij.psi.impl.light.LightMethod;
import com.intellij.psi.impl.light.LightModifierList; import com.intellij.psi.impl.light.LightModifierList;
import com.intellij.psi.impl.light.LightTypeParameterListBuilder;
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.CachedValuesManager; import com.intellij.psi.util.CachedValuesManager;
@@ -185,18 +184,7 @@ public class KotlinLightClassForExplicitDeclaration extends KotlinWrappingLightC
@Nullable @Nullable
@Override @Override
protected PsiTypeParameterList compute() { protected PsiTypeParameterList compute() {
LightTypeParameterListBuilder builder = new LightTypeParameterListBuilder(getManager(), getLanguage()); return LightClassUtil.buildLightTypeParameterList(KotlinLightClassForExplicitDeclaration.this, classOrObject);
if (classOrObject instanceof JetTypeParameterListOwner) {
JetTypeParameterListOwner typeParameterListOwner = (JetTypeParameterListOwner) classOrObject;
List<JetTypeParameter> parameters = typeParameterListOwner.getTypeParameters();
for (int i = 0; i < parameters.size(); i++) {
JetTypeParameter jetTypeParameter = parameters.get(i);
String name = jetTypeParameter.getName();
String safeName = name == null ? "__no_name__" : name;
builder.addParameter(new KotlinLightTypeParameter(KotlinLightClassForExplicitDeclaration.this, i, safeName));
}
}
return builder;
} }
}; };
@@ -23,9 +23,6 @@ import com.intellij.psi.PsiManager
import com.intellij.psi.PsiElement import com.intellij.psi.PsiElement
import com.intellij.psi.PsiNamedElement import com.intellij.psi.PsiNamedElement
import org.jetbrains.jet.lang.psi.JetDeclaration import org.jetbrains.jet.lang.psi.JetDeclaration
import com.intellij.psi.PsiParameterList
import org.jetbrains.jet.plugin.JetLanguage
import kotlin.properties.Delegates
import org.jetbrains.jet.asJava.light.LightParameter import org.jetbrains.jet.asJava.light.LightParameter
import org.jetbrains.jet.asJava.light.LightParameterListBuilder import org.jetbrains.jet.asJava.light.LightParameterListBuilder
import org.jetbrains.jet.lang.resolve.java.jetAsJava.KotlinLightMethod import org.jetbrains.jet.lang.resolve.java.jetAsJava.KotlinLightMethod
@@ -35,8 +32,12 @@ import kotlin.properties.Delegates
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.psi.util.CachedValueProvider import com.intellij.psi.util.CachedValueProvider
import com.intellij.openapi.application.Result
import com.intellij.psi.util.CachedValue import com.intellij.psi.util.CachedValue
import com.intellij.psi.PsiTypeParameterList
import org.jetbrains.jet.lang.psi.JetPropertyAccessor
import org.jetbrains.jet.lang.psi.psiUtil.getParentByType
import org.jetbrains.jet.lang.psi.JetProperty
import com.intellij.psi.PsiTypeParameter
public class KotlinLightMethodForDeclaration(manager: PsiManager, val method: PsiMethod, val jetDeclaration: JetDeclaration, containingClass: PsiClass): public class KotlinLightMethodForDeclaration(manager: PsiManager, val method: PsiMethod, val jetDeclaration: JetDeclaration, containingClass: PsiClass):
LightMethod(manager, method, containingClass), KotlinLightMethod { LightMethod(manager, method, containingClass), KotlinLightMethod {
@@ -55,6 +56,18 @@ public class KotlinLightMethodForDeclaration(manager: PsiManager, val method: Ps
}, false) }, false)
} }
private val typeParamsList: CachedValue<PsiTypeParameterList> by Delegates.blockingLazy {
val cacheManager = CachedValuesManager.getManager(method.getProject())
cacheManager.createCachedValue<PsiTypeParameterList>({
val declaration =
if (jetDeclaration is JetPropertyAccessor) jetDeclaration.getParentByType(javaClass<JetProperty>()) else jetDeclaration
val list = LightClassUtil.buildLightTypeParameterList(this@KotlinLightMethodForDeclaration, jetDeclaration)
CachedValueProvider.Result.create(list, PsiModificationTracker.OUT_OF_CODE_BLOCK_MODIFICATION_COUNT)
}, false)
}
override fun getDelegate(): PsiMethod = method
override fun getNavigationElement() : PsiElement = jetDeclaration override fun getNavigationElement() : PsiElement = jetDeclaration
override fun getOriginalElement() : PsiElement = jetDeclaration override fun getOriginalElement() : PsiElement = jetDeclaration
override fun getOrigin(): JetDeclaration? = jetDeclaration override fun getOrigin(): JetDeclaration? = jetDeclaration
@@ -82,6 +95,10 @@ public class KotlinLightMethodForDeclaration(manager: PsiManager, val method: Ps
override fun getParameterList(): PsiParameterList = paramsList.getValue()!! override fun getParameterList(): PsiParameterList = paramsList.getValue()!!
override fun getTypeParameterList(): PsiTypeParameterList? = typeParamsList.getValue()
override fun getTypeParameters(): Array<PsiTypeParameter> =
getTypeParameterList()?.let { it.getTypeParameters() } ?: PsiTypeParameter.EMPTY_ARRAY
override fun copy(): PsiElement { override fun copy(): PsiElement {
return KotlinLightMethodForDeclaration(getManager()!!, method, jetDeclaration.copy() as JetDeclaration, getContainingClass()!!) return KotlinLightMethodForDeclaration(getManager()!!, method, jetDeclaration.copy() as JetDeclaration, getContainingClass()!!)
} }
@@ -20,20 +20,22 @@ import com.intellij.psi.*;
import com.intellij.psi.impl.light.AbstractLightClass; import com.intellij.psi.impl.light.AbstractLightClass;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.psi.JetClass;
import org.jetbrains.jet.lang.psi.JetTypeParameterListOwner;
import org.jetbrains.jet.lang.resolve.java.jetAsJava.KotlinLightMethod;
import org.jetbrains.jet.plugin.JetLanguage; import org.jetbrains.jet.plugin.JetLanguage;
public class KotlinLightTypeParameter extends AbstractLightClass implements PsiTypeParameter { public class KotlinLightTypeParameter extends AbstractLightClass implements PsiTypeParameter {
private final PsiTypeParameterListOwner owner;
private final KotlinLightClassForExplicitDeclaration lightClass;
private final int index; private final int index;
private final String name; private final String name;
protected KotlinLightTypeParameter( protected KotlinLightTypeParameter(
@NotNull KotlinLightClassForExplicitDeclaration lightClass, @NotNull PsiTypeParameterListOwner owner,
int index, int index,
@NotNull String name) { @NotNull String name) {
super(lightClass.getManager(), JetLanguage.INSTANCE); super(owner.getManager(), JetLanguage.INSTANCE);
this.lightClass = lightClass; this.owner = owner;
this.index = index; this.index = index;
this.name = name; this.name = name;
} }
@@ -41,13 +43,20 @@ public class KotlinLightTypeParameter extends AbstractLightClass implements PsiT
@NotNull @NotNull
@Override @Override
public PsiTypeParameter getDelegate() { public PsiTypeParameter getDelegate() {
return lightClass.getDelegate().getTypeParameters()[index]; return getOwnerDelegate().getTypeParameters()[index];
}
@NotNull
private PsiTypeParameterListOwner getOwnerDelegate() {
if (owner instanceof KotlinLightClass) return ((KotlinLightClass) owner).getDelegate();
if (owner instanceof KotlinLightMethod) return ((KotlinLightMethod) owner).getDelegate();
return owner;
} }
@NotNull @NotNull
@Override @Override
public PsiElement copy() { public PsiElement copy() {
return new KotlinLightTypeParameter(lightClass, index, name); return new KotlinLightTypeParameter(owner, index, name);
} }
@Override @Override
@@ -68,7 +77,7 @@ public class KotlinLightTypeParameter extends AbstractLightClass implements PsiT
@Override @Override
public PsiTypeParameterListOwner getOwner() { public PsiTypeParameterListOwner getOwner() {
return lightClass; return owner;
} }
@Override @Override
@@ -103,4 +112,10 @@ public class KotlinLightTypeParameter extends AbstractLightClass implements PsiT
public String toString() { public String toString() {
return "KotlinLightTypeParameter:" + getName(); return "KotlinLightTypeParameter:" + getName();
} }
@NotNull
@Override
public PsiElement getNavigationElement() {
return ((JetTypeParameterListOwner) owner.getNavigationElement()).getTypeParameters().get(index);
}
} }
@@ -24,10 +24,9 @@ import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.vfs.StandardFileSystems; import com.intellij.openapi.vfs.StandardFileSystems;
import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiClass; import com.intellij.psi.*;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiMethod;
import com.intellij.psi.impl.java.stubs.PsiClassStub; import com.intellij.psi.impl.java.stubs.PsiClassStub;
import com.intellij.psi.impl.light.LightTypeParameterListBuilder;
import com.intellij.psi.search.GlobalSearchScope; import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.stubs.PsiFileStub; import com.intellij.psi.stubs.PsiFileStub;
import com.intellij.psi.stubs.StubElement; import com.intellij.psi.stubs.StubElement;
@@ -289,6 +288,24 @@ public class LightClassUtil {
return new PropertyAccessorsPsiMethods(getterWrapper, setterWrapper); return new PropertyAccessorsPsiMethods(getterWrapper, setterWrapper);
} }
@NotNull
public static PsiTypeParameterList buildLightTypeParameterList(
PsiTypeParameterListOwner owner,
JetDeclaration declaration) {
LightTypeParameterListBuilder builder = new LightTypeParameterListBuilder(owner.getManager(), owner.getLanguage());
if (declaration instanceof JetTypeParameterListOwner) {
JetTypeParameterListOwner typeParameterListOwner = (JetTypeParameterListOwner) declaration;
List<JetTypeParameter> parameters = typeParameterListOwner.getTypeParameters();
for (int i = 0; i < parameters.size(); i++) {
JetTypeParameter jetTypeParameter = parameters.get(i);
String name = jetTypeParameter.getName();
String safeName = name == null ? "__no_name__" : name;
builder.addParameter(new KotlinLightTypeParameter(owner, i, safeName));
}
}
return builder;
}
public static class PropertyAccessorsPsiMethods implements Iterable<PsiMethod> { public static class PropertyAccessorsPsiMethods implements Iterable<PsiMethod> {
private final PsiMethod getter; private final PsiMethod getter;
private final PsiMethod setter; private final PsiMethod setter;