Skip to content
This repository was archived by the owner on Oct 7, 2020. It is now read-only.

Commit bfa37db

Browse files
authored
Merge pull request #1173 from fendor/document-hoogle
Document Hoogle Plugin
2 parents e1b3157 + 2fce6b5 commit bfa37db

File tree

1 file changed

+80
-1
lines changed

1 file changed

+80
-1
lines changed

src/Haskell/Ide/Engine/Plugin/Hoogle.hs

+80-1
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@ data HoogleError = NoDb | NoResults deriving (Eq,Ord,Show)
4646

4747
newtype HoogleDb = HoogleDb (Maybe FilePath)
4848

49+
-- | Convert Hoogle Error's to Ide Error's.
50+
-- Can be used to present errors to the client.
4951
hoogleErrorToIdeError :: HoogleError -> IdeError
5052
hoogleErrorToIdeError NoResults =
5153
IdeError PluginError "No results found" Null
@@ -55,6 +57,16 @@ hoogleErrorToIdeError NoDb =
5557
instance ExtensionClass HoogleDb where
5658
initialValue = HoogleDb Nothing
5759

60+
-- | Initialise the Hoogle Database.
61+
-- Search for the Hoogle Database and set it in the global config if found.
62+
-- Looks first into custom hoogle database locations, then in the default location.
63+
-- Note, that the FilePath must be an absolute path, otherwise Hoogle can not
64+
-- find the database.
65+
--
66+
-- If no hoogle database has been found, Nothing is returned
67+
-- and we will have no access to the hoogle database.
68+
-- However, it is still safe to use the hoogle API,
69+
-- e.g. either error or default values are returned.
5870
initializeHoogleDb :: IdeGhcM (Maybe FilePath)
5971
initializeHoogleDb = do
6072
explicitDbLocation <- liftIO $ lookupEnv "HIE_HOOGLE_DATABASE"
@@ -83,6 +95,15 @@ infoCmd' expr = do
8395
else
8496
return $ T.pack $ targetInfo $ head res
8597

98+
-- | Command to get the prettified documentation of an hoogle identifier.
99+
-- Identifier should be understandable for hoogle.
100+
-- If documentation can be found for it, the result will be rendered
101+
-- in markdown for the lsp-client. If multiple results have been found,
102+
-- only the first result will be shown.
103+
--
104+
-- If no result can be found for the identifier, a hoogle error is returned
105+
-- that can be shown to the client by converting it
106+
-- to an IdeError with 'hoogleErrorToIdeError'.
86107
infoCmdFancyRender :: T.Text -> IdeM (Either HoogleError T.Text)
87108
infoCmdFancyRender expr = do
88109
HoogleDb mdb <- get
@@ -92,6 +113,8 @@ infoCmdFancyRender expr = do
92113
else
93114
return $ renderTarget $ head res
94115

116+
-- | Render the target in valid markdown.
117+
-- Transform haddock documentation into markdown.
95118
renderTarget :: Target -> T.Text
96119
renderTarget t = T.intercalate "\n\n" $
97120
["```haskell\n" <> unHTML (T.pack $ targetItem t) <> "```"]
@@ -114,12 +137,30 @@ renderTarget t = T.intercalate "\n\n" $
114137

115138
------------------------------------------------------------------------
116139

140+
-- | Search for modules that satisfy the given search text.
141+
-- Will return at most five, unique results.
142+
--
143+
-- If an error occurs, such as no hoogle database has been found,
144+
-- or the search term has no match, an empty list will be returned.
117145
searchModules :: T.Text -> IdeM [T.Text]
118146
searchModules = fmap (nub . take 5) . searchTargets (fmap (T.pack . fst) . targetModule)
119147

148+
-- | Search for packages that satisfy the given search text.
149+
-- Will return at most five, unique results.
150+
--
151+
-- If an error occurs, such as no hoogle database has been found,
152+
-- or the search term has no match, an empty list will be returned.
120153
searchPackages :: T.Text -> IdeM [T.Text]
121154
searchPackages = fmap (nub . take 5) . searchTargets (fmap (T.pack . fst) . targetPackage)
122155

156+
-- | Search for Targets that fit to the given Text and satisfy the given predicate.
157+
-- Limits the amount of matches to at most ten.
158+
-- Applies the predicate to the first ten matches. May also return zero matches,
159+
-- although there are matches, if none of the first ten matches
160+
-- satisfies the predicate.
161+
--
162+
-- If an error occurs, such as no hoogle database has been found,
163+
-- or the search term has no match, an empty list will be returned.
123164
searchTargets :: (Target -> Maybe a) -> T.Text -> IdeM [a]
124165
searchTargets f term = do
125166
HoogleDb mdb <- get
@@ -130,13 +171,19 @@ searchTargets f term = do
130171

131172
------------------------------------------------------------------------
132173

174+
-- | Lookup the given Text in the local Hoogle database.
175+
-- Is limited to collect at most ten matches.
176+
-- May fail with a HoogleError that can be shown to the user.
133177
lookupCmd :: CommandFunc T.Text [T.Text]
134178
lookupCmd = CmdSync $ \term -> do
135179
res <- liftToGhc $ bimap hoogleErrorToIdeError id <$> lookupCmd' 10 term
136180
return $ case res of
137181
Left err -> IdeResultFail err
138182
Right x -> IdeResultOk x
139183

184+
-- | Lookup the given Text in the local Hoogle database.
185+
-- Takes the first `n` matches.
186+
-- May fail with a HoogleError that can be shown to the user.
140187
lookupCmd' :: Int -> T.Text -> IdeM (Either HoogleError [T.Text])
141188
lookupCmd' n term = do
142189
HoogleDb mdb <- get
@@ -145,12 +192,36 @@ lookupCmd' n term = do
145192

146193
------------------------------------------------------------------------
147194

195+
-- | Run a query for Hoogle on the given Hoogle database.
196+
-- If no Database is given, no search is executed.
197+
-- If the Database cannot be found at the given location, an IOException will be thrown.
198+
-- Note, that the database file must be an absolute path.
199+
-- The target may be of the form: 'take', 'take :: Int -> [a] -> [a]', 'Data.List'.
200+
-- In general, it is very similar to the Web Api.
201+
-- Found targets can be consumed with the given callback function.
202+
-- You can limit the amount of results, by taking only the first ten results.
203+
-- Example call:
204+
--
205+
-- @
206+
-- runHoogleQuery
207+
-- (Just "/home/user/.hoogle/default-haskell-5.0.17.hoo")
208+
-- (Data.Text.pack "take :: Int -> [a] -> [a]")
209+
-- (Right . Prelude.take 10)
210+
-- @
211+
-- This limits the results to ten and looks for a function `take` that has the given signature.
212+
--
213+
-- HoogleError's can be translated to IdeErrors with @hoogleErrorToIdeError@
214+
-- and shown to the client.
148215
runHoogleQuery :: Maybe FilePath -> T.Text -> ([Target] -> Either HoogleError a) -> IO (Either HoogleError a)
149216
runHoogleQuery Nothing _ _ = return $ Left NoDb
150217
runHoogleQuery (Just db) quer f = do
151218
res <- searchHoogle db quer
152219
return (f res)
153220

221+
222+
-- | Run a query for Hoogle on the given Hoogle database.
223+
-- If the database can not be found, an IOException is thrown.
224+
-- The target may be of the form: `take`, `take :: Int -> [a] -> [a]`
154225
searchHoogle :: FilePath -> T.Text -> IO [Target]
155226
searchHoogle dbf quer = withDatabase dbf (return . flip searchDatabase (T.unpack quer))
156227

@@ -167,7 +238,15 @@ docRules (Just "containers") modName =
167238
fromMaybe modName $ T.stripSuffix ".Base" modName
168239
docRules _ modName = modName
169240

170-
getDocsForName :: T.Text -> Maybe T.Text -> T.Text -> IdeM (Maybe T.Text)
241+
-- | Get the Documentation for a given identifier in a given module.
242+
-- May also specify the according package, to avoid name clashes.
243+
-- Results is a prettified Text that can be sent and shown to the client.
244+
--
245+
-- Might fail, if the identifier can not be found.
246+
getDocsForName :: T.Text -- ^ Identifier within a module.
247+
-> Maybe T.Text -- ^ Optional package name to avoid name clashes.
248+
-> T.Text -- ^ Name of the module to search in.
249+
-> IdeM (Maybe T.Text) -- ^ Prettified hoogle documentation of target.
171250
getDocsForName name pkg modName' = do
172251
let modName = docRules pkg modName'
173252
query = name

0 commit comments

Comments
 (0)