(**
 * Copyright (c) 2015, Facebook, Inc.
 * All rights reserved.
 *
 * This source code is licensed under the BSD-style license found in the
 * LICENSE file in the "hack" directory of this source tree. An additional grant
 * of patent rights can be found in the PATENTS file in the same directory.
 *
 *)

module Reordered_argument_map (S : MyMap.S) = struct
  include S
  let add m ~key ~data = add key data m
  let filter m ~f = filter f m
  let fold m ~init ~f = fold f m init
  let get m k = get k m
  let find_unsafe m k = find_unsafe k m
  let iter m ~f = iter f m
  let map m ~f = map f m
  let mem m v = mem v m
  let remove m v = remove v m
  let exists m ~f = exists f m
  let merge m1 m2 ~f = merge f m1 m2
end

module Reordered_argument_set (S : Set.S) = struct
  include S
  let add s v = add v s
  let filter s ~f = filter f s
  let fold s ~init ~f = fold f s init
  let iter s ~f = iter f s
  let mem s v = mem v s
  let remove s v = remove v s
  let exists s ~f = exists f s
  let of_list l = List.fold_left add S.empty l
end

module SSet = Reordered_argument_set(SSet)
module SMap = Reordered_argument_map(SMap)

(**
 * Copyright (c) 2015, Facebook, Inc.
 * All rights reserved.
 *
 * This source code is licensed under the BSD-style license found in the
 * LICENSE file in the "hack" directory of this source tree. An additional grant
 * of patent rights can be found in the PATENTS file in the same directory.
 *
 *)

module Reordered_argument_map (S : MyMap.S) = struct
  include S
  let add m ~key ~data = add key data m
  let filter m ~f = filter f m
  let fold m ~init ~f = fold f m init
  let get m k = get k m
  let find_unsafe m k = find_unsafe k m
  let iter m ~f = iter f m
  let map m ~f = map f m
  let mem m v = mem v m
  let remove m v = remove v m
  let exists m ~f = exists f m
  let merge m1 m2 ~f = merge f m1 m2
  let filter m ~f = filter m f
  let partition m ~f = partition f m
end

module Reordered_argument_set (S : Set.S) = struct
  include S
  let add s v = add v s
  let filter s ~f = filter f s
  let fold s ~init ~f = fold f s init
  let iter s ~f = iter f s
  let mem s v = mem v s
  let remove s v = remove v s
  let exists s ~f = exists f s
  let of_list l = List.fold_left add S.empty l
end

module SSet = Reordered_argument_set(SSet)
module SMap = Reordered_argument_map(SMap)

Make live global errors a bit less live, but more performant
[hack] Make live global errors a bit less live, but more performant

Summary:
The way it works now: the moment you run global analysis and get thousands of errors, we send only up to 50 of them to editor (and from now on prioritize recomputing them), keeping the rest hidden. If you fix one of them, we'll "top up" with the 51th, etc. until you fix them all.

This keeps the live errors promise ("if something is displayed in editor, we try to keep it live and up to date"), while (in theory) also providing a way to handle "thousands of errors" use case without running expensive global check over and over.

Unfortunately, since D4129071, due to having to fix a correctness issue, maintaining the "hidden rest" up to date incurs a significant (smaller than global recheck, but proportional to number of errors) cost. This leads to complaints from framework developers.

In this diff, I get rid of the "drip errors one by one" part - we just forget about most of the errors in unopened files, and you need to re-run global analysis to top up again after you fix the ones you got. I see a way forward to automate this with some heuristics, but for now it seems like a strict improvement for framework developers, with minimal disadvantage for the rest.

I also lower the number of reported unopened files with errors from 50 to 10 (I don't think that there is any usability difference...)

- changes in ServerTypeCheck.ml are mainly a revert of D4129071.
- a bunch of test files change, because the new approach also implements the filtering solution from D4775042 better: previously we would de-duplicate errors only in non-open files, now we de-duplicate all errors. I checked that all of the changes are deletions of diagnostics that were re-sent unnecessarily
- the scenario that we are changing, error throttling, is in test_error_throttling.ml: I change it by adding another STATUS (i.e. global recheck) to the test

Reviewed By: jamesjwu

Differential Revision: D4974336

fbshipit-source-id: 93ff3a2026b674ede03a3ffa6f991d250c5aa809
