mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
PY-75831 tests for split cache(resolve/type) into library and user part
(cherry picked from commit ca5f003693960b25d78bda050b55fe39900be5a7) IJ-MR-169158 GitOrigin-RevId: 759cb38f76124b5b0709757e8f73ddffbf4a8248
This commit is contained in:
committed by
intellij-monorepo-bot
parent
31991b70bd
commit
fd4360b032
@@ -23,7 +23,6 @@ jvm_library(
|
||||
"//python/python-ast:ast",
|
||||
"//python/python-syntax-core:syntax-core",
|
||||
"@lib//:kotlin-stdlib",
|
||||
"//platform/platform-api:ide",
|
||||
],
|
||||
exports = [
|
||||
"//python/python-parser:parser",
|
||||
|
||||
@@ -20,6 +20,5 @@
|
||||
<orderEntry type="module" module-name="intellij.python.syntax.core" />
|
||||
<orderEntry type="library" name="kotlin-stdlib" level="project" />
|
||||
<orderEntry type="module" module-name="intellij.platform.backend" scope="RUNTIME" />
|
||||
<orderEntry type="module" module-name="intellij.platform.ide" />
|
||||
</component>
|
||||
</module>
|
||||
@@ -99,7 +99,7 @@ public sealed class TypeEvalContext {
|
||||
* the analyzed code was called or may be called. Since this is basically guesswork, the results should be used only for code completion.
|
||||
*/
|
||||
public static @NotNull TypeEvalContext codeCompletion(final @NotNull Project project, final @Nullable PsiFile origin) {
|
||||
if (Registry.is("python.use.library.leve.type.eval.context")) {
|
||||
if (Registry.is("python.use.separated.libraries.type.cache")) {
|
||||
return new LibraryLongLiveTypeEvalContext(true, true, true, origin);
|
||||
}
|
||||
return getContextFromCache(project, new TypeEvalContext(true, true, true, origin));
|
||||
@@ -113,7 +113,7 @@ public sealed class TypeEvalContext {
|
||||
* For code completion see {@link TypeEvalContext#codeCompletion(Project, PsiFile)}.
|
||||
*/
|
||||
public static TypeEvalContext userInitiated(final @NotNull Project project, final @Nullable PsiFile origin) {
|
||||
if (Registry.is("python.use.library.leve.type.eval.context")) {
|
||||
if (Registry.is("python.use.separated.libraries.type.cache")) {
|
||||
return new LibraryLongLiveTypeEvalContext(true, true, false, origin);
|
||||
}
|
||||
return getContextFromCache(project, new TypeEvalContext(true, true, false, origin));
|
||||
|
||||
@@ -49,7 +49,6 @@ jvm_library(
|
||||
"//python/python-parser:parser",
|
||||
"//python/python-syntax-core:syntax-core",
|
||||
"//python/impl.helperLocator:community-helpersLocator",
|
||||
"//platform/platform-api:ide",
|
||||
],
|
||||
exports = ["//python/python-syntax-core:syntax-core"],
|
||||
runtime_deps = [":psi-impl_resources"]
|
||||
|
||||
@@ -45,6 +45,5 @@
|
||||
<orderEntry type="module" module-name="intellij.python.parser" />
|
||||
<orderEntry type="module" module-name="intellij.python.syntax.core" exported="" />
|
||||
<orderEntry type="module" module-name="intellij.python.community.helpersLocator" />
|
||||
<orderEntry type="module" module-name="intellij.platform.ide" />
|
||||
</component>
|
||||
</module>
|
||||
@@ -507,7 +507,7 @@
|
||||
description="When enabled, activates LiteralString inference for Python string literals" />
|
||||
<registryKey key="python.optimized.type.eval.context" defaultValue="true"
|
||||
description="It optimises cache usage for storing calculated types."/>
|
||||
<registryKey key="python.use.library.leve.type.eval.context" defaultValue="true"
|
||||
<registryKey key="python.use.separated.libraries.type.cache" defaultValue="true"
|
||||
description="It enables the use of a library-level cache for PSI elements from packages."/>
|
||||
<registryKey key="python.statement.lists.incremental.reparse" defaultValue="false"
|
||||
description="Enables incremental reparse for statement lists"/>
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
from lib import not_annotated_func_returning_str
|
||||
|
||||
|
||||
x = not_annotated_func_returning_str()
|
||||
|
||||
def expects_int(p: int) -> None:
|
||||
pass
|
||||
|
||||
expects_int(x) # should have no error, because we infer Any for not_annotated_func_returning_str()
|
||||
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
def not_annotated_func_returning_str():
|
||||
return "foo"
|
||||
@@ -0,0 +1,3 @@
|
||||
from mylib2 import func
|
||||
|
||||
attr = func()
|
||||
@@ -0,0 +1,2 @@
|
||||
def func():
|
||||
pass
|
||||
@@ -0,0 +1,3 @@
|
||||
import mylib1
|
||||
|
||||
expr = mylib1.attr
|
||||
@@ -0,0 +1,2 @@
|
||||
def func() -> int:
|
||||
...
|
||||
@@ -0,0 +1,76 @@
|
||||
// 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;
|
||||
|
||||
import com.intellij.openapi.command.WriteCommandAction;
|
||||
import com.intellij.openapi.vfs.StandardFileSystems;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.jetbrains.python.documentation.PythonDocumentationProvider;
|
||||
import com.jetbrains.python.fixtures.PyTestCase;
|
||||
import com.jetbrains.python.inspections.PyTypeCheckerInspection;
|
||||
import com.jetbrains.python.psi.PyFunction;
|
||||
import com.jetbrains.python.psi.PyReferenceExpression;
|
||||
import com.jetbrains.python.psi.PyTargetExpression;
|
||||
import com.jetbrains.python.psi.PyUtil;
|
||||
import com.jetbrains.python.psi.types.TypeEvalContext;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public final class PyTypeCachingTest extends PyTestCase {
|
||||
public void testInspectionPassAfterUserInitiatedAction() {
|
||||
myFixture.copyDirectoryToProject("NonAnnotatedDefinitionInAnotherProjectFile", "");
|
||||
myFixture.configureFromTempProjectFile("a.py");
|
||||
|
||||
// Here can be any action using TypeEvalContext with myAllowStubToAST==true
|
||||
PyTargetExpression argument = myFixture.findElementByText("x", PyTargetExpression.class);
|
||||
String argumentQuickDoc = new PythonDocumentationProvider().generateDoc(argument, argument);
|
||||
assertTrue(argumentQuickDoc.contains("<a href=\"psi_element://#typename#str\">str</a>"));
|
||||
|
||||
myFixture.enableInspections(PyTypeCheckerInspection.class);
|
||||
myFixture.checkHighlighting();
|
||||
}
|
||||
|
||||
public void testUserInitiatedActionAfterInspectionPass() {
|
||||
myFixture.copyDirectoryToProject("NonAnnotatedDefinitionInAnotherProjectFile", "");
|
||||
myFixture.configureFromTempProjectFile("a.py");
|
||||
|
||||
myFixture.enableInspections(PyTypeCheckerInspection.class);
|
||||
myFixture.checkHighlighting();
|
||||
|
||||
PyTargetExpression argument = myFixture.findElementByText("x", PyTargetExpression.class);
|
||||
String argumentQuickDoc = new PythonDocumentationProvider().generateDoc(argument, argument);
|
||||
assertTrue(argumentQuickDoc.contains("<a href=\"psi_element://#typename#str\">str</a>"));
|
||||
}
|
||||
|
||||
public void testProjectPyiStubChangesLibraryType() {
|
||||
final String libRootPath = getTestDataPath() + "/" + getTestName(false) + "/lib";
|
||||
final VirtualFile libRoot = StandardFileSystems.local().findFileByPath(libRootPath);
|
||||
runWithAdditionalClassEntryInSdkRoots(libRoot, () -> {
|
||||
myFixture.copyDirectoryToProject(getTestName(false) + "/user", "");
|
||||
myFixture.configureFromTempProjectFile("main.py");
|
||||
assertType("int",
|
||||
myFixture.findElementByText("expr", PyTargetExpression.class),
|
||||
TypeEvalContext.userInitiated(myFixture.getProject(), myFixture.getFile()));
|
||||
|
||||
// Change the return type annotation in the project .pyi stub
|
||||
PsiFile userPyiStub = myFixture.configureFromTempProjectFile("mylib2.pyi");
|
||||
PyReferenceExpression returnTypeHint = myFixture.findElementByText("int", PyReferenceExpression.class);
|
||||
WriteCommandAction.runWriteCommandAction(myFixture.getProject(), () -> {
|
||||
PyUtil.updateDocumentUnblockedAndCommitted(userPyiStub, document -> {
|
||||
document.replaceString(returnTypeHint.getTextOffset(), returnTypeHint.getTextRange().getEndOffset(), "str");
|
||||
});
|
||||
});
|
||||
PyFunction func = myFixture.findElementByText("func", PyFunction.class);
|
||||
assertType("() -> str", func, TypeEvalContext.userInitiated(myFixture.getProject(), myFixture.getFile()));
|
||||
|
||||
myFixture.configureFromTempProjectFile("main.py");
|
||||
assertType("str",
|
||||
myFixture.findElementByText("expr", PyTargetExpression.class),
|
||||
TypeEvalContext.userInitiated(myFixture.getProject(), myFixture.getFile()));
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull String getTestDataPath() {
|
||||
return super.getTestDataPath() + "/caching/";
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user