git.iko.soy/rowtype-yoga/purescript-docs-search
on master help sign in
added: type rendering

added: "Show more results" link

commitd6d355f5303b396751b127ef879cd95d5a10794d authorklntsky <klntsky@gmail.com> dateWed 26 Jun 2019, 21:36 (7 years ago) parent849bcc0
6 files changed+438−126
src/Spago/Search/App.purs+16 src/Spago/Search/App/SearchResults.purs+170−22 src/Spago/Search/Declarations.purs+23−9 src/Spago/Search/Index.purs+148−90 src/Spago/Search/TypeParser.purs+56−2 test/Main.purs+25−3
src/Spago/Search/App.purs+16
@@ -45,6 +45,22 @@ insertStyle doc = do
4545 .top-banner__actions {
4646 width: 10%;
4747 }
48+ .load_more {
49+ margin-top:2em;
50+ }
51+ .load_more p {
52+ font-style:italic
53+ }
54+ .load_more a {
55+ background:#eee;
56+ padding:0.4em
57+ }
58+ #load-more-link {
59+ cursor: pointer;
60+ }
61+ .result {
62+ font-size: 1.25em;
63+ }
4864 """
4965 mbHead <-
5066 ParentNode.querySelector (wrap "head") (Document.toParentNode doc)
src/Spago/Search/App/SearchResults.purs+170−22
@@ -1,15 +1,13 @@
11module Spago.Search.App.SearchResults where
22
33import Prelude
4−
5−import Spago.Search.App.SearchField (Message(..))
6−import Spago.Search.Declarations (loadDeclarations)
7−import Spago.Search.Extra (whenJust)
8−import Spago.Search.Index (SearchIndex, SearchResult, mkSearchIndex)
4+import Spago.Search.Index
5+import Spago.Search.TypeParser
96
107import CSS (textWhitespace, whitespacePreWrap)
118import Data.Array as Array
129import Data.Either (Either(..))
10+import Data.List (List(..), (:))
1311import Data.List as List
1412import Data.Maybe (Maybe(..), isNothing, isJust)
1513import Data.Newtype (unwrap, wrap)
@@ -25,6 +23,9 @@ import Halogen.HTML as HH
2523import Halogen.HTML.CSS as HS
2624import Halogen.HTML.Events as HE
2725import Halogen.HTML.Properties as HP
26+import Spago.Search.App.SearchField (Message(..))
27+import Spago.Search.Declarations (loadDeclarations)
28+import Spago.Search.Extra (whenJust)
2829import Web.DOM.Element (Element)
2930import Web.DOM.Element as Element
3031import Web.HTML as HTML
@@ -35,6 +36,7 @@ type State = { mbIndex :: Maybe SearchIndex
3536 , results :: Array SearchResult
3637 , input :: String
3738 , contents :: Element
39+ , resultsCount :: Int
3840 }
3941
4042data Query a
@@ -42,11 +44,17 @@ data Query a
4244
4345data Action
4446 = SearchResultClicked String
47+ | ShowMore
4548
4649mkComponent :: forall o i. Element -> H.Component HH.HTML Query i o Aff
4750mkComponent contents =
4851 H.mkComponent
49− { initialState: const { mbIndex: Nothing, results: [], input: "", contents }
52+ { initialState: const { mbIndex: Nothing
53+ , results: []
54+ , input: ""
55+ , contents
56+ , resultsCount: 25
57+ }
5058 , render
5159 , eval: H.mkEval $ H.defaultEval { handleQuery = handleQuery
5260 , handleAction = handleAction }
@@ -65,9 +73,6 @@ handleQuery (SearchFieldMessage Focused next) = do
6573 H.modify_ (_ { mbIndex = Just $ mkSearchIndex declarations })
6674 pure Nothing
6775handleQuery (SearchFieldMessage LostFocus next) = do
68− state <- H.get
69− when (Array.null state.results) do
70− showPageContents
7176 pure Nothing
7277handleQuery (SearchFieldMessage (InputUpdated input) next) = do
7378 H.modify_ (_ { input = input })
@@ -86,11 +91,14 @@ handleQuery (SearchFieldMessage (InputUpdated input) next) = do
8691 List.toUnfoldable $
8792 map List.toUnfoldable $
8893 Trie.queryValues path $
89− index })
94+ index
95+ , resultsCount = 25 })
9096 pure Nothing
9197
9298handleAction :: forall o. Action -> H.HalogenM State Action () o Aff Unit
9399handleAction = case _ of
100+ ShowMore -> do
101+ H.modify_ (\state -> state { resultsCount = state.resultsCount + 25 })
94102 SearchResultClicked moduleName -> do
95103 -- Decide if we are going to load a new page or to jump to a hash on the
96104 -- current page. In the latter case, hide search results and show the main
@@ -140,16 +148,27 @@ render state =
140148 ]
141149 ]
142150 else
143− [ renderSummary $
144− "Found " <>
145− show (Array.length state.results) <>
146− " definitions" ] <>
147−
148− [ HH.div [ HP.id_ "spage-search-results-container" ] $
149− Array.concat $
150− state.results <#> renderResult
151+ let selectedResults = Array.take state.resultsCount state.results in
152+ [ HH.div [ HP.classes [ wrap "result" ] ]
153+ [ HH.text "Found "
154+ , HH.strong_ [ HH.text $ show $ Array.length state.results ]
155+ , HH.text " definitions"
156+ ]
157+
158+ , HH.div [ HP.id_ "spage-search-results-container" ] $
159+ Array.concat $ selectedResults <#> renderResult
160+
161+ , HH.div [ HP.class_ (wrap "load_more"), HP.id_ "load-more" ]
162+ [ if Array.length selectedResults < Array.length state.results
163+ then HH.a [ HP.id_ "load-more-link"
164+ , HE.onClick $ const $ Just ShowMore ]
165+ [ HH.text "Show more results" ]
166+ else HH.p_
167+ [ HH.text "No further results." ]
168+ ]
151169 ]
152170
171+
153172renderSummary :: forall a b. String -> HH.HTML b a
154173renderSummary text =
155174 HH.div [ HP.id_ "spago-search-summary" ]
@@ -171,10 +190,7 @@ renderResult = unwrap >>> \result ->
171190 ]
172191
173192 , HH.div [ HP.class_ (wrap "result__body") ] $
174− [ HH.pre [ HP.class_ (wrap "result__signature") ]
175− [ HH.code_ []
176− ]
177− ] <>
193+ renderResultType result <>
178194
179195 case result.comments of
180196 Just comments -> [ HH.pre [ HS.style do
@@ -207,3 +223,135 @@ renderResult = unwrap >>> \result ->
207223 ]
208224 ]
209225 ]
226+
227+renderResultType
228+ :: forall a rest
229+ . { info :: ResultInfo
230+ , name :: String
231+ | rest
232+ }
233+ -> Array (HH.HTML a Action)
234+renderResultType = \result ->
235+ case result.info of
236+ ValueResult {type:ty} ->
237+ [ HH.pre [ HP.class_ (wrap "result__signature") ]
238+ [ HH.code_ [ HH.text (result.name <> " :: ")
239+ , renderType ty ]
240+ ]
241+ ]
242+ _ -> []
243+
244+renderType :: forall a. Type -> HH.HTML a Action
245+renderType = case _ of
246+ TypeVar str -> HH.text str
247+ TypeLevelString str -> HH.text str
248+ TypeWildcard -> HH.text "_"
249+ TypeConstructor qname -> renderQualifiedName qname
250+ TypeOp qname -> renderQualifiedName qname
251+
252+ TypeApp (TypeApp (TypeConstructor
253+ (QualifiedName { moduleName: ["Prim"]
254+ , name: "Function" })) t1) t2 ->
255+ HH.span_ [ renderType t1
256+ , HH.text " -> "
257+ , renderType t2
258+ ]
259+
260+ TypeApp (TypeConstructor (QualifiedName { moduleName: ["Prim"]
261+ , name: "Record" }))
262+ record -> renderRow record
263+
264+ TypeApp t1 t2 ->
265+ HH.span_ [ renderType t1
266+ , HH.text " "
267+ , renderType t2
268+ ]
269+
270+ ty@(ForAll _ _ _) ->
271+ let foralls = joinForalls ty in
272+ HH.span_ $
273+ [ HH.text "forall" ] <>
274+ ( Array.fromFoldable foralls.vars <#>
275+ \ { var, mbKind } ->
276+ case mbKind of
277+ Nothing -> HH.text (" " <> var)
278+ Just kind ->
279+ HH.span_ [ HH.text ("(" <> var <> " :: ")
280+ , renderKind kind
281+ , HH.text ")"
282+ ]
283+ ) <>
284+ [ HH.text ". ", renderType foralls.ty ]
285+
286+ ConstrainedType cnstr ty ->
287+ HH.span_
288+ [ renderConstraint cnstr
289+ , HH.text " => "
290+ , renderType ty
291+ ]
292+
293+ REmpty -> HH.text "{}"
294+ ty@(RCons _ _ _) -> renderRow ty
295+
296+ BinaryNoParensType t1 t2 t3 ->
297+ HH.span_
298+ [ renderType t1
299+ , renderType t2
300+ , renderType t3
301+ ]
302+ ParensInType ty ->
303+ HH.span_
304+ [ HH.text "("
305+ , renderType ty
306+ , HH.text ")"
307+ ]
308+
309+joinForalls :: Type -> { vars :: List.List { var :: String, mbKind :: Maybe Kind }
310+ , ty :: Type }
311+joinForalls = go Nil
312+ where
313+ go acc (ForAll var ty mbKind) =
314+ go ({ var, mbKind } : acc) ty
315+ go acc ty = { vars: acc, ty }
316+
317+renderRow :: forall a. Type -> HH.HTML a Action
318+renderRow ty =
319+ let rows = joinRows ty in
320+ HH.span_ $
321+ [ HH.text "{ " ] <>
322+ ( Array.intercalate [ HH.text ", " ] $ Array.fromFoldable rows <#>
323+ \entry ->
324+ [ HH.span_ [ HH.text $ entry.row <> " :: "
325+ , renderType entry.ty ] ]
326+ ) <>
327+ [ HH.text " }" ]
328+
329+joinRows :: Type -> List { row :: String
330+ , ty :: Type
331+ }
332+joinRows = go Nil
333+ where
334+ go acc (RCons row ty rest) =
335+ go ({ row, ty } : acc) rest
336+ go acc _ = List.reverse acc
337+
338+
339+htmlSingleton :: forall t406 t407. HH.HTML t407 t406 -> HH.HTML t407 t406
340+htmlSingleton x = HH.span_ [ x ]
341+
342+renderConstraint :: forall a. Constraint -> HH.HTML a Action
343+renderConstraint (Constraint { constraintClass, constraintArgs }) =
344+ HH.span_ $
345+ [ renderQualifiedName constraintClass, HH.text " " ] <>
346+ Array.intercalate [ HH.text " " ] (constraintArgs <#> \ty -> [ renderType ty ])
347+
348+
349+renderQualifiedName :: forall a. QualifiedName -> HH.HTML a Action
350+renderQualifiedName (QualifiedName { moduleName, name })
351+ = HH.text name
352+
353+renderKind :: forall a. Kind -> HH.HTML a Action
354+renderKind = case _ of
355+ Row k1 -> HH.span_ [ HH.text "#", renderKind k1 ]
356+ FunKind k1 k2 -> HH.span_ [ renderKind k1, renderKind k2 ]
357+ NamedKind qname -> renderQualifiedName qname
src/Spago/Search/Declarations.purs+23−9
@@ -2,7 +2,7 @@ module Spago.Search.Declarations where
22
33import Prelude
44
5−import Spago.Search.TypeParser (Kind, Type)
5+import Spago.Search.TypeParser
66
77import Control.Promise (Promise, toAffE)
88import Data.Argonaut.Core (Json, fromString, stringify, toString)
@@ -89,8 +89,12 @@ newtype IndexEntry
8989 = IndexEntry { title :: String
9090 , comments :: Maybe String
9191 , info :: { declType :: DeclType
92− , kind :: Maybe Kind
93− , type :: Maybe Type
92+ , kind :: Maybe Kind
93+ , typeArguments :: Maybe (Array TypeArgument)
94+ , type :: Maybe Type
95+ , superclasses :: Maybe (Array Constraint)
96+ , arguments :: Maybe (Array TypeArgument)
97+ , fundeps :: Maybe FunDeps
9498 }
9599 , sourceSpan :: { start :: Array Int
96100 , end :: Array Int
@@ -112,11 +116,15 @@ instance decodeJsonIndexEntry :: DecodeJson IndexEntry where
112116 title <- handle .: "title"
113117 comments <- handle .:? "comments"
114118 children <- handle .: "children"
115− info <- handle .: "info" >>= \ihandle -> do
116− ty <- ihandle .:? "type"
117− kind <- ihandle .:? "kind"
118− declType <- ihandle .: "declType"
119− pure { type: ty, kind, declType }
119+ info <- handle .: "info" >>= \info -> do
120+ ty <- info .:? "type"
121+ kind <- info .:? "kind"
122+ typeArguments <- info .:? "typeArguments"
123+ arguments <- info .:? "arguments"
124+ superclasses <- info .:? "superclasses"
125+ fundeps <- info .:? "fundeps"
126+ declType <- info .: "declType"
127+ pure { type: ty, kind, declType, typeArguments, superclasses, fundeps, arguments }
120128 sourceSpan <- handle .: "sourceSpan"
121129 pure { title, comments, info, sourceSpan, children }
122130
@@ -127,6 +135,8 @@ newtype ChildIndexEntry
127135 = ChildIndexEntry { title :: String
128136 , comments :: Maybe String
129137 , info :: { declType :: ChildDeclType
138+ , arguments :: Maybe (Array Type)
139+ , type :: Maybe Type
130140 }
131141 , mbSourceSpan :: Maybe { start :: Array Int
132142 , end :: Array Int
@@ -145,7 +155,11 @@ instance decodeJsonChildIndexEntry :: DecodeJson ChildIndexEntry where
145155 handle <- decodeJson json
146156 title <- handle .: "title"
147157 comments <- handle .:? "comments"
148− info <- handle .: "info"
158+ info <- handle .: "info" >>= \info -> do
159+ arguments <- info .:? "arguments"
160+ ty <- info .:? "type"
161+ declType <- info .: "declType"
162+ pure { arguments, declType, type: ty }
149163 mbSourceSpan <- handle .:? "sourceSpan"
150164 pure { title, comments, info, mbSourceSpan }
151165
src/Spago/Search/Index.purs+148−90
@@ -2,15 +2,16 @@ module Spago.Search.Index where
22
33import Prelude
44
5−import Spago.Search.Declarations (ChildDeclType(..), ChildIndexEntry, DeclType(..), Declarations(..), IndexEntry(..))
5+import Spago.Search.TypeParser (Constraint, FunDeps, Kind, Type, TypeArgument)
6+import Spago.Search.Declarations (ChildDeclType(..), ChildIndexEntry(..), DeclType(..), Declarations(..), IndexEntry(..))
67
8+import Control.Alt ((<|>))
79import Data.Array ((!!))
8−import Data.Array as Array
910import Data.Foldable (foldr)
1011import Data.List (List, (:))
1112import Data.List as List
1213import Data.Maybe (Maybe(..), fromMaybe)
13−import Data.Newtype (class Newtype, unwrap)
14+import Data.Newtype (class Newtype)
1415import Data.Search.Trie (Trie, alter)
1516import Data.String.CodeUnits (stripPrefix, stripSuffix, toCharArray)
1617import Data.String.Common (toLower)
@@ -21,16 +22,31 @@ newtype SearchIndex = SearchIndex (Trie Char (List SearchResult))
2122
2223derive instance newtypeSearchIndex :: Newtype SearchIndex _
2324
25+data ResultInfo
26+ = DataResult { typeArguments :: Array TypeArgument }
27+ | ExternDataResult { kind :: Kind }
28+ | TypeSynonymResult { type :: Type }
29+ | DataConstructorResult { arguments :: Array Type }
30+ | TypeClassMemberResult { type :: Type }
31+ | TypeClassResult { fundeps :: FunDeps
32+ , arguments :: Array TypeArgument
33+ , superclasses :: Array Constraint }
34+ | ValueResult { type :: Type }
35+ | ValueAliasResult
36+ | TypeAliasResult
37+ | ExternKindResult
38+
2439newtype SearchResult
2540 = SearchResult { name :: String
2641 , comments :: Maybe String
2742 , hashAnchor :: String
2843 , moduleName :: String
2944 , packageName :: String
30− , sourceSpan :: { start :: Array Int
31− , end :: Array Int
32− , name :: String
33− }
45+ , sourceSpan :: Maybe { start :: Array Int
46+ , end :: Array Int
47+ , name :: String
48+ }
49+ , info :: ResultInfo
3450 }
3551
3652derive instance newtypeSearchResult :: Newtype SearchResult _
@@ -40,16 +56,16 @@ mkSearchIndex = SearchIndex <<< foldr insertDeclarations mempty
4056
4157insertDeclarations
4258 :: Declarations
43− -> Trie Char (List SearchResult)
44− -> Trie Char (List SearchResult)
59+ -> Trie Char (List SearchResult)
60+ -> Trie Char (List SearchResult)
4561insertDeclarations (Declarations { name, declarations }) trie
4662 = foldr (insertIndexEntry name) trie declarations
4763
4864insertIndexEntry
4965 :: String
50− -> IndexEntry
51− -> Trie Char (List SearchResult)
52− -> Trie Char (List SearchResult)
66+ -> IndexEntry
67+ -> Trie Char (List SearchResult)
68+ -> Trie Char (List SearchResult)
5369insertIndexEntry moduleName entry@(IndexEntry { title }) trie
5470 = foldr insertSearchResult trie (resultsForEntry moduleName entry)
5571
@@ -76,60 +92,101 @@ resultsForEntry
7692 -> List { path :: String
7793 , result :: SearchResult
7894 }
79−resultsForEntry moduleName (IndexEntry { title
80− , comments
81− , info
82− , sourceSpan
83− , children }) =
84− let { name, hashAnchor } = extractHashAnchor info.declType title
95+resultsForEntry moduleName ie@(IndexEntry entry@{info, title, sourceSpan, comments, children}) =
96+ let { name, declLevel } = getLevelAndName info.declType title
8597 packageName = extractPackageName sourceSpan.name
86− in
87− { path: name
88− , result: SearchResult { name: title
89− , comments
90− , hashAnchor
91− , moduleName
92− , sourceSpan
93− , packageName
94− }
95− } : (
96− List.fromFoldable $
97− extractChildren sourceSpan packageName moduleName children
98− )
99−
100−extractHashAnchor
98+ in case mkInfo declLevel ie of
99+ Nothing -> mempty
100+ Just info' -> (
101+ List.singleton $
102+ { path: name
103+ , result: SearchResult { name: title
104+ , comments
105+ , hashAnchor: declLevelToHashAnchor declLevel
106+ , moduleName
107+ , sourceSpan: Just sourceSpan
108+ , packageName
109+ , info: info'
110+ }
111+ }
112+ ) <>
113+ ( List.fromFoldable children >>=
114+ resultsForChildIndexEntry packageName moduleName
115+ )
116+
117+mkInfo :: DeclLevel -> IndexEntry -> Maybe ResultInfo
118+mkInfo declLevel (IndexEntry { info, title }) =
119+ case info.declType of
120+
121+ DeclValue ->
122+ info.type <#>
123+ \ty -> ValueResult { type: ty }
124+
125+ DeclData ->
126+ info.typeArguments <#>
127+ \typeArguments -> DataResult { typeArguments }
128+
129+ DeclExternData ->
130+ info.kind <#>
131+ \kind -> ExternDataResult { kind }
132+
133+ DeclTypeSynonym ->
134+ info.type <#>
135+ \ty -> TypeSynonymResult { type: ty }
136+
137+ DeclTypeClass ->
138+ case info.fundeps, info.arguments, info.superclasses of
139+ Just fundeps, Just arguments, Just superclasses ->
140+ Just $ TypeClassResult { fundeps, arguments, superclasses }
141+ _, _, _ -> Nothing
142+
143+ DeclAlias ->
144+ case declLevel of
145+ TypeLevel -> Just TypeAliasResult
146+ ValueLevel -> Just ValueAliasResult
147+ _ -> Nothing
148+
149+ DeclExternKind ->
150+ Just ExternKindResult
151+
152+-- | Level of a declaration, used to determine which URI hash anchor to use in
153+-- | links ("v", "t" or "k").
154+data DeclLevel = ValueLevel | TypeLevel | KindLevel
155+
156+declLevelToHashAnchor :: DeclLevel -> String
157+declLevelToHashAnchor = case _ of
158+ ValueLevel -> "v"
159+ TypeLevel -> "t"
160+ KindLevel -> "k"
161+
162+getLevelAndName
101163 :: DeclType
102164 -> String
103− -> { hashAnchor :: String
165+ -> { declLevel :: DeclLevel
104166 , name :: String
105167 }
106−extractHashAnchor DeclValue name = { name, hashAnchor: "v" }
107−extractHashAnchor DeclData name = { name, hashAnchor: "t" }
108−extractHashAnchor DeclTypeSynonym name = { name, hashAnchor: "t" }
109−extractHashAnchor DeclTypeClass name = { name, hashAnchor: "v" }
110−extractHashAnchor DeclAlias title =
111− case stripPrefix (Pattern "(") title of
112− Just rest ->
113− case stripSuffix (Pattern ")") rest of
114− -- An infix operator
115− Just name -> { name, hashAnchor: "v" }
116− -- Impossible
117− Nothing -> { name: title, hashAnchor: "v" }
118− Nothing ->
119− case stripPrefix (Pattern "type (") title of
120− Nothing ->
121− { name: title, hashAnchor: "v" }
122− -- An infix type operator
123− Just rest ->
124− case stripSuffix (Pattern ")") rest of
125− Just name ->
126− { name, hashAnchor: "t" }
127− Nothing ->
128− { name: title, hashAnchor: "v" }
129−extractHashAnchor DeclExternData name = { name, hashAnchor: "t" }
130−extractHashAnchor DeclExternKind name = { name, hashAnchor: "k" }
131−
132−
168+getLevelAndName DeclValue name = { name, declLevel: ValueLevel }
169+getLevelAndName DeclData name = { name, declLevel: TypeLevel }
170+getLevelAndName DeclTypeSynonym name = { name, declLevel: TypeLevel }
171+getLevelAndName DeclTypeClass name = { name, declLevel: ValueLevel }
172+-- "declType": "alias" does not specify the level of the declaration.
173+-- But for type aliases, name of the declaration is always wrapped into
174+-- "type (" and ")".
175+getLevelAndName DeclAlias title =
176+ fromMaybe (withAnchor ValueLevel title) $
177+ (withAnchor ValueLevel <$>
178+ (stripPrefix (Pattern "(") >=>
179+ stripSuffix (Pattern ")")) title) <|>
180+ (withAnchor TypeLevel <$>
181+ (stripPrefix (Pattern "type (") >=>
182+ stripSuffix (Pattern ")")) title)
183+ where
184+ withAnchor declLevel name = { declLevel, name }
185+getLevelAndName DeclExternData name = { name, declLevel: TypeLevel }
186+getLevelAndName DeclExternKind name = { name, declLevel: KindLevel }
187+
188+-- | Extract package name from `sourceSpan.name`, which contains path to
189+-- | the source file.
133190extractPackageName :: String -> String
134191extractPackageName name =
135192 let chunks = String.split (Pattern "/") name in
@@ -141,33 +198,34 @@ extractPackageName name =
141198 else
142199 Just "<local package>"
143200
144−extractChildren
145− :: { end :: Array Int
146− , name :: String
147− , start :: Array Int
148− }
149− -> String
201+resultsForChildIndexEntry
202+ :: String
150203 -> String
151− -> Array ChildIndexEntry
152− -> Array { path :: String
153− , result :: SearchResult
154− }
155−extractChildren sourceSpan' packageName moduleName =
156− Array.concatMap $ unwrap >>>
157− \ { title, comments, info, mbSourceSpan } ->
158−
159− let sourceSpan = fromMaybe sourceSpan' mbSourceSpan in
160− if info.declType == ChildDeclInstance
161− then mempty
162− else
163− -- `info.declType` is either `ChildDeclDataConstructor` or
164− -- `ChildDeclTypeClassMember`.
165− [ { path: title
166− , result: SearchResult { name: title
167− , comments
168− , hashAnchor: "v"
169− , moduleName
170− , packageName
171− , sourceSpan }
172− }
173− ]
204+ -> ChildIndexEntry
205+ -> List { path :: String, result :: SearchResult }
206+resultsForChildIndexEntry packageName moduleName
207+ cie@(ChildIndexEntry { title, info, comments, mbSourceSpan }) =
208+ case mkChildInfo cie of
209+ Nothing -> mempty
210+ Just resultInfo ->
211+ { path: title
212+ , result: SearchResult { name: title
213+ , comments
214+ , hashAnchor: "v"
215+ , moduleName
216+ , sourceSpan: mbSourceSpan
217+ , packageName
218+ , info: resultInfo
219+ }
220+ } # List.singleton
221+
222+mkChildInfo :: ChildIndexEntry -> Maybe ResultInfo
223+mkChildInfo (ChildIndexEntry { info } ) =
224+ case info.declType of
225+ ChildDeclDataConstructor ->
226+ info.arguments <#>
227+ \arguments -> DataConstructorResult { arguments }
228+ ChildDeclTypeClassMember ->
229+ info.type <#>
230+ \ty -> TypeClassMemberResult { type: ty }
231+ ChildDeclInstance -> Nothing
src/Spago/Search/TypeParser.purs+56−2
@@ -1,12 +1,13 @@
11module Spago.Search.TypeParser where
22
3+import Data.Either
4+import Data.Traversable
35import Prelude
46
5−import Data.Argonaut.Core (Json, caseJsonObject, fromArray, fromObject, jsonEmptyObject, stringify, toArray)
7+import Data.Argonaut.Core (Json, caseJsonArray, caseJsonObject, fromArray, fromObject, jsonEmptyObject, jsonNull, stringify, toArray)
68import Data.Argonaut.Decode (class DecodeJson, decodeJson, (.:))
79import Data.Argonaut.Encode (class EncodeJson, encodeJson)
810import Data.Array ((!!))
9−import Data.Either (Either(..))
1011import Data.Generic.Rep (class Generic)
1112import Data.Generic.Rep.Show (genericShow)
1213import Data.Maybe (Maybe(..), fromMaybe)
@@ -238,6 +239,59 @@ instance encodeJsonType :: EncodeJson Type where
238239 ParensInType t -> encodeTaggedContents "ParensInType" (encodeJson t)
239240 TypeWildcard -> encodeTaggedContents "TypeWildcard" jsonEmptyObject
240241
242+newtype FunDep
243+ = FunDep
244+ { lhs :: Array String
245+ , rhs :: Array String
246+ }
247+
248+derive newtype instance eqFunDep :: Eq FunDep
249+derive newtype instance showFunDep :: Show FunDep
250+derive instance newtypeFunDep :: Newtype FunDep _
251+
252+instance decodeJsonFunDep :: DecodeJson FunDep where
253+ decodeJson json =
254+ decodeTuple
255+ (\lhs rhs -> FunDep { lhs, rhs })
256+ (mkJsonError "FunDep" json)
257+ json
258+
259+instance encodeJsonFunDep :: EncodeJson FunDep where
260+ encodeJson (FunDep {lhs, rhs}) =
261+ fromArray [ encodeJson lhs, encodeJson rhs ]
262+
263+newtype FunDeps = FunDeps (Array FunDep)
264+
265+derive newtype instance eqFunDeps :: Eq FunDeps
266+derive newtype instance showFunDeps :: Show FunDeps
267+derive instance newtypeFunDeps :: Newtype FunDeps _
268+
269+instance decodeJsonFunDeps :: DecodeJson FunDeps where
270+ decodeJson json = FunDeps <$> decodeJson json
271+
272+instance encodeJsonFunDeps :: EncodeJson FunDeps where
273+ encodeJson (FunDeps deps) = encodeJson deps
274+
275+newtype TypeArgument
276+ = TypeArgument
277+ { name :: String
278+ , mbKind :: Maybe Kind
279+ }
280+
281+derive newtype instance eqTypeArgument :: Eq TypeArgument
282+derive newtype instance showTypeArgument :: Show TypeArgument
283+derive instance newtypeTypeArgument :: Newtype TypeArgument _
284+
285+instance decodeJsonTypeArgument :: DecodeJson TypeArgument where
286+ decodeJson json =
287+ decodeTuple (\name mbKind -> TypeArgument { name, mbKind })
288+ (mkJsonError "TypeArgument" json)
289+ json
290+
291+instance encodeJsonTypeArgument :: EncodeJson TypeArgument where
292+ encodeJson (TypeArgument { name, mbKind }) =
293+ fromArray [ encodeJson name, encodeJson mbKind ]
294+
241295-- | Decode a heterogeneous tuple, serialized as an array.
242296-- | e.g. `[0, ""]` to `Tuple 0 ""`
243297decodeTuple
test/Main.purs+25−3
@@ -19,7 +19,28 @@ import Test.Unit.Main (runTest)
1919main :: Effect Unit
2020main = runTest do
2121 let mkJson x = unsafePartial $ fromRight $ jsonParser x
22− suite "Kind parser" do
22+ suite "FunDeps decoder" do
23+ test "FunDeps" do
24+ let funDeps = mkJson """
25+ [
26+ [
27+ [
28+ "lhs",
29+ "rhs"
30+ ],
31+ [
32+ "output"
33+ ]
34+ ]
35+ ]
36+ """
37+ assertRight (decodeJson funDeps)
38+ (FunDeps [ FunDep { lhs: [ "lhs", "rhs" ]
39+ , rhs: [ "output"]
40+ }
41+ ])
42+
43+ suite "Kind decoder" do
2344
2445 test "QualifiedName" do
2546
@@ -131,7 +152,7 @@ main = runTest do
131152 )
132153
133154
134− suite "Constraint parser" do
155+ suite "Constraint decoder" do
135156 test "Constraint" do
136157 let constraint = mkJson """
137158 {
@@ -153,7 +174,7 @@ main = runTest do
153174 , constraintArgs: []
154175 })
155176
156− suite "Type parser" do
177+ suite "Type decoder" do
157178 test "TypeVar" do
158179 let typeVar = mkJson """
159180 {
@@ -385,6 +406,7 @@ main = runTest do
385406 assertRight (decodeJson $ encodeJson $ k1) k1
386407
387408
409+qualified :: Array String -> String -> QualifiedName
388410qualified moduleName name = QualifiedName { moduleName, name }
389411
390412assertRight :: forall a. Show a => Eq a => Either String a -> a -> Aff Unit