From 1399a0c594f7ea23dd7e0328b01ba344bfc542ef Mon Sep 17 00:00:00 2001 From: Petr Date: Tue, 8 Jul 2025 18:49:52 +0200 Subject: [PATCH] PY-81981 Sync pushed language level GitOrigin-RevId: d60893c0631846bf411819c5d2687e411a0a578c --- .../intellij.python.community.impl.xml | 2 + .../jetbrains/python/PyLanguageFacadeBase.kt | 38 +++++++++++++++++++ .../com/jetbrains/python/ast/PyAstFile.java | 5 ++- .../python/psi/PyAstElementGenerator.java | 7 +--- .../com/jetbrains/python/PyLanguageFacade.kt | 24 ++++++++++-- .../jetbrains/python/psi/LanguageLevel.java | 2 +- .../jetbrains/python/PyLanguageFacadeImpl.kt | 22 ++++------- .../psi/impl/PyElementGeneratorImpl.java | 5 --- .../jetbrains/python/psi/impl/PyFileImpl.java | 7 ---- .../psi/impl/PythonLanguageLevelPusher.java | 32 ++++++++-------- .../VirtualFilePyLanguageLevelListener.kt | 15 ++++++++ python/python-syntax/BUILD.bazel | 1 + .../python-syntax/intellij.python.syntax.iml | 23 +++++++++++ .../PySyntaxHighlighterFactoryBase.java | 7 +++- .../python/psi/LanguageLevelHolder.kt | 6 +++ .../PySyntaxHighlighterFactory.java | 10 ----- ...yLangLevelVirtualFileCustomDataProvider.kt | 37 ++++++++++++++++++ .../console/IPythonConsoleParsingTest.kt | 5 +-- 18 files changed, 180 insertions(+), 68 deletions(-) create mode 100644 python/python-ast/src/com/jetbrains/python/PyLanguageFacadeBase.kt create mode 100644 python/python-psi-impl/src/com/jetbrains/python/psi/impl/VirtualFilePyLanguageLevelListener.kt create mode 100644 python/python-syntax/src/com/jetbrains/python/psi/LanguageLevelHolder.kt create mode 100644 python/src/com/jetbrains/python/psi/PyLangLevelVirtualFileCustomDataProvider.kt diff --git a/python/pluginResources/intellij.python.community.impl.xml b/python/pluginResources/intellij.python.community.impl.xml index ce2a4462fc37..77be0882305f 100644 --- a/python/pluginResources/intellij.python.community.impl.xml +++ b/python/pluginResources/intellij.python.community.impl.xml @@ -63,6 +63,8 @@ + + diff --git a/python/python-ast/src/com/jetbrains/python/PyLanguageFacadeBase.kt b/python/python-ast/src/com/jetbrains/python/PyLanguageFacadeBase.kt new file mode 100644 index 000000000000..23e4ce40bb12 --- /dev/null +++ b/python/python-ast/src/com/jetbrains/python/PyLanguageFacadeBase.kt @@ -0,0 +1,38 @@ +package com.jetbrains.python + +import com.intellij.injected.editor.VirtualFileWindow +import com.intellij.notebook.editor.BackedVirtualFile +import com.intellij.openapi.project.Project +import com.intellij.openapi.vfs.VirtualFile +import com.intellij.psi.PsiDirectory +import com.intellij.psi.PsiElement +import com.jetbrains.python.ast.PyAstFile +import com.jetbrains.python.psi.LanguageLevel +import org.jetbrains.annotations.ApiStatus + +@ApiStatus.Internal +abstract class PyLanguageFacadeBase : PyLanguageFacade() { + final override fun getEffectiveLanguageLevel(psiElement: PsiElement): LanguageLevel { + if (psiElement is PsiDirectory) { + return getEffectiveLanguageLevel(psiElement.getProject(), psiElement.getVirtualFile()) + } + + val containingFile = psiElement.getContainingFile() + if (containingFile is PyAstFile) { + return containingFile.languageLevel + } + + return LanguageLevel.getDefault() + } + + final override fun getEffectiveLanguageLevel(project: Project, virtualFile: VirtualFile): LanguageLevel { + var file = virtualFile + if (file is VirtualFileWindow) { + file = file.getDelegate() + } + file = BackedVirtualFile.getOriginFileIfBacked(file) + return doGetEffectiveLanguageLevel(project, file) + } + + protected abstract fun doGetEffectiveLanguageLevel(project: Project, virtualFile: VirtualFile): LanguageLevel +} diff --git a/python/python-ast/src/com/jetbrains/python/ast/PyAstFile.java b/python/python-ast/src/com/jetbrains/python/ast/PyAstFile.java index 0b8ef50e5909..402d0278779d 100644 --- a/python/python-ast/src/com/jetbrains/python/ast/PyAstFile.java +++ b/python/python-ast/src/com/jetbrains/python/ast/PyAstFile.java @@ -18,6 +18,7 @@ package com.jetbrains.python.ast; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; import com.intellij.psi.util.PsiTreeUtil; +import com.jetbrains.python.PyLanguageFacadeKt; import com.jetbrains.python.ast.controlFlow.AstScopeOwner; import com.jetbrains.python.ast.docstring.DocStringUtilCore; import com.jetbrains.python.ast.impl.PyPsiUtilsCore; @@ -43,7 +44,9 @@ public interface PyAstFile extends PyAstElement, PsiFile, PyAstDocStringOwner, A return stmts; } - LanguageLevel getLanguageLevel(); + default LanguageLevel getLanguageLevel() { + return PyLanguageFacadeKt.getEffectiveLanguageLevel(this); + } /** * Return true if the file contains a 'from __future__ import ...' statement with given feature. diff --git a/python/python-ast/src/com/jetbrains/python/psi/PyAstElementGenerator.java b/python/python-ast/src/com/jetbrains/python/psi/PyAstElementGenerator.java index 944dbc0d4415..6e6a74a2699a 100644 --- a/python/python-ast/src/com/jetbrains/python/psi/PyAstElementGenerator.java +++ b/python/python-ast/src/com/jetbrains/python/psi/PyAstElementGenerator.java @@ -2,19 +2,18 @@ package com.jetbrains.python.psi; import com.intellij.lang.ASTNode; import com.intellij.openapi.project.Project; -import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; import com.intellij.psi.PsiFileFactory; import com.intellij.psi.impl.PsiFileFactoryImpl; import com.intellij.testFramework.LightVirtualFile; import com.intellij.util.IncorrectOperationException; +import com.jetbrains.python.PyLanguageFacade; import com.jetbrains.python.PythonFileType; import com.jetbrains.python.PythonLanguage; import com.jetbrains.python.ast.*; import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; import java.util.Arrays; @@ -103,7 +102,7 @@ public class PyAstElementGenerator { final PsiFileFactory factory = PsiFileFactory.getInstance(myProject); final String name = getDummyFileName(); final LightVirtualFile virtualFile = new LightVirtualFile(name, PythonFileType.INSTANCE, contents); - specifyFileLanguageLevel(virtualFile, langLevel); + PyLanguageFacade.getINSTANCE().setEffectiveLanguageLevel(virtualFile, langLevel); final PsiFile psiFile = ((PsiFileFactoryImpl)factory).trySetupPsiForFile(virtualFile, PythonLanguage.getInstance(), physical, true); assert psiFile != null; return psiFile; @@ -127,8 +126,6 @@ public class PyAstElementGenerator { return (PyAstPassStatement)statementList.getStatements()[0]; } - protected void specifyFileLanguageLevel(@NotNull VirtualFile virtualFile, @Nullable LanguageLevel langLevel) { } - public @NotNull PyAstExpression createExpressionFromText(@NotNull LanguageLevel languageLevel, @NotNull String text) throws IncorrectOperationException { final PsiFile dummyFile = createDummyFile(languageLevel, text); diff --git a/python/python-parser/src/com/jetbrains/python/PyLanguageFacade.kt b/python/python-parser/src/com/jetbrains/python/PyLanguageFacade.kt index e4efd3e71bfc..8a25d9ba4a03 100644 --- a/python/python-parser/src/com/jetbrains/python/PyLanguageFacade.kt +++ b/python/python-parser/src/com/jetbrains/python/PyLanguageFacade.kt @@ -2,14 +2,32 @@ package com.jetbrains.python import com.intellij.openapi.application.ApplicationManager import com.intellij.openapi.components.service +import com.intellij.openapi.project.Project +import com.intellij.openapi.vfs.VirtualFile import com.intellij.psi.PsiElement +import com.intellij.psi.PsiFile import com.jetbrains.python.psi.LanguageLevel +import org.jetbrains.annotations.ApiStatus +@ApiStatus.Experimental abstract class PyLanguageFacade { - abstract fun forLanguage(psiElement: PsiElement): LanguageLevel + abstract fun getEffectiveLanguageLevel(psiElement: PsiElement): LanguageLevel + abstract fun getEffectiveLanguageLevel(project: Project, virtualFile: VirtualFile): LanguageLevel + abstract fun setEffectiveLanguageLevel(virtualFile: VirtualFile, languageLevel: LanguageLevel?) companion object { + @JvmStatic val INSTANCE: PyLanguageFacade - get() = ApplicationManager.getApplication().service() + get() = ApplicationManager.getApplication().service() } -} \ No newline at end of file +} + +@ApiStatus.Internal +fun getEffectiveLanguageLevel(file: PsiFile): LanguageLevel { + var curFile = file + while (curFile != curFile.getOriginalFile()) { + curFile = curFile.getOriginalFile() + } + val virtualFile = curFile.getVirtualFile() ?: curFile.getViewProvider().getVirtualFile() + return PyLanguageFacade.INSTANCE.getEffectiveLanguageLevel(curFile.project, virtualFile) +} diff --git a/python/python-parser/src/com/jetbrains/python/psi/LanguageLevel.java b/python/python-parser/src/com/jetbrains/python/psi/LanguageLevel.java index f0eb2c156f95..a172d00470ae 100644 --- a/python/python-parser/src/com/jetbrains/python/psi/LanguageLevel.java +++ b/python/python-parser/src/com/jetbrains/python/psi/LanguageLevel.java @@ -212,7 +212,7 @@ public enum LanguageLevel { } public static @NotNull LanguageLevel forElement(@NotNull PsiElement element) { - return PyLanguageFacade.Companion.getINSTANCE().forLanguage(element); + return PyLanguageFacade.getINSTANCE().getEffectiveLanguageLevel(element); } public static @NotNull LanguageLevel getLatest() { diff --git a/python/python-psi-impl/src/com/jetbrains/python/PyLanguageFacadeImpl.kt b/python/python-psi-impl/src/com/jetbrains/python/PyLanguageFacadeImpl.kt index 3e9989cf60c7..57deac1a2b60 100644 --- a/python/python-psi-impl/src/com/jetbrains/python/PyLanguageFacadeImpl.kt +++ b/python/python-psi-impl/src/com/jetbrains/python/PyLanguageFacadeImpl.kt @@ -1,22 +1,16 @@ package com.jetbrains.python -import com.intellij.psi.PsiDirectory -import com.intellij.psi.PsiElement +import com.intellij.openapi.project.Project +import com.intellij.openapi.vfs.VirtualFile import com.jetbrains.python.psi.LanguageLevel -import com.jetbrains.python.psi.PyFile import com.jetbrains.python.psi.impl.PythonLanguageLevelPusher -class PyLanguageFacadeImpl : PyLanguageFacade() { - override fun forLanguage(psiElement: PsiElement): LanguageLevel { - if (psiElement is PsiDirectory) { - return PythonLanguageLevelPusher.getLanguageLevelForVirtualFile(psiElement.getProject(), psiElement.getVirtualFile()) - } +class PyLanguageFacadeImpl : PyLanguageFacadeBase() { + override fun doGetEffectiveLanguageLevel(project: Project, virtualFile: VirtualFile): LanguageLevel { + return PythonLanguageLevelPusher.getEffectiveLanguageLevel(project, virtualFile) + } - val containingFile = psiElement.getContainingFile() - if (containingFile is PyFile) { - return containingFile.getLanguageLevel() - } - - return LanguageLevel.getDefault() + override fun setEffectiveLanguageLevel(virtualFile: VirtualFile, languageLevel: LanguageLevel?) { + PythonLanguageLevelPusher.specifyFileLanguageLevel(virtualFile, languageLevel) } } \ No newline at end of file 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 ca531850f4a0..c42f8b784e1c 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 @@ -36,11 +36,6 @@ public final class PyElementGeneratorImpl extends PyElementGenerator { super(project); } - @Override - protected void specifyFileLanguageLevel(@NotNull VirtualFile virtualFile, @Nullable LanguageLevel langLevel) { - PythonLanguageLevelPusher.specifyFileLanguageLevel(virtualFile, langLevel); - } - @Override public ASTNode createNameIdentifier(String name, LanguageLevel languageLevel) { final PsiFile dummyFile = createDummyFile(languageLevel, name); diff --git a/python/python-psi-impl/src/com/jetbrains/python/psi/impl/PyFileImpl.java b/python/python-psi-impl/src/com/jetbrains/python/psi/impl/PyFileImpl.java index 1812889dfc20..504a0a1aef55 100644 --- a/python/python-psi-impl/src/com/jetbrains/python/psi/impl/PyFileImpl.java +++ b/python/python-psi-impl/src/com/jetbrains/python/psi/impl/PyFileImpl.java @@ -18,7 +18,6 @@ import com.intellij.psi.scope.DelegatingScopeProcessor; import com.intellij.psi.scope.PsiScopeProcessor; import com.intellij.psi.stubs.StubElement; import com.intellij.psi.util.PsiModificationTracker; -import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.QualifiedName; import com.intellij.util.IncorrectOperationException; import com.intellij.util.Processor; @@ -27,7 +26,6 @@ import com.jetbrains.python.PyNames; import com.jetbrains.python.PythonFileType; import com.jetbrains.python.PythonLanguage; import com.jetbrains.python.ast.PyAstElementVisitor; -import com.jetbrains.python.ast.impl.PyUtilCore; import com.jetbrains.python.codeInsight.controlflow.ControlFlowCache; import com.jetbrains.python.documentation.docstrings.DocStringUtil; import com.jetbrains.python.psi.*; @@ -247,11 +245,6 @@ public class PyFileImpl extends PsiFileBase implements PyFile, PyExpression { return null; } - @Override - public LanguageLevel getLanguageLevel() { - return PythonLanguageLevelPusher.getLanguageLevelForFile(this); - } - @Override public Icon getIcon(int flags) { return PythonFileType.INSTANCE.getIcon(); 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 5bfa916fc962..dc05015dc1af 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 @@ -2,8 +2,6 @@ package com.jetbrains.python.psi.impl; import com.google.common.collect.Maps; -import com.intellij.injected.editor.VirtualFileWindow; -import com.intellij.notebook.editor.BackedVirtualFile; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.ReadAction; import com.intellij.openapi.fileTypes.FileTypeRegistry; @@ -31,9 +29,7 @@ import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.TreeNodeProcessingResult; import com.intellij.util.indexing.IndexingBundle; import com.intellij.util.messages.SimpleMessageBusConnection; -import com.jetbrains.python.PythonCodeStyleService; -import com.jetbrains.python.PythonFileType; -import com.jetbrains.python.PythonRuntimeService; +import com.jetbrains.python.*; import com.jetbrains.python.codeInsight.typing.PyTypeShed; import com.jetbrains.python.module.PyModuleService; import com.jetbrains.python.psi.LanguageLevel; @@ -159,6 +155,15 @@ public final class PythonLanguageLevelPusher implements FilePropertyPusher = Topic(VirtualFilePyLanguageLevelListener::class.java) + } + + fun levelChanged(virtualFile: VirtualFile, newLevel: LanguageLevel) +} diff --git a/python/python-syntax/BUILD.bazel b/python/python-syntax/BUILD.bazel index d8787acf050f..5319a6c87c25 100644 --- a/python/python-syntax/BUILD.bazel +++ b/python/python-syntax/BUILD.bazel @@ -28,6 +28,7 @@ jvm_library( "//platform/code-style-impl:codeStyle-impl", "@lib//:fastutil-min", "@lib//:guava", + "@lib//:kotlinx-serialization-core", ], runtime_deps = [":syntax_resources"] ) diff --git a/python/python-syntax/intellij.python.syntax.iml b/python/python-syntax/intellij.python.syntax.iml index 0dde512bff2e..c4363580c1ce 100644 --- a/python/python-syntax/intellij.python.syntax.iml +++ b/python/python-syntax/intellij.python.syntax.iml @@ -1,5 +1,27 @@ + + + + + + + + + + + + + + $KOTLIN_BUNDLED$/lib/kotlinx-serialization-compiler-plugin.jar + + + + + + + @@ -23,5 +45,6 @@ + \ No newline at end of file diff --git a/python/python-syntax/src/com/jetbrains/python/highlighting/PySyntaxHighlighterFactoryBase.java b/python/python-syntax/src/com/jetbrains/python/highlighting/PySyntaxHighlighterFactoryBase.java index 860a7c29eff2..9ef522a99cf4 100644 --- a/python/python-syntax/src/com/jetbrains/python/highlighting/PySyntaxHighlighterFactoryBase.java +++ b/python/python-syntax/src/com/jetbrains/python/highlighting/PySyntaxHighlighterFactoryBase.java @@ -6,6 +6,7 @@ import com.intellij.openapi.fileTypes.SyntaxHighlighterFactory; import com.intellij.openapi.project.Project; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.util.containers.FactoryMap; +import com.jetbrains.python.PyLanguageFacade; import com.jetbrains.python.lexer.PythonHighlightingLexer; import com.jetbrains.python.parsing.console.PyConsoleHighlightingLexer; import com.jetbrains.python.psi.LanguageLevel; @@ -48,8 +49,10 @@ public class PySyntaxHighlighterFactoryBase extends SyntaxHighlighterFactory { return myMap.get(level); } - protected LanguageLevel getLanguageLevel(final @Nullable Project project, final @Nullable VirtualFile virtualFile) { - return LanguageLevel.getDefault(); + private static @NotNull LanguageLevel getLanguageLevel(final @Nullable Project project, final @Nullable VirtualFile virtualFile) { + return project != null && virtualFile != null ? + PyLanguageFacade.getINSTANCE().getEffectiveLanguageLevel(project, virtualFile) : + LanguageLevel.getDefault(); } protected boolean useConsoleLexer(final @Nullable Project project, final @Nullable VirtualFile virtualFile) { diff --git a/python/python-syntax/src/com/jetbrains/python/psi/LanguageLevelHolder.kt b/python/python-syntax/src/com/jetbrains/python/psi/LanguageLevelHolder.kt new file mode 100644 index 000000000000..410ab7b90f87 --- /dev/null +++ b/python/python-syntax/src/com/jetbrains/python/psi/LanguageLevelHolder.kt @@ -0,0 +1,6 @@ +package com.jetbrains.python.psi + +import kotlinx.serialization.Serializable + +@Serializable +class LanguageLevelHolder(val languageLevel: LanguageLevel) \ No newline at end of file diff --git a/python/src/com/jetbrains/python/highlighting/PySyntaxHighlighterFactory.java b/python/src/com/jetbrains/python/highlighting/PySyntaxHighlighterFactory.java index efb7c6e76908..0e6a7d93b0fe 100644 --- a/python/src/com/jetbrains/python/highlighting/PySyntaxHighlighterFactory.java +++ b/python/src/com/jetbrains/python/highlighting/PySyntaxHighlighterFactory.java @@ -8,20 +8,10 @@ import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.PsiFile; import com.intellij.psi.PsiManager; import com.jetbrains.python.console.PydevConsoleRunnerUtil; -import com.jetbrains.python.psi.LanguageLevel; -import com.jetbrains.python.psi.impl.PythonLanguageLevelPusher; -import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; public final class PySyntaxHighlighterFactory extends PySyntaxHighlighterFactoryBase { - @Override - protected @NotNull LanguageLevel getLanguageLevel(final @Nullable Project project, final @Nullable VirtualFile virtualFile) { - return project != null && virtualFile != null ? - PythonLanguageLevelPusher.getLanguageLevelForVirtualFile(project, virtualFile) : - LanguageLevel.getDefault(); - } - @Override protected boolean useConsoleLexer(final @Nullable Project project, final @Nullable VirtualFile virtualFile) { if (virtualFile == null || project == null || virtualFile instanceof VirtualFileWindow) { diff --git a/python/src/com/jetbrains/python/psi/PyLangLevelVirtualFileCustomDataProvider.kt b/python/src/com/jetbrains/python/psi/PyLangLevelVirtualFileCustomDataProvider.kt new file mode 100644 index 000000000000..e03cb4f7cb5c --- /dev/null +++ b/python/src/com/jetbrains/python/psi/PyLangLevelVirtualFileCustomDataProvider.kt @@ -0,0 +1,37 @@ +// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +package com.jetbrains.python.psi + +import com.intellij.openapi.application.readAction +import com.intellij.openapi.project.Project +import com.intellij.openapi.vfs.VirtualFile +import com.intellij.openapi.vfs.VirtualFileCustomDataProvider +import com.intellij.util.messages.impl.subscribeAsFlow +import com.jetbrains.python.psi.impl.PythonLanguageLevelPusher +import com.jetbrains.python.psi.impl.VirtualFilePyLanguageLevelListener +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.map +import kotlin.reflect.KType +import kotlin.reflect.typeOf + +class PyLangLevelVirtualFileCustomDataProvider : VirtualFileCustomDataProvider { + override val id: String = "virtualFilePyLangLevel" + + override val dataType: KType + get() = typeOf() + + override fun getValues(project: Project, virtualFile: VirtualFile): Flow { + return project.messageBus.subscribeAsFlow(VirtualFilePyLanguageLevelListener.TOPIC) { + val level = readAction { PythonLanguageLevelPusher.getEffectiveLanguageLevel(project, virtualFile) } + trySend(level) + + val vFile = virtualFile + object : VirtualFilePyLanguageLevelListener { + override fun levelChanged(virtualFile: VirtualFile, newLevel: LanguageLevel) { + if (vFile == virtualFile) { + trySend(newLevel) + } + } + } + }.map { LanguageLevelHolder(it) } + } +} \ No newline at end of file diff --git a/python/testSrc/com/jetbrains/python/console/IPythonConsoleParsingTest.kt b/python/testSrc/com/jetbrains/python/console/IPythonConsoleParsingTest.kt index ab27a041ed7c..53ca70130ca0 100644 --- a/python/testSrc/com/jetbrains/python/console/IPythonConsoleParsingTest.kt +++ b/python/testSrc/com/jetbrains/python/console/IPythonConsoleParsingTest.kt @@ -4,9 +4,7 @@ package com.jetbrains.python.console import com.intellij.lang.LanguageASTFactory import com.intellij.openapi.application.PathManager import com.intellij.testFramework.ParsingTestCase -import com.jetbrains.python.PythonDialectsTokenSetContributor -import com.jetbrains.python.PythonLanguage -import com.jetbrains.python.PythonTokenSetContributor +import com.jetbrains.python.* import com.jetbrains.python.psi.impl.PythonASTFactory /** @@ -24,6 +22,7 @@ class IPythonConsoleParsingTest : ParsingTestCase( override fun setUp() { super.setUp() + application.registerService(PyLanguageFacade::class.java, PyLanguageFacadeImpl()) registerExtensionPoint(PythonDialectsTokenSetContributor.EP_NAME, PythonDialectsTokenSetContributor::class.java) registerExtension(PythonDialectsTokenSetContributor.EP_NAME, PythonTokenSetContributor()) addExplicitExtension(LanguageASTFactory.INSTANCE, PythonLanguage.getInstance(), PythonASTFactory())