diff --git a/python/python-core-impl/intellij.python.community.deprecated.extensions/src/com/jetbrains/extensions/ModuleBasedContextAnchor.kt b/python/python-core-impl/intellij.python.community.deprecated.extensions/src/com/jetbrains/extensions/ModuleBasedContextAnchor.kt new file mode 100644 index 000000000000..fbbf469e3193 --- /dev/null +++ b/python/python-core-impl/intellij.python.community.deprecated.extensions/src/com/jetbrains/extensions/ModuleBasedContextAnchor.kt @@ -0,0 +1,28 @@ +// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +package com.jetbrains.extensions + +import com.intellij.openapi.module.Module +import com.intellij.openapi.project.Project +import com.intellij.openapi.projectRoots.Sdk +import com.intellij.openapi.roots.ModuleRootManager +import com.intellij.openapi.vfs.VirtualFile +import com.intellij.psi.search.GlobalSearchScope +import com.jetbrains.python.psi.resolve.PyQualifiedNameResolveContext +import com.jetbrains.python.psi.resolve.fromModule +import org.jetbrains.annotations.ApiStatus + +/** + * @deprecated moved to {@link com.jetbrains.python.extensions} + */ +@ApiStatus.ScheduledForRemoval +@Deprecated(message = "Moved to com.jetbrains.python") +class ModuleBasedContextAnchor(val module: Module) : ContextAnchor { + override val sdk: Sdk? = module.getSdk() + override val project: Project = module.project + override val qualifiedNameResolveContext: PyQualifiedNameResolveContext = fromModule(module) + override val scope: GlobalSearchScope = module.moduleContentScope + override fun getRoots(): Array { + val manager = ModuleRootManager.getInstance(module) + return super.getRoots() + manager.contentRoots + manager.sourceRoots + } +} \ No newline at end of file diff --git a/python/python-core-impl/intellij.python.community.deprecated.extensions/src/com/jetbrains/extensions/ModuleExt.kt b/python/python-core-impl/intellij.python.community.deprecated.extensions/src/com/jetbrains/extensions/ModuleExt.kt new file mode 100644 index 000000000000..9bd87f7dc3e4 --- /dev/null +++ b/python/python-core-impl/intellij.python.community.deprecated.extensions/src/com/jetbrains/extensions/ModuleExt.kt @@ -0,0 +1,11 @@ +// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +package com.jetbrains.extensions + +import com.intellij.openapi.module.Module +import com.intellij.openapi.projectRoots.Sdk +import com.intellij.openapi.roots.ModuleRootManager +import org.jetbrains.annotations.ApiStatus.ScheduledForRemoval + +@Deprecated(message = "Moved to com.jetbrains.python") +@ScheduledForRemoval +fun Module.getSdk(): Sdk? = ModuleRootManager.getInstance(this).sdk diff --git a/python/python-core-impl/intellij.python.community.deprecated.extensions/src/com/jetbrains/extensions/QualifiedNameExt.kt b/python/python-core-impl/intellij.python.community.deprecated.extensions/src/com/jetbrains/extensions/QualifiedNameExt.kt index df60add8b3ea..53ac2cad7f9c 100644 --- a/python/python-core-impl/intellij.python.community.deprecated.extensions/src/com/jetbrains/extensions/QualifiedNameExt.kt +++ b/python/python-core-impl/intellij.python.community.deprecated.extensions/src/com/jetbrains/extensions/QualifiedNameExt.kt @@ -1,21 +1,23 @@ // Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package com.jetbrains.extensions -import com.intellij.openapi.module.Module import com.intellij.openapi.project.Project import com.intellij.openapi.projectRoots.Sdk -import com.intellij.openapi.roots.ModuleRootManager import com.intellij.openapi.roots.OrderRootType +import com.intellij.openapi.roots.ProjectRootManager import com.intellij.openapi.vfs.VirtualFile +import com.intellij.psi.PsiDirectory import com.intellij.psi.PsiElement +import com.intellij.psi.PsiManager import com.intellij.psi.search.GlobalSearchScope import com.intellij.psi.util.QualifiedName -import com.jetbrains.python.extensions.QNameResolveContext -import com.jetbrains.python.extensions.getElementAndResolvableName -import com.jetbrains.python.extensions.getSdk -import com.jetbrains.python.psi.resolve.PyQualifiedNameResolveContext -import com.jetbrains.python.psi.resolve.fromModule +import com.jetbrains.python.PyNames +import com.jetbrains.python.psi.PyClass +import com.jetbrains.python.psi.PyFile +import com.jetbrains.python.psi.resolve.* +import com.jetbrains.python.psi.stubs.PyModuleNameIndex import com.jetbrains.python.psi.types.TypeEvalContext +import com.jetbrains.python.sdk.PySdkUtil import org.jetbrains.annotations.ApiStatus import java.util.* @@ -34,22 +36,6 @@ interface ContextAnchor { } } -/** - * @deprecated moved to {@link com.jetbrains.python.extensions} - */ -@ApiStatus.ScheduledForRemoval -@Deprecated(message = "Moved to com.jetbrains.python") -class ModuleBasedContextAnchor(val module: Module) : ContextAnchor { - override val sdk: Sdk? = module.getSdk() - override val project: Project = module.project - override val qualifiedNameResolveContext: PyQualifiedNameResolveContext = fromModule(module) - override val scope: GlobalSearchScope = module.moduleContentScope - override fun getRoots(): Array { - val manager = ModuleRootManager.getInstance(module) - return super.getRoots() + manager.contentRoots + manager.sourceRoots - } -} - /** * @deprecated moved to {@link com.jetbrains.python.extensions} */ @@ -74,6 +60,15 @@ data class QNameResolveContext( ) +/** + * @deprecated moved to {@link com.jetbrains.python.extensions} + */ +@ApiStatus.ScheduledForRemoval +@Deprecated(message = "Moved to com.jetbrains.python") +fun QualifiedName.resolveToElement(context: QNameResolveContext, stopOnFirstFail: Boolean = false): PsiElement? { + return getElementAndResolvableName(context, stopOnFirstFail)?.element +} + /** * @deprecated moved to {@link com.jetbrains.python.extensions} */ @@ -91,7 +86,90 @@ fun QualifiedName.getRelativeNameTo(root: QualifiedName): QualifiedName? { */ @ApiStatus.ScheduledForRemoval @Deprecated(message = "Moved to com.jetbrains.python") -fun QualifiedName.resolveToElement(context: QNameResolveContext, stopOnFirstFail: Boolean = false): PsiElement? { - return getElementAndResolvableName(context, stopOnFirstFail)?.element +class ProjectSdkContextAnchor(override val project: Project, override val sdk: Sdk?) : ContextAnchor { + override val qualifiedNameResolveContext: PyQualifiedNameResolveContext? = sdk?.let { fromSdk(project, it) } + override val scope: GlobalSearchScope = GlobalSearchScope.projectScope(project) //TODO: Check if project scope includes SDK + override fun getRoots(): Array { + val manager = ProjectRootManager.getInstance(project) + return super.getRoots() + manager.contentRoots + manager.contentSourceRoots + } } +/** + * @deprecated moved to {@link com.jetbrains.python.extensions} + */ +@ApiStatus.ScheduledForRemoval +@Deprecated(message = "Moved to com.jetbrains.python") +data class NameAndElement(val name: QualifiedName, val element: PsiElement) + +/** + * @deprecated moved to {@link com.jetbrains.python.extensions} + */ +@ApiStatus.ScheduledForRemoval +@Deprecated(message = "Moved to com.jetbrains.python") +fun QualifiedName.getElementAndResolvableName(context: QNameResolveContext, stopOnFirstFail: Boolean = false): NameAndElement? { + var currentName = QualifiedName.fromComponents(this.components) + + + var element: PsiElement? = null + + + var lastElement: String? = null + var psiDirectory: PsiDirectory? = null + + var resolveContext = context.contextAnchor.qualifiedNameResolveContext?.copyWithMembers() ?: return null + if (PySdkUtil.getLanguageLevelForSdk(context.sdk).isPy3K || context.allowInaccurateResult) { + resolveContext = resolveContext.copyWithPlainDirectories() + } + + if (context.folderToStart != null) { + psiDirectory = PsiManager.getInstance(context.contextAnchor.project).findDirectory(context.folderToStart) + } + + + // Drill as deep, as we can + while (currentName.componentCount > 0 && element == null) { + if (psiDirectory != null) { // Resolve against folder + // There could be folder and module on the same level. Empty folder should be ignored in this case. + element = resolveModuleAt(currentName, psiDirectory, resolveContext).filterNot { + it is PsiDirectory && it.children.filterIsInstance().isEmpty() + }.firstOrNull() + } + + if (element == null) { // Resolve against roots + element = resolveQualifiedName(currentName, resolveContext).firstOrNull() + } + + if (element != null || stopOnFirstFail) { + break + } + lastElement = currentName.lastComponent!! + currentName = currentName.removeLastComponent() + } + + if (lastElement != null && element is PyClass) { + // Drill in class + + val method = element.findMethodByName(lastElement, true, context.evalContext) + if (method != null) { + return NameAndElement(currentName.append(lastElement), method) + } + + } + + if (element == null && this.firstComponent != null && context.allowInaccurateResult) { + // If name starts with file which is not in root nor in folders -- use index. + val nameToFind = this.firstComponent!! + val pyFile = PyModuleNameIndex.find(nameToFind, context.contextAnchor.project, false).firstOrNull() ?: return element + + val folder = + if (pyFile.name == PyNames.INIT_DOT_PY) { // We are in folder + pyFile.virtualFile.parent.parent + } + else { + pyFile.virtualFile.parent + } + return getElementAndResolvableName(context.copy(folderToStart = folder)) + } + return if (element != null) NameAndElement(currentName, element) else null +} diff --git a/python/python-core-impl/intellij.python.community.deprecated.extensions/src/com/jetbrains/extensions/python/PyCallExpressionExt.kt b/python/python-core-impl/intellij.python.community.deprecated.extensions/src/com/jetbrains/extensions/python/PyCallExpressionExt.kt new file mode 100644 index 000000000000..061d0c0a4727 --- /dev/null +++ b/python/python-core-impl/intellij.python.community.deprecated.extensions/src/com/jetbrains/extensions/python/PyCallExpressionExt.kt @@ -0,0 +1,16 @@ +// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. + +package com.jetbrains.extensions.python; + +import com.jetbrains.python.nameResolver.FQNamesProvider +import com.jetbrains.python.nameResolver.NameResolverTools +import com.jetbrains.python.psi.PyCallExpression +import org.jetbrains.annotations.ApiStatus + +/** + * @deprecated moved to {@link com.jetbrains.python.extensions} + */ +@ApiStatus.ScheduledForRemoval +@Deprecated(message = "Moved to com.jetbrains.python") +fun PyCallExpression.isCalleeName(vararg names: FQNamesProvider): Boolean = NameResolverTools.isCalleeShortCut(this, *names) + diff --git a/python/python-core-impl/intellij.python.community.deprecated.extensions/src/com/jetbrains/extensions/python/package-info.java b/python/python-core-impl/intellij.python.community.deprecated.extensions/src/com/jetbrains/extensions/python/package-info.java new file mode 100644 index 000000000000..7217e64804c1 --- /dev/null +++ b/python/python-core-impl/intellij.python.community.deprecated.extensions/src/com/jetbrains/extensions/python/package-info.java @@ -0,0 +1,7 @@ +// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +/** + * @deprecated moved to {@link com.jetbrains.python.extensions} + */ +@Deprecated(forRemoval = true) +package com.jetbrains.extensions.python; +