mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
PY-16412 Prohibit annotations for structural types
since they cannot be expression in PEP 484 compatible format (yet).
This commit is contained in:
committed by
Andrey Vlasovskikh
parent
7af0d59f92
commit
eedca22cbb
@@ -295,6 +295,8 @@ INTN.convert.static.method.to.function=Convert static method to function
|
||||
#PyConvertMethodToPropertyIntention
|
||||
INTN.convert.method.to.property=Convert method to property
|
||||
|
||||
INTN.annotate.variable.type.PEP484.incompatible.type=The type ''{0}'' cannot be expressed in PEP 484 format
|
||||
|
||||
# Conflict checker
|
||||
CONFLICT.name.$0.obscured=Name ''{0}'' obscured by local definitions
|
||||
CONFLICT.name.$0.obscured.cannot.convert=Name ''{0}'' obscured. Cannot convert.
|
||||
|
||||
+13
-4
@@ -2,6 +2,7 @@
|
||||
package com.jetbrains.python.codeInsight.intentions;
|
||||
|
||||
import com.intellij.codeInsight.TargetElementUtil;
|
||||
import com.intellij.codeInsight.hint.HintManager;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.roots.ProjectFileIndex;
|
||||
@@ -17,6 +18,7 @@ import com.jetbrains.python.codeInsight.controlflow.ScopeOwner;
|
||||
import com.jetbrains.python.codeInsight.dataflow.scope.Scope;
|
||||
import com.jetbrains.python.codeInsight.dataflow.scope.ScopeUtil;
|
||||
import com.jetbrains.python.codeInsight.intentions.PyTypeHintGenerationUtil.AnnotationInfo;
|
||||
import com.jetbrains.python.codeInsight.intentions.PyTypeHintGenerationUtil.Pep484IncompatibleTypeException;
|
||||
import com.jetbrains.python.documentation.PythonDocumentationProvider;
|
||||
import com.jetbrains.python.documentation.doctest.PyDocstringFile;
|
||||
import com.jetbrains.python.psi.*;
|
||||
@@ -192,11 +194,16 @@ public class PyAnnotateVariableTypeIntention extends PyBaseIntentionAction {
|
||||
final List<PyTargetExpression> targets = findSuitableTargetsUnderCaret(project, editor, file);
|
||||
assert targets.size() == 1;
|
||||
final PyTargetExpression annotationTarget = targets.get(0);
|
||||
if (preferSyntacticAnnotation(annotationTarget)) {
|
||||
insertVariableAnnotation(annotationTarget);
|
||||
try {
|
||||
if (preferSyntacticAnnotation(annotationTarget)) {
|
||||
insertVariableAnnotation(annotationTarget);
|
||||
}
|
||||
else {
|
||||
insertVariableTypeComment(annotationTarget);
|
||||
}
|
||||
}
|
||||
else {
|
||||
insertVariableTypeComment(annotationTarget);
|
||||
catch (Pep484IncompatibleTypeException e) {
|
||||
HintManager.getInstance().showErrorHint(editor, e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -207,6 +214,7 @@ public class PyAnnotateVariableTypeIntention extends PyBaseIntentionAction {
|
||||
private static void insertVariableAnnotation(@NotNull PyTargetExpression target) {
|
||||
final TypeEvalContext context = TypeEvalContext.userInitiated(target.getProject(), target.getContainingFile());
|
||||
final PyType inferredType = context.getType(target);
|
||||
PyTypeHintGenerationUtil.checkPep484Compatibility(inferredType);
|
||||
final String annotationText = PythonDocumentationProvider.getTypeName(inferredType, context);
|
||||
final AnnotationInfo info = new AnnotationInfo(annotationText, inferredType);
|
||||
if (isInstanceAttribute(target, context)) {
|
||||
@@ -277,6 +285,7 @@ public class PyAnnotateVariableTypeIntention extends PyBaseIntentionAction {
|
||||
}
|
||||
else if (target instanceof PyTypedElement) {
|
||||
final PyType singleTargetType = context.getType((PyTypedElement)target);
|
||||
PyTypeHintGenerationUtil.checkPep484Compatibility(singleTargetType);
|
||||
final String singleTargetAnnotation = PythonDocumentationProvider.getTypeName(singleTargetType, context);
|
||||
types.add(singleTargetType);
|
||||
typeRanges.add(TextRange.from(builder.length(), singleTargetAnnotation.length()));
|
||||
|
||||
@@ -17,6 +17,7 @@ import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.util.ThrowableRunnable;
|
||||
import com.jetbrains.python.PyBundle;
|
||||
import com.jetbrains.python.codeInsight.imports.AddImportHelper;
|
||||
import com.jetbrains.python.codeInsight.imports.AddImportHelper.ImportPriority;
|
||||
import com.jetbrains.python.codeInsight.typing.PyTypingTypeProvider;
|
||||
@@ -320,6 +321,38 @@ public class PyTypeHintGenerationUtil {
|
||||
}
|
||||
}
|
||||
|
||||
public static void checkPep484Compatibility(@Nullable PyType type) {
|
||||
if (type == null ||
|
||||
type instanceof PyNoneType ||
|
||||
type instanceof PyCallableTypeImpl ||
|
||||
type instanceof PyGenericType ||
|
||||
type instanceof PyFunctionType) {
|
||||
return;
|
||||
}
|
||||
else if (type instanceof PyUnionType) {
|
||||
for (PyType memberType : ((PyUnionType)type).getMembers()) {
|
||||
checkPep484Compatibility(memberType);
|
||||
}
|
||||
}
|
||||
else if (type instanceof PyCollectionType) {
|
||||
for (PyType typeParam : ((PyCollectionType)type).getElementTypes()) {
|
||||
checkPep484Compatibility(typeParam);
|
||||
}
|
||||
}
|
||||
else if (type instanceof PyClassType) {
|
||||
// In this order since PyCollectionTypeImpl implements PyClassType
|
||||
}
|
||||
else {
|
||||
throw new Pep484IncompatibleTypeException(PyBundle.message("INTN.annotate.variable.type.PEP484.incompatible.type", type.getName()));
|
||||
}
|
||||
}
|
||||
|
||||
public static final class Pep484IncompatibleTypeException extends RuntimeException {
|
||||
public Pep484IncompatibleTypeException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
|
||||
public static final class AnnotationInfo {
|
||||
private final String myAnnotationText;
|
||||
private final List<PyType> myTypes;
|
||||
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
def func(x):
|
||||
x.foo()
|
||||
va<caret>r = [x]
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
def func(x):
|
||||
x.foo()
|
||||
var = [x]
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
def func(x):
|
||||
x.foo()
|
||||
va<caret>r = x
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
def func(x):
|
||||
x.foo()
|
||||
var = x
|
||||
+8
@@ -215,6 +215,14 @@ public class PyAnnotateVariableTypeIntentionTest extends PyIntentionTestCase {
|
||||
doAnnotationTest();
|
||||
}
|
||||
|
||||
public void testAnnotationNotPossibleForStructuralType() {
|
||||
doAnnotationTest();
|
||||
}
|
||||
|
||||
public void testAnnotationNotPossibleForNestedStructuralType() {
|
||||
doAnnotationTest();
|
||||
}
|
||||
|
||||
private void doAnnotationTest() {
|
||||
doTest(LanguageLevel.PYTHON36);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user