private void registerUnresolvedReferenceProblem(@NotNull PyElement node, @NotNull final PsiReference reference,
                                                  @NotNull HighlightSeverity severity) {
    if (reference instanceof DocStringTypeReference) {
      return;
    }
    String description = null;
    PsiElement element = reference.getElement();
    final String text = element.getText();
    TextRange rangeInElement = reference.getRangeInElement();
    String refText = text;  // text of the part we're working with
    if (rangeInElement.getStartOffset() >= 0 && rangeInElement.getEndOffset() > 0) {
      refText = rangeInElement.substring(text);
    }

    final String refName = (element instanceof PyQualifiedExpression) ? ((PyQualifiedExpression)element).getReferencedName() : refText;
    // Empty text, nothing to highlight
    if (StringUtil.isEmpty(refName)) {
      return;
    }

    final List<QualifiedName> qualifiedNames = getCanonicalNames(reference, myTypeEvalContext);
    for (QualifiedName name : qualifiedNames) {
      final String canonicalName = name.toString();
      for (String ignored : myIgnoredIdentifiers) {
        if (ignored.endsWith(END_WILDCARD)) {
          final String prefix = ignored.substring(0, ignored.length() - END_WILDCARD.length());
          if (canonicalName.startsWith(prefix)) {
            return;
          }
        }
        else if (canonicalName.equals(ignored)) {
          return;
        }
      }
    }
    // Legacy non-qualified ignore patterns
    if (myIgnoredIdentifiers.contains(refName)) {
      return;
    }
    List<LocalQuickFix> fixes = new ArrayList<>();
    if (element instanceof PyReferenceExpression expr) {
      if (PyNames.COMPARISON_OPERATORS.contains(refName)) {
        return;
      }
      if (!expr.isQualified()) {
        if (PyInspectionsUtil.hasAnyInterruptedControlFlowPaths(expr, myTypeEvalContext)) {
          return;
        }
        ContainerUtil.addIfNotNull(fixes, getTrueFalseQuickFix(refText));
        ContainerUtil.addAll(fixes, getAddSelfFixes(myTypeEvalContext, node, expr));
        ContainerUtil.addIfNotNull(fixes, getCreateFunctionQuickFix(expr));
        ContainerUtil.addIfNotNull(fixes, getAddParameterQuickFix(refName, expr));
        fixes.add(new PyRenameUnresolvedRefQuickFix());
      }
      // unqualified:
      // may be module's
      if (PyModuleType.getPossibleInstanceMembers().contains(refName)) {
        return;
      }
      // may be a "try: import ..."; not an error not to resolve
      if ((
        PsiTreeUtil.getParentOfType(
          PsiTreeUtil.getParentOfType(node, PyImportElement.class), PyTryExceptStatement.class, PyIfStatement.class
        ) != null
      )) {
        severity = HighlightSeverity.WEAK_WARNING;
        description = PyPsiBundle.message("INSP.unresolved.refs.module.not.found", refText);
        // TODO: mark the node so that future references pointing to it won't result in a error, but in a warning
      }
    }
    if (reference instanceof PsiReferenceEx && description == null) {
      description = ((PsiReferenceEx)reference).getUnresolvedDescription();
    }
    if (description == null) {
      boolean markedQualified = false;
      if (element instanceof PyQualifiedExpression) {
        // TODO: Add __qualname__ for Python 3.3 to the skeleton of <class 'object'>, introduce a pseudo-class skeleton for
        // <class 'function'>
        if ("__qualname__".equals(refText) && !LanguageLevel.forElement(element).isPython2()) {
          return;
        }
        if (PyNames.COMPARISON_OPERATORS.contains(refName)) {
          return;
        }
      }
      final PyExpression qualifier = getReferenceQualifier(reference);
      if (qualifier != null) {
        final PyType type = myTypeEvalContext.getType(qualifier);
        if (type != null) {
          if (ignoreUnresolvedMemberForType(type, reference, refName) || isDeclaredInSlots(type, refName)) {
            return;
          }
          ContainerUtil.addAll(fixes, getCreateMemberFromUsageFixes(type, reference, refText));
          if (type instanceof PyClassType classType) {
            if (reference instanceof PyOperatorReference) {
              String className = type.getName();
              if (classType.isDefinition()) {
                final PyClassLikeType metaClassType = classType.getMetaClassType(myTypeEvalContext, true);
                if (metaClassType != null) {
                  className = metaClassType.getName();
                }
              }
              description = PyPsiBundle.message("INSP.unresolved.refs.class.does.not.define.operator",
                                                className, refName,
                                                ((PyOperatorReference)reference).getReadableOperatorName());
            }
            else {
              description = PyPsiBundle.message("INSP.unresolved.refs.unresolved.attribute.for.class", refText, type.getName());
            }
          }
          else {
            description = PyPsiBundle.message("INSP.unresolved.refs.cannot.find.reference.in.type", refText, type.getName());
          }
          markedQualified = true;
        }
      }
      if (!markedQualified) {
        description = PyPsiBundle.message("INSP.unresolved.refs.unresolved.reference", refText);

        ContainerUtil.addAll(fixes, getAutoImportFixes(node, reference, element));
        ContainerUtil.addIfNotNull(fixes, getCreateClassFix(refText, element));
      }
    }
    ProblemHighlightType hl_type;
    if (severity == HighlightSeverity.WARNING) {
      hl_type = ProblemHighlightType.GENERIC_ERROR_OR_WARNING;
    }
    else if (severity == HighlightSeverity.ERROR) {
      hl_type = ProblemHighlightType.GENERIC_ERROR;
    }
    else {
      hl_type = ProblemHighlightType.LIKE_UNKNOWN_SYMBOL;
    }

    ContainerUtil.addAll(fixes, getImportStatementQuickFixes(element));
    ContainerUtil.addAll(fixes, getAddIgnoredIdentifierQuickFixes(qualifiedNames));
    ContainerUtil.addAll(fixes, getInstallPackageQuickFixes(node, reference, refName));

    if (reference instanceof PySubstitutionChunkReference) {
      return;
    }

    getPluginQuickFixes(fixes, reference);
    registerProblem(node, description, hl_type, null, rangeInElement, fixes.toArray(LocalQuickFix.EMPTY_ARRAY));
  }
private void registerUnresolvedReferenceProblem(@NotNull PyElement node, @NotNull final PsiReference reference,
                                                  @NotNull HighlightSeverity severity)