module Unison.Codebase.Editor.HandleInput.Dependents
  ( handleDependents,
  )
where

import Control.Lens (review)
import Data.Bifoldable (binull)
import Data.Map.Strict qualified as Map
import Data.Set qualified as Set
import Data.Set.NonEmpty (NESet)
import Data.Set.NonEmpty qualified as Set.NonEmpty
import U.Codebase.Sqlite.Operations qualified as Operations
import Unison.Cli.Monad (Cli)
import Unison.Cli.Monad qualified as Cli
import Unison.Cli.MonadUtils qualified as Cli
import Unison.Cli.NameResolutionUtils (resolveHQName)
import Unison.Codebase.Branch qualified as Branch
import Unison.Codebase.Branch.Names qualified as Branch
import Unison.Codebase.Editor.Output
import Unison.Codebase.Editor.StructuredArgument qualified as SA
import Unison.ConstructorReference (ConstructorReferenceId)
import Unison.DataDeclaration (DataDeclaration, Decl, EffectDeclaration)
import Unison.DataDeclaration qualified as DataDeclaration
import Unison.HashQualified qualified as HQ
import Unison.HashQualifiedPrime qualified as HQ'
import Unison.Name (Name)
import Unison.Name qualified as Name
import Unison.NamesUtils qualified as NamesUtils
import Unison.Prelude
import Unison.PrettyPrintEnv qualified as PPE
import Unison.PrettyPrintEnv.Names qualified as PPE
import Unison.Reference (TermReference, TermReferenceId, TypeReference, TypeReferenceId)
import Unison.Reference qualified as Reference
import Unison.Referent (Referent)
import Unison.Referent qualified as Referent
import Unison.ReferentPrime qualified as Referent'
import Unison.Syntax.HashQualifiedPrime qualified as HQ'
import Unison.Syntax.Name qualified as Name
import Unison.Term (Term)
import Unison.Term qualified as Term
import Unison.Type (Type)
import Unison.UnisonFile (TypecheckedUnisonFile)
import Unison.UnisonFile qualified as UnisonFile
import Unison.UnisonFile.Names qualified as UnisonFile
import Unison.Util.Defns (Defns (..), DefnsF, DefnsF2, defnsAreEmpty, zipDefnsWith)
import Unison.Util.Map qualified as Map
import Unison.Var (Var)
import Unison.WatchKind (WatchKind)
import Unison.WatchKind qualified as WatchKind

handleDependents :: HQ.HashQualified Name -> Cli ()
handleDependents :: HashQualified Name -> Cli ()
handleDependents HashQualified Name
hq = do
  DefnsF Set Referent TypeReference
codebaseRefs <- HashQualified Name -> Cli (DefnsF Set Referent TypeReference)
resolveHQName HashQualified Name
hq

  -- If the given name doesn't match anything in the codebase, then as a fallback, we look at the latest Unison file to
  -- report dependents. This covers the common case that something (and all of its dependents) were removed from the
  -- underlying namespace and placed in a file, e.g. when resolving a failed update.
  if DefnsF Set Referent TypeReference -> Bool
forall (f :: * -> *) (g :: * -> *) a b.
(Foldable f, Foldable g) =>
Defns (f a) (g b) -> Bool
defnsAreEmpty DefnsF Set Referent TypeReference
codebaseRefs
    then HashQualified Name -> Cli ()
handleFileDependents HashQualified Name
hq
    else DefnsF Set Referent TypeReference -> Cli ()
handleCodebaseDependents DefnsF Set Referent TypeReference
codebaseRefs

handleCodebaseDependents :: DefnsF Set Referent TypeReference -> Cli ()
handleCodebaseDependents :: DefnsF Set Referent TypeReference -> Cli ()
handleCodebaseDependents DefnsF Set Referent TypeReference
dependenciesRefs = do
  Branch0 IO
namespace <- Cli (Branch0 IO)
Cli.getCurrentProjectRoot0
  let ppe :: PrettyPrintEnv
ppe =
        let names :: Names
names = Branch0 IO -> Names
forall (m :: * -> *). Branch0 m -> Names
Branch.toNames (Branch0 IO -> Branch0 IO
forall (m :: * -> *). Branch0 m -> Branch0 m
Branch.deleteLibdeps Branch0 IO
namespace)
         in Namer -> Suffixifier -> PrettyPrintEnv
PPE.makePPE (Int -> Names -> Namer
PPE.hqNamer Int
10 Names
names) (Names -> Suffixifier
PPE.suffixifyByHash Names
names)

  DefnsF Set TypeReferenceId TypeReferenceId
dependents <-
    Transaction (DefnsF Set TypeReferenceId TypeReferenceId)
-> Cli (DefnsF Set TypeReferenceId TypeReferenceId)
forall a. Transaction a -> Cli a
Cli.runTransaction do
      DefnsF Set TypeReferenceId TypeReferenceId
-> DefnsF Set TypeReference TypeReference
-> Transaction (DefnsF Set TypeReferenceId TypeReferenceId)
Operations.directDependentsWithinScope
        (Branch0 IO -> DefnsF Set TypeReferenceId TypeReferenceId
forall (m :: * -> *).
Branch0 m -> DefnsF Set TypeReferenceId TypeReferenceId
Branch.deepDefnsIds Branch0 IO
namespace)
        (DefnsF Set Referent TypeReference
-> DefnsF Set TypeReference TypeReference
forall r. Ord r => DefnsF Set (Referent' r) r -> DefnsF Set r r
NamesUtils.referentsToRefs DefnsF Set Referent TypeReference
dependenciesRefs)

  let dependentNames ::
        DefnsF
          []
          (HQ'.HashQualified Name, HQ'.HashQualified Name)
          (HQ'.HashQualified Name, HQ'.HashQualified Name)
      dependentNames :: DefnsF
  []
  (HashQualified Name, HashQualified Name)
  (HashQualified Name, HashQualified Name)
dependentNames =
        PrettyPrintEnv
-> DefnsF Set TypeReferenceId TypeReferenceId
-> DefnsF
     []
     (HashQualified Name, HashQualified Name)
     (HashQualified Name, HashQualified Name)
nameDependents PrettyPrintEnv
ppe DefnsF Set TypeReferenceId TypeReferenceId
dependents

  -- Set numbered args
  (DefnsF
  []
  (HashQualified Name, HashQualified Name)
  (HashQualified Name, HashQualified Name)
dependentNames.types [(HashQualified Name, HashQualified Name)]
-> [(HashQualified Name, HashQualified Name)]
-> [(HashQualified Name, HashQualified Name)]
forall a. [a] -> [a] -> [a]
++ DefnsF
  []
  (HashQualified Name, HashQualified Name)
  (HashQualified Name, HashQualified Name)
dependentNames.terms)
    [(HashQualified Name, HashQualified Name)]
-> ([(HashQualified Name, HashQualified Name)]
    -> [StructuredArgument])
-> [StructuredArgument]
forall a b. a -> (a -> b) -> b
& ((HashQualified Name, HashQualified Name) -> StructuredArgument)
-> [(HashQualified Name, HashQualified Name)]
-> [StructuredArgument]
forall a b. (a -> b) -> [a] -> [b]
map (HashQualified Name -> StructuredArgument
SA.HashQualified (HashQualified Name -> StructuredArgument)
-> ((HashQualified Name, HashQualified Name) -> HashQualified Name)
-> (HashQualified Name, HashQualified Name)
-> StructuredArgument
forall b c a. (b -> c) -> (a -> b) -> a -> c
. HashQualified Name -> HashQualified Name
forall n. HashQualified n -> HashQualified n
HQ'.toHQ (HashQualified Name -> HashQualified Name)
-> ((HashQualified Name, HashQualified Name) -> HashQualified Name)
-> (HashQualified Name, HashQualified Name)
-> HashQualified Name
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (HashQualified Name, HashQualified Name) -> HashQualified Name
forall a b. (a, b) -> a
fst)
    [StructuredArgument] -> ([StructuredArgument] -> Cli ()) -> Cli ()
forall a b. a -> (a -> b) -> b
& [StructuredArgument] -> Cli ()
Cli.setNumberedArgs

  let ppe :: PrettyPrintEnv
ppe =
        let names :: Names
names = Branch0 IO -> Names
forall (m :: * -> *). Branch0 m -> Names
Branch.toNames Branch0 IO
namespace
         in Namer -> Suffixifier -> PrettyPrintEnv
PPE.makePPE (Int -> Names -> Namer
PPE.hqNamer Int
10 Names
names) (Names -> Suffixifier
PPE.suffixifyByHash Names
names)

  -- Name the dependencies, for output
  let namedDependencies :: DefnsF2 Set HQ.HashQualified Name Name
      namedDependencies :: DefnsF2 Set HashQualified Name Name
namedDependencies =
        PrettyPrintEnv
-> DefnsF Set Referent TypeReference
-> DefnsF2 Set HashQualified Name Name
nameDependencies PrettyPrintEnv
ppe DefnsF Set Referent TypeReference
dependenciesRefs

  Maybe (TypecheckedUnisonFile Symbol Ann)
maybeUnisonFile <-
    Cli (Maybe (TypecheckedUnisonFile Symbol Ann))
Cli.getLatestTypecheckedFile

  -- Determine whether we want to put an "(in codebase)" next to each dependency. We do when that name is also found
  -- in the latest typechecked file (since we're reporting on the codebase version).
  let namedDependencies1 :: DefnsF2 (Map (HQ.HashQualified Name)) Maybe Bool Bool
      namedDependencies1 :: DefnsF2 (Map (HashQualified Name)) Maybe Bool Bool
namedDependencies1 =
        case Maybe (TypecheckedUnisonFile Symbol Ann)
maybeUnisonFile of
          Maybe (TypecheckedUnisonFile Symbol Ann)
Nothing -> let f :: Set k -> Map k (Maybe a)
f = (k -> Maybe a) -> Set k -> Map k (Maybe a)
forall k a. (k -> a) -> Set k -> Map k a
Map.fromSet \k
_ -> Maybe a
forall a. Maybe a
Nothing in (Set (HashQualified Name) -> Map (HashQualified Name) (Maybe Bool))
-> (Set (HashQualified Name)
    -> Map (HashQualified Name) (Maybe Bool))
-> DefnsF2 Set HashQualified Name Name
-> DefnsF2 (Map (HashQualified Name)) Maybe Bool Bool
forall a b c d. (a -> b) -> (c -> d) -> Defns a c -> Defns b d
forall (p :: * -> * -> *) a b c d.
Bifunctor p =>
(a -> b) -> (c -> d) -> p a c -> p b d
bimap Set (HashQualified Name) -> Map (HashQualified Name) (Maybe Bool)
forall {k} {a}. Set k -> Map k (Maybe a)
f Set (HashQualified Name) -> Map (HashQualified Name) (Maybe Bool)
forall {k} {a}. Set k -> Map k (Maybe a)
f DefnsF2 Set HashQualified Name Name
namedDependencies
          Just TypecheckedUnisonFile Symbol Ann
unisonFile ->
            let f :: Map Name ref -> Set (HQ.HashQualified Name) -> Map (HQ.HashQualified Name) (Maybe Bool)
                f :: forall ref.
Map Name ref
-> Set (HashQualified Name)
-> Map (HashQualified Name) (Maybe Bool)
f Map Name ref
defnsInFile =
                  (HashQualified Name -> Maybe Bool)
-> Set (HashQualified Name)
-> Map (HashQualified Name) (Maybe Bool)
forall k a. (k -> a) -> Set k -> Map k a
Map.fromSet \case
                    HQ.NameOnly Name
name | Name -> Map Name ref -> Bool
forall k a. Ord k => k -> Map k a -> Bool
Map.member Name
name Map Name ref
defnsInFile -> Bool -> Maybe Bool
forall a. a -> Maybe a
Just Bool
False
                    HashQualified Name
_ -> Maybe Bool
forall a. Maybe a
Nothing
             in (Map Name Id
 -> Set (HashQualified Name)
 -> Map (HashQualified Name) (Maybe Bool))
-> (Map Name TypeReferenceId
    -> Set (HashQualified Name)
    -> Map (HashQualified Name) (Maybe Bool))
-> Defns (Map Name Id) (Map Name TypeReferenceId)
-> DefnsF2 Set HashQualified Name Name
-> DefnsF2 (Map (HashQualified Name)) Maybe Bool Bool
forall tm1 tm2 tm3 ty1 ty2 ty3.
(tm1 -> tm2 -> tm3)
-> (ty1 -> ty2 -> ty3)
-> Defns tm1 ty1
-> Defns tm2 ty2
-> Defns tm3 ty3
zipDefnsWith Map Name Id
-> Set (HashQualified Name)
-> Map (HashQualified Name) (Maybe Bool)
forall ref.
Map Name ref
-> Set (HashQualified Name)
-> Map (HashQualified Name) (Maybe Bool)
f Map Name TypeReferenceId
-> Set (HashQualified Name)
-> Map (HashQualified Name) (Maybe Bool)
forall ref.
Map Name ref
-> Set (HashQualified Name)
-> Map (HashQualified Name) (Maybe Bool)
f (TypecheckedUnisonFile Symbol Ann
-> Defns (Map Name Id) (Map Name TypeReferenceId)
forall a v.
Var v =>
TypecheckedUnisonFile v a
-> Defns (Map Name Id) (Map Name TypeReferenceId)
fileToReferentsIds TypecheckedUnisonFile Symbol Ann
unisonFile) DefnsF2 Set HashQualified Name Name
namedDependencies

  Output -> Cli ()
Cli.respond (DefnsF2 (Map (HashQualified Name)) Maybe Bool Bool
-> DefnsF
     []
     (HashQualified Name, HashQualified Name)
     (HashQualified Name, HashQualified Name)
-> Output
ListDependents DefnsF2 (Map (HashQualified Name)) Maybe Bool Bool
namedDependencies1 DefnsF
  []
  (HashQualified Name, HashQualified Name)
  (HashQualified Name, HashQualified Name)
dependentNames)

handleFileDependents :: HQ.HashQualified Name -> Cli ()
handleFileDependents :: HashQualified Name -> Cli ()
handleFileDependents HashQualified Name
hq = do
  -- If searching with a hash, don't bother looking in the file.
  Name
name <-
    case HashQualified Name
hq of
      HQ.NameOnly Name
name -> Name -> Cli Name
forall a. a -> Cli a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Name
name
      HashQualified Name
_ -> Cli Name
forall a. Cli a
notFound

  -- Require a latest typechecked file to search.
  TypecheckedUnisonFile Symbol Ann
unisonFile <-
    Cli (Maybe (TypecheckedUnisonFile Symbol Ann))
Cli.getLatestTypecheckedFile Cli (Maybe (TypecheckedUnisonFile Symbol Ann))
-> (Cli (Maybe (TypecheckedUnisonFile Symbol Ann))
    -> Cli (TypecheckedUnisonFile Symbol Ann))
-> Cli (TypecheckedUnisonFile Symbol Ann)
forall a b. a -> (a -> b) -> b
& Cli (TypecheckedUnisonFile Symbol Ann)
-> Cli (Maybe (TypecheckedUnisonFile Symbol Ann))
-> Cli (TypecheckedUnisonFile Symbol Ann)
forall (m :: * -> *) a. Monad m => m a -> m (Maybe a) -> m a
onNothingM do
      Cli (TypecheckedUnisonFile Symbol Ann)
forall a. Cli a
notFound

  -- Search the file for dependencies that match the given name.
  let dependenciesRefs :: DefnsF Set Referent.Id TypeReferenceId
      dependenciesRefs :: DefnsF Set Id TypeReferenceId
dependenciesRefs =
        TypecheckedUnisonFile Symbol Ann
unisonFile
          TypecheckedUnisonFile Symbol Ann
-> (TypecheckedUnisonFile Symbol Ann
    -> Defns (Map Name Id) (Map Name TypeReferenceId))
-> Defns (Map Name Id) (Map Name TypeReferenceId)
forall a b. a -> (a -> b) -> b
& TypecheckedUnisonFile Symbol Ann
-> Defns (Map Name Id) (Map Name TypeReferenceId)
forall a v.
Var v =>
TypecheckedUnisonFile v a
-> Defns (Map Name Id) (Map Name TypeReferenceId)
fileToReferentsIds
          Defns (Map Name Id) (Map Name TypeReferenceId)
-> (Defns (Map Name Id) (Map Name TypeReferenceId)
    -> DefnsF Set Id TypeReferenceId)
-> DefnsF Set Id TypeReferenceId
forall a b. a -> (a -> b) -> b
& (Map Name Id -> Set Id)
-> (Map Name TypeReferenceId -> Set TypeReferenceId)
-> Defns (Map Name Id) (Map Name TypeReferenceId)
-> DefnsF Set Id TypeReferenceId
forall a b c d. (a -> b) -> (c -> d) -> Defns a c -> Defns b d
forall (p :: * -> * -> *) a b c d.
Bifunctor p =>
(a -> b) -> (c -> d) -> p a c -> p b d
bimap Map Name Id -> Set Id
forall ref. Ord ref => Map Name ref -> Set ref
search Map Name TypeReferenceId -> Set TypeReferenceId
forall ref. Ord ref => Map Name ref -> Set ref
search
        where
          search :: (Ord ref) => Map Name ref -> Set ref
          search :: forall ref. Ord ref => Map Name ref -> Set ref
search Map Name ref
defns =
            (Name -> Set ref)
-> ((Name -> Ordering) -> Set ref) -> Name -> Set ref
forall r.
Ord r =>
(Name -> Set r) -> ((Name -> Ordering) -> Set r) -> Name -> Set r
Name.gsearchBySuffix
              (Set ref -> (ref -> Set ref) -> Maybe ref -> Set ref
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Set ref
forall a. Set a
Set.empty ref -> Set ref
forall a. a -> Set a
Set.singleton (Maybe ref -> Set ref) -> (Name -> Maybe ref) -> Name -> Set ref
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Name -> Map Name ref -> Maybe ref
forall k a. Ord k => k -> Map k a -> Maybe a
`Map.lookup` Map Name ref
defns))
              (\Name -> Ordering
order -> (Name -> ref -> Set ref)
-> (Name -> Ordering) -> Map Name ref -> Set ref
forall m k v.
Monoid m =>
(k -> v -> m) -> (k -> Ordering) -> Map k v -> m
Map.search (\Name
_ -> ref -> Set ref
forall a. a -> Set a
Set.singleton) Name -> Ordering
order Map Name ref
defns)
              Name
name

  Bool -> Cli () -> Cli ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (DefnsF Set Id TypeReferenceId -> Bool
forall (t :: * -> * -> *) a b. Bifoldable t => t a b -> Bool
binull DefnsF Set Id TypeReferenceId
dependenciesRefs) do
    Cli ()
forall a. Cli a
notFound

  let dependenciesRefs1 :: DefnsF Set TermReferenceId TypeReferenceId
      dependenciesRefs1 :: DefnsF Set TypeReferenceId TypeReferenceId
dependenciesRefs1 =
        DefnsF Set Id TypeReferenceId
-> DefnsF Set TypeReferenceId TypeReferenceId
forall r. Ord r => DefnsF Set (Referent' r) r -> DefnsF Set r r
NamesUtils.referentsToRefs DefnsF Set Id TypeReferenceId
dependenciesRefs

  Branch0 IO
namespace <- Cli (Branch0 IO)
Cli.getCurrentProjectRoot0
  let ppe :: PrettyPrintEnv
ppe =
        let names :: Names
names =
              Branch0 IO
namespace
                Branch0 IO -> (Branch0 IO -> Branch0 IO) -> Branch0 IO
forall a b. a -> (a -> b) -> b
& Branch0 IO -> Branch0 IO
forall (m :: * -> *). Branch0 m -> Branch0 m
Branch.deleteLibdeps
                Branch0 IO -> (Branch0 IO -> Names) -> Names
forall a b. a -> (a -> b) -> b
& Branch0 IO -> Names
forall (m :: * -> *). Branch0 m -> Names
Branch.toNames
                Names -> (Names -> Names) -> Names
forall a b. a -> (a -> b) -> b
& TypecheckedUnisonFile Symbol Ann -> Names -> Names
forall v a. Var v => TypecheckedUnisonFile v a -> Names -> Names
UnisonFile.addNamesFromTypeCheckedUnisonFile TypecheckedUnisonFile Symbol Ann
unisonFile
         in Namer -> Suffixifier -> PrettyPrintEnv
PPE.makePPE (Int -> Names -> Namer
PPE.hqNamer Int
10 Names
names) (Names -> Suffixifier
PPE.suffixifyByHash Names
names)

  let dependents :: DefnsF Set TermReferenceId TypeReferenceId
      dependents :: DefnsF Set TypeReferenceId TypeReferenceId
dependents =
        DefnsF Set TypeReferenceId TypeReferenceId
-> TypecheckedUnisonFile Symbol Ann
-> DefnsF Set TypeReferenceId TypeReferenceId
forall a v.
Ord v =>
DefnsF Set TypeReferenceId TypeReferenceId
-> TypecheckedUnisonFile v a
-> DefnsF Set TypeReferenceId TypeReferenceId
identifyFileDependents DefnsF Set TypeReferenceId TypeReferenceId
dependenciesRefs1 TypecheckedUnisonFile Symbol Ann
unisonFile

  let dependentNames ::
        DefnsF
          []
          (HQ'.HashQualified Name, HQ'.HashQualified Name)
          (HQ'.HashQualified Name, HQ'.HashQualified Name)
      dependentNames :: DefnsF
  []
  (HashQualified Name, HashQualified Name)
  (HashQualified Name, HashQualified Name)
dependentNames =
        PrettyPrintEnv
-> DefnsF Set TypeReferenceId TypeReferenceId
-> DefnsF
     []
     (HashQualified Name, HashQualified Name)
     (HashQualified Name, HashQualified Name)
nameDependents PrettyPrintEnv
ppe DefnsF Set TypeReferenceId TypeReferenceId
dependents

  -- Set numbered args
  (DefnsF
  []
  (HashQualified Name, HashQualified Name)
  (HashQualified Name, HashQualified Name)
dependentNames.types [(HashQualified Name, HashQualified Name)]
-> [(HashQualified Name, HashQualified Name)]
-> [(HashQualified Name, HashQualified Name)]
forall a. [a] -> [a] -> [a]
++ DefnsF
  []
  (HashQualified Name, HashQualified Name)
  (HashQualified Name, HashQualified Name)
dependentNames.terms)
    [(HashQualified Name, HashQualified Name)]
-> ([(HashQualified Name, HashQualified Name)]
    -> [StructuredArgument])
-> [StructuredArgument]
forall a b. a -> (a -> b) -> b
& ((HashQualified Name, HashQualified Name) -> StructuredArgument)
-> [(HashQualified Name, HashQualified Name)]
-> [StructuredArgument]
forall a b. (a -> b) -> [a] -> [b]
map (HashQualified Name -> StructuredArgument
SA.HashQualified (HashQualified Name -> StructuredArgument)
-> ((HashQualified Name, HashQualified Name) -> HashQualified Name)
-> (HashQualified Name, HashQualified Name)
-> StructuredArgument
forall b c a. (b -> c) -> (a -> b) -> a -> c
. HashQualified Name -> HashQualified Name
forall n. HashQualified n -> HashQualified n
HQ'.toHQ (HashQualified Name -> HashQualified Name)
-> ((HashQualified Name, HashQualified Name) -> HashQualified Name)
-> (HashQualified Name, HashQualified Name)
-> HashQualified Name
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (HashQualified Name, HashQualified Name) -> HashQualified Name
forall a b. (a, b) -> a
fst)
    [StructuredArgument] -> ([StructuredArgument] -> Cli ()) -> Cli ()
forall a b. a -> (a -> b) -> b
& [StructuredArgument] -> Cli ()
Cli.setNumberedArgs

  Output -> Cli ()
Cli.respond (Output -> Cli ()) -> Output -> Cli ()
forall a b. (a -> b) -> a -> b
$
    DefnsF2 (Map (HashQualified Name)) Maybe Bool Bool
-> DefnsF
     []
     (HashQualified Name, HashQualified Name)
     (HashQualified Name, HashQualified Name)
-> Output
ListDependents
      ( let f :: Set k -> Map k (Maybe Bool)
f = (k -> Maybe Bool) -> Set k -> Map k (Maybe Bool)
forall k a. (k -> a) -> Set k -> Map k a
Map.fromSet \k
_ -> Bool -> Maybe Bool
forall a. a -> Maybe a
Just Bool
True
         in (Set (HashQualified Name) -> Map (HashQualified Name) (Maybe Bool))
-> (Set (HashQualified Name)
    -> Map (HashQualified Name) (Maybe Bool))
-> DefnsF2 Set HashQualified Name Name
-> DefnsF2 (Map (HashQualified Name)) Maybe Bool Bool
forall a b c d. (a -> b) -> (c -> d) -> Defns a c -> Defns b d
forall (p :: * -> * -> *) a b c d.
Bifunctor p =>
(a -> b) -> (c -> d) -> p a c -> p b d
bimap
              Set (HashQualified Name) -> Map (HashQualified Name) (Maybe Bool)
forall {k}. Set k -> Map k (Maybe Bool)
f
              Set (HashQualified Name) -> Map (HashQualified Name) (Maybe Bool)
forall {k}. Set k -> Map k (Maybe Bool)
f
              ( PrettyPrintEnv
-> DefnsF Set Referent TypeReference
-> DefnsF2 Set HashQualified Name Name
nameDependencies
                  PrettyPrintEnv
ppe
                  ( (Set Id -> Set Referent)
-> (Set TypeReferenceId -> Set TypeReference)
-> DefnsF Set Id TypeReferenceId
-> DefnsF Set Referent TypeReference
forall a b c d. (a -> b) -> (c -> d) -> Defns a c -> Defns b d
forall (p :: * -> * -> *) a b c d.
Bifunctor p =>
(a -> b) -> (c -> d) -> p a c -> p b d
bimap
                      ((Id -> Referent) -> Set Id -> Set Referent
forall b a. Ord b => (a -> b) -> Set a -> Set b
Set.map Id -> Referent
Referent.fromId)
                      ((TypeReferenceId -> TypeReference)
-> Set TypeReferenceId -> Set TypeReference
forall b a. Ord b => (a -> b) -> Set a -> Set b
Set.map TypeReferenceId -> TypeReference
Reference.fromId)
                      DefnsF Set Id TypeReferenceId
dependenciesRefs
                  )
              )
      )
      DefnsF
  []
  (HashQualified Name, HashQualified Name)
  (HashQualified Name, HashQualified Name)
dependentNames
  where
    notFound :: Cli a
    notFound :: forall a. Cli a
notFound =
      Output -> Cli a
forall a. Output -> Cli a
Cli.returnEarly (HashQualified Name -> Output
LabeledReferenceNotFound HashQualified Name
hq)

-- Extract the referents ids out of a unison file. This probably doesn't belong in this module; it's just kind of a
-- variant of 'toNames', but more efficient (no relations, just maps) and with fewer impossible cases (e.g. conflicted
-- names, builtins).
fileToReferentsIds :: forall a v. (Var v) => TypecheckedUnisonFile v a -> DefnsF (Map Name) Referent.Id TypeReferenceId
fileToReferentsIds :: forall a v.
Var v =>
TypecheckedUnisonFile v a
-> Defns (Map Name Id) (Map Name TypeReferenceId)
fileToReferentsIds TypecheckedUnisonFile v a
unisonFile =
  Defns
    { $sel:terms:Defns :: Map Name Id
terms =
        Map Name Id
forall k a. Map k a
Map.empty
          Map Name Id -> (Map Name Id -> Map Name Id) -> Map Name Id
forall a b. a -> (a -> b) -> b
& Map v (a, TypeReferenceId, Maybe WatchKind, Term v a, Type v a)
-> Map Name Id -> Map Name Id
addTerms TypecheckedUnisonFile v a
unisonFile.hashTermsId
          Map Name Id -> (Map Name Id -> Map Name Id) -> Map Name Id
forall a b. a -> (a -> b) -> b
& Map v (ConstructorReferenceId, Decl v a)
-> Map Name Id -> Map Name Id
addConstructors (TypecheckedUnisonFile v a
-> Map v (ConstructorReferenceId, Decl v a)
forall v a.
(Ord v, Show v) =>
TypecheckedUnisonFile v a
-> Map v (ConstructorReferenceId, Decl v a)
UnisonFile.constructorsId TypecheckedUnisonFile v a
unisonFile),
      $sel:types:Defns :: Map Name TypeReferenceId
types =
        Map Name TypeReferenceId
forall k a. Map k a
Map.empty
          Map Name TypeReferenceId
-> (Map Name TypeReferenceId -> Map Name TypeReferenceId)
-> Map Name TypeReferenceId
forall a b. a -> (a -> b) -> b
& Map v (TypeReferenceId, DataDeclaration v a)
-> Map Name TypeReferenceId -> Map Name TypeReferenceId
forall decl.
Map v (TypeReferenceId, decl)
-> Map Name TypeReferenceId -> Map Name TypeReferenceId
addDecls TypecheckedUnisonFile v a
unisonFile.dataDeclarationsId'
          Map Name TypeReferenceId
-> (Map Name TypeReferenceId -> Map Name TypeReferenceId)
-> Map Name TypeReferenceId
forall a b. a -> (a -> b) -> b
& Map v (TypeReferenceId, EffectDeclaration v a)
-> Map Name TypeReferenceId -> Map Name TypeReferenceId
forall decl.
Map v (TypeReferenceId, decl)
-> Map Name TypeReferenceId -> Map Name TypeReferenceId
addDecls TypecheckedUnisonFile v a
unisonFile.effectDeclarationsId'
    }
  where
    addTerms ::
      Map v (a, TermReferenceId, Maybe WatchKind, Term v a, Type v a) ->
      Map Name Referent.Id ->
      Map Name Referent.Id
    addTerms :: Map v (a, TypeReferenceId, Maybe WatchKind, Term v a, Type v a)
-> Map Name Id -> Map Name Id
addTerms Map v (a, TypeReferenceId, Maybe WatchKind, Term v a, Type v a)
terms Map Name Id
acc =
      (Map Name Id
 -> v
 -> (a, TypeReferenceId, Maybe WatchKind, Term v a, Type v a)
 -> Map Name Id)
-> Map Name Id
-> Map v (a, TypeReferenceId, Maybe WatchKind, Term v a, Type v a)
-> Map Name Id
forall a k b. (a -> k -> b -> a) -> a -> Map k b -> a
Map.foldlWithKey' Map Name Id
-> v
-> (a, TypeReferenceId, Maybe WatchKind, Term v a, Type v a)
-> Map Name Id
forall {v} {b} {a} {c} {d} {e}.
Var v =>
Map Name (Referent' b)
-> v -> (a, b, c, d, e) -> Map Name (Referent' b)
f Map Name Id
acc Map v (a, TypeReferenceId, Maybe WatchKind, Term v a, Type v a)
terms
      where
        f :: Map Name (Referent' b)
-> v -> (a, b, c, d, e) -> Map Name (Referent' b)
f Map Name (Referent' b)
acc v
var (a
_, b
ref, c
_, d
_, e
_) =
          Name
-> Referent' b -> Map Name (Referent' b) -> Map Name (Referent' b)
forall k a. Ord k => k -> a -> Map k a -> Map k a
Map.insert
            (v -> Name
forall v. Var v => v -> Name
Name.unsafeParseVar v
var)
            (AReview (Referent' b) b -> b -> Referent' b
forall b (m :: * -> *) t. MonadReader b m => AReview t b -> m t
review AReview (Referent' b) b
forall r (p :: * -> * -> *) (f :: * -> *).
(Choice p, Applicative f) =>
p r (f r) -> p (Referent' r) (f (Referent' r))
Referent'.termReference_ b
ref)
            Map Name (Referent' b)
acc

    addConstructors :: Map v (ConstructorReferenceId, Decl v a) -> Map Name Referent.Id -> Map Name Referent.Id
    addConstructors :: Map v (ConstructorReferenceId, Decl v a)
-> Map Name Id -> Map Name Id
addConstructors Map v (ConstructorReferenceId, Decl v a)
constructors Map Name Id
acc =
      (Map Name Id
 -> v -> (ConstructorReferenceId, Decl v a) -> Map Name Id)
-> Map Name Id
-> Map v (ConstructorReferenceId, Decl v a)
-> Map Name Id
forall a k b. (a -> k -> b -> a) -> a -> Map k b -> a
Map.foldlWithKey' Map Name Id
-> v -> (ConstructorReferenceId, Decl v a) -> Map Name Id
forall {v} {r} {v} {a}.
Var v =>
Map Name (Referent' r)
-> v
-> (GConstructorReference r, Decl v a)
-> Map Name (Referent' r)
f Map Name Id
acc Map v (ConstructorReferenceId, Decl v a)
constructors
      where
        f :: Map Name (Referent' r)
-> v
-> (GConstructorReference r, Decl v a)
-> Map Name (Referent' r)
f Map Name (Referent' r)
acc v
var (GConstructorReference r
ref, Decl v a
decl) =
          Name
-> Referent' r -> Map Name (Referent' r) -> Map Name (Referent' r)
forall k a. Ord k => k -> a -> Map k a -> Map k a
Map.insert
            (v -> Name
forall v. Var v => v -> Name
Name.unsafeParseVar v
var)
            (GConstructorReference r -> ConstructorType -> Referent' r
forall r. GConstructorReference r -> ConstructorType -> Referent' r
Referent'.Con' GConstructorReference r
ref (Decl v a -> ConstructorType
forall v a. Decl v a -> ConstructorType
DataDeclaration.constructorType Decl v a
decl))
            Map Name (Referent' r)
acc

    addDecls :: Map v (TypeReferenceId, decl) -> Map Name TypeReferenceId -> Map Name TypeReferenceId
    addDecls :: forall decl.
Map v (TypeReferenceId, decl)
-> Map Name TypeReferenceId -> Map Name TypeReferenceId
addDecls Map v (TypeReferenceId, decl)
decls Map Name TypeReferenceId
acc =
      (Map Name TypeReferenceId
 -> v -> (TypeReferenceId, decl) -> Map Name TypeReferenceId)
-> Map Name TypeReferenceId
-> Map v (TypeReferenceId, decl)
-> Map Name TypeReferenceId
forall a k b. (a -> k -> b -> a) -> a -> Map k b -> a
Map.foldlWithKey' Map Name TypeReferenceId
-> v -> (TypeReferenceId, decl) -> Map Name TypeReferenceId
forall {v} {a} {b}.
Var v =>
Map Name a -> v -> (a, b) -> Map Name a
f Map Name TypeReferenceId
acc Map v (TypeReferenceId, decl)
decls
      where
        f :: Map Name a -> v -> (a, b) -> Map Name a
f Map Name a
acc v
var (a
ref, b
_) =
          Name -> a -> Map Name a -> Map Name a
forall k a. Ord k => k -> a -> Map k a -> Map k a
Map.insert (v -> Name
forall v. Var v => v -> Name
Name.unsafeParseVar v
var) a
ref Map Name a
acc

identifyFileDependents ::
  forall a v.
  (Ord v) =>
  DefnsF Set TermReferenceId TypeReferenceId ->
  TypecheckedUnisonFile v a ->
  DefnsF Set TermReferenceId TypeReferenceId
identifyFileDependents :: forall a v.
Ord v =>
DefnsF Set TypeReferenceId TypeReferenceId
-> TypecheckedUnisonFile v a
-> DefnsF Set TypeReferenceId TypeReferenceId
identifyFileDependents DefnsF Set TypeReferenceId TypeReferenceId
dependencies TypecheckedUnisonFile v a
unisonFile =
  Defns
    { $sel:terms:Defns :: Set TypeReferenceId
terms =
        Set TypeReferenceId -> Set TypeReferenceId -> Set TypeReferenceId
forall a. Ord a => Set a -> Set a -> Set a
Set.union
          ((TypeReferenceId -> Set TypeReferenceId)
-> Set TypeReferenceId -> Set TypeReferenceId
forall m a. Monoid m => (a -> m) -> Set a -> m
forall (t :: * -> *) m a.
(Foldable t, Monoid m) =>
(a -> m) -> t a -> m
foldMap (Map TypeReferenceId (NESet TypeReferenceId)
-> TypeReferenceId -> Set TypeReferenceId
forall k a. Ord k => Map k (NESet a) -> k -> Set a
lookupSet Map TypeReferenceId (NESet TypeReferenceId)
termTermDependents) DefnsF Set TypeReferenceId TypeReferenceId
dependencies.terms)
          ((TypeReferenceId -> Set TypeReferenceId)
-> Set TypeReferenceId -> Set TypeReferenceId
forall m a. Monoid m => (a -> m) -> Set a -> m
forall (t :: * -> *) m a.
(Foldable t, Monoid m) =>
(a -> m) -> t a -> m
foldMap (Map TypeReferenceId (NESet TypeReferenceId)
-> TypeReferenceId -> Set TypeReferenceId
forall k a. Ord k => Map k (NESet a) -> k -> Set a
lookupSet Map TypeReferenceId (NESet TypeReferenceId)
typeTermDependents) DefnsF Set TypeReferenceId TypeReferenceId
dependencies.types),
      $sel:types:Defns :: Set TypeReferenceId
types = (TypeReferenceId -> Set TypeReferenceId)
-> Set TypeReferenceId -> Set TypeReferenceId
forall m a. Monoid m => (a -> m) -> Set a -> m
forall (t :: * -> *) m a.
(Foldable t, Monoid m) =>
(a -> m) -> t a -> m
foldMap (Map TypeReferenceId (NESet TypeReferenceId)
-> TypeReferenceId -> Set TypeReferenceId
forall k a. Ord k => Map k (NESet a) -> k -> Set a
lookupSet Map TypeReferenceId (NESet TypeReferenceId)
typeTypeDependents) DefnsF Set TypeReferenceId TypeReferenceId
dependencies.types
    }
  where
    termTermDependents :: Map TermReferenceId (NESet TermReferenceId)
    typeTermDependents :: Map TypeReferenceId (NESet TermReferenceId)
    (Map TypeReferenceId (NESet TypeReferenceId)
termTermDependents, Map TypeReferenceId (NESet TypeReferenceId)
typeTermDependents) =
      DefnsF Set TypeReferenceId TypeReferenceId
-> Map v (a, TypeReferenceId, Maybe WatchKind, Term v a, Type v a)
-> (Map TypeReferenceId (NESet TypeReferenceId),
    Map TypeReferenceId (NESet TypeReferenceId))
forall v a.
Ord v =>
DefnsF Set TypeReferenceId TypeReferenceId
-> Map v (a, TypeReferenceId, Maybe WatchKind, Term v a, Type v a)
-> (Map TypeReferenceId (NESet TypeReferenceId),
    Map TypeReferenceId (NESet TypeReferenceId))
termDependenciesByDependent DefnsF Set TypeReferenceId TypeReferenceId
dependencies TypecheckedUnisonFile v a
unisonFile.hashTermsId

    typeTypeDependents :: Map TypeReferenceId (NESet TypeReferenceId)
    typeTypeDependents :: Map TypeReferenceId (NESet TypeReferenceId)
typeTypeDependents =
      Map TypeReferenceId (NESet TypeReferenceId)
-> Map TypeReferenceId (NESet TypeReferenceId)
-> Map TypeReferenceId (NESet TypeReferenceId)
forall k a. Ord k => Map k a -> Map k a -> Map k a
Map.union
        (DefnsF Set TypeReferenceId TypeReferenceId
-> Map v (TypeReferenceId, DataDeclaration v a)
-> Map TypeReferenceId (NESet TypeReferenceId)
forall v a.
Ord v =>
DefnsF Set TypeReferenceId TypeReferenceId
-> Map v (TypeReferenceId, DataDeclaration v a)
-> Map TypeReferenceId (NESet TypeReferenceId)
typeDependenciesByDependent DefnsF Set TypeReferenceId TypeReferenceId
dependencies TypecheckedUnisonFile v a
unisonFile.dataDeclarationsId')
        ( DefnsF Set TypeReferenceId TypeReferenceId
-> Map v (TypeReferenceId, DataDeclaration v a)
-> Map TypeReferenceId (NESet TypeReferenceId)
forall v a.
Ord v =>
DefnsF Set TypeReferenceId TypeReferenceId
-> Map v (TypeReferenceId, DataDeclaration v a)
-> Map TypeReferenceId (NESet TypeReferenceId)
typeDependenciesByDependent
            DefnsF Set TypeReferenceId TypeReferenceId
dependencies
            ( forall a b. Coercible a b => a -> b
forall a b. Coercible a b => a -> b
coerce
                @(Map v (TypeReferenceId, EffectDeclaration v a))
                @(Map v (TypeReferenceId, DataDeclaration v a))
                TypecheckedUnisonFile v a
unisonFile.effectDeclarationsId'
            )
        )

    lookupSet :: forall k a. (Ord k) => Map k (NESet a) -> k -> Set a
    lookupSet :: forall k a. Ord k => Map k (NESet a) -> k -> Set a
lookupSet Map k (NESet a)
m k
k =
      Set a -> (NESet a -> Set a) -> Maybe (NESet a) -> Set a
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Set a
forall a. Set a
Set.empty NESet a -> Set a
forall a. NESet a -> Set a
Set.NonEmpty.toSet (k -> Map k (NESet a) -> Maybe (NESet a)
forall k a. Ord k => k -> Map k a -> Maybe a
Map.lookup k
k Map k (NESet a)
m)

termDependenciesByDependent ::
  (Ord v) =>
  DefnsF Set TermReferenceId TypeReferenceId ->
  Map v (a, TermReferenceId, Maybe WatchKind, Term v a, Type v a) ->
  (Map TermReferenceId (NESet TermReferenceId), Map TypeReferenceId (NESet TermReferenceId))
termDependenciesByDependent :: forall v a.
Ord v =>
DefnsF Set TypeReferenceId TypeReferenceId
-> Map v (a, TypeReferenceId, Maybe WatchKind, Term v a, Type v a)
-> (Map TypeReferenceId (NESet TypeReferenceId),
    Map TypeReferenceId (NESet TypeReferenceId))
termDependenciesByDependent DefnsF Set TypeReferenceId TypeReferenceId
dependenciesRefs1 =
  ((Map TypeReferenceId (NESet TypeReferenceId),
  Map TypeReferenceId (NESet TypeReferenceId))
 -> (a, TypeReferenceId, Maybe WatchKind, Term v a, Type v a)
 -> (Map TypeReferenceId (NESet TypeReferenceId),
     Map TypeReferenceId (NESet TypeReferenceId)))
-> (Map TypeReferenceId (NESet TypeReferenceId),
    Map TypeReferenceId (NESet TypeReferenceId))
-> Map v (a, TypeReferenceId, Maybe WatchKind, Term v a, Type v a)
-> (Map TypeReferenceId (NESet TypeReferenceId),
    Map TypeReferenceId (NESet TypeReferenceId))
forall a b k. (a -> b -> a) -> a -> Map k b -> a
Map.foldl' (Map TypeReferenceId (NESet TypeReferenceId),
 Map TypeReferenceId (NESet TypeReferenceId))
-> (a, TypeReferenceId, Maybe WatchKind, Term v a, Type v a)
-> (Map TypeReferenceId (NESet TypeReferenceId),
    Map TypeReferenceId (NESet TypeReferenceId))
f (Map TypeReferenceId (NESet TypeReferenceId)
forall k a. Map k a
Map.empty, Map TypeReferenceId (NESet TypeReferenceId)
forall k a. Map k a
Map.empty)
  where
    f :: (Map TypeReferenceId (NESet TypeReferenceId),
 Map TypeReferenceId (NESet TypeReferenceId))
-> (a, TypeReferenceId, Maybe WatchKind, Term v a, Type v a)
-> (Map TypeReferenceId (NESet TypeReferenceId),
    Map TypeReferenceId (NESet TypeReferenceId))
f (Map TypeReferenceId (NESet TypeReferenceId)
accTerms, Map TypeReferenceId (NESet TypeReferenceId)
accTypes) (a
_, TypeReferenceId
x, Maybe WatchKind
wk, Term v a
term, Type v a
_)
      | Maybe WatchKind -> Bool
WatchKind.watchKindShouldBeStoredInDatabase Maybe WatchKind
wk =
          ( (Map TypeReferenceId (NESet TypeReferenceId)
 -> TypeReference -> Map TypeReferenceId (NESet TypeReferenceId))
-> Map TypeReferenceId (NESet TypeReferenceId)
-> Set TypeReference
-> Map TypeReferenceId (NESet TypeReferenceId)
forall a b. (a -> b -> a) -> a -> Set b -> a
Set.foldl' Map TypeReferenceId (NESet TypeReferenceId)
-> TypeReference -> Map TypeReferenceId (NESet TypeReferenceId)
dependsOnTerm Map TypeReferenceId (NESet TypeReferenceId)
accTerms DefnsF Set TypeReference TypeReference
dependencies.terms,
            (Map TypeReferenceId (NESet TypeReferenceId)
 -> TypeReference -> Map TypeReferenceId (NESet TypeReferenceId))
-> Map TypeReferenceId (NESet TypeReferenceId)
-> Set TypeReference
-> Map TypeReferenceId (NESet TypeReferenceId)
forall a b. (a -> b -> a) -> a -> Set b -> a
Set.foldl' Map TypeReferenceId (NESet TypeReferenceId)
-> TypeReference -> Map TypeReferenceId (NESet TypeReferenceId)
dependsOnType Map TypeReferenceId (NESet TypeReferenceId)
accTypes DefnsF Set TypeReference TypeReference
dependencies.types
          )
      | Bool
otherwise = (Map TypeReferenceId (NESet TypeReferenceId)
accTerms, Map TypeReferenceId (NESet TypeReferenceId)
accTypes)
      where
        dependencies :: DefnsF Set TermReference TypeReference
        dependencies :: DefnsF Set TypeReference TypeReference
dependencies =
          Term v a -> DefnsF Set TypeReference TypeReference
forall v vt at ap a.
(Ord v, Ord vt) =>
Term2 vt at ap v a -> DefnsF Set TypeReference TypeReference
Term.dependencies Term v a
term

        -- If `term x` depends on `term y`, and `term y` is in the set of things we want to report dependents of,
        -- then record `term y` => {`term x`} in our term dependents map.
        dependsOnTerm :: Map TypeReferenceId (NESet TypeReferenceId)
-> TypeReference -> Map TypeReferenceId (NESet TypeReferenceId)
dependsOnTerm Map TypeReferenceId (NESet TypeReferenceId)
acc TypeReference
y =
          Map TypeReferenceId (NESet TypeReferenceId)
-> Maybe (Map TypeReferenceId (NESet TypeReferenceId))
-> Map TypeReferenceId (NESet TypeReferenceId)
forall a. a -> Maybe a -> a
fromMaybe Map TypeReferenceId (NESet TypeReferenceId)
acc do
            TypeReferenceId
y' <- TypeReference -> Maybe TypeReferenceId
Reference.toId TypeReference
y
            Bool -> Maybe ()
forall (f :: * -> *). Alternative f => Bool -> f ()
guard (TypeReferenceId -> Set TypeReferenceId -> Bool
forall a. Ord a => a -> Set a -> Bool
Set.member TypeReferenceId
y' DefnsF Set TypeReferenceId TypeReferenceId
dependenciesRefs1.terms)
            Map TypeReferenceId (NESet TypeReferenceId)
-> Maybe (Map TypeReferenceId (NESet TypeReferenceId))
forall a. a -> Maybe a
Just ((Maybe (NESet TypeReferenceId) -> NESet TypeReferenceId)
-> TypeReferenceId
-> Map TypeReferenceId (NESet TypeReferenceId)
-> Map TypeReferenceId (NESet TypeReferenceId)
forall k v. Ord k => (Maybe v -> v) -> k -> Map k v -> Map k v
Map.upsert (NESet TypeReferenceId
-> (NESet TypeReferenceId -> NESet TypeReferenceId)
-> Maybe (NESet TypeReferenceId)
-> NESet TypeReferenceId
forall b a. b -> (a -> b) -> Maybe a -> b
maybe (TypeReferenceId -> NESet TypeReferenceId
forall a. a -> NESet a
Set.NonEmpty.singleton TypeReferenceId
x) (TypeReferenceId -> NESet TypeReferenceId -> NESet TypeReferenceId
forall a. Ord a => a -> NESet a -> NESet a
Set.NonEmpty.insert TypeReferenceId
x)) TypeReferenceId
y' Map TypeReferenceId (NESet TypeReferenceId)
acc)

        -- If `term x` depends on `type y`, and `type y` is in the set of things we want to report dependents of,
        -- then record `type y` => {`term x`} in our type dependents map.
        dependsOnType :: Map TypeReferenceId (NESet TypeReferenceId)
-> TypeReference -> Map TypeReferenceId (NESet TypeReferenceId)
dependsOnType Map TypeReferenceId (NESet TypeReferenceId)
acc TypeReference
y =
          Map TypeReferenceId (NESet TypeReferenceId)
-> Maybe (Map TypeReferenceId (NESet TypeReferenceId))
-> Map TypeReferenceId (NESet TypeReferenceId)
forall a. a -> Maybe a -> a
fromMaybe Map TypeReferenceId (NESet TypeReferenceId)
acc do
            TypeReferenceId
y' <- TypeReference -> Maybe TypeReferenceId
Reference.toId TypeReference
y
            Bool -> Maybe ()
forall (f :: * -> *). Alternative f => Bool -> f ()
guard (TypeReferenceId -> Set TypeReferenceId -> Bool
forall a. Ord a => a -> Set a -> Bool
Set.member TypeReferenceId
y' DefnsF Set TypeReferenceId TypeReferenceId
dependenciesRefs1.types)
            Map TypeReferenceId (NESet TypeReferenceId)
-> Maybe (Map TypeReferenceId (NESet TypeReferenceId))
forall a. a -> Maybe a
Just ((Maybe (NESet TypeReferenceId) -> NESet TypeReferenceId)
-> TypeReferenceId
-> Map TypeReferenceId (NESet TypeReferenceId)
-> Map TypeReferenceId (NESet TypeReferenceId)
forall k v. Ord k => (Maybe v -> v) -> k -> Map k v -> Map k v
Map.upsert (NESet TypeReferenceId
-> (NESet TypeReferenceId -> NESet TypeReferenceId)
-> Maybe (NESet TypeReferenceId)
-> NESet TypeReferenceId
forall b a. b -> (a -> b) -> Maybe a -> b
maybe (TypeReferenceId -> NESet TypeReferenceId
forall a. a -> NESet a
Set.NonEmpty.singleton TypeReferenceId
x) (TypeReferenceId -> NESet TypeReferenceId -> NESet TypeReferenceId
forall a. Ord a => a -> NESet a -> NESet a
Set.NonEmpty.insert TypeReferenceId
x)) TypeReferenceId
y' Map TypeReferenceId (NESet TypeReferenceId)
acc)

typeDependenciesByDependent ::
  (Ord v) =>
  DefnsF Set TermReferenceId TypeReferenceId ->
  Map v (TypeReferenceId, DataDeclaration v a) ->
  Map TypeReferenceId (NESet TypeReferenceId)
typeDependenciesByDependent :: forall v a.
Ord v =>
DefnsF Set TypeReferenceId TypeReferenceId
-> Map v (TypeReferenceId, DataDeclaration v a)
-> Map TypeReferenceId (NESet TypeReferenceId)
typeDependenciesByDependent DefnsF Set TypeReferenceId TypeReferenceId
dependencies =
  (Map TypeReferenceId (NESet TypeReferenceId)
 -> (TypeReferenceId, DataDeclaration v a)
 -> Map TypeReferenceId (NESet TypeReferenceId))
-> Map TypeReferenceId (NESet TypeReferenceId)
-> Map v (TypeReferenceId, DataDeclaration v a)
-> Map TypeReferenceId (NESet TypeReferenceId)
forall a b k. (a -> b -> a) -> a -> Map k b -> a
Map.foldl' Map TypeReferenceId (NESet TypeReferenceId)
-> (TypeReferenceId, DataDeclaration v a)
-> Map TypeReferenceId (NESet TypeReferenceId)
forall {v} {a}.
Ord v =>
Map TypeReferenceId (NESet TypeReferenceId)
-> (TypeReferenceId, DataDeclaration v a)
-> Map TypeReferenceId (NESet TypeReferenceId)
f Map TypeReferenceId (NESet TypeReferenceId)
forall k a. Map k a
Map.empty
  where
    f :: Map TypeReferenceId (NESet TypeReferenceId)
-> (TypeReferenceId, DataDeclaration v a)
-> Map TypeReferenceId (NESet TypeReferenceId)
f Map TypeReferenceId (NESet TypeReferenceId)
acc (TypeReferenceId
x, DataDeclaration v a
dataDecl) =
      (Map TypeReferenceId (NESet TypeReferenceId)
 -> TypeReference -> Map TypeReferenceId (NESet TypeReferenceId))
-> Map TypeReferenceId (NESet TypeReferenceId)
-> Set TypeReference
-> Map TypeReferenceId (NESet TypeReferenceId)
forall a b. (a -> b -> a) -> a -> Set b -> a
Set.foldl (TypeReferenceId
-> Map TypeReferenceId (NESet TypeReferenceId)
-> TypeReference
-> Map TypeReferenceId (NESet TypeReferenceId)
g TypeReferenceId
x) Map TypeReferenceId (NESet TypeReferenceId)
acc (DataDeclaration v a -> Set TypeReference
forall v a. Ord v => DataDeclaration v a -> Set TypeReference
DataDeclaration.typeDependencies DataDeclaration v a
dataDecl)

    -- If `type x` depends on `type y`, and `type y` is in the set of things we want to report dependents of,
    -- either directly or because we want to report dependents of one of its constructors, then record
    -- `type y` => {`type x`} in our type dependents map.
    g ::
      TypeReferenceId ->
      Map TypeReferenceId (NESet TypeReferenceId) ->
      TypeReference ->
      Map TypeReferenceId (NESet TypeReferenceId)
    g :: TypeReferenceId
-> Map TypeReferenceId (NESet TypeReferenceId)
-> TypeReference
-> Map TypeReferenceId (NESet TypeReferenceId)
g TypeReferenceId
x Map TypeReferenceId (NESet TypeReferenceId)
acc TypeReference
y =
      Map TypeReferenceId (NESet TypeReferenceId)
-> Maybe (Map TypeReferenceId (NESet TypeReferenceId))
-> Map TypeReferenceId (NESet TypeReferenceId)
forall a. a -> Maybe a -> a
fromMaybe Map TypeReferenceId (NESet TypeReferenceId)
acc do
        TypeReferenceId
y' <- TypeReference -> Maybe TypeReferenceId
Reference.toId TypeReference
y
        Bool -> Maybe ()
forall (f :: * -> *). Alternative f => Bool -> f ()
guard (TypeReferenceId -> Set TypeReferenceId -> Bool
forall a. Ord a => a -> Set a -> Bool
Set.member TypeReferenceId
y' DefnsF Set TypeReferenceId TypeReferenceId
dependencies.types)
        Map TypeReferenceId (NESet TypeReferenceId)
-> Maybe (Map TypeReferenceId (NESet TypeReferenceId))
forall a. a -> Maybe a
Just ((Maybe (NESet TypeReferenceId) -> NESet TypeReferenceId)
-> TypeReferenceId
-> Map TypeReferenceId (NESet TypeReferenceId)
-> Map TypeReferenceId (NESet TypeReferenceId)
forall k v. Ord k => (Maybe v -> v) -> k -> Map k v -> Map k v
Map.upsert (NESet TypeReferenceId
-> (NESet TypeReferenceId -> NESet TypeReferenceId)
-> Maybe (NESet TypeReferenceId)
-> NESet TypeReferenceId
forall b a. b -> (a -> b) -> Maybe a -> b
maybe (TypeReferenceId -> NESet TypeReferenceId
forall a. a -> NESet a
Set.NonEmpty.singleton TypeReferenceId
x) (TypeReferenceId -> NESet TypeReferenceId -> NESet TypeReferenceId
forall a. Ord a => a -> NESet a -> NESet a
Set.NonEmpty.insert TypeReferenceId
x)) TypeReferenceId
y' Map TypeReferenceId (NESet TypeReferenceId)
acc)

nameDependencies ::
  PPE.PrettyPrintEnv ->
  DefnsF Set Referent TypeReference ->
  DefnsF2 Set HQ.HashQualified Name Name
nameDependencies :: PrettyPrintEnv
-> DefnsF Set Referent TypeReference
-> DefnsF2 Set HashQualified Name Name
nameDependencies PrettyPrintEnv
ppe =
  (Set Referent -> Set (HashQualified Name))
-> (Set TypeReference -> Set (HashQualified Name))
-> DefnsF Set Referent TypeReference
-> DefnsF2 Set HashQualified Name Name
forall a b c d. (a -> b) -> (c -> d) -> Defns a c -> Defns b d
forall (p :: * -> * -> *) a b c d.
Bifunctor p =>
(a -> b) -> (c -> d) -> p a c -> p b d
bimap
    ((Referent -> HashQualified Name)
-> Set Referent -> Set (HashQualified Name)
forall b a. Ord b => (a -> b) -> Set a -> Set b
Set.map (PrettyPrintEnv -> Referent -> HashQualified Name
PPE.termNameOrHashOnly PrettyPrintEnv
ppe))
    ((TypeReference -> HashQualified Name)
-> Set TypeReference -> Set (HashQualified Name)
forall b a. Ord b => (a -> b) -> Set a -> Set b
Set.map (PrettyPrintEnv -> TypeReference -> HashQualified Name
PPE.typeNameOrHashOnly PrettyPrintEnv
ppe))

nameDependents ::
  PPE.PrettyPrintEnv ->
  DefnsF Set TermReferenceId TypeReferenceId ->
  DefnsF
    []
    (HQ'.HashQualified Name, HQ'.HashQualified Name)
    (HQ'.HashQualified Name, HQ'.HashQualified Name)
nameDependents :: PrettyPrintEnv
-> DefnsF Set TypeReferenceId TypeReferenceId
-> DefnsF
     []
     (HashQualified Name, HashQualified Name)
     (HashQualified Name, HashQualified Name)
nameDependents PrettyPrintEnv
ppe =
  (Set TypeReferenceId -> [(HashQualified Name, HashQualified Name)])
-> (Set TypeReferenceId
    -> [(HashQualified Name, HashQualified Name)])
-> DefnsF Set TypeReferenceId TypeReferenceId
-> DefnsF
     []
     (HashQualified Name, HashQualified Name)
     (HashQualified Name, HashQualified Name)
forall a b c d. (a -> b) -> (c -> d) -> Defns a c -> Defns b d
forall (p :: * -> * -> *) a b c d.
Bifunctor p =>
(a -> b) -> (c -> d) -> p a c -> p b d
bimap
    ((TypeReferenceId -> [(HashQualified Name, HashQualified Name)])
-> Set TypeReferenceId
-> [(HashQualified Name, HashQualified Name)]
forall {a} {b}.
(a -> [(HashQualified Name, b)])
-> Set a -> [(HashQualified Name, b)]
f (TypeReferenceId -> Referent
Referent.fromTermReferenceId (TypeReferenceId -> Referent)
-> (Referent -> [(HashQualified Name, HashQualified Name)])
-> TypeReferenceId
-> [(HashQualified Name, HashQualified Name)]
forall {k} (cat :: k -> k -> *) (a :: k) (b :: k) (c :: k).
Category cat =>
cat a b -> cat b c -> cat a c
>>> PrettyPrintEnv
-> Referent -> [(HashQualified Name, HashQualified Name)]
PPE.termNames PrettyPrintEnv
ppe))
    ((TypeReferenceId -> [(HashQualified Name, HashQualified Name)])
-> Set TypeReferenceId
-> [(HashQualified Name, HashQualified Name)]
forall {a} {b}.
(a -> [(HashQualified Name, b)])
-> Set a -> [(HashQualified Name, b)]
f (TypeReferenceId -> TypeReference
Reference.fromId (TypeReferenceId -> TypeReference)
-> (TypeReference -> [(HashQualified Name, HashQualified Name)])
-> TypeReferenceId
-> [(HashQualified Name, HashQualified Name)]
forall {k} (cat :: k -> k -> *) (a :: k) (b :: k) (c :: k).
Category cat =>
cat a b -> cat b c -> cat a c
>>> PrettyPrintEnv
-> TypeReference -> [(HashQualified Name, HashQualified Name)]
PPE.typeNames PrettyPrintEnv
ppe))
  where
    f :: (a -> [(HashQualified Name, b)])
-> Set a -> [(HashQualified Name, b)]
f a -> [(HashQualified Name, b)]
g =
      Set a -> [a]
forall a. Set a -> [a]
Set.toList
        (Set a -> [a])
-> ([a] -> [(HashQualified Name, b)])
-> Set a
-> [(HashQualified Name, b)]
forall {k} (cat :: k -> k -> *) (a :: k) (b :: k) (c :: k).
Category cat =>
cat a b -> cat b c -> cat a c
>>> (a -> Maybe (HashQualified Name, b))
-> [a] -> [(HashQualified Name, b)]
forall a b. (a -> Maybe b) -> [a] -> [b]
forall (f :: * -> *) a b.
Filterable f =>
(a -> Maybe b) -> f a -> f b
mapMaybe (a -> [(HashQualified Name, b)]
g (a -> [(HashQualified Name, b)])
-> ([(HashQualified Name, b)] -> Maybe (HashQualified Name, b))
-> a
-> Maybe (HashQualified Name, b)
forall {k} (cat :: k -> k -> *) (a :: k) (b :: k) (c :: k).
Category cat =>
cat a b -> cat b c -> cat a c
>>> [(HashQualified Name, b)] -> Maybe (HashQualified Name, b)
forall a. [a] -> Maybe a
listToMaybe)
        ([a] -> [(HashQualified Name, b)])
-> ([(HashQualified Name, b)] -> [(HashQualified Name, b)])
-> [a]
-> [(HashQualified Name, b)]
forall {k} (cat :: k -> k -> *) (a :: k) (b :: k) (c :: k).
Category cat =>
cat a b -> cat b c -> cat a c
>>> ((HashQualified Name, b) -> Text)
-> [(HashQualified Name, b)] -> [(HashQualified Name, b)]
forall a. (a -> Text) -> [a] -> [a]
Name.sortByText ((HashQualified Name, b) -> HashQualified Name
forall a b. (a, b) -> a
fst ((HashQualified Name, b) -> HashQualified Name)
-> (HashQualified Name -> Text) -> (HashQualified Name, b) -> Text
forall {k} (cat :: k -> k -> *) (a :: k) (b :: k) (c :: k).
Category cat =>
cat a b -> cat b c -> cat a c
>>> HashQualified Name -> Text
HQ'.toText)