@NotNull
  private static List<QualifiedName> getCanonicalNames(@NotNull PsiReference reference, @NotNull TypeEvalContext context) {
    final PsiElement element = reference.getElement();
    final List<QualifiedName> result = new SmartList<>();
    if (reference instanceof PyOperatorReference && element instanceof PyQualifiedExpression) {
      final PyExpression receiver = ((PyOperatorReference)reference).getReceiver();
      if (receiver != null) {
        final PyType type = context.getType(receiver);
        if (type instanceof PyClassType) {
          final String methodName = ((PyQualifiedExpression)element).getReferencedName();
          ContainerUtil.addIfNotNull(result, extractAttributeQNameFromClassType(methodName, (PyClassType)type));
        }
      }
    }
    else if (element instanceof PyReferenceExpression expr) {
      final PyExpression qualifier = expr.getQualifier();
      final String exprName = expr.getName();
      if (exprName != null) {
        if (qualifier != null) {
          final PyType qualifierType = context.getType(qualifier);
          PyTypeUtil.toStream(qualifierType)
            .map(type -> {
              if (type instanceof PyClassType) {
                return extractAttributeQNameFromClassType(exprName, (PyClassType)type);
              }
              else if (type instanceof PyModuleType) {
                final PyFile file = ((PyModuleType)type).getModule();
                final QualifiedName name = QualifiedNameFinder.findCanonicalImportPath(file, element);
                if (name != null) {
                  return name.append(exprName);
                }
              }
              else if (type instanceof PyImportedModuleType) {
                final PyImportedModule module = ((PyImportedModuleType)type).getImportedModule();
                final PsiElement resolved = module.resolve();
                if (resolved != null) {
                  final QualifiedName path = QualifiedNameFinder.findCanonicalImportPath(resolved, element);
                  if (path != null) {
                    return path.append(exprName);
                  }
                }
              }
              else if (type instanceof PyFunctionType) {
                final PyCallable callable = ((PyFunctionType)type).getCallable();
                final String callableName = callable.getName();
                if (callableName != null) {
                  final QualifiedName path = QualifiedNameFinder.findCanonicalImportPath(callable, element);
                  if (path != null) {
                    return path.append(QualifiedName.fromComponents(callableName, exprName));
                  }
                }
              }
              return null;
            })
            .nonNull()
            .into(result);
        }
        else {
          final PsiElement parent = element.getParent();
          if (parent instanceof PyImportElement) {
            final PyImportStatementBase importStmt = PsiTreeUtil.getParentOfType(parent, PyImportStatementBase.class);
            if (importStmt instanceof PyImportStatement) {
              ContainerUtil.addIfNotNull(result, QualifiedName.fromComponents(exprName));
            }
            else if (importStmt instanceof PyFromImportStatement) {
              final PsiElement resolved = ((PyFromImportStatement)importStmt).resolveImportSource();
              if (resolved != null) {
                final QualifiedName path = QualifiedNameFinder.findCanonicalImportPath(resolved, element);
                if (path != null) {
                  ContainerUtil.addIfNotNull(result, path.append(exprName));
                }
              }
            }
          }
          else {
            final QualifiedName path = QualifiedNameFinder.findCanonicalImportPath(element, element);
            if (path != null) {
              ContainerUtil.addIfNotNull(result, path.append(exprName));
            }
          }
        }
      }
    }
    else if (reference instanceof DocStringParameterReference) {
      ContainerUtil.addIfNotNull(result, QualifiedName.fromDottedString(reference.getCanonicalText()));
    }
    return result;
  }
@NotNull
  private static List<QualifiedName> getCanonicalNames(@NotNull PsiReference reference, @NotNull TypeEvalContext context)