public IndexedMethod findMethodDeclaration(
      PythonParserResult info,
      org.python.antlr.ast.Call call,
      AstPath path,
      Set<IndexedMethod>[] alternativesHolder) {
    PythonParserResult parseResult = PythonAstUtils.getParseResult(info);
    PythonIndex index = PythonIndex.get(info.getSnapshot().getSource().getFileObject());
    Set<IndexedElement> functions = null;

    // TODO - do more accurate lookup of types here!
    // (a) For functions, look in imported symbols first!
    // (b) For methods, try to resolve the lhs type first and search within specific types!

    String callName = PythonAstUtils.getCallName(call);
    if (callName == null) {
      return null;
    }

    if (call.getInternalFunc() instanceof Attribute) {
      // Method/member access
      functions = index.getAllMembers(callName, QuerySupport.Kind.EXACT, parseResult, false);
    } else {
      functions = index.getAllElements(callName, QuerySupport.Kind.EXACT, parseResult, false);
    }

    if (functions != null && functions.size() > 0) {
      Set<IndexedElement> eligible = new HashSet<IndexedElement>();
      for (IndexedElement element : functions) {
        if (element instanceof IndexedMethod) {
          eligible.add(element);
        }
      }

      int astOffset = call.getCharStartIndex();
      int lexOffset = PythonLexerUtils.getLexerOffset(info, astOffset);
      IndexedElement candidate =
          findBestMatch(
              info,
              callName,
              eligible,
              (BaseDocument) info.getSnapshot().getSource().getDocument(false),
              astOffset,
              lexOffset,
              path,
              call,
              index);
      assert candidate instanceof IndexedMethod; // Filtered into earlier already
      return (IndexedMethod) candidate;
    }

    return null;
  }