use of com.jetbrains.python.psi.impl.PyBuiltinCache in project intellij-community by JetBrains.
the class NumpyDocStringTypeProvider method getNominalType.
/**
* Converts literal into type, e.g. -1 -> int, 'fro' -> str
*/
@Nullable
private static PyType getNominalType(@NotNull PsiElement anchor, @NotNull String typeString) {
final PyExpressionCodeFragmentImpl codeFragment = new PyExpressionCodeFragmentImpl(anchor.getProject(), "dummy.py", typeString, false);
final PsiElement element = codeFragment.getFirstChild();
if (element instanceof PyExpressionStatement) {
final PyExpression expression = ((PyExpressionStatement) element).getExpression();
final PyBuiltinCache builtinCache = PyBuiltinCache.getInstance(anchor);
if (expression instanceof PyStringLiteralExpression) {
return builtinCache.getStrType();
}
if (expression instanceof PyNumericLiteralExpression) {
return builtinCache.getIntType();
}
}
return null;
}
use of com.jetbrains.python.psi.impl.PyBuiltinCache in project intellij-community by JetBrains.
the class PyTypeChecker method match.
private static boolean match(@Nullable PyType expected, @Nullable PyType actual, @NotNull TypeEvalContext context, @Nullable Map<PyGenericType, PyType> substitutions, boolean recursive) {
// TODO: subscriptable types?, module types?, etc.
final PyClassType expectedClassType = as(expected, PyClassType.class);
final PyClassType actualClassType = as(actual, PyClassType.class);
// Special cases: object and type
if (expectedClassType != null && ArrayUtil.contains(expectedClassType.getName(), PyNames.OBJECT, PyNames.TYPE)) {
final PyBuiltinCache builtinCache = PyBuiltinCache.getInstance(expectedClassType.getPyClass());
if (expectedClassType.equals(builtinCache.getObjectType())) {
return true;
}
if (expectedClassType.equals(builtinCache.getTypeType()) && actual instanceof PyInstantiableType && ((PyInstantiableType) actual).isDefinition()) {
return true;
}
}
if (expected instanceof PyInstantiableType && actual instanceof PyInstantiableType && !(expected instanceof PyGenericType && typeVarAcceptsBothClassAndInstanceTypes((PyGenericType) expected)) && ((PyInstantiableType) expected).isDefinition() ^ ((PyInstantiableType) actual).isDefinition()) {
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);
PyType bound = generic.getBound();
// Promote int in Type[TypeVar('T', int)] to Type[int] before checking that bounds match
if (generic.isDefinition() && bound instanceof PyInstantiableType) {
bound = ((PyInstantiableType) bound).toClass();
}
if (!match(bound, actual, context, substitutions, recursive)) {
return false;
} else if (subst != null) {
if (expected.equals(actual)) {
return true;
} else if (recursive) {
return match(subst, actual, context, substitutions, false);
} else {
return false;
}
} else if (actual != null) {
substitutions.put(generic, actual);
} else if (bound != null) {
substitutions.put(generic, bound);
}
return true;
}
if (expected == null || actual == null) {
return true;
}
if (isUnknown(actual)) {
return true;
}
if (actual instanceof PyUnionType) {
final PyUnionType actualUnionType = (PyUnionType) actual;
if (expected instanceof PyTupleType) {
final PyTupleType expectedTupleType = (PyTupleType) expected;
final int elementCount = expectedTupleType.getElementCount();
if (!expectedTupleType.isHomogeneous() && consistsOfSameElementNumberTuples(actualUnionType, elementCount)) {
return substituteExpectedElementsWithUnions(expectedTupleType, elementCount, actualUnionType, context, substitutions, recursive);
}
}
for (PyType m : actualUnionType.getMembers()) {
if (match(expected, m, context, substitutions, recursive)) {
return true;
}
}
return false;
}
if (expected instanceof PyUnionType) {
final Collection<PyType> expectedUnionTypeMembers = ((PyUnionType) expected).getMembers();
final StreamEx<PyType> notGenericTypes = StreamEx.of(expectedUnionTypeMembers).filter(type -> !PyGenericType.class.isInstance(type));
final StreamEx<PyGenericType> genericTypes = StreamEx.of(expectedUnionTypeMembers).select(PyGenericType.class);
for (PyType t : notGenericTypes.append(genericTypes)) {
if (match(t, actual, context, substitutions, recursive)) {
return true;
}
}
return false;
}
if (expectedClassType != null && actualClassType != null) {
final PyClass superClass = expectedClassType.getPyClass();
final PyClass subClass = actualClassType.getPyClass();
if (expected instanceof PyTupleType && actual instanceof PyTupleType) {
final PyTupleType superTupleType = (PyTupleType) expected;
final PyTupleType subTupleType = (PyTupleType) actual;
if (!superTupleType.isHomogeneous() && !subTupleType.isHomogeneous()) {
if (superTupleType.getElementCount() != subTupleType.getElementCount()) {
return false;
} else {
for (int i = 0; i < superTupleType.getElementCount(); i++) {
if (!match(superTupleType.getElementType(i), subTupleType.getElementType(i), context, substitutions, recursive)) {
return false;
}
}
return true;
}
} else if (superTupleType.isHomogeneous() && !subTupleType.isHomogeneous()) {
final PyType expectedElementType = superTupleType.getIteratedItemType();
for (int i = 0; i < subTupleType.getElementCount(); i++) {
if (!match(expectedElementType, subTupleType.getElementType(i), context)) {
return false;
}
}
return true;
} else if (!superTupleType.isHomogeneous() && subTupleType.isHomogeneous()) {
return false;
} else {
return match(superTupleType.getIteratedItemType(), subTupleType.getIteratedItemType(), context);
}
} else if (expected instanceof PyCollectionType && actual instanceof PyTupleType) {
if (!matchClasses(superClass, subClass, context)) {
return false;
}
final PyType superElementType = ((PyCollectionType) expected).getIteratedItemType();
final PyType subElementType = ((PyTupleType) actual).getIteratedItemType();
if (!match(superElementType, subElementType, context, substitutions, recursive)) {
return false;
}
return true;
} else if (expected instanceof PyCollectionType) {
if (!matchClasses(superClass, subClass, context)) {
return false;
}
// TODO: Match generic parameters based on the correspondence between the generic parameters of subClass and its base classes
final List<PyType> superElementTypes = ((PyCollectionType) expected).getElementTypes(context);
final PyCollectionType actualCollectionType = as(actual, PyCollectionType.class);
final List<PyType> subElementTypes = actualCollectionType != null ? actualCollectionType.getElementTypes(context) : Collections.emptyList();
for (int i = 0; i < superElementTypes.size(); i++) {
final PyType subElementType = i < subElementTypes.size() ? subElementTypes.get(i) : null;
if (!match(superElementTypes.get(i), subElementType, context, substitutions, recursive)) {
return false;
}
}
return true;
} else if (matchClasses(superClass, subClass, context)) {
return true;
} else if (actualClassType.isDefinition() && PyNames.CALLABLE.equals(expected.getName())) {
return true;
}
if (expected.equals(actual)) {
return true;
}
}
if (actual instanceof PyFunctionTypeImpl && expectedClassType != null) {
final PyClass superClass = expectedClassType.getPyClass();
if (PyNames.CALLABLE.equals(superClass.getName())) {
return true;
}
}
if (actual instanceof PyStructuralType && ((PyStructuralType) actual).isInferredFromUsages()) {
return true;
}
if (expected instanceof PyStructuralType && actual instanceof PyStructuralType) {
final PyStructuralType expectedStructural = (PyStructuralType) expected;
final PyStructuralType actualStructural = (PyStructuralType) actual;
if (expectedStructural.isInferredFromUsages()) {
return true;
}
return expectedStructural.getAttributeNames().containsAll(actualStructural.getAttributeNames());
}
if (expected instanceof PyStructuralType && actualClassType != null) {
if (overridesGetAttr(actualClassType.getPyClass(), context)) {
return true;
}
final Set<String> actualAttributes = actualClassType.getMemberNames(true, context);
return actualAttributes.containsAll(((PyStructuralType) expected).getAttributeNames());
}
if (actual instanceof PyStructuralType && expectedClassType != null) {
final Set<String> expectedAttributes = expectedClassType.getMemberNames(true, context);
return expectedAttributes.containsAll(((PyStructuralType) actual).getAttributeNames());
}
if (actual instanceof PyCallableType && expected instanceof PyCallableType) {
final PyCallableType expectedCallable = (PyCallableType) expected;
final PyCallableType actualCallable = (PyCallableType) actual;
if (expectedCallable.isCallable() && actualCallable.isCallable()) {
final List<PyCallableParameter> expectedParameters = expectedCallable.getParameters(context);
final List<PyCallableParameter> actualParameters = actualCallable.getParameters(context);
if (expectedParameters != null && actualParameters != null) {
final int size = Math.min(expectedParameters.size(), actualParameters.size());
for (int i = 0; i < size; i++) {
final PyCallableParameter expectedParam = expectedParameters.get(i);
final PyCallableParameter actualParam = actualParameters.get(i);
// TODO: Check named and star params, not only positional ones
if (!match(expectedParam.getType(context), actualParam.getType(context), context, substitutions, recursive)) {
return false;
}
}
}
if (!match(expectedCallable.getReturnType(context), actualCallable.getReturnType(context), context, substitutions, recursive)) {
return false;
}
return true;
}
}
return matchNumericTypes(expected, actual);
}
use of com.jetbrains.python.psi.impl.PyBuiltinCache in project intellij-community by JetBrains.
the class PythonBuiltinReferenceResolveProvider method resolveName.
@NotNull
@Override
public List<RatedResolveResult> resolveName(@NotNull PyQualifiedExpression element, @NotNull TypeEvalContext context) {
final String referencedName = element.getReferencedName();
if (referencedName == null) {
return Collections.emptyList();
}
final List<RatedResolveResult> result = new ArrayList<>();
final PyBuiltinCache builtinCache = PyBuiltinCache.getInstance(PyPsiUtils.getRealContext(element));
// resolve to module __doc__
if (PyNames.DOC.equals(referencedName)) {
result.addAll(Optional.ofNullable(builtinCache.getObjectType()).map(type -> type.resolveMember(referencedName, element, AccessDirection.of(element), PyResolveContext.noImplicits().withTypeEvalContext(context))).orElse(Collections.emptyList()));
}
// ...as a builtin symbol
final PyFile builtinsFile = builtinCache.getBuiltinsFile();
if (builtinsFile != null && !PyUtil.isClassPrivateName(referencedName)) {
for (RatedResolveResult resolveResult : builtinsFile.multiResolveName(referencedName)) {
result.add(new ImportedResolveResult(resolveResult.getElement(), resolveResult.getRate(), null));
}
}
return result;
}
use of com.jetbrains.python.psi.impl.PyBuiltinCache in project intellij-community by JetBrains.
the class QualifiedNameFinder method getQualifiedName.
@Nullable
public static String getQualifiedName(@NotNull PyElement element) {
final String name = element.getName();
if (name != null) {
final ScopeOwner owner = ScopeUtil.getScopeOwner(element);
final PyBuiltinCache builtinCache = PyBuiltinCache.getInstance(element);
if (owner instanceof PyClass) {
final String classQName = ((PyClass) owner).getQualifiedName();
if (classQName != null) {
return classQName + "." + name;
}
} else if (owner instanceof PyFile) {
if (builtinCache.isBuiltin(element)) {
return name;
} else {
final VirtualFile virtualFile = ((PyFile) owner).getVirtualFile();
if (virtualFile != null) {
final String fileQName = findShortestImportableName(element, virtualFile);
if (fileQName != null) {
return fileQName + "." + name;
}
}
}
}
}
return null;
}
use of com.jetbrains.python.psi.impl.PyBuiltinCache in project intellij-community by JetBrains.
the class PyUtil method isSuperCall.
public static boolean isSuperCall(@NotNull PyCallExpression node) {
PyClass klass = PsiTreeUtil.getParentOfType(node, PyClass.class);
if (klass == null)
return false;
PyExpression callee = node.getCallee();
if (callee == null)
return false;
String name = callee.getName();
if (PyNames.SUPER.equals(name)) {
PsiReference reference = callee.getReference();
if (reference == null)
return false;
PsiElement resolved = reference.resolve();
PyBuiltinCache cache = PyBuiltinCache.getInstance(node);
if (resolved != null && cache.isBuiltin(resolved)) {
PyExpression[] args = node.getArguments();
if (args.length > 0) {
String firstArg = args[0].getText();
if (firstArg.equals(klass.getName()) || firstArg.equals(PyNames.CANONICAL_SELF + "." + PyNames.__CLASS__)) {
return true;
}
for (PyClass s : klass.getAncestorClasses(null)) {
if (firstArg.equals(s.getName())) {
return true;
}
}
} else {
return true;
}
}
}
return false;
}
Aggregations