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 abb6930b3835..2c5fd76c53b2 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 @@ -16,9 +16,9 @@ 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.util.ArrayUtil; +import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -96,6 +96,7 @@ public enum LanguageLevel { private static final LanguageLevel DEFAULT2 = PYTHON27; private static final LanguageLevel DEFAULT3 = PYTHON39; + @ApiStatus.Internal public static LanguageLevel FORCE_LANGUAGE_LEVEL = null; @NotNull @@ -217,8 +218,6 @@ public enum LanguageLevel { return version / 10 + "." + version % 10; } - public static final Key KEY = new Key<>("python.language.level"); - @NotNull public static LanguageLevel forElement(@NotNull PsiElement element) { return PyPsiFacade.getInstance(element.getProject()).getLanguageLevel(element); diff --git a/python/python-psi-impl/src/com/jetbrains/python/psi/PyUtil.java b/python/python-psi-impl/src/com/jetbrains/python/psi/PyUtil.java index df75f767d4d5..428f9567e4a0 100644 --- a/python/python-psi-impl/src/com/jetbrains/python/psi/PyUtil.java +++ b/python/python-psi-impl/src/com/jetbrains/python/psi/PyUtil.java @@ -582,7 +582,7 @@ public class PyUtil { // Most of the cases should be handled by this one, PyLanguageLevelPusher pushes folders only final VirtualFile folder = virtualFile.getParent(); if (folder != null) { - final LanguageLevel folderLevel = LanguageLevel.fromPythonVersion(folder.getUserData(LanguageLevel.KEY)); + final LanguageLevel folderLevel = PythonLanguageLevelPusher.specifiedFileLanguageLevel(folder); if (folderLevel != null) { return folderLevel; } @@ -594,7 +594,7 @@ public class PyUtil { else { // However this allows us to setup language level per file manually // in case when it is LightVirtualFile - final LanguageLevel level = LanguageLevel.fromPythonVersion(virtualFile.getUserData(LanguageLevel.KEY)); + final LanguageLevel level = PythonLanguageLevelPusher.specifiedFileLanguageLevel(virtualFile); if (level != null) return level; if (ApplicationManager.getApplication().isUnitTestMode()) { diff --git a/python/python-psi-impl/src/com/jetbrains/python/psi/impl/PyElementGeneratorImpl.java b/python/python-psi-impl/src/com/jetbrains/python/psi/impl/PyElementGeneratorImpl.java index 9d7265ec2ade..66bba7428ff0 100644 --- a/python/python-psi-impl/src/com/jetbrains/python/psi/impl/PyElementGeneratorImpl.java +++ b/python/python-psi-impl/src/com/jetbrains/python/psi/impl/PyElementGeneratorImpl.java @@ -65,7 +65,7 @@ public class PyElementGeneratorImpl extends PyElementGenerator { final PsiFileFactory factory = PsiFileFactory.getInstance(myProject); final String name = getDummyFileName(); final LightVirtualFile virtualFile = new LightVirtualFile(name, PythonFileType.INSTANCE, contents); - virtualFile.putUserData(LanguageLevel.KEY, LanguageLevel.toPythonVersion(langLevel)); + PythonLanguageLevelPusher.specifyFileLanguageLevel(virtualFile, langLevel); final PsiFile psiFile = ((PsiFileFactoryImpl)factory).trySetupPsiForFile(virtualFile, PythonLanguage.getInstance(), physical, true); assert psiFile != null; return psiFile; diff --git a/python/python-psi-impl/src/com/jetbrains/python/psi/impl/PythonLanguageLevelPusher.java b/python/python-psi-impl/src/com/jetbrains/python/psi/impl/PythonLanguageLevelPusher.java index bb9803331a7b..8dc86b9889d4 100644 --- a/python/python-psi-impl/src/com/jetbrains/python/psi/impl/PythonLanguageLevelPusher.java +++ b/python/python-psi-impl/src/com/jetbrains/python/psi/impl/PythonLanguageLevelPusher.java @@ -52,7 +52,7 @@ import java.util.stream.Collectors; * @author yole */ public class PythonLanguageLevelPusher implements FilePropertyPusher { - private static final Key PYTHON_LANGUAGE_LEVEL = Key.create("PYTHON_LANGUAGE_LEVEL"); + private static final Key KEY = new Key<>("python.language.level"); /* It so happens that no single language level is compatible with more than one other. So a map suffices for representation*/ public static final Map COMPATIBLE_LEVELS; @@ -85,7 +85,7 @@ public class PythonLanguageLevelPusher implements FilePropertyPusher { @Override @NotNull public Key getFileDataKey() { - return LanguageLevel.KEY; + return KEY; } @Override @@ -306,17 +306,17 @@ public class PythonLanguageLevelPusher implements FilePropertyPusher { @NotNull public static LanguageLevel guessLanguageLevelWithCaching(@NotNull Project project) { - LanguageLevel languageLevel = LanguageLevel.fromPythonVersion(project.getUserData(PYTHON_LANGUAGE_LEVEL)); + LanguageLevel languageLevel = LanguageLevel.fromPythonVersion(project.getUserData(KEY)); if (languageLevel == null) { languageLevel = guessLanguageLevel(project); - project.putUserData(PYTHON_LANGUAGE_LEVEL, LanguageLevel.toPythonVersion(languageLevel)); + project.putUserData(KEY, LanguageLevel.toPythonVersion(languageLevel)); } return languageLevel; } private static void resetProjectLanguageLevel(@NotNull Project project) { - project.putUserData(PYTHON_LANGUAGE_LEVEL, null); + project.putUserData(KEY, null); } @NotNull @@ -399,6 +399,15 @@ public class PythonLanguageLevelPusher implements FilePropertyPusher { PushedFilePropertiesUpdater.getInstance(project).pushAll(new PythonLanguageLevelPusher()); } + public static void specifyFileLanguageLevel(@NotNull VirtualFile file, @Nullable LanguageLevel languageLevel) { + file.putUserData(KEY, LanguageLevel.toPythonVersion(languageLevel)); + } + + @Nullable + public static LanguageLevel specifiedFileLanguageLevel(@NotNull VirtualFile file) { + return LanguageLevel.fromPythonVersion(file.getUserData(KEY)); + } + public void flushLanguageLevelCache() { myModuleSdks.clear(); } diff --git a/python/src/com/jetbrains/python/console/PydevConsoleExecuteActionHandler.kt b/python/src/com/jetbrains/python/console/PydevConsoleExecuteActionHandler.kt index 52da052e102d..fd862e713460 100644 --- a/python/src/com/jetbrains/python/console/PydevConsoleExecuteActionHandler.kt +++ b/python/src/com/jetbrains/python/console/PydevConsoleExecuteActionHandler.kt @@ -12,10 +12,10 @@ import com.intellij.openapi.editor.markup.TextAttributes import com.intellij.psi.util.PsiTreeUtil import com.jetbrains.python.console.pydev.ConsoleCommunication import com.jetbrains.python.console.pydev.ConsoleCommunicationListener -import com.jetbrains.python.psi.LanguageLevel import com.jetbrains.python.psi.PyElementGenerator import com.jetbrains.python.psi.PyFile import com.jetbrains.python.psi.PyStatementList +import com.jetbrains.python.psi.PyUtil import java.awt.Font open class PydevConsoleExecuteActionHandler(private val myConsoleView: LanguageConsoleView, @@ -51,7 +51,7 @@ open class PydevConsoleExecuteActionHandler(private val myConsoleView: LanguageC } override fun checkSingleLine(text: String): Boolean { - val languageLevel = LanguageLevel.fromPythonVersion(myConsoleView.virtualFile.getUserData(LanguageLevel.KEY)) + val languageLevel = PyUtil.getLanguageLevelForVirtualFile(project, myConsoleView.virtualFile) val pyFile = PyElementGenerator.getInstance(project).createDummyFile(languageLevel, text) as PyFile return PsiTreeUtil.findChildOfAnyType(pyFile, PyStatementList::class.java) == null && pyFile.statements.size < 2 } diff --git a/python/src/com/jetbrains/python/console/PythonConsoleView.java b/python/src/com/jetbrains/python/console/PythonConsoleView.java index 668f2d3a586e..3f2e202dbeff 100644 --- a/python/src/com/jetbrains/python/console/PythonConsoleView.java +++ b/python/src/com/jetbrains/python/console/PythonConsoleView.java @@ -48,6 +48,7 @@ import com.jetbrains.python.debugger.PyStackFrame; import com.jetbrains.python.debugger.PyStackFrameInfo; import com.jetbrains.python.highlighting.PyHighlighter; import com.jetbrains.python.psi.LanguageLevel; +import com.jetbrains.python.psi.impl.PythonLanguageLevelPusher; import com.jetbrains.python.sdk.PythonSdkType; import com.jetbrains.python.sdk.flavors.PythonSdkFlavor; import com.jetbrains.python.testing.PyTestsSharedKt; @@ -88,7 +89,7 @@ public class PythonConsoleView extends LanguageConsoleImpl implements Observable myTestMode = testMode; isShowVars = PyConsoleOptions.getInstance(project).isShowVariableByDefault(); VirtualFile virtualFile = getVirtualFile(); - virtualFile.putUserData(LanguageLevel.KEY, LanguageLevel.toPythonVersion(PythonSdkType.getLanguageLevelForSdk(sdk))); + PythonLanguageLevelPusher.specifyFileLanguageLevel(virtualFile, PythonSdkType.getLanguageLevelForSdk(sdk)); virtualFile.putUserData(CONSOLE_KEY, true); // Mark editor as console one, to prevent autopopup completion getConsoleEditor().putUserData(PythonConsoleAutopopupBlockingHandler.REPL_KEY, new Object()); diff --git a/python/testSrc/com/jetbrains/python/console/PythonConsoleParsingTest.java b/python/testSrc/com/jetbrains/python/console/PythonConsoleParsingTest.java index 33f08917ca63..5433472c9b9c 100644 --- a/python/testSrc/com/jetbrains/python/console/PythonConsoleParsingTest.java +++ b/python/testSrc/com/jetbrains/python/console/PythonConsoleParsingTest.java @@ -12,6 +12,7 @@ import com.intellij.testFramework.ParsingTestCase; import com.intellij.testFramework.TestDataPath; import com.jetbrains.python.*; import com.jetbrains.python.psi.LanguageLevel; +import com.jetbrains.python.psi.impl.PythonLanguageLevelPusher; import org.jetbrains.annotations.NotNull; import java.nio.charset.StandardCharsets; @@ -112,7 +113,7 @@ public class PythonConsoleParsingTest extends ParsingTestCase { virtualFile.setOriginalFile(originalFile); originalFile.setCharset(StandardCharsets.UTF_8); - originalFile.putUserData(LanguageLevel.KEY, LanguageLevel.toPythonVersion(myLanguageLevel)); + PythonLanguageLevelPusher.specifyFileLanguageLevel(originalFile, myLanguageLevel); PyConsoleUtil.markIPython(originalFile); return createFile(virtualFile); } diff --git a/python/testSrc/com/jetbrains/python/parsing/PythonParsingTest.java b/python/testSrc/com/jetbrains/python/parsing/PythonParsingTest.java index 3c6c0d43523c..e256e6edaf4d 100644 --- a/python/testSrc/com/jetbrains/python/parsing/PythonParsingTest.java +++ b/python/testSrc/com/jetbrains/python/parsing/PythonParsingTest.java @@ -12,6 +12,7 @@ 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 com.jetbrains.python.psi.impl.PythonLanguageLevelPusher; import org.jetbrains.annotations.NotNull; import java.util.Collection; @@ -954,7 +955,7 @@ public class PythonParsingTest extends ParsingTestCase { @Override protected PsiFile createFile(@NotNull String name, @NotNull String text) { final PsiFile file = super.createFile(name, text); - file.getVirtualFile().putUserData(LanguageLevel.KEY, LanguageLevel.toPythonVersion(myLanguageLevel)); + PythonLanguageLevelPusher.specifyFileLanguageLevel(file.getVirtualFile(), myLanguageLevel); return file; }