diff --git a/python/python-psi-api/src/com/jetbrains/python/psi/LanguageLevel.java b/python/python-psi-api/src/com/jetbrains/python/psi/LanguageLevel.java index b59dd8142521..1e2469cfbcea 100644 --- a/python/python-psi-api/src/com/jetbrains/python/psi/LanguageLevel.java +++ b/python/python-psi-api/src/com/jetbrains/python/psi/LanguageLevel.java @@ -18,7 +18,6 @@ package com.jetbrains.python.psi; import com.google.common.collect.ImmutableList; import com.intellij.openapi.util.Key; import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiFile; import com.intellij.util.ArrayUtil; import org.jetbrains.annotations.NotNull; @@ -204,11 +203,7 @@ public enum LanguageLevel { @NotNull public static LanguageLevel forElement(@NotNull PsiElement element) { - final PsiFile containingFile = element.getContainingFile(); - if (containingFile instanceof PyFile) { - return ((PyFile)containingFile).getLanguageLevel(); - } - return getDefault(); + return PyPsiFacade.getInstance(element.getProject()).getLanguageLevel(element); } @NotNull diff --git a/python/python-psi-api/src/com/jetbrains/python/psi/PyPsiFacade.java b/python/python-psi-api/src/com/jetbrains/python/psi/PyPsiFacade.java index a76d31093b7c..481cd3bda6b7 100644 --- a/python/python-psi-api/src/com/jetbrains/python/psi/PyPsiFacade.java +++ b/python/python-psi-api/src/com/jetbrains/python/psi/PyPsiFacade.java @@ -78,4 +78,7 @@ public abstract class PyPsiFacade { @Nullable public abstract String findShortestImportableName(@NotNull VirtualFile targetFile, @NotNull PsiElement anchor); + + @NotNull + public abstract LanguageLevel getLanguageLevel(@NotNull PsiElement element); } diff --git a/python/python-psi-impl/src/com/jetbrains/python/psi/impl/PyPsiFacadeImpl.java b/python/python-psi-impl/src/com/jetbrains/python/psi/impl/PyPsiFacadeImpl.java index 802f0dfc0035..91ae062c94c0 100644 --- a/python/python-psi-impl/src/com/jetbrains/python/psi/impl/PyPsiFacadeImpl.java +++ b/python/python-psi-impl/src/com/jetbrains/python/psi/impl/PyPsiFacadeImpl.java @@ -19,11 +19,12 @@ import com.intellij.openapi.module.Module; import com.intellij.openapi.module.ModuleUtilCore; import com.intellij.openapi.project.Project; import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.psi.PsiDirectory; import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiFile; import com.intellij.psi.util.QualifiedName; import com.intellij.util.ObjectUtils; -import com.jetbrains.python.psi.PyClass; -import com.jetbrains.python.psi.PyPsiFacade; +import com.jetbrains.python.psi.*; import com.jetbrains.python.psi.resolve.PyQualifiedNameResolveContext; import com.jetbrains.python.psi.resolve.PyResolveImportUtil; import com.jetbrains.python.psi.resolve.QualifiedNameFinder; @@ -36,6 +37,8 @@ import org.jetbrains.annotations.Nullable; import java.util.Collection; import java.util.List; +import static com.jetbrains.python.psi.LanguageLevel.getDefault; + /** * @author yole */ @@ -113,4 +116,20 @@ public class PyPsiFacadeImpl extends PyPsiFacade { public String findShortestImportableName(@NotNull VirtualFile targetFile, @NotNull PsiElement anchor) { return QualifiedNameFinder.findShortestImportableName(anchor, targetFile); } + + @NotNull + @Override + public LanguageLevel getLanguageLevel(@NotNull PsiElement element) { + if (element instanceof PsiDirectory) { + final PsiDirectory directory = (PsiDirectory)element; + return PyUtil.getLanguageLevelForVirtualFile(directory.getProject(), directory.getVirtualFile()); + } + + final PsiFile containingFile = element.getContainingFile(); + if (containingFile instanceof PyFile) { + return ((PyFile)containingFile).getLanguageLevel(); + } + + return getDefault(); + } } diff --git a/python/python-psi-impl/test/com/jetbrains/python/PythonParsingTest.java b/python/python-psi-impl/test/com/jetbrains/python/PythonParsingTest.java index 09d492e6c957..4e854280977c 100644 --- a/python/python-psi-impl/test/com/jetbrains/python/PythonParsingTest.java +++ b/python/python-psi-impl/test/com/jetbrains/python/PythonParsingTest.java @@ -22,6 +22,8 @@ import com.intellij.testFramework.ParsingTestCase; import com.intellij.testFramework.TestDataPath; import com.jetbrains.python.psi.LanguageLevel; import com.jetbrains.python.psi.PyFunction; +import com.jetbrains.python.psi.PyPsiFacade; +import com.jetbrains.python.psi.impl.PyPsiFacadeImpl; import com.jetbrains.python.psi.impl.PythonASTFactory; import org.jetbrains.annotations.NotNull; @@ -50,6 +52,7 @@ public class PythonParsingTest extends ParsingTestCase { registerExtension(PythonDialectsTokenSetContributor.EP_NAME, new PythonTokenSetContributor()); addExplicitExtension(LanguageASTFactory.INSTANCE, PythonLanguage.getInstance(), new PythonASTFactory()); PythonDialectsTokenSetProvider.reset(); + getProject().registerService(PyPsiFacade.class, PyPsiFacadeImpl.class); } @Override diff --git a/python/testSrc/com/jetbrains/python/PyMultiFileResolveTest.java b/python/testSrc/com/jetbrains/python/PyMultiFileResolveTest.java index 5c02e81f8057..aba809348836 100644 --- a/python/testSrc/com/jetbrains/python/PyMultiFileResolveTest.java +++ b/python/testSrc/com/jetbrains/python/PyMultiFileResolveTest.java @@ -534,9 +534,14 @@ public class PyMultiFileResolveTest extends PyMultiFileResolveTestCase { // PY-19989 public void testAmbiguousImplicitRelativeImport() { - prepareTestDirectory(); - assertSameElements(doMultiResolveAndGetFileUrls("pkg2/__init__.py"), "pkg2/mod.py"); - assertSameElements(doMultiResolveAndGetFileUrls("pkg/__init__.py"), "pkg/mod.py"); + runWithLanguageLevel( + LanguageLevel.PYTHON27, + () -> { + prepareTestDirectory(); + assertSameElements(doMultiResolveAndGetFileUrls("pkg2/__init__.py"), "pkg2/mod.py"); + assertSameElements(doMultiResolveAndGetFileUrls("pkg/__init__.py"), "pkg/mod.py"); + } + ); } // PY-21088