restore resolve from Python to Java, introduce Java package type

This commit is contained in:
Dmitry Jemerov
2011-04-13 18:04:54 +02:00
parent 9cba5d7a99
commit 8e8e2ab055
13 changed files with 133 additions and 30 deletions

View File

@@ -11,16 +11,10 @@ import org.jetbrains.annotations.Nullable;
*/
public class PyJavaImportResolver implements PyImportResolver {
@Nullable
public PsiElement resolveImportReference(final PyElement importElement, final String importText, PsiElement importFrom) {
String fqn = importText;
if (importFrom instanceof PsiDirectory) {
PsiPackage fromPackage = JavaDirectoryService.getInstance().getPackage((PsiDirectory) importFrom);
if (fromPackage != null) {
importFrom = fromPackage;
}
}
if (importFrom instanceof PsiPackage) {
fqn = ((PsiPackage) importFrom).getQualifiedName() + "." + fqn;
public PsiElement resolveImportReference(final PyElement importElement, final PyQualifiedName importText, PyQualifiedName importFrom) {
String fqn = importText.toString();
if (importFrom != null) {
fqn = importFrom.toString() + "." + fqn;
}
final JavaPsiFacade psiFacade = JavaPsiFacade.getInstance(importElement.getProject());

View File

@@ -0,0 +1,82 @@
package com.jetbrains.python.psi.impl;
import com.intellij.codeInsight.lookup.LookupElementBuilder;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.project.Project;
import com.intellij.psi.JavaPsiFacade;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiPackage;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.search.ProjectScope;
import com.intellij.util.ArrayUtil;
import com.intellij.util.ProcessingContext;
import com.jetbrains.python.psi.AccessDirection;
import com.jetbrains.python.psi.PyExpression;
import com.jetbrains.python.psi.resolve.PyResolveContext;
import com.jetbrains.python.psi.types.PyType;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
* @author yole
*/
public class PyJavaPackageType implements PyType {
private final PsiPackage myPackage;
@Nullable private final Module myModule;
public PyJavaPackageType(PsiPackage aPackage, @Nullable Module module) {
myPackage = aPackage;
myModule = module;
}
@Override
public List<? extends PsiElement> resolveMember(String name,
@Nullable PyExpression location,
AccessDirection direction,
PyResolveContext resolveContext) {
Project project = myPackage.getProject();
JavaPsiFacade facade = JavaPsiFacade.getInstance(project);
String childName = myPackage.getQualifiedName() + "." + name;
GlobalSearchScope scope = getScope(project);
List<PsiElement> result = new ArrayList<PsiElement>();
Collections.addAll(result, facade.findClasses(childName, scope));
final PsiPackage psiPackage = facade.findPackage(childName);
if (psiPackage != null) {
result.add(psiPackage);
}
return result;
}
private GlobalSearchScope getScope(Project project) {
return myModule != null ? myModule.getModuleWithDependenciesAndLibrariesScope(false) : ProjectScope.getAllScope(project);
}
@Override
public Object[] getCompletionVariants(String completionPrefix, PyExpression location, ProcessingContext context) {
List<Object> variants = new ArrayList<Object>();
final GlobalSearchScope scope = getScope(location.getProject());
final PsiClass[] classes = myPackage.getClasses(scope);
for (PsiClass psiClass : classes) {
variants.add(LookupElementBuilder.create(psiClass).setIcon(psiClass.getIcon(0)));
}
final PsiPackage[] subPackages = myPackage.getSubPackages(scope);
for (PsiPackage subPackage : subPackages) {
variants.add(LookupElementBuilder.create(subPackage).setIcon(subPackage.getIcon(0)));
}
return ArrayUtil.toObjectArray(variants);
}
@Override
public String getName() {
return myPackage.getQualifiedName();
}
@Override
public boolean isBuiltin() {
return false;
}
}

View File

@@ -1,11 +1,11 @@
package com.jetbrains.python.psi.impl;
import com.intellij.openapi.module.ModuleUtil;
import com.intellij.psi.*;
import com.intellij.util.Processor;
import com.jetbrains.python.psi.PyFunction;
import com.jetbrains.python.psi.PyNamedParameter;
import com.jetbrains.python.psi.PyParameterList;
import com.jetbrains.python.psi.PyReferenceExpression;
import com.jetbrains.python.psi.search.PySuperMethodsSearch;
import com.jetbrains.python.psi.types.PyType;
import com.jetbrains.python.psi.types.PyTypeProviderBase;
@@ -21,10 +21,13 @@ import java.util.List;
*/
public class PyJavaTypeProvider extends PyTypeProviderBase {
@Nullable
public PyType getReferenceType(@NotNull final PsiElement referenceTarget, TypeEvalContext context) {
public PyType getReferenceType(@NotNull final PsiElement referenceTarget, TypeEvalContext context, @Nullable PsiElement anchor) {
if (referenceTarget instanceof PsiClass) {
return new PyJavaClassType((PsiClass) referenceTarget);
}
if (referenceTarget instanceof PsiPackage) {
return new PyJavaPackageType((PsiPackage) referenceTarget, anchor == null ? null : ModuleUtil.findModuleForPsiElement(anchor));
}
if (referenceTarget instanceof PsiMethod) {
PsiMethod method = (PsiMethod) referenceTarget;
final PsiType type = method.getReturnType();

View File

@@ -1,7 +1,5 @@
package com.jetbrains.jython;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.openapi.projectRoots.impl.JavaSdkImpl;
import com.intellij.psi.*;
import com.intellij.testFramework.ResolveTestCase;
import com.intellij.testFramework.TestDataPath;
@@ -42,6 +40,24 @@ public class PyToJavaResolveTest extends ResolveTestCase {
Assert.assertEquals("java.util.List", ((PsiMethod) target).getContainingClass().getQualifiedName());
}
public void testPackageType() throws Exception {
PsiElement target = resolve();
Assert.assertTrue(target instanceof PsiClass);
Assert.assertEquals("java.util.ArrayList", ((PsiClass) target).getQualifiedName());
}
public void testJavaPackage() throws Exception {
PsiElement target = resolve();
Assert.assertTrue(target instanceof PsiPackage);
Assert.assertEquals("java", ((PsiPackage) target).getQualifiedName());
}
public void testJavaLangPackage() throws Exception {
PsiElement target = resolve();
Assert.assertTrue(target instanceof PsiPackage);
Assert.assertEquals("java.lang", ((PsiPackage) target).getQualifiedName());
}
@Override
protected String getTestDataPath() {
return PythonTestUtil.getTestDataPath() + "/resolve/pyToJava/";

View File

@@ -99,7 +99,7 @@ public class PyCallExpressionImpl extends PyElementImpl implements PyCallExpress
return new PyClassType(((PyFunction)target).getContainingClass(), false); // resolved to __init__, back to class
}
// TODO: look at well-known functions and their return types
final PyType providedType = PyReferenceExpressionImpl.getReferenceTypeFromProviders(target, context);
final PyType providedType = PyReferenceExpressionImpl.getReferenceTypeFromProviders(target, context, this);
if (providedType != null) {
return providedType;
}

View File

@@ -12,5 +12,5 @@ public interface PyImportResolver {
ExtensionPointName<PyImportResolver> EP_NAME = ExtensionPointName.create("Pythonid.importResolver");
@Nullable
PsiElement resolveImportReference(PyElement importElement, String importText, final PsiElement importFrom);
PsiElement resolveImportReference(PyElement importElement, PyQualifiedName importText, PyQualifiedName importFrom);
}

View File

@@ -279,7 +279,7 @@ public class PyReferenceExpressionImpl extends PyElementImpl implements PyRefere
public static PyType getTypeFromTarget(@NotNull final PsiElement target,
final TypeEvalContext context,
@Nullable PyReferenceExpression anchor) {
final PyType pyType = getReferenceTypeFromProviders(target, context);
final PyType pyType = getReferenceTypeFromProviders(target, context, anchor);
if (pyType != null) {
return pyType;
}
@@ -350,9 +350,11 @@ public class PyReferenceExpressionImpl extends PyElementImpl implements PyRefere
}
@Nullable
public static PyType getReferenceTypeFromProviders(@NotNull final PsiElement target, TypeEvalContext context) {
public static PyType getReferenceTypeFromProviders(@NotNull final PsiElement target,
TypeEvalContext context,
@Nullable PsiElement anchor) {
for (PyTypeProvider provider : Extensions.getExtensions(PyTypeProvider.EP_NAME)) {
final PyType result = provider.getReferenceType(target, context);
final PyType result = provider.getReferenceType(target, context, anchor);
if (result != null) return result;
}

View File

@@ -21,7 +21,7 @@ public interface PyTypeProvider {
PyType getReferenceExpressionType(PyReferenceExpression referenceExpression, TypeEvalContext context);
@Nullable
PyType getReferenceType(@NotNull PsiElement referenceTarget, TypeEvalContext context);
PyType getReferenceType(@NotNull PsiElement referenceTarget, TypeEvalContext context, @Nullable PsiElement anchor);
@Nullable
PyType getParameterType(PyNamedParameter param, final PyFunction func, TypeEvalContext context);

View File

@@ -138,16 +138,14 @@ public class ResolveImportUtil {
}
}
else if (importStatement instanceof PyImportStatement) { // "import foo"
return resolveModule(qName, file, absolute_import_enabled, 0);
final List<PsiElement> result = resolveModule(qName, file, absolute_import_enabled, 0);
if (result.size() > 0) {
return result;
}
}
// in-python resolution failed
if (moduleQName != null) {
final List<PsiElement> importFrom = resolveModule(moduleQName, file, false, 0);
final PsiElement result = resolveForeignImport(import_element, StringUtil.join(qName.getComponents(), "."),
importFrom.isEmpty() ? null : importFrom.get(0));
return result != null ? Collections.singletonList(result) : Collections.<PsiElement>emptyList();
}
return Collections.emptyList();
final PsiElement result = resolveForeignImport(import_element, qName, moduleQName);
return result != null ? Collections.singletonList(result) : Collections.<PsiElement>emptyList();
}
@NotNull
@@ -500,7 +498,7 @@ public class ResolveImportUtil {
}
@Nullable
private static PsiElement resolveForeignImport(final PyElement importElement, final String importText, final PsiElement importFrom) {
private static PsiElement resolveForeignImport(final PyElement importElement, final PyQualifiedName importText, final PyQualifiedName importFrom) {
for (PyImportResolver resolver : Extensions.getExtensions(PyImportResolver.EP_NAME)) {
PsiElement result = resolver.resolveImportReference(importElement, importText, importFrom);
if (result != null) {

View File

@@ -69,7 +69,7 @@ public class PyTypeProviderBase implements PyTypeProvider {
}
@Override
public PyType getReferenceType(@NotNull PsiElement referenceTarget, TypeEvalContext context) {
public PyType getReferenceType(@NotNull PsiElement referenceTarget, TypeEvalContext context, @Nullable PsiElement anchor) {
return null;
}

View File

@@ -0,0 +1,3 @@
import java
java.la<ref>ng.System.out

View File

@@ -0,0 +1 @@
import ja<ref>va

View File

@@ -0,0 +1,4 @@
import java
from java import util
l = util.ArrayLi<ref>st()