@Nullable
 @Override
 public PsiElement getElementByReference(PsiReference ref, int flags) {
   if ((flags & TargetElementUtilBase.ELEMENT_NAME_ACCEPTED) == 0) {
     return null;
   }
   final PsiElement element = ref.getElement();
   PsiElement result = ref.resolve();
   Set<PsiElement> visited = new HashSet<PsiElement>();
   visited.add(result);
   while (result instanceof PyReferenceExpression || result instanceof PyTargetExpression) {
     PsiElement nextResult =
         ((PyQualifiedExpression) result).getReference(PyResolveContext.noImplicits()).resolve();
     if (nextResult != null
         && !visited.contains(nextResult)
         && PsiTreeUtil.getParentOfType(element, ScopeOwner.class)
             == PsiTreeUtil.getParentOfType(result, ScopeOwner.class)
         && (nextResult instanceof PyReferenceExpression
             || nextResult instanceof PyTargetExpression
             || nextResult instanceof PyParameter)) {
       visited.add(nextResult);
       result = nextResult;
     } else {
       break;
     }
   }
   return result;
 }
  protected Collection<String> generateSuggestedNames(PyExpression expression) {
    Collection<String> candidates =
        new LinkedHashSet<String>() {
          @Override
          public boolean add(String s) {
            if (PyNames.isReserved(s)) {
              return false;
            }
            return super.add(s);
          }
        };
    String text = expression.getText();
    final Pair<PsiElement, TextRange> selection =
        expression.getUserData(PyReplaceExpressionUtil.SELECTION_BREAKS_AST_NODE);
    if (selection != null) {
      text = selection.getSecond().substring(text);
    }
    if (expression instanceof PyCallExpression) {
      final PyExpression callee = ((PyCallExpression) expression).getCallee();
      if (callee != null) {
        text = callee.getText();
      }
    }
    if (text != null) {
      candidates.addAll(NameSuggesterUtil.generateNames(text));
    }
    final TypeEvalContext context = TypeEvalContext.userInitiated(expression.getContainingFile());
    PyType type = context.getType(expression);
    if (type != null && type != PyNoneType.INSTANCE) {
      String typeName = type.getName();
      if (typeName != null) {
        if (type.isBuiltin()) {
          typeName = typeName.substring(0, 1);
        }
        candidates.addAll(NameSuggesterUtil.generateNamesByType(typeName));
      }
    }
    final PyKeywordArgument kwArg =
        PsiTreeUtil.getParentOfType(expression, PyKeywordArgument.class);
    if (kwArg != null && kwArg.getValueExpression() == expression) {
      candidates.add(kwArg.getKeyword());
    }

    final PyArgumentList argList = PsiTreeUtil.getParentOfType(expression, PyArgumentList.class);
    if (argList != null) {
      final CallArgumentsMapping result = argList.analyzeCall(PyResolveContext.noImplicits());
      if (result.getMarkedCallee() != null) {
        final PyNamedParameter namedParameter = result.getPlainMappedParams().get(expression);
        if (namedParameter != null) {
          candidates.add(namedParameter.getName());
        }
      }
    }
    return candidates;
  }
  public PyType getType(@NotNull TypeEvalContext context, @NotNull TypeEvalContext.Key key) {
    if (!TypeEvalStack.mayEvaluate(this)) {
      return null;
    }
    try {
      final boolean qualified = isQualified();
      if (!qualified) {
        String name = getReferencedName();
        if (PyNames.NONE.equals(name)) {
          return PyNoneType.INSTANCE;
        }
      }
      PyType type = getTypeFromProviders(context);
      if (type != null) {
        return type;
      }
      if (qualified) {
        PyType maybe_type = PyUtil.getSpecialAttributeType(this, context);
        if (maybe_type != null) return maybe_type;
        Ref<PyType> typeOfProperty = getTypeOfProperty(context);
        if (typeOfProperty != null) {
          return typeOfProperty.get();
        }
      }
      final PsiPolyVariantReference reference =
          getReference(PyResolveContext.noImplicits().withTypeEvalContext(context));
      final List<PsiElement> targets = PyUtil.multiResolveTopPriority(reference);
      if (targets.isEmpty()) {
        return getQualifiedReferenceTypeByControlFlow(context);
      }

      final List<PyType> members = new ArrayList<PyType>();
      for (PsiElement target : targets) {
        if (target == this || target == null) {
          continue;
        }
        if (!target.isValid()) {
          LOG.error(
              "Reference "
                  + this
                  + " resolved to invalid element "
                  + target
                  + " (text="
                  + target.getText()
                  + ")");
          continue;
        }
        members.add(getTypeFromTarget(target, context, this));
      }

      return PyUnionType.union(members);
    } finally {
      TypeEvalStack.evaluated(this);
    }
  }
 @NotNull
 public QualifiedResolveResult followAssignmentsChain(PyResolveContext resolveContext) {
   PyReferenceExpression seeker = this;
   QualifiedResolveResult ret = null;
   List<PyExpression> qualifiers = new ArrayList<PyExpression>();
   PyExpression qualifier = seeker.getQualifier();
   if (qualifier != null) {
     qualifiers.add(qualifier);
   }
   Set<PsiElement> visited = new HashSet<PsiElement>();
   visited.add(this);
   SEARCH:
   while (ret == null) {
     ResolveResult[] targets = seeker.getReference(resolveContext).multiResolve(false);
     for (ResolveResult target : targets) {
       PsiElement elt = target.getElement();
       if (elt instanceof PyTargetExpression) {
         PsiElement assigned_from = null;
         final PyTargetExpression expr = (PyTargetExpression) elt;
         final TypeEvalContext context = resolveContext.getTypeEvalContext();
         if (context.maySwitchToAST(expr) || expr.getStub() == null) {
           assigned_from = expr.findAssignedValue();
         }
         // TODO: Maybe findAssignedValueByStub() should become a part of the PyTargetExpression
         // interface
         else if (elt instanceof PyTargetExpressionImpl) {
           assigned_from = ((PyTargetExpressionImpl) elt).findAssignedValueByStub(context);
         }
         if (assigned_from instanceof PyReferenceExpression) {
           if (visited.contains(assigned_from)) {
             break;
           }
           visited.add(assigned_from);
           seeker = (PyReferenceExpression) assigned_from;
           if (seeker.getQualifier() != null) {
             qualifiers.add(seeker.getQualifier());
           }
           continue SEARCH;
         } else if (assigned_from != null)
           ret = new QualifiedResolveResultImpl(assigned_from, qualifiers, false);
       } else if (ret == null && elt instanceof PyElement && target.isValidResult()) {
         // remember this result, but a further reference may be the next resolve result
         ret =
             new QualifiedResolveResultImpl(
                 elt, qualifiers, target instanceof ImplicitResolveResult);
       }
     }
     // all resolve results checked, reassignment not detected, nothing more to do
     break;
   }
   if (ret == null) ret = EMPTY_RESULT;
   return ret;
 }
 @Nullable
 @Override
 public PyType getCallType(
     @NotNull TypeEvalContext context, @NotNull PyCallSiteExpression callSite) {
   for (PyTypeProvider typeProvider : Extensions.getExtensions(PyTypeProvider.EP_NAME)) {
     final PyType type = typeProvider.getCallType(this, callSite, context);
     if (type != null) {
       type.assertValid(typeProvider.toString());
       return type;
     }
   }
   final PyExpression receiver = PyTypeChecker.getReceiver(callSite, this);
   final List<PyExpression> arguments = PyTypeChecker.getArguments(callSite, this);
   final List<PyParameter> parameters = PyUtil.getParameters(this, context);
   final PyResolveContext resolveContext =
       PyResolveContext.noImplicits().withTypeEvalContext(context);
   final List<PyParameter> explicitParameters =
       PyTypeChecker.filterExplicitParameters(parameters, this, callSite, resolveContext);
   final Map<PyExpression, PyNamedParameter> mapping =
       PyCallExpressionHelper.mapArguments(arguments, explicitParameters);
   return getCallType(receiver, mapping, context);
 }
 public static void inspectPyArgumentList(
     PyArgumentList node,
     ProblemsHolder holder,
     final TypeEvalContext context,
     int implicitOffset) {
   if (node.getParent() instanceof PyClass) return; // class Foo(object) is also an arg list
   CallArgumentsMapping result =
       node.analyzeCall(
           PyResolveContext.noImplicits().withTypeEvalContext(context), implicitOffset);
   final PyCallExpression.PyMarkedCallee callee = result.getMarkedCallee();
   if (callee != null) {
     final Callable callable = callee.getCallable();
     // Decorate functions may have different parameter lists. We don't match arguments with
     // parameters of decorators yet
     if (callable instanceof PyFunction && PyUtil.hasCustomDecorators((PyFunction) callable)) {
       return;
     }
   }
   highlightIncorrectArguments(holder, result, context);
   highlightMissingArguments(node, holder, result);
   highlightStarArgumentTypeMismatch(node, holder, context);
 }
 @NotNull
 private static List<PsiElement> tryResolving(
     @NotNull PyExpression expression, @NotNull TypeEvalContext context) {
   final List<PsiElement> elements = Lists.newArrayList();
   if (expression instanceof PyReferenceExpression) {
     final PyReferenceExpression referenceExpr = (PyReferenceExpression) expression;
     final PyResolveContext resolveContext =
         PyResolveContext.noImplicits().withTypeEvalContext(context);
     final PsiPolyVariantReference reference = referenceExpr.getReference(resolveContext);
     final List<PsiElement> resolved = PyUtil.multiResolveTopPriority(reference);
     for (PsiElement element : resolved) {
       if (element instanceof PyFunction) {
         final PyFunction function = (PyFunction) element;
         if (PyUtil.isInit(function)) {
           final PyClass cls = function.getContainingClass();
           if (cls != null) {
             elements.add(cls);
             continue;
           }
         }
       } else if (element instanceof PyTargetExpression) {
         final PyTargetExpression targetExpr = (PyTargetExpression) element;
         // XXX: Requires switching from stub to AST
         final PyExpression assignedValue = targetExpr.findAssignedValue();
         if (assignedValue != null) {
           elements.add(assignedValue);
           continue;
         }
       }
       if (element != null) {
         elements.add(element);
       }
     }
   }
   return !elements.isEmpty() ? elements : Collections.singletonList(expression);
 }
 @NotNull
 @Override
 public PsiPolyVariantReference getReference() {
   return getReference(PyResolveContext.defaultContext());
 }
 private static PsiElement resolveWithoutImplicits(final PyReferenceExpression element) {
   final QualifiedResolveResult resolveResult =
       element.followAssignmentsChain(PyResolveContext.noImplicits());
   return resolveResult.isImplicit() ? null : resolveResult.getElement();
 }
 @NotNull
 @Override
 public PsiPolyVariantReference getReference() {
   return getReference(PyResolveContext.noImplicits());
 }
    @Nullable
    @Override
    public ParseResult fun(@NotNull Pair<Token<PyElementType>, List<Token<PyElementType>>> value) {
      final Token<PyElementType> first = value.getFirst();
      final List<Token<PyElementType>> rest = value.getSecond();
      final TextRange firstRange = first.getRange();
      final boolean unqualified = rest.isEmpty();

      if (unqualified) {
        final ParseResult result = parseBuiltinType(first);
        if (result != null) {
          return result;
        }
      }

      final PsiFile file = myAnchor.getContainingFile();
      final List<Token<PyElementType>> tokens = new ArrayList<>();
      tokens.add(first);
      tokens.addAll(rest);

      if (file instanceof PyFile) {
        final PyFile pyFile = (PyFile) file;
        final TypeEvalContext context = TypeEvalContext.codeInsightFallback(file.getProject());
        final Map<TextRange, PyType> types = new HashMap<>();
        final Map<PyType, TextRange> fullRanges = new HashMap<>();
        final Map<PyType, PyImportElement> imports = new HashMap<>();

        PyType type = resolveQualifierType(tokens, pyFile, context, types, fullRanges, imports);
        PsiElement resolved = type != null ? getElement(type) : null;

        if (type != null) {
          final PyResolveContext resolveContext =
              PyResolveContext.defaultContext().withTypeEvalContext(context);
          final PyExpression expression =
              myAnchor instanceof PyExpression ? (PyExpression) myAnchor : null;

          for (Token<PyElementType> token : tokens) {
            final PyType qualifierType = type;
            type = null;
            final List<? extends RatedResolveResult> results =
                qualifierType.resolveMember(
                    token.getText().toString(), expression, AccessDirection.READ, resolveContext);
            if (results != null && !results.isEmpty()) {
              resolved = results.get(0).getElement();
              if (resolved instanceof PyTypedElement) {
                type = context.getType((PyTypedElement) resolved);
                if (type != null && !allowResolveToType(type)) {
                  type = null;
                  break;
                }
                if (type instanceof PyClassLikeType) {
                  type = ((PyClassLikeType) type).toInstance();
                }
              }
            }
            if (type == null) {
              break;
            }
            types.put(token.getRange(), type);
            fullRanges.put(
                type,
                TextRange.create(firstRange.getStartOffset(), token.getRange().getEndOffset()));
          }
          if (type != null) {
            return new ParseResult(resolved, type, types, fullRanges, imports);
          }
        }
      }

      return EMPTY_RESULT;
    }