-- | Utilities related to resolving names to things.
module Unison.Cli.NameResolutionUtils
  ( resolveHQName,
    resolveHQToLabeledDependencies,
  )
where

import Control.Monad.Reader (ask)
import Data.Bifoldable (bifoldMap)
import Data.Set qualified as Set
import Unison.Cli.Monad (Cli)
import Unison.Cli.Monad qualified as Cli
import Unison.Cli.NamesUtils qualified as Cli
import Unison.Codebase qualified as Codebase
import Unison.HashQualified qualified as HQ
import Unison.LabeledDependency (LabeledDependency)
import Unison.LabeledDependency qualified as LD
import Unison.Name (Name)
import Unison.Name qualified as Name
import Unison.Names qualified as Names
import Unison.Prelude
import Unison.Reference (TypeReference)
import Unison.Referent (Referent)
import Unison.ShortHash (ShortHash)
import Unison.Util.Defns (Defns (..), DefnsF)

resolveHQName :: HQ.HashQualified Name -> Cli (DefnsF Set Referent TypeReference)
resolveHQName :: HashQualified Name -> Cli (DefnsF Set Referent TypeReference)
resolveHQName = \case
  HQ.NameOnly Name
name -> do
    names <- Cli Names
Cli.currentNames
    pure
      Defns
        { terms = Name.searchByRankedSuffix name names.terms,
          types = Name.searchByRankedSuffix name names.types
        }
  -- rationale: the hash should be unique enough that the name never helps
  -- mitchell says: that seems wrong
  HQ.HashQualified Name
_n ShortHash
hash -> ShortHash -> Cli (DefnsF Set Referent TypeReference)
resolveHashOnly ShortHash
hash
  HQ.HashOnly ShortHash
hash -> ShortHash -> Cli (DefnsF Set Referent TypeReference)
resolveHashOnly ShortHash
hash
  where
    resolveHashOnly :: ShortHash -> Cli (DefnsF Set Referent TypeReference)
    resolveHashOnly :: ShortHash -> Cli (DefnsF Set Referent TypeReference)
resolveHashOnly ShortHash
hash = do
      env <- Cli Env
forall r (m :: * -> *). MonadReader r m => m r
ask
      Cli.runTransaction do
        terms <- Codebase.termReferentsByShortHash env.codebase hash
        types <- Codebase.typeReferencesByShortHash hash
        pure Defns {terms, types}

resolveHQToLabeledDependencies :: HQ.HashQualified Name -> Cli (Set LabeledDependency)
resolveHQToLabeledDependencies :: HashQualified Name -> Cli (Set LabeledDependency)
resolveHQToLabeledDependencies =
  (DefnsF Set Referent TypeReference -> Set LabeledDependency)
-> Cli (DefnsF Set Referent TypeReference)
-> Cli (Set LabeledDependency)
forall a b. (a -> b) -> Cli a -> Cli b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ((Set Referent -> Set LabeledDependency)
-> (Set TypeReference -> Set LabeledDependency)
-> DefnsF Set Referent TypeReference
-> Set LabeledDependency
forall m a b. Monoid m => (a -> m) -> (b -> m) -> Defns a b -> m
forall (p :: * -> * -> *) m a b.
(Bifoldable p, Monoid m) =>
(a -> m) -> (b -> m) -> p a b -> m
bifoldMap ((Referent -> LabeledDependency)
-> Set Referent -> Set LabeledDependency
forall b a. Ord b => (a -> b) -> Set a -> Set b
Set.map Referent -> LabeledDependency
LD.referent) ((TypeReference -> LabeledDependency)
-> Set TypeReference -> Set LabeledDependency
forall b a. Ord b => (a -> b) -> Set a -> Set b
Set.map TypeReference -> LabeledDependency
LD.typeRef)) (Cli (DefnsF Set Referent TypeReference)
 -> Cli (Set LabeledDependency))
-> (HashQualified Name -> Cli (DefnsF Set Referent TypeReference))
-> HashQualified Name
-> Cli (Set LabeledDependency)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. HashQualified Name -> Cli (DefnsF Set Referent TypeReference)
resolveHQName