{-# LANGUAGE LambdaCase, MultiWayIf, RecordWildCards, ScopedTypeVariables,
TupleSections #-}
module Action.Search
(actionSearch, withSearch, search
,targetInfo
,targetResultDisplay
,action_search_test
) where
import Control.DeepSeq
import Control.Exception.Extra
import Control.Monad.Extra
import qualified Data.Aeson as JSON
import qualified Data.ByteString.Lazy.Char8 as LBS
import Data.Functor.Identity
import Data.List.Extra
import qualified Data.Map as Map
import Data.Maybe
import qualified Data.Set as Set
import System.Directory
import Text.Blaze.Renderer.Utf8
import Action.CmdLine
import General.Store
import General.Util
import Input.Item
import Output.Items
import Output.Names
import Output.Tags
import Output.Types
import Query
actionSearch :: CmdLine -> IO ()
actionSearch :: CmdLine -> IO ()
actionSearch Search{Bool
Int
FilePath
[FilePath]
Maybe Bool
Maybe Int
Language
compare_ :: CmdLine -> [FilePath]
language :: CmdLine -> Language
repeat_ :: CmdLine -> Int
query :: CmdLine -> [FilePath]
count :: CmdLine -> Maybe Int
database :: CmdLine -> FilePath
info :: CmdLine -> Bool
numbers :: CmdLine -> Bool
link :: CmdLine -> Bool
jsonl :: CmdLine -> Bool
json :: CmdLine -> Bool
color :: CmdLine -> Maybe Bool
compare_ :: [FilePath]
language :: Language
repeat_ :: Int
query :: [FilePath]
count :: Maybe Int
database :: FilePath
info :: Bool
numbers :: Bool
link :: Bool
jsonl :: Bool
json :: Bool
color :: Maybe Bool
..} = Int -> IO () -> IO ()
forall (m :: * -> *) a. Applicative m => Int -> m a -> m ()
replicateM_ Int
repeat_ (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$
FilePath -> (StoreRead -> IO ()) -> IO ()
forall a. NFData a => FilePath -> (StoreRead -> IO a) -> IO a
withSearch FilePath
database ((StoreRead -> IO ()) -> IO ()) -> (StoreRead -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \StoreRead
store ->
if [FilePath] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [FilePath]
compare_ then do
Int
count' <- Int -> IO Int
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Int -> IO Int) -> Int -> IO Int
forall a b. (a -> b) -> a -> b
$ Int -> Maybe Int -> Int
forall a. a -> Maybe a -> a
fromMaybe Int
10 Maybe Int
count
([Query]
q, [Target]
res) <- ([Query], [Target]) -> IO ([Query], [Target])
forall (f :: * -> *) a. Applicative f => a -> f a
pure (([Query], [Target]) -> IO ([Query], [Target]))
-> ([Query], [Target]) -> IO ([Query], [Target])
forall a b. (a -> b) -> a -> b
$ StoreRead -> [Query] -> ([Query], [Target])
search StoreRead
store ([Query] -> ([Query], [Target])) -> [Query] -> ([Query], [Target])
forall a b. (a -> b) -> a -> b
$ FilePath -> [Query]
parseQuery (FilePath -> [Query]) -> FilePath -> [Query]
forall a b. (a -> b) -> a -> b
$ [FilePath] -> FilePath
unwords [FilePath]
query
IO () -> IO ()
whenLoud (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$ FilePath -> IO ()
putStrLn (FilePath -> IO ()) -> FilePath -> IO ()
forall a b. (a -> b) -> a -> b
$ FilePath
"Query: " FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath -> FilePath
unescapeHTML (ByteString -> FilePath
LBS.unpack (ByteString -> FilePath) -> ByteString -> FilePath
forall a b. (a -> b) -> a -> b
$ Markup -> ByteString
renderMarkup (Markup -> ByteString) -> Markup -> ByteString
forall a b. (a -> b) -> a -> b
$ [Query] -> Markup
renderQuery [Query]
q)
let ([FilePath]
shown, [FilePath]
hidden) = Int -> [FilePath] -> ([FilePath], [FilePath])
forall a. Int -> [a] -> ([a], [a])
splitAt Int
count' ([FilePath] -> ([FilePath], [FilePath]))
-> [FilePath] -> ([FilePath], [FilePath])
forall a b. (a -> b) -> a -> b
$ [FilePath] -> [FilePath]
forall a. Ord a => [a] -> [a]
nubOrd ([FilePath] -> [FilePath]) -> [FilePath] -> [FilePath]
forall a b. (a -> b) -> a -> b
$ (Target -> FilePath) -> [Target] -> [FilePath]
forall a b. (a -> b) -> [a] -> [b]
map (Bool -> Target -> FilePath
targetResultDisplay Bool
link) [Target]
res
if [Target] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [Target]
res then
FilePath -> IO ()
putStrLn FilePath
"No results found"
else if Bool
info then do
FilePath -> IO ()
putStr (FilePath -> IO ()) -> FilePath -> IO ()
forall a b. (a -> b) -> a -> b
$ Target -> FilePath
targetInfo (Target -> FilePath) -> Target -> FilePath
forall a b. (a -> b) -> a -> b
$ [Target] -> Target
forall a. [a] -> a
head [Target]
res
else do
let toShow :: [FilePath]
toShow = if Bool
numbers Bool -> Bool -> Bool
&& Bool -> Bool
not Bool
info then [FilePath] -> [FilePath]
addCounter [FilePath]
shown else [FilePath]
shown
if | Bool
json -> ByteString -> IO ()
LBS.putStrLn (ByteString -> IO ()) -> ByteString -> IO ()
forall a b. (a -> b) -> a -> b
$ [Target] -> ByteString
forall a. ToJSON a => a -> ByteString
JSON.encode ([Target] -> ByteString) -> [Target] -> ByteString
forall a b. (a -> b) -> a -> b
$ ([Target] -> [Target])
-> (Int -> [Target] -> [Target])
-> Maybe Int
-> [Target]
-> [Target]
forall b a. b -> (a -> b) -> Maybe a -> b
maybe [Target] -> [Target]
forall a. a -> a
id Int -> [Target] -> [Target]
forall a. Int -> [a] -> [a]
take Maybe Int
count ([Target] -> [Target]) -> [Target] -> [Target]
forall a b. (a -> b) -> a -> b
$ (Target -> Target) -> [Target] -> [Target]
forall a b. (a -> b) -> [a] -> [b]
map Target -> Target
unHTMLtargetItem [Target]
res
| Bool
jsonl -> (Target -> IO ()) -> [Target] -> IO ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ (ByteString -> IO ()
LBS.putStrLn (ByteString -> IO ()) -> (Target -> ByteString) -> Target -> IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Target -> ByteString
forall a. ToJSON a => a -> ByteString
JSON.encode) ([Target] -> IO ()) -> [Target] -> IO ()
forall a b. (a -> b) -> a -> b
$ ([Target] -> [Target])
-> (Int -> [Target] -> [Target])
-> Maybe Int
-> [Target]
-> [Target]
forall b a. b -> (a -> b) -> Maybe a -> b
maybe [Target] -> [Target]
forall a. a -> a
id Int -> [Target] -> [Target]
forall a. Int -> [a] -> [a]
take Maybe Int
count ([Target] -> [Target]) -> [Target] -> [Target]
forall a b. (a -> b) -> a -> b
$ (Target -> Target) -> [Target] -> [Target]
forall a b. (a -> b) -> [a] -> [b]
map Target -> Target
unHTMLtargetItem [Target]
res
| Bool
otherwise -> FilePath -> IO ()
putStr (FilePath -> IO ()) -> FilePath -> IO ()
forall a b. (a -> b) -> a -> b
$ [FilePath] -> FilePath
unlines [FilePath]
toShow
Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when ([FilePath]
hidden [FilePath] -> [FilePath] -> Bool
forall a. Eq a => a -> a -> Bool
/= [] Bool -> Bool -> Bool
&& Bool -> Bool
not Bool
json) (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$ do
IO () -> IO ()
whenNormal (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$ FilePath -> IO ()
putStrLn (FilePath -> IO ()) -> FilePath -> IO ()
forall a b. (a -> b) -> a -> b
$ FilePath
"-- plus more results not shown, pass --count=" FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ Int -> FilePath
forall a. Show a => a -> FilePath
show (Int
count'Int -> Int -> Int
forall a. Num a => a -> a -> a
+Int
10) FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
" to see more"
else do
let parseType :: FilePath -> (FilePath, Sig FilePath)
parseType FilePath
x = case FilePath -> [Query]
parseQuery FilePath
x of
[QueryType Type ()
t] -> (Type () -> FilePath
forall a. Pretty a => a -> FilePath
pretty Type ()
t, Type () -> Sig FilePath
forall a. Type a -> Sig FilePath
hseToSig Type ()
t)
[Query]
_ -> FilePath -> (FilePath, Sig FilePath)
forall a. HasCallStack => FilePath -> a
error (FilePath -> (FilePath, Sig FilePath))
-> FilePath -> (FilePath, Sig FilePath)
forall a b. (a -> b) -> a -> b
$ FilePath
"Expected a type signature, got: " FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
x
FilePath -> IO ()
putStr (FilePath -> IO ()) -> FilePath -> IO ()
forall a b. (a -> b) -> a -> b
$ [FilePath] -> FilePath
unlines ([FilePath] -> FilePath) -> [FilePath] -> FilePath
forall a b. (a -> b) -> a -> b
$ StoreRead
-> (FilePath, Sig FilePath)
-> [(FilePath, Sig FilePath)]
-> [FilePath]
searchFingerprintsDebug StoreRead
store (FilePath -> (FilePath, Sig FilePath)
parseType (FilePath -> (FilePath, Sig FilePath))
-> FilePath -> (FilePath, Sig FilePath)
forall a b. (a -> b) -> a -> b
$ [FilePath] -> FilePath
unwords [FilePath]
query) ((FilePath -> (FilePath, Sig FilePath))
-> [FilePath] -> [(FilePath, Sig FilePath)]
forall a b. (a -> b) -> [a] -> [b]
map FilePath -> (FilePath, Sig FilePath)
parseType [FilePath]
compare_)
targetInfo :: Target -> String
targetInfo :: Target -> FilePath
targetInfo Target{FilePath
Maybe (FilePath, FilePath)
targetDocs :: Target -> FilePath
targetItem :: Target -> FilePath
targetType :: Target -> FilePath
targetModule :: Target -> Maybe (FilePath, FilePath)
targetPackage :: Target -> Maybe (FilePath, FilePath)
targetURL :: Target -> FilePath
targetDocs :: FilePath
targetItem :: FilePath
targetType :: FilePath
targetModule :: Maybe (FilePath, FilePath)
targetPackage :: Maybe (FilePath, FilePath)
targetURL :: FilePath
..} =
[FilePath] -> FilePath
unlines ([FilePath] -> FilePath) -> [FilePath] -> FilePath
forall a b. (a -> b) -> a -> b
$ [ FilePath -> FilePath
unHTML FilePath
targetItem ] [FilePath] -> [FilePath] -> [FilePath]
forall a. [a] -> [a] -> [a]
++
[ [FilePath] -> FilePath
unwords [FilePath]
packageModule | Bool -> Bool
not (Bool -> Bool) -> Bool -> Bool
forall a b. (a -> b) -> a -> b
$ [FilePath] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [FilePath]
packageModule] [FilePath] -> [FilePath] -> [FilePath]
forall a. [a] -> [a] -> [a]
++
[ FilePath -> FilePath
unHTML FilePath
targetDocs ]
where packageModule :: [FilePath]
packageModule = ((FilePath, FilePath) -> FilePath)
-> [(FilePath, FilePath)] -> [FilePath]
forall a b. (a -> b) -> [a] -> [b]
map (FilePath, FilePath) -> FilePath
forall a b. (a, b) -> a
fst ([(FilePath, FilePath)] -> [FilePath])
-> [(FilePath, FilePath)] -> [FilePath]
forall a b. (a -> b) -> a -> b
$ [Maybe (FilePath, FilePath)] -> [(FilePath, FilePath)]
forall a. [Maybe a] -> [a]
catMaybes [Maybe (FilePath, FilePath)
targetPackage, Maybe (FilePath, FilePath)
targetModule]
targetResultDisplay :: Bool -> Target -> String
targetResultDisplay :: Bool -> Target -> FilePath
targetResultDisplay Bool
link Target{FilePath
Maybe (FilePath, FilePath)
targetDocs :: FilePath
targetItem :: FilePath
targetType :: FilePath
targetModule :: Maybe (FilePath, FilePath)
targetPackage :: Maybe (FilePath, FilePath)
targetURL :: FilePath
targetDocs :: Target -> FilePath
targetItem :: Target -> FilePath
targetType :: Target -> FilePath
targetModule :: Target -> Maybe (FilePath, FilePath)
targetPackage :: Target -> Maybe (FilePath, FilePath)
targetURL :: Target -> FilePath
..} = FilePath -> FilePath
unHTML (FilePath -> FilePath) -> FilePath -> FilePath
forall a b. (a -> b) -> a -> b
$ [FilePath] -> FilePath
unwords ([FilePath] -> FilePath) -> [FilePath] -> FilePath
forall a b. (a -> b) -> a -> b
$
((FilePath, FilePath) -> FilePath)
-> [(FilePath, FilePath)] -> [FilePath]
forall a b. (a -> b) -> [a] -> [b]
map (FilePath, FilePath) -> FilePath
forall a b. (a, b) -> a
fst (Maybe (FilePath, FilePath) -> [(FilePath, FilePath)]
forall a. Maybe a -> [a]
maybeToList Maybe (FilePath, FilePath)
targetModule) [FilePath] -> [FilePath] -> [FilePath]
forall a. [a] -> [a] -> [a]
++
[FilePath
targetItem] [FilePath] -> [FilePath] -> [FilePath]
forall a. [a] -> [a] -> [a]
++
[FilePath
"-- " FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
targetURL | Bool
link]
unHTMLtargetItem :: Target -> Target
unHTMLtargetItem :: Target -> Target
unHTMLtargetItem Target
target = Target
target {targetItem :: FilePath
targetItem = FilePath -> FilePath
unHTML (FilePath -> FilePath) -> FilePath -> FilePath
forall a b. (a -> b) -> a -> b
$ Target -> FilePath
targetItem Target
target}
addCounter :: [String] -> [String]
addCounter :: [FilePath] -> [FilePath]
addCounter = (Integer -> FilePath -> FilePath)
-> Integer -> [FilePath] -> [FilePath]
forall a b c. Enum a => (a -> b -> c) -> a -> [b] -> [c]
zipWithFrom (\Integer
i FilePath
x -> Integer -> FilePath
forall a. Show a => a -> FilePath
show Integer
i FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
") " FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
x) Integer
1
withSearch :: NFData a => FilePath -> (StoreRead -> IO a) -> IO a
withSearch :: FilePath -> (StoreRead -> IO a) -> IO a
withSearch FilePath
database StoreRead -> IO a
act = do
IO Bool -> IO () -> IO ()
forall (m :: * -> *). Monad m => m Bool -> m () -> m ()
unlessM (FilePath -> IO Bool
doesFileExist FilePath
database) (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$ do
FilePath -> IO ()
exitFail (FilePath -> IO ()) -> FilePath -> IO ()
forall a b. (a -> b) -> a -> b
$ FilePath
"Error, database does not exist (run 'hoogle generate' first)\n" FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++
FilePath
" Filename: " FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
database
FilePath -> (StoreRead -> IO a) -> IO a
forall a. NFData a => FilePath -> (StoreRead -> IO a) -> IO a
storeReadFile FilePath
database StoreRead -> IO a
act
search :: StoreRead -> [Query] -> ([Query], [Target])
search :: StoreRead -> [Query] -> ([Query], [Target])
search StoreRead
store [Query]
qs = Identity ([Query], [Target]) -> ([Query], [Target])
forall a. Identity a -> a
runIdentity (Identity ([Query], [Target]) -> ([Query], [Target]))
-> Identity ([Query], [Target]) -> ([Query], [Target])
forall a b. (a -> b) -> a -> b
$ do
([Query]
qs, Bool
exact, TargetId -> Bool
filt, [TargetId]
list) <- ([Query], Bool, TargetId -> Bool, [TargetId])
-> Identity ([Query], Bool, TargetId -> Bool, [TargetId])
forall (f :: * -> *) a. Applicative f => a -> f a
pure (([Query], Bool, TargetId -> Bool, [TargetId])
-> Identity ([Query], Bool, TargetId -> Bool, [TargetId]))
-> ([Query], Bool, TargetId -> Bool, [TargetId])
-> Identity ([Query], Bool, TargetId -> Bool, [TargetId])
forall a b. (a -> b) -> a -> b
$ StoreRead
-> [Query] -> ([Query], Bool, TargetId -> Bool, [TargetId])
applyTags StoreRead
store [Query]
qs
[TargetId]
is <- case ((Query -> Bool) -> [Query] -> [Query]
forall a. (a -> Bool) -> [a] -> [a]
filter Query -> Bool
isQueryName [Query]
qs, (Query -> Bool) -> [Query] -> [Query]
forall a. (a -> Bool) -> [a] -> [a]
filter Query -> Bool
isQueryType [Query]
qs) of
([], [] ) -> [TargetId] -> Identity [TargetId]
forall (f :: * -> *) a. Applicative f => a -> f a
pure [TargetId]
list
([], Query
t:[Query]
_) -> [TargetId] -> Identity [TargetId]
forall (f :: * -> *) a. Applicative f => a -> f a
pure ([TargetId] -> Identity [TargetId])
-> [TargetId] -> Identity [TargetId]
forall a b. (a -> b) -> a -> b
$ StoreRead -> Sig FilePath -> [TargetId]
searchTypes StoreRead
store (Sig FilePath -> [TargetId]) -> Sig FilePath -> [TargetId]
forall a b. (a -> b) -> a -> b
$ Type () -> Sig FilePath
forall a. Type a -> Sig FilePath
hseToSig (Type () -> Sig FilePath) -> Type () -> Sig FilePath
forall a b. (a -> b) -> a -> b
$ Query -> Type ()
fromQueryType Query
t
([Query]
xs, [] ) -> [TargetId] -> Identity [TargetId]
forall (f :: * -> *) a. Applicative f => a -> f a
pure ([TargetId] -> Identity [TargetId])
-> [TargetId] -> Identity [TargetId]
forall a b. (a -> b) -> a -> b
$ StoreRead -> Bool -> [FilePath] -> [TargetId]
searchNames StoreRead
store Bool
exact ([FilePath] -> [TargetId]) -> [FilePath] -> [TargetId]
forall a b. (a -> b) -> a -> b
$ (Query -> FilePath) -> [Query] -> [FilePath]
forall a b. (a -> b) -> [a] -> [b]
map Query -> FilePath
fromQueryName [Query]
xs
([Query]
xs, Query
t:[Query]
_) -> do
Set TargetId
nam <- Set TargetId -> Identity (Set TargetId)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Set TargetId -> Identity (Set TargetId))
-> Set TargetId -> Identity (Set TargetId)
forall a b. (a -> b) -> a -> b
$ [TargetId] -> Set TargetId
forall a. Ord a => [a] -> Set a
Set.fromList ([TargetId] -> Set TargetId) -> [TargetId] -> Set TargetId
forall a b. (a -> b) -> a -> b
$ StoreRead -> Bool -> [FilePath] -> [TargetId]
searchNames StoreRead
store Bool
exact ([FilePath] -> [TargetId]) -> [FilePath] -> [TargetId]
forall a b. (a -> b) -> a -> b
$ (Query -> FilePath) -> [Query] -> [FilePath]
forall a b. (a -> b) -> [a] -> [b]
map Query -> FilePath
fromQueryName [Query]
xs
[TargetId] -> Identity [TargetId]
forall (f :: * -> *) a. Applicative f => a -> f a
pure ([TargetId] -> Identity [TargetId])
-> [TargetId] -> Identity [TargetId]
forall a b. (a -> b) -> a -> b
$ (TargetId -> Bool) -> [TargetId] -> [TargetId]
forall a. (a -> Bool) -> [a] -> [a]
filter (TargetId -> Set TargetId -> Bool
forall a. Ord a => a -> Set a -> Bool
`Set.member` Set TargetId
nam) ([TargetId] -> [TargetId]) -> [TargetId] -> [TargetId]
forall a b. (a -> b) -> a -> b
$ StoreRead -> Sig FilePath -> [TargetId]
searchTypes StoreRead
store (Sig FilePath -> [TargetId]) -> Sig FilePath -> [TargetId]
forall a b. (a -> b) -> a -> b
$ Type () -> Sig FilePath
forall a. Type a -> Sig FilePath
hseToSig (Type () -> Sig FilePath) -> Type () -> Sig FilePath
forall a b. (a -> b) -> a -> b
$ Query -> Type ()
fromQueryType Query
t
let look :: TargetId -> Target
look = StoreRead -> TargetId -> Target
lookupItem StoreRead
store
([Query], [Target]) -> Identity ([Query], [Target])
forall (f :: * -> *) a. Applicative f => a -> f a
pure ([Query]
qs, (TargetId -> Target) -> [TargetId] -> [Target]
forall a b. (a -> b) -> [a] -> [b]
map TargetId -> Target
look ([TargetId] -> [Target]) -> [TargetId] -> [Target]
forall a b. (a -> b) -> a -> b
$ (TargetId -> Bool) -> [TargetId] -> [TargetId]
forall a. (a -> Bool) -> [a] -> [a]
filter TargetId -> Bool
filt [TargetId]
is)
action_search_test :: Bool -> FilePath -> IO ()
action_search_test :: Bool -> FilePath -> IO ()
action_search_test Bool
sample FilePath
database = FilePath -> IO () -> IO ()
testing FilePath
"Action.Search.search" (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$ FilePath -> (StoreRead -> IO ()) -> IO ()
forall a. NFData a => FilePath -> (StoreRead -> IO a) -> IO a
withSearch FilePath
database ((StoreRead -> IO ()) -> IO ()) -> (StoreRead -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \StoreRead
store -> do
let noResults :: FilePath -> IO ()
noResults FilePath
a = do
[Target]
res <- [Target] -> IO [Target]
forall (f :: * -> *) a. Applicative f => a -> f a
pure ([Target] -> IO [Target]) -> [Target] -> IO [Target]
forall a b. (a -> b) -> a -> b
$ ([Query], [Target]) -> [Target]
forall a b. (a, b) -> b
snd (([Query], [Target]) -> [Target])
-> ([Query], [Target]) -> [Target]
forall a b. (a -> b) -> a -> b
$ StoreRead -> [Query] -> ([Query], [Target])
search StoreRead
store (FilePath -> [Query]
parseQuery FilePath
a)
case [Target]
res of
[] -> Char -> IO ()
putChar Char
'.'
[Target]
_ -> FilePath -> IO ()
forall a. HasCallStack => FilePath -> IO a
errorIO (FilePath -> IO ()) -> FilePath -> IO ()
forall a b. (a -> b) -> a -> b
$ FilePath
"Searching for: " FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath -> FilePath
forall a. Show a => a -> FilePath
show FilePath
a FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
"\nGot: " FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ [Target] -> FilePath
forall a. Show a => a -> FilePath
show (Int -> [Target] -> [Target]
forall a. Int -> [a] -> [a]
take Int
1 [Target]
res) FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
"\n expected none"
let FilePath
a ==$ :: FilePath -> (FilePath -> Bool) -> IO ()
==$ FilePath -> Bool
f = do
[Target]
res <- [Target] -> IO [Target]
forall (f :: * -> *) a. Applicative f => a -> f a
pure ([Target] -> IO [Target]) -> [Target] -> IO [Target]
forall a b. (a -> b) -> a -> b
$ ([Query], [Target]) -> [Target]
forall a b. (a, b) -> b
snd (([Query], [Target]) -> [Target])
-> ([Query], [Target]) -> [Target]
forall a b. (a -> b) -> a -> b
$ StoreRead -> [Query] -> ([Query], [Target])
search StoreRead
store (FilePath -> [Query]
parseQuery FilePath
a)
case [Target]
res of
Target{FilePath
Maybe (FilePath, FilePath)
targetDocs :: FilePath
targetItem :: FilePath
targetType :: FilePath
targetModule :: Maybe (FilePath, FilePath)
targetPackage :: Maybe (FilePath, FilePath)
targetURL :: FilePath
targetDocs :: Target -> FilePath
targetItem :: Target -> FilePath
targetType :: Target -> FilePath
targetModule :: Target -> Maybe (FilePath, FilePath)
targetPackage :: Target -> Maybe (FilePath, FilePath)
targetURL :: Target -> FilePath
..}:[Target]
_ | FilePath -> Bool
f FilePath
targetURL -> Char -> IO ()
putChar Char
'.'
[Target]
_ -> FilePath -> IO ()
forall a. HasCallStack => FilePath -> IO a
errorIO (FilePath -> IO ()) -> FilePath -> IO ()
forall a b. (a -> b) -> a -> b
$ FilePath
"Searching for: " FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath -> FilePath
forall a. Show a => a -> FilePath
show FilePath
a FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
"\nGot: " FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ [Target] -> FilePath
forall a. Show a => a -> FilePath
show (Int -> [Target] -> [Target]
forall a. Int -> [a] -> [a]
take Int
1 [Target]
res)
let FilePath
a === :: FilePath -> FilePath -> IO ()
=== FilePath
b = FilePath
a FilePath -> (FilePath -> Bool) -> IO ()
==$ (FilePath -> FilePath -> Bool
forall a. Eq a => a -> a -> Bool
== FilePath
b)
let query :: String -> [ExpectedQueryResult] -> IO ()
query :: FilePath -> [ExpectedQueryResult] -> IO ()
query FilePath
a [ExpectedQueryResult]
qrs = let results :: [[Target]]
results = [Target] -> [[Target]]
deDup ([Target] -> [[Target]]) -> [Target] -> [[Target]]
forall a b. (a -> b) -> a -> b
$ ([Query], [Target]) -> [Target]
forall a b. (a, b) -> b
snd (StoreRead -> [Query] -> ([Query], [Target])
search StoreRead
store (FilePath -> [Query]
parseQuery FilePath
a))
in [ExpectedQueryResult] -> (ExpectedQueryResult -> IO ()) -> IO ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ [ExpectedQueryResult]
qrs ((ExpectedQueryResult -> IO ()) -> IO ())
-> (ExpectedQueryResult -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \ExpectedQueryResult
qr -> case ExpectedQueryResult -> [[Target]] -> TestResult
matchQR ExpectedQueryResult
qr [[Target]]
results of
TestResult
Success -> Char -> IO ()
putChar Char
'.'
TestResult
ExpectedFailure -> Char -> IO ()
putChar Char
'o'
TestResult
_ -> FilePath -> IO ()
forall a. HasCallStack => FilePath -> IO a
errorIO (FilePath -> IO ()) -> FilePath -> IO ()
forall a b. (a -> b) -> a -> b
$ FilePath
"Searching for: " FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath -> FilePath
forall a. Show a => a -> FilePath
show FilePath
a
FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
"\nGot: " FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ [[Target]] -> FilePath
forall a. Show a => a -> FilePath
show (Int -> [[Target]] -> [[Target]]
forall a. Int -> [a] -> [a]
take Int
5 [[Target]]
results)
FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
"\n expected " FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ ExpectedQueryResult -> FilePath
expected ExpectedQueryResult
qr
let hackage :: FilePath -> FilePath
hackage FilePath
x = FilePath
"https://hackage.haskell.org/package/" FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
x
if Bool
sample then do
FilePath
"__prefix__" FilePath -> FilePath -> IO ()
=== FilePath
"http://henry.com?too_long"
FilePath
"__suffix__" FilePath -> FilePath -> IO ()
=== FilePath
"http://henry.com?too_long"
FilePath
"__infix__" FilePath -> FilePath -> IO ()
=== FilePath
"http://henry.com?too_long"
FilePath
"Wife" FilePath -> FilePath -> IO ()
=== FilePath
"http://eghmitchell.com/Mitchell.html#a_wife"
StoreRead -> [FilePath]
completionTags StoreRead
store [FilePath] -> [FilePath] -> IO ()
forall a. (Show a, Eq a) => a -> a -> IO ()
`testEq` [FilePath
"set:all",FilePath
"set:sample-data",FilePath
"package:emily",FilePath
"package:henry"]
else do
FilePath
"base" FilePath -> FilePath -> IO ()
=== FilePath -> FilePath
hackage FilePath
"base"
FilePath
"Prelude" FilePath -> FilePath -> IO ()
=== FilePath -> FilePath
hackage FilePath
"base/docs/Prelude.html"
FilePath
"map" FilePath -> FilePath -> IO ()
=== FilePath -> FilePath
hackage FilePath
"base/docs/Prelude.html#v:map"
FilePath
"map is:ping" FilePath -> FilePath -> IO ()
=== FilePath -> FilePath
hackage FilePath
"base/docs/Prelude.html#v:map"
FilePath
"map package:base" FilePath -> FilePath -> IO ()
=== FilePath -> FilePath
hackage FilePath
"base/docs/Prelude.html#v:map"
FilePath -> IO ()
noResults FilePath
"map package:package-not-in-db"
FilePath -> IO ()
noResults FilePath
"map module:Module.Not.In.Db"
FilePath
"True" FilePath -> FilePath -> IO ()
=== FilePath -> FilePath
hackage FilePath
"base/docs/Prelude.html#v:True"
FilePath
"Bool" FilePath -> FilePath -> IO ()
=== FilePath -> FilePath
hackage FilePath
"base/docs/Prelude.html#t:Bool"
FilePath
"String" FilePath -> FilePath -> IO ()
=== FilePath -> FilePath
hackage FilePath
"base/docs/Prelude.html#t:String"
FilePath
"Ord" FilePath -> FilePath -> IO ()
=== FilePath -> FilePath
hackage FilePath
"base/docs/Prelude.html#t:Ord"
FilePath
">>=" FilePath -> FilePath -> IO ()
=== FilePath -> FilePath
hackage FilePath
"base/docs/Prelude.html#v:-62--62--61-"
FilePath
"sequen" FilePath -> FilePath -> IO ()
=== FilePath -> FilePath
hackage FilePath
"base/docs/Prelude.html#v:sequence"
FilePath
"foldl'" FilePath -> FilePath -> IO ()
=== FilePath -> FilePath
hackage FilePath
"base/docs/Data-List.html#v:foldl-39-"
FilePath
"Action package:shake" FilePath -> FilePath -> IO ()
=== FilePath
"https://hackage.haskell.org/package/shake/docs/Development-Shake.html#t:Action"
FilePath
"Action package:shake set:stackage" FilePath -> FilePath -> IO ()
=== FilePath
"https://hackage.haskell.org/package/shake/docs/Development-Shake.html#t:Action"
FilePath
"map -package:base" FilePath -> (FilePath -> Bool) -> IO ()
==$ \FilePath
x -> Bool -> Bool
not (Bool -> Bool) -> Bool -> Bool
forall a b. (a -> b) -> a -> b
$ FilePath
"/base/" FilePath -> FilePath -> Bool
forall a. Eq a => [a] -> [a] -> Bool
`isInfixOf` FilePath
x
FilePath
"<>" FilePath -> FilePath -> IO ()
=== FilePath -> FilePath
hackage FilePath
"base/docs/Prelude.html#v:-60--62-"
FilePath
"Data.Set.insert" FilePath -> FilePath -> IO ()
=== FilePath -> FilePath
hackage FilePath
"containers/docs/Data-Set.html#v:insert"
FilePath
"Set.insert" FilePath -> FilePath -> IO ()
=== FilePath -> FilePath
hackage FilePath
"containers/docs/Data-Set.html#v:insert"
FilePath
"Prelude.mapM_" FilePath -> FilePath -> IO ()
=== FilePath -> FilePath
hackage FilePath
"base/docs/Prelude.html#v:mapM_"
FilePath
"Data.Complex.(:+)" FilePath -> FilePath -> IO ()
=== FilePath -> FilePath
hackage FilePath
"base/docs/Data-Complex.html#v::-43-"
FilePath
"\8801" FilePath -> FilePath -> IO ()
=== FilePath -> FilePath
hackage FilePath
"base-unicode-symbols/docs/Data-Eq-Unicode.html#v:-8801-"
FilePath
"\8484" FilePath -> FilePath -> IO ()
=== FilePath -> FilePath
hackage FilePath
"base-unicode-symbols/docs/Prelude-Unicode.html#t:-8484-"
FilePath
"copilot" FilePath -> FilePath -> IO ()
=== FilePath -> FilePath
hackage FilePath
"copilot"
FilePath
"supero" FilePath -> FilePath -> IO ()
=== FilePath -> FilePath
hackage FilePath
"supero"
FilePath
"set:stackage" FilePath -> FilePath -> IO ()
=== FilePath -> FilePath
hackage FilePath
"base"
FilePath
"author:Neil-Mitchell" FilePath -> FilePath -> IO ()
=== FilePath -> FilePath
hackage FilePath
"filepath"
FilePath
"set:-haskell-platform author:Neil-Mitchell" FilePath -> FilePath -> IO ()
=== FilePath -> FilePath
hackage FilePath
"safe"
FilePath
"author:Neil-Mitchell category:Javascript" FilePath -> FilePath -> IO ()
=== FilePath -> FilePath
hackage FilePath
"js-jquery"
FilePath
"( )" FilePath -> (FilePath -> Bool) -> IO ()
==$ (FilePath -> Bool -> Bool) -> Bool -> FilePath -> Bool
forall a b c. (a -> b -> c) -> b -> a -> c
flip FilePath -> Bool -> Bool
seq Bool
True
FilePath
"( -is:exact) package:base=" FilePath -> (FilePath -> Bool) -> IO ()
==$ (FilePath -> Bool -> Bool) -> Bool -> FilePath -> Bool
forall a b c. (a -> b -> c) -> b -> a -> c
flip FilePath -> Bool -> Bool
seq Bool
True
FilePath
"(a -> b) -> [a] -> [b]" FilePath -> FilePath -> IO ()
=== FilePath -> FilePath
hackage FilePath
"base/docs/Prelude.html#v:map"
FilePath
"Ord a => [a] -> [a]" FilePath -> FilePath -> IO ()
=== FilePath -> FilePath
hackage FilePath
"base/docs/Data-List.html#v:sort"
FilePath
"ShakeOptions -> Int" FilePath -> FilePath -> IO ()
=== FilePath -> FilePath
hackage FilePath
"shake/docs/Development-Shake.html#v:shakeThreads"
FilePath
"is:module" FilePath -> FilePath -> IO ()
=== FilePath -> FilePath
hackage FilePath
"base/docs/Prelude.html"
FilePath
"visibleDataCons" FilePath -> FilePath -> IO ()
=== FilePath -> FilePath
hackage FilePath
"ghc/docs/GHC-Core-TyCon.html#v:visibleDataCons"
FilePath
"sparkle" FilePath -> FilePath -> IO ()
=== FilePath -> FilePath
hackage FilePath
"sparkle"
FilePath
"weeder" FilePath -> FilePath -> IO ()
=== FilePath -> FilePath
hackage FilePath
"weeder"
FilePath
"supero" FilePath -> FilePath -> IO ()
=== FilePath -> FilePath
hackage FilePath
"supero"
FilePath -> [ExpectedQueryResult] -> IO ()
query FilePath
"(a -> [a]) -> [a] -> [a]"
[ TargetMatcher -> ExpectedQueryResult
TopHit (FilePath
"concatMap" FilePath -> FilePath -> TargetMatcher
`inPackage` FilePath
"base")
, Int -> TargetMatcher -> ExpectedQueryResult
InTop Int
10 (FilePath
"(=<<)" FilePath -> FilePath -> TargetMatcher
`inPackage` FilePath
"base")
, Int -> TargetMatcher -> ExpectedQueryResult
InTop Int
50 (FilePath
"(>>=)" FilePath -> FilePath -> TargetMatcher
`inPackage` FilePath
"base")
]
FilePath -> [ExpectedQueryResult] -> IO ()
query FilePath
"[a] -> Maybe a"
[ TargetMatcher -> ExpectedQueryResult
TopHit (FilePath
"listToMaybe" FilePath -> FilePath -> TargetMatcher
`inModule` FilePath
"Data.Maybe")
, Int -> TargetMatcher -> ExpectedQueryResult
InTop Int
10 (FilePath
"headMay" FilePath -> FilePath -> TargetMatcher
`inModule` FilePath
"Safe")
]
FilePath -> [ExpectedQueryResult] -> IO ()
query FilePath
"a -> [a]"
[ Int -> TargetMatcher -> ExpectedQueryResult
InTop Int
10 (FilePath
"repeat" FilePath -> FilePath -> TargetMatcher
`inPackage` FilePath
"base")
, FilePath -> ExpectedQueryResult -> ExpectedQueryResult
KnownFailure FilePath
"" (ExpectedQueryResult -> ExpectedQueryResult)
-> ExpectedQueryResult -> ExpectedQueryResult
forall a b. (a -> b) -> a -> b
$ Int -> TargetMatcher -> ExpectedQueryResult
InTop Int
50 (FilePath
"singleton" FilePath -> FilePath -> TargetMatcher
`inModule` FilePath
"Util")
, TargetMatcher -> ExpectedQueryResult
DoesNotFind (FilePath
"head" FilePath -> FilePath -> TargetMatcher
`inPackage` FilePath
"base")
, TargetMatcher -> ExpectedQueryResult
DoesNotFind (FilePath
"last" FilePath -> FilePath -> TargetMatcher
`inPackage` FilePath
"base")
, Int -> TargetMatcher -> ExpectedQueryResult
InTop Int
50 (FilePath
"pure" FilePath -> FilePath -> TargetMatcher
`inPackage` FilePath
"base")
, FilePath -> ExpectedQueryResult -> ExpectedQueryResult
KnownFailure FilePath
"" (ExpectedQueryResult -> ExpectedQueryResult)
-> ExpectedQueryResult -> ExpectedQueryResult
forall a b. (a -> b) -> a -> b
$ Int -> TargetMatcher -> ExpectedQueryResult
InTop Int
100 (FilePath
"return" FilePath -> FilePath -> TargetMatcher
`inPackage` FilePath
"base")
, FilePath -> ExpectedQueryResult -> ExpectedQueryResult
KnownFailure FilePath
"GitHub issue #267" (ExpectedQueryResult -> ExpectedQueryResult)
-> ExpectedQueryResult -> ExpectedQueryResult
forall a b. (a -> b) -> a -> b
$
(FilePath
"pure" FilePath -> FilePath -> TargetMatcher
`inPackage` FilePath
"base") TargetMatcher -> TargetMatcher -> ExpectedQueryResult
`AppearsBefore` (FilePath
"shrinkNothing" FilePath -> FilePath -> TargetMatcher
`inModule` FilePath
"Test.QuickCheck")
]
FilePath -> [ExpectedQueryResult] -> IO ()
query FilePath
"[a] -> a"
[ Int -> TargetMatcher -> ExpectedQueryResult
InTop Int
10 (FilePath
"head" FilePath -> FilePath -> TargetMatcher
`inPackage` FilePath
"base")
, Int -> TargetMatcher -> ExpectedQueryResult
InTop Int
10 (FilePath
"last" FilePath -> FilePath -> TargetMatcher
`inPackage` FilePath
"base")
, TargetMatcher -> ExpectedQueryResult
DoesNotFind (FilePath
"repeat" FilePath -> FilePath -> TargetMatcher
`inPackage` FilePath
"base")
]
FilePath -> [ExpectedQueryResult] -> IO ()
query FilePath
"[Char] -> Char"
[ Int -> TargetMatcher -> ExpectedQueryResult
InTop Int
10 (FilePath
"head" FilePath -> FilePath -> TargetMatcher
`inPackage` FilePath
"base")
, Int -> TargetMatcher -> ExpectedQueryResult
RanksBelow Int
10 (FilePath
"mconcat" FilePath -> FilePath -> TargetMatcher
`inPackage` FilePath
"base")
]
FilePath -> [ExpectedQueryResult] -> IO ()
query FilePath
"a -> b"
[ TargetMatcher -> ExpectedQueryResult
TopHit (FilePath
"unsafeCoerce" FilePath -> FilePath -> TargetMatcher
`inModule` FilePath
"Unsafe.Coerce")
, TargetMatcher -> ExpectedQueryResult
DoesNotFind (FilePath
"id" FilePath -> FilePath -> TargetMatcher
`inPackage` FilePath
"base")
, FilePath -> ExpectedQueryResult -> ExpectedQueryResult
KnownFailure FilePath
"GitHub issue #268" (ExpectedQueryResult -> ExpectedQueryResult)
-> ExpectedQueryResult -> ExpectedQueryResult
forall a b. (a -> b) -> a -> b
$
Int -> TargetMatcher -> ExpectedQueryResult
InTop Int
20 (FilePath
"coerce" FilePath -> FilePath -> TargetMatcher
`inModule` FilePath
"Data.Coerce")
, FilePath -> ExpectedQueryResult -> ExpectedQueryResult
KnownFailure FilePath
"GitHub issue #268" (ExpectedQueryResult -> ExpectedQueryResult)
-> ExpectedQueryResult -> ExpectedQueryResult
forall a b. (a -> b) -> a -> b
$
Int -> TargetMatcher -> ExpectedQueryResult
InTop Int
5 (FilePath
"coerce" FilePath -> FilePath -> TargetMatcher
`inModule` FilePath
"Data.Coerce")
]
FilePath -> [ExpectedQueryResult] -> IO ()
query FilePath
"String -> (Char -> Maybe Char) -> Maybe String"
[ FilePath -> ExpectedQueryResult -> ExpectedQueryResult
KnownFailure FilePath
"GitHub issue #266" (ExpectedQueryResult -> ExpectedQueryResult)
-> ExpectedQueryResult -> ExpectedQueryResult
forall a b. (a -> b) -> a -> b
$
Int -> TargetMatcher -> ExpectedQueryResult
InTop Int
10 (FilePath
"traverse" FilePath -> FilePath -> TargetMatcher
`inPackage` FilePath
"base")
, FilePath -> ExpectedQueryResult -> ExpectedQueryResult
KnownFailure FilePath
"GitHub issue #266" (ExpectedQueryResult -> ExpectedQueryResult)
-> ExpectedQueryResult -> ExpectedQueryResult
forall a b. (a -> b) -> a -> b
$
Int -> TargetMatcher -> ExpectedQueryResult
InTop Int
10 (FilePath
"mapM" FilePath -> FilePath -> TargetMatcher
`inPackage` FilePath
"base")
, FilePath -> ExpectedQueryResult -> ExpectedQueryResult
KnownFailure FilePath
"GitHub issue #266" (ExpectedQueryResult -> ExpectedQueryResult)
-> ExpectedQueryResult -> ExpectedQueryResult
forall a b. (a -> b) -> a -> b
$
Int -> TargetMatcher -> ExpectedQueryResult
InTop Int
10 (FilePath
"forM" FilePath -> FilePath -> TargetMatcher
`inPackage` FilePath
"base")
]
FilePath -> [ExpectedQueryResult] -> IO ()
query FilePath
"a -> [(a,b)] -> b"
[ FilePath -> ExpectedQueryResult -> ExpectedQueryResult
KnownFailure FilePath
"GitHub issue #267" (ExpectedQueryResult -> ExpectedQueryResult)
-> ExpectedQueryResult -> ExpectedQueryResult
forall a b. (a -> b) -> a -> b
$
TargetMatcher -> ExpectedQueryResult
TopHit (FilePath
"lookup" FilePath -> FilePath -> TargetMatcher
`inPackage` FilePath
"base")
, Int -> TargetMatcher -> ExpectedQueryResult
InTop Int
3 (FilePath
"lookup" FilePath -> FilePath -> TargetMatcher
`inPackage` FilePath
"base")
, TargetMatcher -> ExpectedQueryResult
DoesNotFind (FilePath
"zip" FilePath -> FilePath -> TargetMatcher
`inPackage` FilePath
"base")
]
FilePath -> [ExpectedQueryResult] -> IO ()
query FilePath
"[(a,b)] -> a -> b"
[ FilePath -> ExpectedQueryResult -> ExpectedQueryResult
KnownFailure FilePath
"GitHub issue #267" (ExpectedQueryResult -> ExpectedQueryResult)
-> ExpectedQueryResult -> ExpectedQueryResult
forall a b. (a -> b) -> a -> b
$
TargetMatcher -> ExpectedQueryResult
TopHit (FilePath
"lookup" FilePath -> FilePath -> TargetMatcher
`inPackage` FilePath
"base")
, Int -> TargetMatcher -> ExpectedQueryResult
InTop Int
3 (FilePath
"lookup" FilePath -> FilePath -> TargetMatcher
`inPackage` FilePath
"base")
, TargetMatcher -> ExpectedQueryResult
DoesNotFind (FilePath
"zip" FilePath -> FilePath -> TargetMatcher
`inPackage` FilePath
"base")
]
FilePath -> [ExpectedQueryResult] -> IO ()
query FilePath
"(a -> m b) -> t a -> m (t b)"
[ Int -> TargetMatcher -> ExpectedQueryResult
InTop Int
10 (FilePath
"traverse" FilePath -> FilePath -> TargetMatcher
`inPackage` FilePath
"base")
, Int -> TargetMatcher -> ExpectedQueryResult
InTop Int
10 (FilePath
"mapConcurrently" FilePath -> FilePath -> TargetMatcher
`inModule` FilePath
"Control.Concurrent.Async.Lifted")
, Int -> TargetMatcher -> ExpectedQueryResult
InTop Int
10 (FilePath
"mapM" FilePath -> FilePath -> TargetMatcher
`inPackage` FilePath
"base")
, Int -> TargetMatcher -> ExpectedQueryResult
InTop Int
50 (FilePath
"forM" FilePath -> FilePath -> TargetMatcher
`inPackage` FilePath
"base")
]
FilePath -> [ExpectedQueryResult] -> IO ()
query FilePath
"m (m a) -> m a"
[ TargetMatcher -> ExpectedQueryResult
TopHit (FilePath
"join" FilePath -> FilePath -> TargetMatcher
`inPackage` FilePath
"base")
]
FilePath -> [ExpectedQueryResult] -> IO ()
query FilePath
"(a -> b -> c) -> (a -> b) -> a -> c"
[ FilePath -> ExpectedQueryResult -> ExpectedQueryResult
KnownFailure FilePath
"GitHub issue #269" (ExpectedQueryResult -> ExpectedQueryResult)
-> ExpectedQueryResult -> ExpectedQueryResult
forall a b. (a -> b) -> a -> b
$
Int -> TargetMatcher -> ExpectedQueryResult
InTop Int
5 (FilePath
"ap" FilePath -> FilePath -> TargetMatcher
`inPackage` FilePath
"base")
, FilePath -> ExpectedQueryResult -> ExpectedQueryResult
KnownFailure FilePath
"GitHub issue #269" (ExpectedQueryResult -> ExpectedQueryResult)
-> ExpectedQueryResult -> ExpectedQueryResult
forall a b. (a -> b) -> a -> b
$
Int -> TargetMatcher -> ExpectedQueryResult
InTop Int
5 (FilePath
"(<*>)" FilePath -> FilePath -> TargetMatcher
`inPackage` FilePath
"base")
]
FilePath -> [ExpectedQueryResult] -> IO ()
query FilePath
"String -> Int"
[ TargetMatcher -> ExpectedQueryResult
DoesNotFind (FilePath
"cursorUpCode" FilePath -> FilePath -> TargetMatcher
`inPackage` FilePath
"ansi-terminal")
, FilePath -> ExpectedQueryResult -> ExpectedQueryResult
KnownFailure FilePath
"GitHub issue #266" (ExpectedQueryResult -> ExpectedQueryResult)
-> ExpectedQueryResult -> ExpectedQueryResult
forall a b. (a -> b) -> a -> b
$ Int -> TargetMatcher -> ExpectedQueryResult
InTop Int
20 (FilePath
"length" FilePath -> FilePath -> TargetMatcher
`inPackage` FilePath
"base")
]
FilePath -> [ExpectedQueryResult] -> IO ()
query FilePath
"(a -> b) -> f a -> f b"
[ TargetMatcher -> ExpectedQueryResult
TopHit (FilePath
"fmap" FilePath -> FilePath -> TargetMatcher
`inPackage` FilePath
"base")
]
FilePath -> [ExpectedQueryResult] -> IO ()
query FilePath
"(a -> b) -> Maybe a -> Maybe b"
[ Int -> TargetMatcher -> ExpectedQueryResult
InTop Int
3 (FilePath
"fmap" FilePath -> FilePath -> TargetMatcher
`inPackage` FilePath
"base")
]
FilePath -> [ExpectedQueryResult] -> IO ()
query FilePath
"IO a -> m a"
[ Int -> TargetMatcher -> ExpectedQueryResult
InTop Int
5 (FilePath
"liftIO" FilePath -> FilePath -> TargetMatcher
`inPackage` FilePath
"base")
]
FilePath -> [ExpectedQueryResult] -> IO ()
query FilePath
"a -> m a"
[ Int -> TargetMatcher -> ExpectedQueryResult
InTop Int
20 (FilePath
"pure" FilePath -> FilePath -> TargetMatcher
`inPackage` FilePath
"base")
, Int -> TargetMatcher -> ExpectedQueryResult
InTop Int
50 (FilePath
"return" FilePath -> FilePath -> TargetMatcher
`inPackage` FilePath
"base")
, FilePath -> ExpectedQueryResult -> ExpectedQueryResult
KnownFailure FilePath
"GitHub issue #267" (ExpectedQueryResult -> ExpectedQueryResult)
-> ExpectedQueryResult -> ExpectedQueryResult
forall a b. (a -> b) -> a -> b
$
Int -> TargetMatcher -> ExpectedQueryResult
InTop Int
5 (FilePath
"pure" FilePath -> FilePath -> TargetMatcher
`inPackage` FilePath
"base")
, FilePath -> ExpectedQueryResult -> ExpectedQueryResult
KnownFailure FilePath
"GitHub issue #267" (ExpectedQueryResult -> ExpectedQueryResult)
-> ExpectedQueryResult -> ExpectedQueryResult
forall a b. (a -> b) -> a -> b
$
Int -> TargetMatcher -> ExpectedQueryResult
InTop Int
3 (FilePath
"return" FilePath -> FilePath -> TargetMatcher
`inPackage` FilePath
"base")
]
FilePath -> [ExpectedQueryResult] -> IO ()
query FilePath
"(a -> a) -> k -> Map k a -> Map k a"
[ TargetMatcher -> ExpectedQueryResult
TopHit (FilePath
"adjust" FilePath -> FilePath -> TargetMatcher
`inPackage` FilePath
"containers")
]
FilePath -> [ExpectedQueryResult] -> IO ()
query FilePath
"Int -> Integer"
[ Int -> TargetMatcher -> ExpectedQueryResult
InTop Int
40 (FilePath
"toInteger" FilePath -> FilePath -> TargetMatcher
`inPackage` FilePath
"base")
, FilePath -> ExpectedQueryResult -> ExpectedQueryResult
KnownFailure FilePath
"GitHub issue #127" (ExpectedQueryResult -> ExpectedQueryResult)
-> ExpectedQueryResult -> ExpectedQueryResult
forall a b. (a -> b) -> a -> b
$
TargetMatcher -> ExpectedQueryResult
TopHit (FilePath
"toInteger" FilePath -> FilePath -> TargetMatcher
`inPackage` FilePath
"base")
]
FilePath -> [ExpectedQueryResult] -> IO ()
query FilePath
"Integer -> Int"
[ Int -> TargetMatcher -> ExpectedQueryResult
InTop Int
40 (FilePath
"fromInteger" FilePath -> FilePath -> TargetMatcher
`inPackage` FilePath
"base")
, FilePath -> ExpectedQueryResult -> ExpectedQueryResult
KnownFailure FilePath
"GitHub issue #127" (ExpectedQueryResult -> ExpectedQueryResult)
-> ExpectedQueryResult -> ExpectedQueryResult
forall a b. (a -> b) -> a -> b
$
TargetMatcher -> ExpectedQueryResult
TopHit (FilePath
"fromInteger" FilePath -> FilePath -> TargetMatcher
`inPackage` FilePath
"base")
]
FilePath -> [ExpectedQueryResult] -> IO ()
query FilePath
"[Parser a] -> Parser a"
[ FilePath -> ExpectedQueryResult -> ExpectedQueryResult
KnownFailure FilePath
"Todo" (ExpectedQueryResult -> ExpectedQueryResult)
-> ExpectedQueryResult -> ExpectedQueryResult
forall a b. (a -> b) -> a -> b
$ Int -> TargetMatcher -> ExpectedQueryResult
InTop Int
10 (FilePath
"choice" FilePath -> FilePath -> TargetMatcher
`inPackage` FilePath
"attoparsec")
]
let tags :: [FilePath]
tags = StoreRead -> [FilePath]
completionTags StoreRead
store
let asserts :: Bool -> FilePath -> IO ()
asserts Bool
b FilePath
x = if Bool
b then Char -> IO ()
putChar Char
'.' else FilePath -> IO ()
forall a. HasCallStack => FilePath -> IO a
errorIO (FilePath -> IO ()) -> FilePath -> IO ()
forall a b. (a -> b) -> a -> b
$ FilePath
"Assertion failed, got False for " FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
x
Bool -> FilePath -> IO ()
asserts (FilePath
"set:haskell-platform" FilePath -> [FilePath] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [FilePath]
tags) FilePath
"set:haskell-platform `elem` tags"
Bool -> FilePath -> IO ()
asserts (FilePath
"author:Neil-Mitchell" FilePath -> [FilePath] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [FilePath]
tags) FilePath
"author:Neil-Mitchell `elem` tags"
Bool -> FilePath -> IO ()
asserts (FilePath
"package:uniplate" FilePath -> [FilePath] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [FilePath]
tags) FilePath
"package:uniplate `elem` tags"
Bool -> FilePath -> IO ()
asserts (FilePath
"package:supero" FilePath -> [FilePath] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`notElem` [FilePath]
tags) FilePath
"package:supero `notElem` tags"
data ExpectedQueryResult
= TopHit TargetMatcher
| InTop Int TargetMatcher
| RanksBelow Int TargetMatcher
| DoesNotFind TargetMatcher
| AppearsBefore TargetMatcher TargetMatcher
| NoHits
| KnownFailure String ExpectedQueryResult
expected :: ExpectedQueryResult -> String
expected :: ExpectedQueryResult -> FilePath
expected = \case
TopHit TargetMatcher
tm -> TargetMatcher -> FilePath
showTM TargetMatcher
tm FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
" as first hit."
InTop Int
n TargetMatcher
tm -> TargetMatcher -> FilePath
showTM TargetMatcher
tm FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
" in top " FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ Int -> FilePath
forall a. Show a => a -> FilePath
show Int
n FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
" hits."
RanksBelow Int
n TargetMatcher
tm -> TargetMatcher -> FilePath
showTM TargetMatcher
tm FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
" not in top " FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ Int -> FilePath
forall a. Show a => a -> FilePath
show Int
n FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
" hits."
DoesNotFind TargetMatcher
tm -> FilePath
"to not match " FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ TargetMatcher -> FilePath
showTM TargetMatcher
tm FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
"."
AppearsBefore TargetMatcher
tm TargetMatcher
tm' -> TargetMatcher -> FilePath
showTM TargetMatcher
tm FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
" to appear before " FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ TargetMatcher -> FilePath
showTM TargetMatcher
tm' FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
"."
ExpectedQueryResult
NoHits -> FilePath
"no results."
KnownFailure FilePath
why ExpectedQueryResult
qr -> FilePath
"to see a failure (" FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
why FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
"): \"" FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ ExpectedQueryResult -> FilePath
expected ExpectedQueryResult
qr FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
"\" But it succeeded!"
data TestResult
= Success
| Failure
| ExpectedFailure
| UnexpectedSuccess
matchQR :: ExpectedQueryResult -> [[Target]] -> TestResult
matchQR :: ExpectedQueryResult -> [[Target]] -> TestResult
matchQR ExpectedQueryResult
qr [[Target]]
res = case ExpectedQueryResult
qr of
TopHit TargetMatcher
tm -> Bool -> TestResult
success (Bool -> TestResult) -> Bool -> TestResult
forall a b. (a -> b) -> a -> b
$ (Target -> Bool) -> [Target] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any (TargetMatcher -> Target -> Bool
runTargetMatcher TargetMatcher
tm) ([[Target]] -> [Target]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat ([[Target]] -> [Target]) -> [[Target]] -> [Target]
forall a b. (a -> b) -> a -> b
$ Int -> [[Target]] -> [[Target]]
forall a. Int -> [a] -> [a]
take Int
1 [[Target]]
res)
InTop Int
n TargetMatcher
tm -> Bool -> TestResult
success (Bool -> TestResult) -> Bool -> TestResult
forall a b. (a -> b) -> a -> b
$ (Target -> Bool) -> [Target] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any (TargetMatcher -> Target -> Bool
runTargetMatcher TargetMatcher
tm) ([[Target]] -> [Target]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat ([[Target]] -> [Target]) -> [[Target]] -> [Target]
forall a b. (a -> b) -> a -> b
$ Int -> [[Target]] -> [[Target]]
forall a. Int -> [a] -> [a]
take Int
n [[Target]]
res)
RanksBelow Int
n TargetMatcher
tm -> Bool -> TestResult
success (Bool -> TestResult) -> Bool -> TestResult
forall a b. (a -> b) -> a -> b
$ (Target -> Bool) -> [Target] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any (TargetMatcher -> Target -> Bool
runTargetMatcher TargetMatcher
tm) ([[Target]] -> [Target]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat ([[Target]] -> [Target]) -> [[Target]] -> [Target]
forall a b. (a -> b) -> a -> b
$ Int -> [[Target]] -> [[Target]]
forall a. Int -> [a] -> [a]
drop Int
n [[Target]]
res)
DoesNotFind TargetMatcher
tm -> Bool -> TestResult
success (Bool -> TestResult) -> Bool -> TestResult
forall a b. (a -> b) -> a -> b
$ Bool -> Bool
not (Bool -> Bool) -> Bool -> Bool
forall a b. (a -> b) -> a -> b
$ (Target -> Bool) -> [Target] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any (TargetMatcher -> Target -> Bool
runTargetMatcher TargetMatcher
tm) ([[Target]] -> [Target]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat [[Target]]
res)
AppearsBefore TargetMatcher
tm TargetMatcher
tm' -> Bool -> TestResult
success (Bool -> TestResult) -> Bool -> TestResult
forall a b. (a -> b) -> a -> b
$ ( Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
(<) (Integer -> Integer -> Bool)
-> Maybe Integer -> Maybe (Integer -> Bool)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> TargetMatcher -> Maybe Integer
forall b. (Enum b, Num b) => TargetMatcher -> Maybe b
matchIdx TargetMatcher
tm Maybe (Integer -> Bool) -> Maybe Integer -> Maybe Bool
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> TargetMatcher -> Maybe Integer
forall b. (Enum b, Num b) => TargetMatcher -> Maybe b
matchIdx TargetMatcher
tm' ) Maybe Bool -> Maybe Bool -> Bool
forall a. Eq a => a -> a -> Bool
== Bool -> Maybe Bool
forall a. a -> Maybe a
Just Bool
True
ExpectedQueryResult
NoHits -> Bool -> TestResult
success (Bool -> TestResult) -> Bool -> TestResult
forall a b. (a -> b) -> a -> b
$ [[Target]] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [[Target]]
res
KnownFailure FilePath
_ ExpectedQueryResult
qr' -> case ExpectedQueryResult -> [[Target]] -> TestResult
matchQR ExpectedQueryResult
qr' [[Target]]
res of
TestResult
Success -> TestResult
UnexpectedSuccess
TestResult
Failure -> TestResult
ExpectedFailure
TestResult
ExpectedFailure -> TestResult
Failure
TestResult
UnexpectedSuccess -> TestResult
Failure
where
success :: Bool -> TestResult
success Bool
p = if Bool
p then TestResult
Success else TestResult
Failure
matchIdx :: TargetMatcher -> Maybe b
matchIdx TargetMatcher
tm = ((b, Target) -> b) -> Maybe (b, Target) -> Maybe b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (b, Target) -> b
forall a b. (a, b) -> a
fst (Maybe (b, Target) -> Maybe b) -> Maybe (b, Target) -> Maybe b
forall a b. (a -> b) -> a -> b
$ ((b, Target) -> Bool) -> [(b, Target)] -> Maybe (b, Target)
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Maybe a
find (TargetMatcher -> Target -> Bool
runTargetMatcher TargetMatcher
tm (Target -> Bool) -> ((b, Target) -> Target) -> (b, Target) -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (b, Target) -> Target
forall a b. (a, b) -> b
snd) (b -> [Target] -> [(b, Target)]
forall a b. Enum a => a -> [b] -> [(a, b)]
zipFrom b
0 ([Target] -> [(b, Target)]) -> [Target] -> [(b, Target)]
forall a b. (a -> b) -> a -> b
$ [[Target]] -> [Target]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat [[Target]]
res)
data TargetMatcher
= MatchFunctionInModule String String
| MatchFunctionInPackage String String
showTM :: TargetMatcher -> String
showTM :: TargetMatcher -> FilePath
showTM = \case
MatchFunctionInModule FilePath
f FilePath
m -> FilePath
m FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
"'s " FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
f
MatchFunctionInPackage FilePath
f FilePath
p -> FilePath
f FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
" from package " FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
p
runTargetMatcher :: TargetMatcher -> Target -> Bool
runTargetMatcher :: TargetMatcher -> Target -> Bool
runTargetMatcher TargetMatcher
matcher Target{FilePath
Maybe (FilePath, FilePath)
targetDocs :: FilePath
targetItem :: FilePath
targetType :: FilePath
targetModule :: Maybe (FilePath, FilePath)
targetPackage :: Maybe (FilePath, FilePath)
targetURL :: FilePath
targetDocs :: Target -> FilePath
targetItem :: Target -> FilePath
targetType :: Target -> FilePath
targetModule :: Target -> Maybe (FilePath, FilePath)
targetPackage :: Target -> Maybe (FilePath, FilePath)
targetURL :: Target -> FilePath
..} = case TargetMatcher
matcher of
MatchFunctionInModule FilePath
f FilePath
m ->
FilePath -> Maybe FilePath
forall a. a -> Maybe a
Just FilePath
m Maybe FilePath -> Maybe FilePath -> Bool
forall a. Eq a => a -> a -> Bool
== ((FilePath, FilePath) -> FilePath)
-> Maybe (FilePath, FilePath) -> Maybe FilePath
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (FilePath, FilePath) -> FilePath
forall a b. (a, b) -> a
fst Maybe (FilePath, FilePath)
targetModule
Bool -> Bool -> Bool
&& FilePath
f FilePath -> FilePath -> Bool
forall a. Eq a => [a] -> [a] -> Bool
`isPrefixOf` FilePath -> FilePath
unHTML FilePath
targetItem
MatchFunctionInPackage FilePath
f FilePath
m ->
FilePath -> Maybe FilePath
forall a. a -> Maybe a
Just FilePath
m Maybe FilePath -> Maybe FilePath -> Bool
forall a. Eq a => a -> a -> Bool
== ((FilePath, FilePath) -> FilePath)
-> Maybe (FilePath, FilePath) -> Maybe FilePath
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (FilePath, FilePath) -> FilePath
forall a b. (a, b) -> a
fst Maybe (FilePath, FilePath)
targetPackage
Bool -> Bool -> Bool
&& FilePath
f FilePath -> FilePath -> Bool
forall a. Eq a => [a] -> [a] -> Bool
`isPrefixOf` FilePath -> FilePath
unHTML FilePath
targetItem
inModule :: String -> String -> TargetMatcher
inModule :: FilePath -> FilePath -> TargetMatcher
inModule = FilePath -> FilePath -> TargetMatcher
MatchFunctionInModule
inPackage :: String -> String -> TargetMatcher
inPackage :: FilePath -> FilePath -> TargetMatcher
inPackage = FilePath -> FilePath -> TargetMatcher
MatchFunctionInPackage
deDup :: [Target] -> [[Target]]
deDup :: [Target] -> [[Target]]
deDup [Target]
tgts = Map Int [Target] -> [[Target]]
forall k a. Map k a -> [a]
Map.elems ([(Int, [Target])] -> Map Int [Target]
forall k a. Ord k => [(k, a)] -> Map k a
Map.fromList ([(Int, [Target])] -> Map Int [Target])
-> [(Int, [Target])] -> Map Int [Target]
forall a b. (a -> b) -> a -> b
$ Map Target (Int, [Target]) -> [(Int, [Target])]
forall k a. Map k a -> [a]
Map.elems Map Target (Int, [Target])
tgtMap)
where
tgtMap :: Map.Map Target (Int, [Target])
tgtMap :: Map Target (Int, [Target])
tgtMap = ((Int, [Target]) -> (Int, [Target]) -> (Int, [Target]))
-> [(Target, (Int, [Target]))] -> Map Target (Int, [Target])
forall k a. Ord k => (a -> a -> a) -> [(k, a)] -> Map k a
Map.fromListWith (\(Int
n, [Target]
ts) (Int
n', [Target]
ts') -> (Int -> Int -> Int
forall a. Ord a => a -> a -> a
min Int
n Int
n', [Target]
ts [Target] -> [Target] -> [Target]
forall a. [a] -> [a] -> [a]
++ [Target]
ts'))
([(Target, (Int, [Target]))] -> Map Target (Int, [Target]))
-> [(Target, (Int, [Target]))] -> Map Target (Int, [Target])
forall a b. (a -> b) -> a -> b
$ (Int -> Target -> (Target, (Int, [Target])))
-> Int -> [Target] -> [(Target, (Int, [Target]))]
forall a b c. Enum a => (a -> b -> c) -> a -> [b] -> [c]
zipWithFrom (\Int
n Target
t -> (Target -> Target
simple Target
t, (Int
n, [Target
t]))) Int
0 [Target]
tgts
simple :: Target -> Target
simple :: Target -> Target
simple Target
t = Target
t { targetURL :: FilePath
targetURL = FilePath
"", targetPackage :: Maybe (FilePath, FilePath)
targetPackage = Maybe (FilePath, FilePath)
forall a. Maybe a
Nothing, targetModule :: Maybe (FilePath, FilePath)
targetModule = Maybe (FilePath, FilePath)
forall a. Maybe a
Nothing }