mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
PY-16066 Fixed: basestring not treated as a type by PyTypeChecker inspection
Remove replacing basestring with union of str and unicode from PyTypeChecker. Force this replacement while inferring type. Update PyTypeAssertionEvaluator to correctly transform union types.
This commit is contained in:
@@ -17,6 +17,7 @@ package com.jetbrains.python.codeInsight.controlflow;
|
||||
|
||||
import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.jetbrains.python.PyNames;
|
||||
import com.jetbrains.python.PyTokenTypes;
|
||||
import com.jetbrains.python.psi.*;
|
||||
@@ -26,6 +27,7 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Stack;
|
||||
import java.util.function.Function;
|
||||
@@ -184,6 +186,10 @@ public class PyTypeAssertionEvaluator extends PyRecursiveElementVisitor {
|
||||
}
|
||||
return PyUnionType.union(members);
|
||||
}
|
||||
else if (type instanceof PyUnionType) {
|
||||
final Collection<PyType> members = ((PyUnionType)type).getMembers();
|
||||
return PyUnionType.union(ContainerUtil.map(members, member -> transformTypeFromAssertion(member, transformToDefinition)));
|
||||
}
|
||||
else if (type instanceof PyInstantiableType) {
|
||||
final PyInstantiableType instantiableType = (PyInstantiableType)type;
|
||||
return transformToDefinition ? instantiableType.toClass() : instantiableType.toInstance();
|
||||
|
||||
@@ -118,7 +118,7 @@ public class PyStdlibTypeProvider extends PyTypeProviderBase {
|
||||
final PyBuiltinCache builtinCache = PyBuiltinCache.getInstance(referenceTarget);
|
||||
if (referenceTarget instanceof PyElement && builtinCache.isBuiltin(referenceTarget) &&
|
||||
PyNames.BASESTRING.equals(((PyElement)referenceTarget).getName())) {
|
||||
return builtinCache.getStrOrUnicodeType();
|
||||
return builtinCache.getStrOrUnicodeType(true);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2016 JetBrains s.r.o.
|
||||
* Copyright 2000-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -393,7 +393,23 @@ public class PyBuiltinCache {
|
||||
|
||||
@Nullable
|
||||
public PyType getStrOrUnicodeType() {
|
||||
return PyUnionType.union(getObjectType("str"), getObjectType("unicode"));
|
||||
return getStrOrUnicodeType(false);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public PyType getStrOrUnicodeType(boolean definition) {
|
||||
PyClassLikeType str = getObjectType("str");
|
||||
PyClassLikeType unicode = getObjectType("unicode");
|
||||
|
||||
if (str != null && str.isDefinition() ^ definition) {
|
||||
str = definition ? str.toClass() : str.toInstance();
|
||||
}
|
||||
|
||||
if (unicode != null && unicode.isDefinition() ^ definition) {
|
||||
unicode = definition ? unicode.toClass() : unicode.toInstance();
|
||||
}
|
||||
|
||||
return PyUnionType.union(str, unicode);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
|
||||
@@ -90,12 +90,6 @@ public class PyTypeChecker {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if (actualClassType != null && PyNames.BASESTRING.equals(actualClassType.getName())) {
|
||||
final PyBuiltinCache builtinCache = PyBuiltinCache.getInstance(actualClassType.getPyClass());
|
||||
if (actualClassType.equals(builtinCache.getObjectType(PyNames.BASESTRING))) {
|
||||
return match(expected, builtinCache.getStrOrUnicodeType(), context, substitutions, recursive);
|
||||
}
|
||||
}
|
||||
if (expected instanceof PyGenericType && substitutions != null) {
|
||||
final PyGenericType generic = (PyGenericType)expected;
|
||||
final PyType subst = substitutions.get(generic);
|
||||
|
||||
@@ -528,6 +528,10 @@ public class PyTypeParser {
|
||||
final PyClassType type = builtinCache.getDictType();
|
||||
return type != null ? new ParseResult(type, range) : EMPTY_RESULT;
|
||||
}
|
||||
else if (PyNames.BASESTRING.equals(name)) {
|
||||
final PyType type = builtinCache.getStrOrUnicodeType();
|
||||
return type != null ? new ParseResult(type, range) : EMPTY_RESULT;
|
||||
}
|
||||
|
||||
final PyType builtinType = builtinCache.getObjectType(name);
|
||||
if (builtinType != null) {
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
class Filter(object):
|
||||
def __init__(self, allowed_types):
|
||||
"""
|
||||
:type allowed_types: type
|
||||
"""
|
||||
pass
|
||||
|
||||
Filter(basestring)
|
||||
@@ -442,6 +442,11 @@ public class PyTypeCheckerInspectionTest extends PyTestCase {
|
||||
doTest();
|
||||
}
|
||||
|
||||
// PY-16066
|
||||
public void testBasestringMatchesType() {
|
||||
doTest();
|
||||
}
|
||||
|
||||
// PY-23864
|
||||
public void testClassObjectAndMetaclassCompatibility() {
|
||||
doTest();
|
||||
|
||||
Reference in New Issue
Block a user