-- | 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.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.PrettyPrintEnvDecl.Names 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 =
  String
-> Cli (PrettyPrintEnv, BranchDiffOutput Symbol Ann)
-> Cli (PrettyPrintEnv, BranchDiffOutput Symbol Ann)
forall a. String -> Cli a -> Cli a
Cli.time String
"diffHelper" do
    Cli.Env {Codebase IO Symbol Ann
codebase :: Codebase IO Symbol Ann
$sel:codebase:Env :: Env -> Codebase IO Symbol Ann
codebase} <- Cli Env
forall r (m :: * -> *). MonadReader r m => m r
ask
    Int
hqLength <- Transaction Int -> Cli Int
forall a. Transaction a -> Cli a
Cli.runTransaction Transaction Int
Codebase.hashLength
    BranchDiff
diff <- IO BranchDiff -> Cli BranchDiff
forall a. IO a -> Cli a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (Branch0 IO -> Branch0 IO -> IO BranchDiff
forall (m :: * -> *).
Monad m =>
Branch0 m -> Branch0 m -> m BranchDiff
BranchDiff.diff0 Branch0 IO
before Branch0 IO
after)
    Names
names <- Cli Names
Cli.currentNames Cli Names -> (Names -> Names) -> Cli Names
forall (f :: * -> *) a b. Functor f => f a -> (a -> b) -> f b
<&> \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 :: PrettyPrintEnvDecl
pped = Namer -> Suffixifier -> PrettyPrintEnvDecl
PPED.makePPED (Int -> Names -> Namer
PPE.hqNamer Int
10 Names
names) (Names -> Suffixifier
PPE.suffixifyByHash Names
names)

    let suffixifiedPPE :: PrettyPrintEnv
suffixifiedPPE = PrettyPrintEnvDecl -> PrettyPrintEnv
PPED.suffixifiedPPE PrettyPrintEnvDecl
pped
    (BranchDiffOutput Symbol Ann
 -> (PrettyPrintEnv, BranchDiffOutput Symbol Ann))
-> Cli (BranchDiffOutput Symbol Ann)
-> Cli (PrettyPrintEnv, BranchDiffOutput Symbol Ann)
forall a b. (a -> b) -> Cli a -> Cli b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (PrettyPrintEnv
suffixifiedPPE,) do
      (Referent -> Cli (Maybe (Type Symbol Ann)))
-> (Reference -> Cli (Maybe (DeclOrBuiltin Symbol Ann)))
-> Int
-> Names
-> Names
-> BranchDiff
-> Cli (BranchDiffOutput Symbol Ann)
forall (m :: * -> *) v a.
Monad m =>
(Referent -> m (Maybe (Type v a)))
-> (Reference -> m (Maybe (DeclOrBuiltin v a)))
-> Int
-> Names
-> Names
-> BranchDiff
-> m (BranchDiffOutput v a)
OBranchDiff.toOutput
        (Transaction (Maybe (Type Symbol Ann))
-> Cli (Maybe (Type Symbol Ann))
forall a. Transaction a -> Cli a
Cli.runTransaction (Transaction (Maybe (Type Symbol Ann))
 -> Cli (Maybe (Type Symbol Ann)))
-> (Referent -> Transaction (Maybe (Type Symbol Ann)))
-> Referent
-> Cli (Maybe (Type Symbol Ann))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Codebase IO Symbol Ann
-> Referent -> Transaction (Maybe (Type Symbol Ann))
forall a (m :: * -> *).
BuiltinAnnotation a =>
Codebase m Symbol a
-> Referent -> Transaction (Maybe (Type Symbol a))
Codebase.getTypeOfReferent Codebase IO Symbol Ann
codebase)
        (Transaction (Maybe (DeclOrBuiltin Symbol Ann))
-> Cli (Maybe (DeclOrBuiltin Symbol Ann))
forall a. Transaction a -> Cli a
Cli.runTransaction (Transaction (Maybe (DeclOrBuiltin Symbol Ann))
 -> Cli (Maybe (DeclOrBuiltin Symbol Ann)))
-> (Reference -> Transaction (Maybe (DeclOrBuiltin Symbol Ann)))
-> Reference
-> Cli (Maybe (DeclOrBuiltin Symbol Ann))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Codebase IO Symbol Ann
-> Reference -> Transaction (Maybe (DeclOrBuiltin Symbol Ann))
forall (m :: * -> *).
Codebase m Symbol Ann
-> Reference -> Transaction (Maybe (DeclOrBuiltin Symbol Ann))
declOrBuiltin Codebase IO Symbol Ann
codebase)
        Int
hqLength
        (Branch0 IO -> Names
forall (m :: * -> *). Branch0 m -> Names
Branch.toNames Branch0 IO
before)
        (Branch0 IO -> Names
forall (m :: * -> *). Branch0 m -> Names
Branch.toNames Branch0 IO
after)
        BranchDiff
diff

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 v a. ConstructorType -> DeclOrBuiltin v a
DD.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 v a. Decl v a -> DeclOrBuiltin v a
DD.Decl (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