PyDynamicMember -> python-psi-api

This commit is contained in:
Dmitry Jemerov
2012-08-09 13:30:49 +02:00
parent 408b9e0116
commit 8ff184dcda
3 changed files with 15 additions and 7 deletions
@@ -0,0 +1,187 @@
package com.jetbrains.python.codeInsight;
import com.intellij.extapi.psi.ASTWrapperPsiElement;
import com.intellij.icons.AllIcons;
import com.intellij.psi.PsiElement;
import com.intellij.util.Function;
import com.jetbrains.python.psi.PyClass;
import com.jetbrains.python.psi.PyFunction;
import com.jetbrains.python.psi.PyPsiFacade;
import com.jetbrains.python.psi.PyTypedElement;
import com.jetbrains.python.psi.types.PyType;
import com.jetbrains.python.psi.types.TypeEvalContext;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
/**
* @author Dennis.Ushakov
*/
public class PyDynamicMember {
private String myName;
private final boolean myResolveToInstance;
private final Function<PsiElement, PyType> myTypeCallback;
private final String myTypeName;
private final PsiElement myTarget;
private PyPsiPath myPsiPath;
boolean myFunction = false;
public PyDynamicMember(@NotNull final String name, @NotNull final String type, final boolean resolveToInstance) {
myName = name;
myResolveToInstance = resolveToInstance;
myTypeName = type;
myTarget = null;
myTypeCallback = null;
}
public PyDynamicMember(@NotNull final String name) {
myName = name;
myResolveToInstance = false;
myTypeName = null;
myTarget = null;
myTypeCallback = null;
}
public PyDynamicMember(@NotNull final String name,
@NotNull final String type,
final Function<PsiElement, PyType> typeCallback) {
myName = name;
myResolveToInstance = false;
myTypeName = type;
myTarget = null;
myTypeCallback = typeCallback;
}
public PyDynamicMember(@NotNull final String name, @Nullable final PsiElement target) {
myName = name;
myTarget = target;
myResolveToInstance = false;
myTypeName = null;
myTypeCallback = null;
}
public PyDynamicMember resolvesTo(String moduleQName) {
myPsiPath = new PyPsiPath.ToFile(moduleQName);
return this;
}
public PyDynamicMember resolvesToClass(String classQName) {
myPsiPath = new PyPsiPath.ToClassQName(classQName);
return this;
}
public PyDynamicMember toClass(String name) {
myPsiPath = new PyPsiPath.ToClass(myPsiPath, name);
return this;
}
public PyDynamicMember toFunction(String name) {
myPsiPath = new PyPsiPath.ToFunction(myPsiPath, name);
return this;
}
public PyDynamicMember toFunctionRecursive(String name) {
myPsiPath = new PyPsiPath.ToFunctionRecursive(myPsiPath, name);
return this;
}
public PyDynamicMember toClassAttribute(String name) {
myPsiPath = new PyPsiPath.ToClassAttribute(myPsiPath, name);
return this;
}
public PyDynamicMember toCall(String name, String... args) {
myPsiPath = new PyPsiPath.ToCall(myPsiPath, name, args);
return this;
}
public PyDynamicMember toPsiElement(final PsiElement psiElement) {
myPsiPath = new PyPsiPath() {
@Override
public PsiElement resolve(PsiElement module) {
return psiElement;
}
};
return this;
}
public String getName() {
return myName;
}
public Icon getIcon() {
if (myTarget != null) {
return myTarget.getIcon(0);
}
return AllIcons.Nodes.Method;
}
@Nullable
public PsiElement resolve(@NotNull PsiElement context) {
if (myTarget != null) {
return myTarget;
}
PyClass targetClass =
myTypeName != null && myTypeName.indexOf('.') > 0 ? PyPsiFacade.getInstance(context.getProject()).findClass(myTypeName) : null;
final PsiElement resolveTarget = findResolveTarget(context);
if (resolveTarget instanceof PyFunction) {
return resolveTarget;
}
if (resolveTarget != null || targetClass != null) {
return new MyInstanceElement(targetClass, context, resolveTarget);
}
return null;
}
@Nullable
private PsiElement findResolveTarget(@NotNull PsiElement context) {
if (myPsiPath != null) {
return myPsiPath.resolve(context);
}
return null;
}
@Nullable
public String getShortType() {
if (myTypeName == null) {
return null;
}
int pos = myTypeName.lastIndexOf('.');
return myTypeName.substring(pos + 1);
}
public PyDynamicMember asFunction() {
myFunction = true;
return this;
}
public boolean isFunction() {
return myFunction;
}
private class MyInstanceElement extends ASTWrapperPsiElement implements PyTypedElement {
private final PyClass myClass;
private final PsiElement myContext;
public MyInstanceElement(PyClass clazz, PsiElement context, PsiElement resolveTarget) {
super(resolveTarget != null ? resolveTarget.getNode() : clazz.getNode());
myClass = clazz;
myContext = context;
}
public PyType getType(@NotNull TypeEvalContext context) {
if (myTypeCallback != null) {
return myTypeCallback.fun(myContext);
}
return PyPsiFacade.getInstance(getProject()).createClassType(myClass, !myResolveToInstance);
}
}
}
@@ -4,6 +4,7 @@ import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.project.Project;
import com.jetbrains.python.psi.impl.PyQualifiedName;
import com.jetbrains.python.psi.resolve.QualifiedNameResolver;
import com.jetbrains.python.psi.types.PyClassType;
import org.jetbrains.annotations.Nullable;
/**
@@ -20,4 +21,5 @@ public abstract class PyPsiFacade {
@Nullable
public abstract PyClass findClass(String qName);
public abstract PyClassType createClassType(PyClass pyClass, boolean isDefinition);
}