@NotNull
  private static List<OperationChain> search(CompilerReferenceServiceEx referenceServiceEx,
                                             SearchInitializer initializer,
                                             int chainMaxLength,
                                             int maxResultSize,
                                             ChainCompletionContext context) {
    LinkedList<OperationChain> q = initializer.getChainQueue();

    List<OperationChain> result = new ArrayList<>();
    while (!q.isEmpty()) {

      OperationChain currentChain = q.poll();
      ProgressManager.checkCanceled();
      RefChainOperation head = currentChain.getHead();

      if (addChainIfTerminal(currentChain, result, chainMaxLength, context)) continue;

      // otherwise try to find chain continuation
      boolean updated = false;
      SortedSet<ChainOpAndOccurrences<MethodCall>> candidates = referenceServiceEx.findMethodReferenceOccurrences(head.getQualifierRawName(), SignatureData.ZERO_DIM, context);
      CompilerRef ref = head.getCompilerRef();
      for (ChainOpAndOccurrences<MethodCall> candidate : candidates) {
        if (candidate.getOccurrenceCount() * ChainSearchMagicConstants.FILTER_RATIO < currentChain.getChainWeight()) {
          break;
        }
        MethodCall sign = candidate.getOperation();
        if ((sign.isStatic() || !sign.getQualifierRawName().equals(context.getTarget().getClassQName())) &&
            (!(ref instanceof CompilerRef.JavaCompilerMethodRef) ||
             referenceServiceEx.mayHappen(candidate.getOperation().getCompilerRef(), ref, ChainSearchMagicConstants.METHOD_PROBABILITY_THRESHOLD))) {

          OperationChain
            continuation = currentChain.continuationWithMethod(candidate.getOperation(), candidate.getOccurrenceCount(), context);
          if (continuation != null) {
            boolean stopChain =
              candidate.getOperation().isStatic() || context.hasQualifier(context.resolvePsiClass(candidate.getOperation().getQualifierDef()));
            if (stopChain) {
              addChainIfNotPresent(continuation, result);
            }
            else {
              q.addFirst(continuation);
            }
            updated = true;
          }
        }
      }

      if (ref instanceof CompilerRef.JavaCompilerMethodRef) {
        CompilerRef.CompilerClassHierarchyElementDef def =
          referenceServiceEx.mayCallOfTypeCast((CompilerRef.JavaCompilerMethodRef)ref, ChainSearchMagicConstants.METHOD_PROBABILITY_THRESHOLD);
        if (def != null) {
          OperationChain
            continuation = currentChain.continuationWithCast(new TypeCast(def, head.getQualifierDef(), referenceServiceEx), context);
          if (continuation != null) {
            q.addFirst(continuation);
            updated = true;
          }
        }
      }

      if (!updated) {
        addChainIfQualifierCanBeOccurredInContext(currentChain, result, context, referenceServiceEx);
      }

      if (result.size() > maxResultSize) {
        return result;
      }
    }
    return result;
  }
@NotNull
  private static List<OperationChain> search(CompilerReferenceServiceEx referenceServiceEx,
                                             SearchInitializer initializer,
                                             int chainMaxLength,
                                             int maxResultSize,
                                             ChainCompletionContext context)