-- | Helpers/utils that have to do with namespace diffs.
module Unison.Codebase.Editor.HandleInput.NamespaceDiffUtils
  ( diffHelper,
  )
where

import Control.Monad.Reader (ask)
import Data.Map qualified as Map
import Unison.Builtin qualified as Builtin
import Unison.Cli.Monad (Cli)
import Unison.Cli.Monad qualified as Cli
import Unison.Cli.NamesUtils qualified as Cli
import Unison.Codebase (Codebase)
import Unison.Codebase qualified as Codebase
import Unison.Codebase.Branch (Branch0)
import Unison.Codebase.Branch.Names qualified as Branch
import Unison.Codebase.BranchDiff qualified as BranchDiff
import Unison.Codebase.Editor.Output.BranchDiff qualified as OBranchDiff
import Unison.DataDeclaration qualified as DD
import Unison.OrBuiltin (OrBuiltin (..))
import Unison.Parser.Ann (Ann (..))
import Unison.Prelude
import Unison.PrettyPrintEnv qualified as PPE
import Unison.PrettyPrintEnv.Names qualified as PPE
import Unison.PrettyPrintEnvDecl qualified as PPED
import Unison.Reference (Reference)
import Unison.Reference qualified as Reference
import Unison.Sqlite qualified as Sqlite
import Unison.Symbol (Symbol)

diffHelper ::
  Branch0 IO ->
  Branch0 IO ->
  Cli (PPE.PrettyPrintEnv, OBranchDiff.BranchDiffOutput Symbol Ann)
diffHelper :: Branch0 IO
-> Branch0 IO -> Cli (PrettyPrintEnv, BranchDiffOutput Symbol Ann)
diffHelper Branch0 IO
before Branch0 IO
after =
  Text
-> Cli (PrettyPrintEnv, BranchDiffOutput Symbol Ann)
-> Cli (PrettyPrintEnv, BranchDiffOutput Symbol Ann)
forall a. Text -> Cli a -> Cli a
Cli.time Text
"diffHelper" do
    Cli.Env {codebase} <- Cli Env
forall r (m :: * -> *). MonadReader r m => m r
ask
    hqLength <- Cli.runTransaction Codebase.hashLength
    names <- Cli.currentNames <&> \Names
currentNames -> Names
currentNames Names -> Names -> Names
forall a. Semigroup a => a -> a -> a
<> Branch0 IO -> Names
forall (m :: * -> *). Branch0 m -> Names
Branch.toNames Branch0 IO
before Names -> Names -> Names
forall a. Semigroup a => a -> a -> a
<> Branch0 IO -> Names
forall (m :: * -> *). Branch0 m -> Names
Branch.toNames Branch0 IO
after
    let pped = Namer -> Suffixifier -> PrettyPrintEnvDecl
PPED.makePPED (Int -> Names -> Namer
PPE.hqNamer Int
10 Names
names) (Names -> Suffixifier
PPE.suffixifyByHash Names
names)

    let suffixifiedPPE = PrettyPrintEnvDecl -> PrettyPrintEnv
PPED.suffixifiedPPE PrettyPrintEnvDecl
pped
    fmap (suffixifiedPPE,) do
      OBranchDiff.toOutput
        (Cli.runTransaction . Codebase.getTypeOfReferent codebase)
        (Cli.runTransaction . declOrBuiltin codebase)
        hqLength
        (Branch.toNames before)
        (Branch.toNames after)
        (BranchDiff.diff0 before after)

declOrBuiltin :: Codebase m Symbol Ann -> Reference -> Sqlite.Transaction (Maybe (DD.DeclOrBuiltin Symbol Ann))
declOrBuiltin :: forall (m :: * -> *).
Codebase m Symbol Ann
-> Reference -> Transaction (Maybe (DeclOrBuiltin Symbol Ann))
declOrBuiltin Codebase m Symbol Ann
codebase Reference
r = case Reference
r of
  Reference.Builtin {} -> Maybe (DeclOrBuiltin Symbol Ann)
-> Transaction (Maybe (DeclOrBuiltin Symbol Ann))
forall a. a -> Transaction a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Maybe (DeclOrBuiltin Symbol Ann)
 -> Transaction (Maybe (DeclOrBuiltin Symbol Ann)))
-> (Maybe ConstructorType -> Maybe (DeclOrBuiltin Symbol Ann))
-> Maybe ConstructorType
-> Transaction (Maybe (DeclOrBuiltin Symbol Ann))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (ConstructorType -> DeclOrBuiltin Symbol Ann)
-> Maybe ConstructorType -> Maybe (DeclOrBuiltin Symbol Ann)
forall a b. (a -> b) -> Maybe a -> Maybe b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ConstructorType -> DeclOrBuiltin Symbol Ann
forall a b. a -> OrBuiltin a b
Builtin (Maybe ConstructorType
 -> Transaction (Maybe (DeclOrBuiltin Symbol Ann)))
-> Maybe ConstructorType
-> Transaction (Maybe (DeclOrBuiltin Symbol Ann))
forall a b. (a -> b) -> a -> b
$ Reference -> Map Reference ConstructorType -> Maybe ConstructorType
forall k a. Ord k => k -> Map k a -> Maybe a
Map.lookup Reference
r Map Reference ConstructorType
Builtin.builtinConstructorType
  Reference.DerivedId Id' Hash
id -> (Decl Symbol Ann -> DeclOrBuiltin Symbol Ann)
-> Maybe (Decl Symbol Ann) -> Maybe (DeclOrBuiltin Symbol Ann)
forall a b. (a -> b) -> Maybe a -> Maybe b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Decl Symbol Ann -> DeclOrBuiltin Symbol Ann
forall a b. b -> OrBuiltin a b
NotBuiltin (Maybe (Decl Symbol Ann) -> Maybe (DeclOrBuiltin Symbol Ann))
-> Transaction (Maybe (Decl Symbol Ann))
-> Transaction (Maybe (DeclOrBuiltin Symbol Ann))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Codebase m Symbol Ann
-> Id' Hash -> Transaction (Maybe (Decl Symbol Ann))
forall (m :: * -> *) v a.
Codebase m v a -> Id' Hash -> Transaction (Maybe (Decl v a))
Codebase.getTypeDeclaration Codebase m Symbol Ann
codebase Id' Hash
id