{-# LANGUAGE PatternSynonyms #-}

module Unison.Server.SearchResultPrime where

import Data.Set qualified as Set
import Unison.Codebase.Editor.DisplayObject (DisplayObject)
import Unison.Codebase.Editor.DisplayObject qualified as DT
import Unison.DataDeclaration (Decl)
import Unison.DataDeclaration qualified as DD
import Unison.HashQualified qualified as HQ
import Unison.HashQualifiedPrime qualified as HQ'
import Unison.LabeledDependency (LabeledDependency)
import Unison.LabeledDependency qualified as LD
import Unison.Name (Name)
import Unison.Prelude
import Unison.Reference (Reference)
import Unison.Referent (Referent)
import Unison.Type (Type)
import Unison.Type qualified as Type

data SearchResult' v a
  = Tm' (TermResult' v a)
  | Tp' (TypeResult' v a)
  deriving (SearchResult' v a -> SearchResult' v a -> Bool
(SearchResult' v a -> SearchResult' v a -> Bool)
-> (SearchResult' v a -> SearchResult' v a -> Bool)
-> Eq (SearchResult' v a)
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
forall v a.
(Var v, Eq a) =>
SearchResult' v a -> SearchResult' v a -> Bool
$c== :: forall v a.
(Var v, Eq a) =>
SearchResult' v a -> SearchResult' v a -> Bool
== :: SearchResult' v a -> SearchResult' v a -> Bool
$c/= :: forall v a.
(Var v, Eq a) =>
SearchResult' v a -> SearchResult' v a -> Bool
/= :: SearchResult' v a -> SearchResult' v a -> Bool
Eq, Int -> SearchResult' v a -> ShowS
[SearchResult' v a] -> ShowS
SearchResult' v a -> String
(Int -> SearchResult' v a -> ShowS)
-> (SearchResult' v a -> String)
-> ([SearchResult' v a] -> ShowS)
-> Show (SearchResult' v a)
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
forall v a. (Show v, Show a) => Int -> SearchResult' v a -> ShowS
forall v a. (Show v, Show a) => [SearchResult' v a] -> ShowS
forall v a. (Show v, Show a) => SearchResult' v a -> String
$cshowsPrec :: forall v a. (Show v, Show a) => Int -> SearchResult' v a -> ShowS
showsPrec :: Int -> SearchResult' v a -> ShowS
$cshow :: forall v a. (Show v, Show a) => SearchResult' v a -> String
show :: SearchResult' v a -> String
$cshowList :: forall v a. (Show v, Show a) => [SearchResult' v a] -> ShowS
showList :: [SearchResult' v a] -> ShowS
Show)

data TermResult' v a
  = TermResult'
      (HQ.HashQualified Name)
      (Maybe (Type v a))
      Referent
      (Set (HQ'.HashQualified Name))
  deriving (TermResult' v a -> TermResult' v a -> Bool
(TermResult' v a -> TermResult' v a -> Bool)
-> (TermResult' v a -> TermResult' v a -> Bool)
-> Eq (TermResult' v a)
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
forall v a. Var v => TermResult' v a -> TermResult' v a -> Bool
$c== :: forall v a. Var v => TermResult' v a -> TermResult' v a -> Bool
== :: TermResult' v a -> TermResult' v a -> Bool
$c/= :: forall v a. Var v => TermResult' v a -> TermResult' v a -> Bool
/= :: TermResult' v a -> TermResult' v a -> Bool
Eq, Int -> TermResult' v a -> ShowS
[TermResult' v a] -> ShowS
TermResult' v a -> String
(Int -> TermResult' v a -> ShowS)
-> (TermResult' v a -> String)
-> ([TermResult' v a] -> ShowS)
-> Show (TermResult' v a)
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
forall v a. Show v => Int -> TermResult' v a -> ShowS
forall v a. Show v => [TermResult' v a] -> ShowS
forall v a. Show v => TermResult' v a -> String
$cshowsPrec :: forall v a. Show v => Int -> TermResult' v a -> ShowS
showsPrec :: Int -> TermResult' v a -> ShowS
$cshow :: forall v a. Show v => TermResult' v a -> String
show :: TermResult' v a -> String
$cshowList :: forall v a. Show v => [TermResult' v a] -> ShowS
showList :: [TermResult' v a] -> ShowS
Show)

data TypeResult' v a
  = TypeResult'
      (HQ.HashQualified Name)
      (DisplayObject () (Decl v a))
      Reference
      (Set (HQ'.HashQualified Name))
  deriving (TypeResult' v a -> TypeResult' v a -> Bool
(TypeResult' v a -> TypeResult' v a -> Bool)
-> (TypeResult' v a -> TypeResult' v a -> Bool)
-> Eq (TypeResult' v a)
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
forall v a.
(Var v, Eq a) =>
TypeResult' v a -> TypeResult' v a -> Bool
$c== :: forall v a.
(Var v, Eq a) =>
TypeResult' v a -> TypeResult' v a -> Bool
== :: TypeResult' v a -> TypeResult' v a -> Bool
$c/= :: forall v a.
(Var v, Eq a) =>
TypeResult' v a -> TypeResult' v a -> Bool
/= :: TypeResult' v a -> TypeResult' v a -> Bool
Eq, Int -> TypeResult' v a -> ShowS
[TypeResult' v a] -> ShowS
TypeResult' v a -> String
(Int -> TypeResult' v a -> ShowS)
-> (TypeResult' v a -> String)
-> ([TypeResult' v a] -> ShowS)
-> Show (TypeResult' v a)
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
forall v a. (Show a, Show v) => Int -> TypeResult' v a -> ShowS
forall v a. (Show a, Show v) => [TypeResult' v a] -> ShowS
forall v a. (Show a, Show v) => TypeResult' v a -> String
$cshowsPrec :: forall v a. (Show a, Show v) => Int -> TypeResult' v a -> ShowS
showsPrec :: Int -> TypeResult' v a -> ShowS
$cshow :: forall v a. (Show a, Show v) => TypeResult' v a -> String
show :: TypeResult' v a -> String
$cshowList :: forall v a. (Show a, Show v) => [TypeResult' v a] -> ShowS
showList :: [TypeResult' v a] -> ShowS
Show)

pattern Tm ::
  HQ.HashQualified Name ->
  Maybe (Type v a) ->
  Referent ->
  Set (HQ'.HashQualified Name) ->
  SearchResult' v a
pattern $mTm :: forall {r} {v} {a}.
SearchResult' v a
-> (HashQualified Name
    -> Maybe (Type v a) -> Referent -> Set (HashQualified Name) -> r)
-> ((# #) -> r)
-> r
$bTm :: forall v a.
HashQualified Name
-> Maybe (Type v a)
-> Referent
-> Set (HashQualified Name)
-> SearchResult' v a
Tm n t r as = Tm' (TermResult' n t r as)

pattern Tp ::
  HQ.HashQualified Name ->
  DisplayObject () (Decl v a) ->
  Reference ->
  Set (HQ'.HashQualified Name) ->
  SearchResult' v a
pattern $mTp :: forall {r} {v} {a}.
SearchResult' v a
-> (HashQualified Name
    -> DisplayObject () (Decl v a)
    -> Reference' Text Hash
    -> Set (HashQualified Name)
    -> r)
-> ((# #) -> r)
-> r
$bTp :: forall v a.
HashQualified Name
-> DisplayObject () (Decl v a)
-> Reference' Text Hash
-> Set (HashQualified Name)
-> SearchResult' v a
Tp n t r as = Tp' (TypeResult' n t r as)

tmReferent :: SearchResult' v a -> Maybe Referent
tmReferent :: forall v a. SearchResult' v a -> Maybe Referent
tmReferent = \case Tm HashQualified Name
_ Maybe (Type v a)
_ Referent
r Set (HashQualified Name)
_ -> Referent -> Maybe Referent
forall a. a -> Maybe a
Just Referent
r; SearchResult' v a
_ -> Maybe Referent
forall a. Maybe a
Nothing

tpReference :: SearchResult' v a -> Maybe Reference
tpReference :: forall v a. SearchResult' v a -> Maybe (Reference' Text Hash)
tpReference = \case Tp HashQualified Name
_ DisplayObject () (Decl v a)
_ Reference' Text Hash
r Set (HashQualified Name)
_ -> Reference' Text Hash -> Maybe (Reference' Text Hash)
forall a. a -> Maybe a
Just Reference' Text Hash
r; SearchResult' v a
_ -> Maybe (Reference' Text Hash)
forall a. Maybe a
Nothing

foldResult' :: (TermResult' v a -> b) -> (TypeResult' v a -> b) -> SearchResult' v a -> b
foldResult' :: forall v a b.
(TermResult' v a -> b)
-> (TypeResult' v a -> b) -> SearchResult' v a -> b
foldResult' TermResult' v a -> b
f TypeResult' v a -> b
g = \case
  Tm' TermResult' v a
tm -> TermResult' v a -> b
f TermResult' v a
tm
  Tp' TypeResult' v a
tp -> TypeResult' v a -> b
g TypeResult' v a
tp

-- todo: comment me out, is this actually useful, given what we saw in ShowDefinitionI?
-- namely, that it doesn't include the Term's deps, just the Decl's and the
-- result Term/Type names.
labeledDependencies :: (Ord v) => SearchResult' v a -> Set LabeledDependency
labeledDependencies :: forall v a. Ord v => SearchResult' v a -> Set LabeledDependency
labeledDependencies = \case
  Tm' (TermResult' HashQualified Name
_ Maybe (Type v a)
t Referent
r Set (HashQualified Name)
_) ->
    LabeledDependency -> Set LabeledDependency -> Set LabeledDependency
forall a. Ord a => a -> Set a -> Set a
Set.insert (Referent -> LabeledDependency
LD.referent Referent
r) (Set LabeledDependency -> Set LabeledDependency)
-> Set LabeledDependency -> Set LabeledDependency
forall a b. (a -> b) -> a -> b
$ Set LabeledDependency
-> (Type v a -> Set LabeledDependency)
-> Maybe (Type v a)
-> Set LabeledDependency
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Set LabeledDependency
forall a. Monoid a => a
mempty ((Reference' Text Hash -> LabeledDependency)
-> Set (Reference' Text Hash) -> Set LabeledDependency
forall b a. Ord b => (a -> b) -> Set a -> Set b
Set.map Reference' Text Hash -> LabeledDependency
LD.typeRef (Set (Reference' Text Hash) -> Set LabeledDependency)
-> (Type v a -> Set (Reference' Text Hash))
-> Type v a
-> Set LabeledDependency
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Type v a -> Set (Reference' Text Hash)
forall v a. Ord v => Type v a -> Set (Reference' Text Hash)
Type.dependencies) Maybe (Type v a)
t
  Tp' (TypeResult' HashQualified Name
_ DisplayObject () (Decl v a)
d Reference' Text Hash
r Set (HashQualified Name)
_) ->
    Set LabeledDependency
-> (Decl v a -> Set LabeledDependency)
-> Maybe (Decl v a)
-> Set LabeledDependency
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Set LabeledDependency
forall a. Monoid a => a
mempty (Reference' Text Hash -> Decl v a -> Set LabeledDependency
forall v a.
Ord v =>
Reference' Text Hash -> Decl v a -> Set LabeledDependency
DD.labeledDeclDependenciesIncludingSelf Reference' Text Hash
r) (DisplayObject () (Decl v a) -> Maybe (Decl v a)
forall b a. DisplayObject b a -> Maybe a
DT.toMaybe DisplayObject () (Decl v a)
d)